Android GUI FramebufferNativeWindow ANativeWindow

Android GUI FramebufferNativeWindow ANativeWindow

Android系统的GUI设计的两种本地窗口:
面向管理者(SurfaceFlinger)
SurfaceFlinger扮演了系统中所有UI界面的管理者,它需要直接或间接地持有“本地窗口”,这个窗口就是FramebufferNativeWindow
面向应用程序
—-这类窗口是SurfaceTextureClient
这里写图片描述
Window-1 是能直接显示在终端屏幕上, 它使用了帧缓冲区
Window-2 是从内存缓冲区分配的空间

OpenGL“本地窗口”(NativeWindow),Android系统通过ANativeWindow实现OpenGL ES的本地化, 而FramebufferNativeWindow是ANativeWindow子类,对应的是真实的物理屏幕。
OpenGL ES ->ANativeWindow->FramebufferNativeWindow

OpenGL ES 本质上是一个图形渲染管线的状态机
EGL
1、为 OpenGL ES 提供平台独立性而设计
2、是 OpenGL ES 和底层 Native 平台视窗系统之间的接口
3、用于监控图形渲染管线的状态以及维护 Frame buffer 和其他渲染 Surface 的外部层
—-OpenGL ES 图形管线的状态被存储于 EGL 管理的一个 Context 中。 Frame Buffers 和其他绘制 Surfaces 通过 EGL API 创建、管理和销毁。 EGL 同时也控制和提供了对设备显示和可能的设备渲染配置的访问
这里写图片描述

EGL 应用:

EGLDisplay mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); // 1、获取显示设备 
//EGLDisplay eglGetDisplay (NativeDisplayType display); //display 参数是native系统的窗口显示ID值 
eglInitialize(mEglDisplay, &major, &minor); // 2、初始化显示设备、获取EGL版本号

EGLint config_attribs[] = {
    EGL_BLUE_SIZE, 8,
    EGL_GREEN_SIZE, 8,
    EGL_RED_SIZE, 8,
    EGL_RENDERABLE_TYPE, //指定渲染api类别, 这里或者是硬编码的4
    EGL_OPENGL_ES2_BIT,  //或者是EGL14.EGL_OPENGL_ES2_BIT 
    EGL_SURFACE_TYPE, 
    EGL_WINDOW_BIT,
    EGL_NONE
};
int num_configs = 0;
EGLConfig   eglConfig;

//3、获取满足attributes的所有config, EGLConfig---描述EGLSurface配置信息的数据类型(绘制目标framebuffer的配置属性)
eglChooseConfig(mEglDisplay, config_attribs, &eglConfig, 1, &num_configs)) 

//通过ANativeWindow 创建本地surface---EGLSurface,它是系统窗口或frame buffer句柄,可以理解为一个后端的渲染目标窗口
// 4、将Surface转换为本地窗口
EGLSurface mEglSurface = eglCreateWindowSurface(mEglDisplay, eglConfig, mWin, NULL); 

eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &mSurfaceWidth); 
// 5、查询高宽
eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &mSurfaceHeight);

EGLint context_attrib[] = {
    EGL_CONTEXT_CLIENT_VERSION, 2,
    EGL_NONE
};

//创建EGL环境, EGLContext: OpenGL ES图形上下文,它代表了OpenGL状态机
EGLContext mEglContext = eglCreateContext(mEglDisplay, eglConfig, EGL_NO_CONTEXT, context_attrib); 
// 6、根据EGLConfig、context_attrib创建EGLContext

//7、将EGLDisplay、EGLSurface和EGLContext进行绑定(渲染上下文绑定到渲染面,指定当前的环境为绘制环境 EGLContext->context)
//eglMakeCurrent后生成的surface就可以利用opengl画图了
eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); 
render: 
//双缓冲刷新 front buffer 和 back buffer 
//eglSwapBuffers会去触发queuebuffer,dequeuebuffer, 
//queuebuffer将画好的buffer(back->front)交给surfaceflinger处理, 
//dequeuebuffer新创建一个buffer用来画图 
eglSwapBuffers(mEglDisplay, mEglSurface);

//release流程: 
eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); //1、 
eglDestroyContext(mEglDisplay, mEglContext); // 2、 
eglDestroySurface(mEglDisplay, mEglSurface); // 3、 
eglTerminate(mEglDisplay); // 4、

mEglDisplay = EGL_NO_DISPLAY; // 5、 
mEglContext = EGL_NO_CONTEXT; 
mEglSurface = EGL_NO_SURFACE;

1、
ANativeWindow
EGL创建一个Window Surface函数原型列出如下:
EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
NativeWindowType window, const EGLint *attrib_list);

frameworks/base/opengl/include/egl/Eglplatform.h

#ifndef __eglplatform_h_
#define __eglplatform_h_

#include <KHR/khrplatform.h>

#ifndef EGLAPI
#define EGLAPI KHRONOS_APICALL
#endif

#ifndef EGLAPIENTRY
#define EGLAPIENTRY  KHRONOS_APIENTRY
#endif
#define EGLAPIENTRYP EGLAPIENTRY*

#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>

typedef HDC     EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
typedef HWND    EGLNativeWindowType;

#elif defined(__WINSCW__) || defined(__SYMBIAN32__)  /* Symbian */

typedef int   EGLNativeDisplayType;
typedef void *EGLNativeWindowType;
typedef void *EGLNativePixmapType;

#elif defined(__ANDROID__) || defined(ANDROID) //针对android平台,关键定义项

#include <android/native_window.h>
struct egl_native_pixmap_t;
typedef struct ANativeWindow*           EGLNativeWindowType;
typedef struct egl_native_pixmap_t*     EGLNativePixmapType;
typedef void*                           EGLNativeDisplayType;

#elif defined(__unix__)

/* X11 (tentative)  */
#include <X11/Xlib.h>
#include <X11/Xutil.h>

typedef Display *EGLNativeDisplayType;
typedef Pixmap   EGLNativePixmapType;
typedef Window   EGLNativeWindowType;

#else
#error "Platform not recognized"
#endif

/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
typedef EGLNativeDisplayType NativeDisplayType;
typedef EGLNativePixmapType  NativePixmapType;
typedef EGLNativeWindowType  NativeWindowType;

typedef khronos_int32_t EGLint;

#endif /* __eglplatform_h */

ANativeWindow
system/core/include/system/Window.h

...
typedef const native_handle_t* buffer_handle_t;

typedef struct android_native_base_t
{
    /* a magic value defined by the actual EGL native type */
    int magic;

    /* the sizeof() of the actual EGL native type */
    int version;
    void* reserved[4];

    /* reference-counting interface */
    void (*incRef)(struct android_native_base_t* base);
    void (*decRef)(struct android_native_base_t* base);
} android_native_base_t;

typedef struct ANativeWindowBuffer
{
#ifdef __cplusplus
    ANativeWindowBuffer() {
        common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
        common.version = sizeof(ANativeWindowBuffer);
        memset(common.reserved, 0, sizeof(common.reserved));
    }

    // Implement the methods that sp<ANativeWindowBuffer> expects so that it
    // can be used to automatically refcount ANativeWindowBuffer's.
    void incStrong(const void* id) const {
        common.incRef(const_cast<android_native_base_t*>(&common));
    }
    void decStrong(const void* id) const {
        common.decRef(const_cast<android_native_base_t*>(&common));
    }
#endif
    struct android_native_base_t common;
    int width;
    int height;
    int stride;
    int format;
    int usage;

    void* reserved[2];
    buffer_handle_t handle;
    void* reserved_proc[8];
} ANativeWindowBuffer_t;

// Old typedef for backwards compatibility.
typedef ANativeWindowBuffer_t android_native_buffer_t;

...
struct ANativeWindow
{
#ifdef __cplusplus
    ANativeWindow()
        : flags(0), minSwapInterval(0), maxSwapInterval(0), xdpi(0), ydpi(0)
    {
        common.magic = ANDROID_NATIVE_WINDOW_MAGIC;
        common.version = sizeof(ANativeWindow);
        memset(common.reserved, 0, sizeof(common.reserved));
    }

    /* Implement the methods that sp<ANativeWindow> expects so that it
       can be used to automatically refcount ANativeWindow's. */
    void incStrong(const void* id) const {
        common.incRef(const_cast<android_native_base_t*>(&common));
    }
    void decStrong(const void* id) const {
        common.decRef(const_cast<android_native_base_t*>(&common));
    }
#endif

    struct android_native_base_t common;

    /* flags describing some attributes of this surface or its updater */
    const uint32_t flags;

    /* min swap interval supported by this updated */
    const int   minSwapInterval;

    /* max swap interval supported by this updated */
    const int   maxSwapInterval;

    /* horizontal and vertical resolution in DPI */
    const float xdpi;
    const float ydpi;

    /* Some storage reserved for the OEM's driver. */
    intptr_t    oem[4];
    //设置交换间隔时间
    int     (*setSwapInterval)(struct ANativeWindow* window,
                int interval);

    //EGL通过这个dequeueBuffer来申请一个buffer。本地窗口所提供的buffer分别来自于帧缓冲区和内存空间。
    int     (*dequeueBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer** buffer);

    int     (*lockBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer);

    //当EGL对一块buffer渲染完成后,调用queueBuffer来unlock和post buffer
    int     (*queueBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer);

    int     (*query)(const struct ANativeWindow* window,
                int what, int* value);

    /*
     * hook used to perform various operations on the surface.
     * (*perform)() is a generic mechanism to add functionality to
     * ANativeWindow while keeping backward binary compatibility.
     *
     * DO NOT CALL THIS HOOK DIRECTLY.  Instead, use the helper functions
     * defined below.
     *
     *  (*perform)() returns -ENOENT if the 'what' parameter is not supported
     *  by the surface's implementation.
     *
     * The valid operations are:
     *     NATIVE_WINDOW_SET_USAGE
     *     NATIVE_WINDOW_CONNECT               (deprecated)
     *     NATIVE_WINDOW_DISCONNECT            (deprecated)
     *     NATIVE_WINDOW_SET_CROP
     *     NATIVE_WINDOW_SET_BUFFER_COUNT
     *     NATIVE_WINDOW_SET_BUFFERS_GEOMETRY  (deprecated)
     *     NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
     *     NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
     *     NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS
     *     NATIVE_WINDOW_SET_BUFFERS_FORMAT
     *     NATIVE_WINDOW_SET_SCALING_MODE
     *     NATIVE_WINDOW_LOCK                   (private)
     *     NATIVE_WINDOW_UNLOCK_AND_POST        (private)
     *     NATIVE_WINDOW_API_CONNECT            (private)
     *     NATIVE_WINDOW_API_DISCONNECT         (private)
     *
     */

    int     (*perform)(struct ANativeWindow* window,
                int operation, ... );

    int     (*cancelBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer);


    void* reserved_proc[2];
};

native_handle_t代表一块内存块
system/core/include/cutils/native_handle.h

typedef struct native_handle
{
    int version;        /* sizeof(native_handle_t) */
    int numFds;         /* number of file-descriptors at &data[0] */
    int numInts;        /* number of ints at &data[numFds] */
    int data[0];        /* numFds + numInts ints */
} native_handle_t;

2、
FramebufferNativeWindow对应的是真实的物理屏幕
frameworks/base/include/ui/FramebufferNativeWindow.h

...
#define NUM_FRAME_BUFFERS  2

class FramebufferNativeWindow 
    : public EGLNativeBase<
        ANativeWindow, 
        FramebufferNativeWindow, 
        LightRefBase<FramebufferNativeWindow> >
{
public:
    FramebufferNativeWindow(); 
    framebuffer_device_t const * getDevice() const { return fbDev; } 

    bool isUpdateOnDemand() const { return mUpdateOnDemand; }
    status_t setUpdateRectangle(const Rect& updateRect);
    status_t compositionComplete();

    void dump(String8& result);
    // for debugging only
    int getCurrentBufferIndex() const;

private:
    friend class LightRefBase<FramebufferNativeWindow>;    
    ~FramebufferNativeWindow(); // this class cannot be overloaded
    static int setSwapInterval(ANativeWindow* window, int interval);
    static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer);
    static int lockBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
    static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer);
    static int query(const ANativeWindow* window, int what, int* value);
    static int perform(ANativeWindow* window, int operation, ...);

    framebuffer_device_t* fbDev;
    alloc_device_t* grDev;

    sp<NativeBuffer> buffers[NUM_FRAME_BUFFERS];
    sp<NativeBuffer> front;

    mutable Mutex mutex;
    Condition mCondition;
    int32_t mNumBuffers; //FramebufferNativeWindow管理的buffer总数
    int32_t mNumFreeBuffers; // 空闲的buffer数
    int32_t mBufferHead;
    int32_t mCurrentBufferIndex;
    bool mUpdateOnDemand;
#if defined(BOARD_USES_HDMI)
    SecHdmiClient *mHdmiClient;
#endif
};

frameworks/base/libs/ui/FramebufferNativeWindow.cpp

...
class NativeBuffer 
    : public EGLNativeBase<
        ANativeWindowBuffer, 
        NativeBuffer, 
        LightRefBase<NativeBuffer> >
{
public:
    NativeBuffer(int w, int h, int f, int u) : BASE() {
        ANativeWindowBuffer::width  = w;
        ANativeWindowBuffer::height = h;
        ANativeWindowBuffer::format = f;
        ANativeWindowBuffer::usage  = u;
    }
private:
    friend class LightRefBase<NativeBuffer>;    
    ~NativeBuffer() { }; // this class cannot be overloaded
};

FramebufferNativeWindow::FramebufferNativeWindow() 
    : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
{
    hw_module_t const* module;

#if defined(BOARD_USES_HDMI)
    mHdmiClient = android::SecHdmiClient::getInstance();
#endif
    //1\将指定的模块加载到内存来
    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
        int stride;
        int err;
        int i;
        //2\打开Gralloc模块中的gralloc设备和fb设备
        //Gralloc模块负责注册图形缓冲区,gralloc设备负责分配图形缓冲区,fb设备负责渲染图形缓冲区
        //framebuffer_open()\gralloc_open()实际都调用gralloc.cpp中的gralloc_device_open()打开实际的设备
        err = framebuffer_open(module, &fbDev); //打开framebuffer设备
        LOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));

        err = gralloc_open(module, &grDev); //grallo设备
        LOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));

        // bail out if we can't initialize the modules
        if (!fbDev || !grDev)
            return;

        mUpdateOnDemand = (fbDev->setUpdateRect != 0);

        // initialize the buffer FIFO
        mNumBuffers = NUM_FRAME_BUFFERS;
        mNumFreeBuffers = NUM_FRAME_BUFFERS;
        mBufferHead = mNumBuffers-1;

        for (i = 0; i < mNumBuffers; i++)
        {
        //向HAL层的Gralloc申请缓冲空间
                buffers[i] = new NativeBuffer(
                        fbDev->width, fbDev->height, fbDev->format, GRALLOC_USAGE_HW_FB);
        }

        for (i = 0; i < mNumBuffers; i++)
        {
        //hardware/libhardware/include/hardware/Gralloc.h 函数原型:
        // int (*alloc)(struct alloc_device_t* dev,
        //    int w, int h, int format, int usage,
        //    buffer_handle_t* handle, int* stride);
        //通过 gralloc_device_open()函数的 dev->device.alloc   = gralloc_alloc;进行一步步函数调用实现分配图形缓冲区   
                err = grDev->alloc(grDev,
                        fbDev->width, fbDev->height, fbDev->format,
                        GRALLOC_USAGE_HW_FB, &buffers[i]->handle, &buffers[i]->stride);

                LOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",
                        i, fbDev->width, fbDev->height, strerror(-err));

                if (err)
                {
                        mNumBuffers = i;
                        mNumFreeBuffers = i;
                        mBufferHead = mNumBuffers-1;
                        break;
                }
        }

        const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags; 
        const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
        const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
        const_cast<int&>(ANativeWindow::minSwapInterval) = 
            fbDev->minSwapInterval;
        const_cast<int&>(ANativeWindow::maxSwapInterval) = 
            fbDev->maxSwapInterval;
    } else {
        LOGE("Couldn't get gralloc module");
    }

    //FramebufferNativeWindow将其setSwapInterval/dequeueBuffer等成员函数填充   到ANativeWindow中的函数指针中,OpenGL ES才能通过一个ANativeWindow来正确地与本地窗口建立真正的连接
    ANativeWindow::setSwapInterval = setSwapInterval;
    ANativeWindow::dequeueBuffer = dequeueBuffer;
    ANativeWindow::lockBuffer = lockBuffer;
    ANativeWindow::queueBuffer = queueBuffer;
    ANativeWindow::query = query;
    ANativeWindow::perform = perform;
}

hardware/libhardware/include/hardware/FB.h

...
static inline int framebuffer_open(const struct hw_module_t* module,
        struct framebuffer_device_t** device) {
    return module->methods->open(module,
            GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device);
}

hardware/libhardware/include/hardware/Gralloc.h

...
static inline int gralloc_open(const struct hw_module_t* module, 
        struct alloc_device_t** device) {
    return module->methods->open(module, 
            GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);
}

3、

用户空间的应用程序在使用帧缓冲区之前,首先要加载Gralloc模块,并且获得一个gralloc设备和一个fb设备。
有了gralloc设备之后,用户空间中的应用程序就可以申请分配一块图形缓冲区,并且将这块图形缓冲区映射到应用程序的地址空间来,以便可以向里面写入要绘制的画面的内容。最后,用户空间中的应用程序就通过fb设备来将前面已经准备好了的图形缓冲区渲染到帧缓冲区中去,即将图形缓冲区的内容绘制到显示屏中去。
当用户空间中的应用程序不再需要使用一块图形缓冲区的时候,就可以通过gralloc设备来释放它,并且将它从地址空间中解除映射。

分配图形缓冲区: grDev->alloc()
gralloc_device_open() =>gralloc_alloc()
=>gralloc_alloc_framebuffer()=>gralloc_alloc_framebuffer_locked()
=>mapFrameBufferLocked()=>mapFrameBuffer()//帧缓冲区分配

gralloc_device_open() =>gralloc_alloc()=>gralloc_alloc_buffer()
=>ashmem_create_region()
//创建一块匿名共享内存,接着再在这块匿名共享内存上分配一个图形缓冲区
=>mapBuffer()
//把从匿名共享内存中分配的图形缓冲区映射到进程的地址空间,然后才可以使用,通过调用函数mapBuffer实现映射
=>gralloc_map(module, hnd, &vaddr);
//将参数hnd所描述的一个图形缓冲区映射到当前进程的地址空间

framebuffer设备渲染:fb_post()
framebuffer_open() => gralloc_device_open() => fb_device_open() => fb_post() 将图形缓冲区渲染到系统帧缓冲区中去,把画面绘制到设备显示屏中

hardware/libhardware/module/gralloc/gralloc.cpp

int gralloc_device_open(const hw_module_t* module, const char* name,
        hw_device_t** device)
{
    int status = -EINVAL;
    if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
        gralloc_context_t *dev;
        dev = (gralloc_context_t*)malloc(sizeof(*dev));

        /* initialize our state here */
        memset(dev, 0, sizeof(*dev));

        /* initialize the procs */
        dev->device.common.tag = HARDWARE_DEVICE_TAG;
        dev->device.common.version = 0;
        dev->device.common.module = const_cast<hw_module_t*>(module);
        dev->device.common.close = gralloc_close;

        dev->device.alloc   = gralloc_alloc; //
        dev->device.free    = gralloc_free;

        *device = &dev->device.common;
        status = 0;
    } else {
        status = fb_device_open(module, name, device);
    }
    return status;
}

分配图形缓冲区
//用户空间的应用程序用到的图形缓冲区是由Gralloc模块中的函数gralloc_alloc来分配
static int gralloc_alloc(alloc_device_t* dev,
        int w, int h, int format, int usage,
        buffer_handle_t* pHandle, int* pStride)
{
    if (!pHandle || !pStride)
        return -EINVAL;

    size_t size, stride;

    int align = 4;
    int bpp = 0;
    switch (format) {
        case HAL_PIXEL_FORMAT_RGBA_8888:
        case HAL_PIXEL_FORMAT_RGBX_8888:
        case HAL_PIXEL_FORMAT_BGRA_8888:
            bpp = 4;
            break;
        case HAL_PIXEL_FORMAT_RGB_888:
            bpp = 3;
            break;
        case HAL_PIXEL_FORMAT_RGB_565:
        case HAL_PIXEL_FORMAT_RGBA_5551:
        case HAL_PIXEL_FORMAT_RGBA_4444:
            bpp = 2;
            break;
        default:
            return -EINVAL;
    }
    size_t bpr = (w*bpp + (align-1)) & ~(align-1);
    size = bpr * h;
    stride = bpr / bpp;

    int err;
    //系统帧缓冲区中分配还是在内存中分配缓冲,内存中分配的图形缓冲区,最终是需要拷贝到系统帧缓冲区去的
    if (usage & GRALLOC_USAGE_HW_FB) {
        err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);
    } else {
        err = gralloc_alloc_buffer(dev, size, usage, pHandle);
    }

    if (err < 0) {
        return err;
    }

    *pStride = stride;
    return 0;
}

//函数gralloc_alloc_framebuffer用来在系统帧缓冲区中分配图形缓冲区
static int gralloc_alloc_framebuffer(alloc_device_t* dev,  
        size_t size, int usage, buffer_handle_t* pHandle)  
{  
    private_module_t* m = reinterpret_cast<private_module_t*>(  
            dev->common.module);  
    pthread_mutex_lock(&m->lock);  
    //函数gralloc_alloc_framebuffer_locked才是真正用来分配图形缓冲区
    int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle);  
    pthread_mutex_unlock(&m->lock);  
    return err;  
} 

static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev,  
        size_t size, int usage, buffer_handle_t* pHandle)  
{  
    private_module_t* m = reinterpret_cast<private_module_t*>(  
            dev->common.module);  

    // allocate the framebuffer  
    if (m->framebuffer == NULL) {  
        // initialize the framebuffer, the framebuffer is mapped once  
        // and forever.  
        int err = mapFrameBufferLocked(m);  
        if (err < 0) {  
            return err;  
        }  
    }  

    const uint32_t bufferMask = m->bufferMask;  
    const uint32_t numBuffers = m->numBuffers;  
    const size_t bufferSize = m->finfo.line_length * m->info.yres;  
    if (numBuffers == 1) {  
        // If we have only one buffer, we never use page-flipping. Instead,  
        // we return a regular buffer which will be memcpy'ed to the main  
        // screen when post is called.  
        int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;  
        return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle);  
    }  

    if (bufferMask >= ((1LU<<numBuffers)-1)) {  
        // We ran out of buffers.  
        return -ENOMEM;  
    }  

    // create a "fake" handles for it  
    intptr_t vaddr = intptr_t(m->framebuffer->base);  
    private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size,  
            private_handle_t::PRIV_FLAGS_FRAMEBUFFER);  

    // find a free slot  
    for (uint32_t i=0 ; i<numBuffers ; i++) {  
        if ((bufferMask & (1LU<<i)) == 0) {  
            m->bufferMask |= (1LU<<i);  
            break;  
        }  
        vaddr += bufferSize;  
    }  

    hnd->base = vaddr;  
    hnd->offset = vaddr - intptr_t(m->framebuffer->base);  
    *pHandle = hnd;  

    return 0;  
}

//函数gralloc_alloc_buffer用来在内存在分配图形缓冲区
static int gralloc_alloc_buffer(alloc_device_t* dev,
        size_t size, int usage, buffer_handle_t* pHandle)
{
    int err = 0;
    int fd = -1;

    size = roundUpToPageSize(size);

    //创建一块匿名共享内存,接着再在这块匿名共享内存上分配一个图形缓冲区
    fd = ashmem_create_region("gralloc-buffer", size);
    if (fd < 0) {
        LOGE("couldn't create ashmem (%s)", strerror(-errno));
        err = -errno;
    }

    if (err == 0) {
        private_handle_t* hnd = new private_handle_t(fd, size, 0);
        gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
                dev->common.module);
        //把从匿名共享内存中分配的图形缓冲区映射到进程的地址空间,然后才可以使用,通过调用函数mapBuffer实现映射
        err = mapBuffer(module, hnd);
        if (err == 0) {
            *pHandle = hnd;
        }
    }

    LOGE_IF(err, "gralloc failed err=%s", strerror(-err));

    return err;
}

函数mapBuffer实现在文件hardware/libhardware/modules/gralloc/mapper.cpp

int mapBuffer(gralloc_module_t const* module,  
        private_handle_t* hnd)  
{  
    void* vaddr;  
    return gralloc_map(module, hnd, &vaddr); //将参数hnd所描述的一个图形缓冲区映射到当前进程的地址空间  
} 

hardware/libhardware/modules/gralloc/framebuffer.cpp

int fb_device_open(hw_module_t const* module, const char* name,
        hw_device_t** device)
{
    int status = -EINVAL;
    if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
        alloc_device_t* gralloc_device;
        status = gralloc_open(module, &gralloc_device);
        if (status < 0)
            return status;

        /* initialize our state here */
        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
        memset(dev, 0, sizeof(*dev));

        /* initialize the procs */
        dev->device.common.tag = HARDWARE_DEVICE_TAG;
        dev->device.common.version = 0;
        dev->device.common.module = const_cast<hw_module_t*>(module);
        dev->device.common.close = fb_close;
        dev->device.setSwapInterval = fb_setSwapInterval;
        dev->device.post            = fb_post;
        dev->device.setUpdateRect = 0;

        private_module_t* m = (private_module_t*)module;
        status = mapFrameBuffer(m);
        if (status >= 0) {
            int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
            int format = (m->info.bits_per_pixel == 32)
                         ? HAL_PIXEL_FORMAT_RGBX_8888
                         : HAL_PIXEL_FORMAT_RGB_565;
            const_cast<uint32_t&>(dev->device.flags) = 0;
            const_cast<uint32_t&>(dev->device.width) = m->info.xres;
            const_cast<uint32_t&>(dev->device.height) = m->info.yres;
            const_cast<int&>(dev->device.stride) = stride;
            const_cast<int&>(dev->device.format) = format;
            const_cast<float&>(dev->device.xdpi) = m->xdpi;
            const_cast<float&>(dev->device.ydpi) = m->ydpi;
            const_cast<float&>(dev->device.fps) = m->fps;
            const_cast<int&>(dev->device.minSwapInterval) = 1;
            const_cast<int&>(dev->device.maxSwapInterval) = 1;
            *device = &dev->device.common;
        }
    }
    return status;
}

//将图形缓冲区渲染到系统帧缓冲区中去,把画面绘制到设备显示屏中
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
{
    if (private_handle_t::validate(buffer) < 0)
        return -EINVAL;

    fb_context_t* ctx = (fb_context_t*)dev;

    private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
    private_module_t* m = reinterpret_cast<private_module_t*>(
            dev->common.module);

    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
        const size_t offset = hnd->base - m->framebuffer->base;
        m->info.activate = FB_ACTIVATE_VBL;
        m->info.yoffset = offset / m->finfo.line_length;
        if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
            LOGE("FBIOPUT_VSCREENINFO failed");
            m->base.unlock(&m->base, buffer); 
            return -errno;
        }
        m->currentBuffer = buffer;

    } else {
        // If we can't do the page_flip, just copy the buffer to the front 
        // FIXME: use copybit HAL instead of memcpy

        void* fb_vaddr;
        void* buffer_vaddr;

        m->base.lock(&m->base, m->framebuffer, 
                GRALLOC_USAGE_SW_WRITE_RARELY, 
                0, 0, m->info.xres, m->info.yres,
                &fb_vaddr);

        m->base.lock(&m->base, buffer, 
                GRALLOC_USAGE_SW_READ_RARELY, 
                0, 0, m->info.xres, m->info.yres,
                &buffer_vaddr);

        memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);

        m->base.unlock(&m->base, buffer); 
        m->base.unlock(&m->base, m->framebuffer); 
    }

    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值