android Surface(1, 2)

android的Surface相关内容从底层依次往上分别是:

1.frameBuffer,简称fb,对于同一个android系统,可以同时存在多个frameBuffer,本机是fb0,依次外接时,fb1, fb2, ……fbn等。fb文件的目录在类Linux操作系统的dev/目录下,因为一般而言,只有一个显示器。

2.hal层对设备的定义gralloc。

3.FrameBufferNativeWindow。

4.HWCompose。

5.SurfaceFlinger。

6.java层的frameWork。

7.应用。

他们的大致关系图如下所示:
在这里插入图片描述
这个图是参考的,在最新的版本中会有一些变动的,比如FrameBufferNativeWindow在新的andori版本已经没有了,被ANativeWindow替换掉了。

1.FrameBuffer

android底层在绘制图形时分为两种方式:

1.CPU为主,GPU为辅。?

2.GPU绘制,CPU为辅。?

​ 其中CPU作为主要角色绘制时,在底层是通过gralloc,framebuffer绘制的,这个过程中CPU为主,GPU为辅。FrameBuffer绘制是使用CPU进行图形绘制和渲染,然后将最终结果存储在内存中的一个FrameBuffer对象中。这种方式虽然简单,但是在绘制复杂图形时会占用大量的CPU资源,导致性能下降。如果是GPU为主进行绘制时,这个过程中,GPU绘制使用GPU进行图形绘制和渲染,最终的结果直接输出到屏幕上。这种方式可以充分利用GPU的性能,提高图形渲染的速度和质量。但是相对于FrameBuffer绘制,GPU绘制需要更加复杂的渲染管线和硬件支持。

​ 但是他们两个不是互相独立的,framebuffer绘制时,也需要GPU参与,GPU绘制时也需要framebuffer参与。

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

这个过程中相关的头文件路径如下:

hardware/libhardware/include/hardware/

其中涉及到的头文件如下:

fb.h 指的就是framebuffer

gralloc.h

hardware.h

对应定义的文件路径如下:

hardware/libhardware/modules/gralloc/

其中涉及到的文件如下:

framebuffer.cpp

gr.h

gralloc.cpp

gralloc_priv.h

mapper.cpp

1.1Hardware
 Every hardware module must have a data structure named HAL_MODULE_INFO_SYM and the fields of this data structure must begin with hw_module_t followed by module specific information.

hardware.h文件中主要定义了三个结构体,分别是:

1.hw_module_t

2.hw_module_methods_t

3.hw_device_t

​ 其中hw_module_t定义了一些基本的内容,包括tag,版本,作者,还有hw_module_methods_t。hw_module_methods_t结构体中定义了一个打开设备的方法。hw_device_t中包含hw_module_t,还多了一些其他的变量,还有一个指向关闭设备的指针。

1.2FrameBuffer

​ framebuffer的头文件中定义了一些内容:

#define GRALLOC_HARDWARE_FB0 "fb0" //这个指的是本机的设备
typedef struct framebuffer_device_t {
    /**
     * Common methods of the framebuffer device.  This *must* be the first member of
     * framebuffer_device_t as users of this structure will cast a hw_device_t to
     * framebuffer_device_t pointer in contexts where it's known the hw_device_t references a
     * framebuffer_device_t.
     */
    struct hw_device_t common;//这个在hardware.h里面有定义

    /* flags describing some attributes of the framebuffer */
    const uint32_t  flags;

    /* dimensions of the framebuffer in pixels */
    const uint32_t  width;
    const uint32_t  height;

    /* frambuffer stride in pixels */
    const int       stride;

    /* framebuffer pixel format */
    const int       format;

    /* resolution of the framebuffer's display panel in pixel per inch*/
    const float     xdpi;
    const float     ydpi;

    /* framebuffer's display panel refresh rate in frames per second */
    const float     fps;

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

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

    /* Number of framebuffers supported*/
    const int       numFramebuffers;

    int reserved[7];

    /*
     * requests a specific swap-interval (same definition than EGL)
     *
     * Returns 0 on success or -errno on error.
     */
    int (*setSwapInterval)(struct framebuffer_device_t* window,
            int interval);

    //设置更新区域,一般通过framebuffer更新
    /*
     * This hook is OPTIONAL.
     *
     * It is non NULL If the framebuffer driver supports "update-on-demand"
     * and the given rectangle is the area of the screen that gets
     * updated during (*post)().
     *
     * This is useful on devices that are able to DMA only a portion of
     * the screen to the display panel, upon demand -- as opposed to
     * constantly refreshing the panel 60 times per second, for instance.
     *
     * Only the area defined by this rectangle is guaranteed to be valid, that
     * is, the driver is not allowed to post anything outside of this
     * rectangle.
     *
     * The rectangle evaluated during (*post)() and specifies which area
     * of the buffer passed in (*post)() shall to be posted.
     *
     * return -EINVAL if width or height <=0, or if left or top < 0
     */
    int (*setUpdateRect)(struct framebuffer_device_t* window,
            int left, int top, int width, int height);

    //post数据,刷新
    /*
     * Post <buffer> to the display (display it on the screen)
     * The buffer must have been allocated with the
     *   GRALLOC_USAGE_HW_FB usage flag.
     * buffer must be the same width and height as the display and must NOT
     * be locked.
     *
     * The buffer is shown during the next VSYNC.
     *
     * If the same buffer is posted again (possibly after some other buffer),
     * post() will block until the the first post is completed.
     *
     * Internally, post() is expected to lock the buffer so that a
     * subsequent call to gralloc_module_t::(*lock)() with USAGE_RENDER or
     * USAGE_*_WRITE will block until it is safe; that is typically once this
     * buffer is shown and another buffer has been posted.
     *
     * Returns 0 on success or -errno on error.
     */
    int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);


    /*
     * The (*compositionComplete)() method must be called after the
     * compositor has finished issuing GL commands for client buffers.
     */

    int (*compositionComplete)(struct framebuffer_device_t* dev);

    /*
     * This hook is OPTIONAL.
     *
     * If non NULL it will be caused by SurfaceFlinger on dumpsys
     */
    void (*dump)(struct framebuffer_device_t* dev, char *buff, int buff_len);

    /*
     * (*enableScreen)() is used to either blank (enable=0) or
     * unblank (enable=1) the screen this framebuffer is attached to.
     *
     * Returns 0 on success or -errno on error.
     */
    int (*enableScreen)(struct framebuffer_device_t* dev, int enable);

    void* reserved_proc[6];

} framebuffer_device_t;


/** convenience API for opening and closing a supported device */

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

static inline int framebuffer_close(struct framebuffer_device_t* device) {
    return device->common.close(&device->common);
}

总结:

​ fb.h的头文件中主要定义了framebuffer_device_t这个结构体,framebuffer_device_t结构体中大致如下:hw_device_t,宽高,像素步幅,x方向的像素,y方向的像素,帧率,framebuffer交换间隔,刷新区域。

他的实现文件framebuffer.cpp里面主要解释如下:定义了android设备的buffer数量是2(默认是2),里面有6个函数,分别是:

//设置两个buffer的交换间隔
static int fb_setSwapInterval(struct framebuffer_device_t* dev,
            int interval)
//往framebuffer里面写数据
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
//映射buffer的数据,并初始化buffer的内容
int mapFrameBufferLocked(struct private_module_t* module, int format)
//带了个锁,里面执行的是mapFrameBufferLocked函数
static int mapFrameBuffer(struct private_module_t* module)
//关闭设备
static int fb_close(struct hw_device_t *dev)
//打开设备
int fb_device_open(hw_module_t const* module, const char* name,
        hw_device_t** device)

Q1:CPU和GPU是怎么协作的?

2.Gralloc

2.1基本定义

gralloc和Framebuffer是密不可分的。他的头文件主要内容如下:

路径:hardware/libhardware/include/hardware/gralloc.h

主要定义了两个结构体和几个静态方法:

typedef struct gralloc_module_t {
    struct hw_module_t common;//在hardware.h里面定义的
    
    /*
     * 在buffer_handle_t没有被初始化之前调用
     * (*registerBuffer)() must be called before a buffer_handle_t that has not
     * been created with (*alloc_device_t::alloc)() can be used.
     * 
     * This is intended to be used with buffer_handle_t's that have been
     * received in this process through IPC.
     * 
     * This function checks that the handle is indeed a valid one and prepares
     * it for use with (*lock)() and (*unlock)().
     * 
     * It is not necessary to call (*registerBuffer)() on a handle created 
     * with (*alloc_device_t::alloc)().
     * 
     * returns an error if this buffer_handle_t is not valid.
     */
    int (*registerBuffer)(struct gralloc_module_t const* module,
            buffer_handle_t handle);

    /*
     * (*unregisterBuffer)() is called once this handle is no longer needed in
     * this process. After this call, it is an error to call (*lock)(),
     * (*unlock)(), or (*registerBuffer)().
     * 
     * This function doesn't close or free the handle itself; this is done
     * by other means, usually through libcutils's native_handle_close() and
     * native_handle_free(). 
     * 
     * It is an error to call (*unregisterBuffer)() on a buffer that wasn't
     * explicitly registered first.
     */
    int (*unregisterBuffer)(struct gralloc_module_t const* module,
            buffer_handle_t handle);
    
    //当一个buffer被使用之前调用,会阻塞,比如硬件需要完成渲染或者CPU缓存需要被同步时
    /*
     * The (*lock)() method is called before a buffer is accessed for the 
     * specified usage. This call may block, for instance if the h/w needs
     * to finish rendering or if CPU caches need to be synchronized.
     * 
     * The caller promises to modify only pixels in the area specified 
     * by (l,t,w,h).
     * 
     * The content of the buffer outside of the specified area is NOT modified
     * by this call.
     *
     * If usage specifies GRALLOC_USAGE_SW_*, vaddr is filled with the address
     * of the buffer in virtual memory.
     *
     * Note calling (*lock)() on HAL_PIXEL_FORMAT_YCbCr_*_888 buffers will fail
     * and return -EINVAL.  These buffers must be locked with (*lock_ycbcr)()
     * instead.
     *
     * THREADING CONSIDERATIONS:
     *
     * It is legal for several different threads to lock a buffer from 
     * read access, none of the threads are blocked.
     * 
     * However, locking a buffer simultaneously for write or read/write is
     * undefined, but:
     * - shall not result in termination of the process
     * - shall not block the caller
     * It is acceptable to return an error or to leave the buffer's content
     * into an indeterminate state.
     *
     * If the buffer was created with a usage mask incompatible with the
     * requested usage flags here, -EINVAL is returned. 
     * 
     */
    
    int (*lock)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            void** vaddr);

    
    /*
     * The (*unlock)() method must be called after all changes to the buffer
     * are completed.
     */
    
    int (*unlock)(struct gralloc_module_t const* module,
            buffer_handle_t handle);


    //留作扩展用
    /* reserved for future use */
    int (*perform)(struct gralloc_module_t const* module,
            int operation, ... );

    /*
     * 和lock差不多,只不过使用的ycbcr的格式存储的像素之类的数据
     * The (*lock_ycbcr)() method is like the (*lock)() method, with the
     * difference that it fills a struct ycbcr with a description of the buffer
     * layout, and zeroes out the reserved fields.
     *
     * If the buffer format is not compatible with a flexible YUV format (e.g.
     * the buffer layout cannot be represented with the ycbcr struct), it
     * will return -EINVAL.
     *
     * This method must work on buffers with HAL_PIXEL_FORMAT_YCbCr_*_888
     * if supported by the device, as well as with any other format that is
     * requested by the multimedia codecs when they are configured with a
     * flexible-YUV-compatible color-format with android native buffers.
     *
     * Note that this method may also be called on buffers of other formats,
     * including non-YUV formats.
     *
     * Added in GRALLOC_MODULE_API_VERSION_0_2.
     */

    int (*lock_ycbcr)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            struct android_ycbcr *ycbcr);

    /*
     * 把锁传进去不用让调用者等待结束
     * The (*lockAsync)() method is like the (*lock)() method except
     * that the buffer's sync fence object is passed into the lock
     * call instead of requiring the caller to wait for completion.
     *
     * The gralloc implementation takes ownership of the fenceFd and
     * is responsible for closing it when no longer needed.
     *
     * Added in GRALLOC_MODULE_API_VERSION_0_3.
     */
    int (*lockAsync)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            void** vaddr, int fenceFd);

    /*
     * The (*unlockAsync)() method is like the (*unlock)() method
     * except that a buffer sync fence object is returned from the
     * lock call, representing the completion of any pending work
     * performed by the gralloc implementation.
     *
     * The caller takes ownership of the fenceFd and is responsible
     * for closing it when no longer needed.
     *
     * Added in GRALLOC_MODULE_API_VERSION_0_3.
     */
    int (*unlockAsync)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int* fenceFd);

    /*
     * The (*lockAsync_ycbcr)() method is like the (*lock_ycbcr)()
     * method except that the buffer's sync fence object is passed
     * into the lock call instead of requiring the caller to wait for
     * completion.
     *
     * The gralloc implementation takes ownership of the fenceFd and
     * is responsible for closing it when no longer needed.
     *
     * Added in GRALLOC_MODULE_API_VERSION_0_3.
     */
    int (*lockAsync_ycbcr)(struct gralloc_module_t const* module,
            buffer_handle_t handle, int usage,
            int l, int t, int w, int h,
            struct android_ycbcr *ycbcr, int fenceFd);

    /* 获取缓冲区的大小
     * getTransportSize(..., outNumFds, outNumInts)
     * This function is mandatory on devices running IMapper2.1 or higher.
     *
     * Get the transport size of a buffer. An imported buffer handle is a raw
     * buffer handle with the process-local runtime data appended. This
     * function, for example, allows a caller to omit the process-local
     * runtime data at the tail when serializing the imported buffer handle.
     *
     * Note that a client might or might not omit the process-local runtime
     * data when sending an imported buffer handle. The mapper must support
     * both cases on the receiving end.
     */
    int32_t (*getTransportSize)(
            struct gralloc_module_t const* module, buffer_handle_t handle, uint32_t *outNumFds,
            uint32_t *outNumInts);

    /* validateBufferSize(..., w, h, format, usage, stride)
     * This function is mandatory on devices running IMapper2.1 or higher.
     *
     * Validate that the buffer can be safely accessed by a caller who assumes
     * the specified width, height, format, usage, and stride. This must at least validate
     * that the buffer size is large enough. Validating the buffer against
     * individual buffer attributes is optional.
     */
    int32_t (*validateBufferSize)(
            struct gralloc_module_t const* device, buffer_handle_t handle,
            uint32_t w, uint32_t h, int32_t format, int usage,
            uint32_t stride);

    //留作扩展用
    /* reserved for future use */
    void* reserved_proc[1];

} gralloc_module_t;

下面又定义了另外一个结构体:

/**
 * Every device data structure must begin with hw_device_t
 * followed by module specific public methods and attributes.
 */

typedef struct alloc_device_t {
    struct hw_device_t common; //在hardware.h里面有定义

    //分配buffer,返回buffer_handle_t
    /* 
     * (*alloc)() Allocates a buffer in graphic memory with the requested
     * parameters and returns a buffer_handle_t and the stride in pixels to
     * allow the implementation to satisfy hardware constraints on the width
     * of a pixmap (eg: it may have to be multiple of 8 pixels). 
     * The CALLER TAKES OWNERSHIP of the buffer_handle_t.
     *
     * If format is HAL_PIXEL_FORMAT_YCbCr_420_888, the returned stride must be
     * 0, since the actual strides are available from the android_ycbcr
     * structure.
     * 
     * Returns 0 on success or -errno on error.
     */
    
    int (*alloc)(struct alloc_device_t* dev,
            int w, int h, int format, int usage,
            buffer_handle_t* handle, int* stride);

    /*
     * (*free)() Frees a previously allocated buffer. 
     * Behavior is undefined if the buffer is still mapped in any process,
     * but shall not result in termination of the program or security breaches
     * (allowing a process to get access to another process' buffers).
     * THIS FUNCTION TAKES OWNERSHIP of the buffer_handle_t which becomes
     * invalid after the call. 
     * 
     * Returns 0 on success or -errno on error.
     */
    int (*free)(struct alloc_device_t* dev,
            buffer_handle_t handle);

    /* This hook is OPTIONAL.
     *
     * If non NULL it will be caused by SurfaceFlinger on dumpsys
     */
    void (*dump)(struct alloc_device_t *dev, char *buff, int buff_len);

    void* reserved_proc[7];
} alloc_device_t;

总结:

​ 1.gralloc_module_t结构体里面定义了hw_module_t common(hw_module_t 在hardware.h中定义)一个变量,还有注册,取消注册缓冲器,加锁,去锁,常规,yuv分量存储,获取缓冲区大小,校验缓冲区大小的几个方法。

​ 2.alloc_device_t结构体中定义了hw_device_t common(hw_device_t 在hardware.h中定义)一个变量,还有分配,释放buffer的两个指向函数的变量。

后面还有几个静态方法:

/** convenience API for opening and closing a supported device */

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

static inline int gralloc_close(struct alloc_device_t* device) {
    return device->common.close(&device->common);
}		

​ 上面的是gralloc.h中文件的大概内容,gralloc.cpp的文件路径是hardware/libhardware/modules/gralloc/gralloc.cpp,在gralloc.cpp里面的内容大致如下:

​ 1.定义了一个gralloc_context_t结构体变量,gralloc_context_t结构体里面有一个alloc_device_t。

​ 2.初始化了HAL_MODULE_INFO_SYM这个private_module_t结构体类型的变量,其中private_module_t结构体在同级目录下的gralloc_priv.h中。

​ 为了方便直接查找上下文的代码,这里把他的代码大概罗列一下:

struct gralloc_context_t {
    alloc_device_t  device;
    /* our private data here */
};

struct private_module_t HAL_MODULE_INFO_SYM = {
    .base = {
        .common = {
            .tag = HARDWARE_MODULE_TAG,
            .version_major = 1,
            .version_minor = 0,
            .id = GRALLOC_HARDWARE_MODULE_ID,
            .name = "Graphics Memory Allocator Module",
            .author = "The Android Open Source Project",
            .methods = &gralloc_module_methods
        },
        .registerBuffer = gralloc_register_buffer,
        .unregisterBuffer = gralloc_unregister_buffer,
        .lock = gralloc_lock,
        .unlock = gralloc_unlock,
    },
    .framebuffer = 0,
    .flags = 0,
    .numBuffers = 0,
    .bufferMask = 0,
    .lock = PTHREAD_MUTEX_INITIALIZER,
    .currentBuffer = 0,
};

​ 上述是在gralloc中主要做的两个大的操作。

​ 下面是gralloc_priv.h中定义的两个结构体:

struct private_module_t {
    gralloc_module_t base;

    private_handle_t* framebuffer;
    uint32_t flags;
    uint32_t numBuffers;
    uint32_t bufferMask;
    pthread_mutex_t lock;
    buffer_handle_t currentBuffer;
    int pmem_master;
    void* pmem_master_base;

    struct fb_var_screeninfo info;
    struct fb_fix_screeninfo finfo;
    float xdpi;
    float ydpi;
    float fps;
};

#ifdef __cplusplus
struct private_handle_t : public native_handle {
#else
struct private_handle_t {
    struct native_handle nativeHandle;
#endif

    enum {
        PRIV_FLAGS_FRAMEBUFFER = 0x00000001
    };

    // file-descriptors
    int     fd;
    // ints
    int     magic;
    int     flags;
    int     size;
    int     offset;

    // FIXME: the attributes below should be out-of-line
    uint64_t base __attribute__((aligned(8)));
    int     pid;

#ifdef __cplusplus
    static inline int sNumInts() {
        return (((sizeof(private_handle_t) - sizeof(native_handle_t))/sizeof(int)) - sNumFds);
    }
    static const int sNumFds = 1;
    static const int sMagic = 0x3141592;

    //这里是赋值操作
    private_handle_t(int fd, int size, int flags) :
        fd(fd), magic(sMagic), flags(flags), size(size), offset(0),
        base(0), pid(getpid())
    {
        version = sizeof(native_handle);
        numInts = sNumInts();
        numFds = sNumFds;
    }
    ~private_handle_t() {
        magic = 0;
    }

    static int validate(const native_handle* h) {
        const private_handle_t* hnd = (const private_handle_t*)h;
        if (!h || h->version != sizeof(native_handle) ||
                h->numInts != sNumInts() || h->numFds != sNumFds ||
                hnd->magic != sMagic)
        {
            ALOGE("invalid gralloc handle (at %p)", h);
            return -EINVAL;
        }
        return 0;
    }
#endif
};

​ 设备gpu用于分配图形缓冲区,而设备fb用于渲染图形缓冲区;hw_module_t用于描述硬件抽象层Gralloc模块,而hw_device_t则用于描述硬件抽象层Gralloc设备,通过硬件抽象层设备可以找到对应的硬件抽象层模块。

2.2Gralloc打开流程
2.2.1FB打开流程

​ fb的打开流程如下:

​ framebuffer_open的最终定义是在gralloc.cpp文件中:

int gralloc_device_open(const hw_module_t* module, const char* name,
        hw_device_t** device)
{
    int status = -EINVAL;
    //if里面是打开GPU的函数,传GPU0,进到函数里面,传frameBuffer,走到else里面
    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 {
        //这里是打开framebuffer
        status = fb_device_open(module, name, device);
    }
    return status;
}

​ fb_device_open函数定义:

int fb_device_open(hw_module_t const* module, const char* name,
        hw_device_t** device)
{
    int status = -EINVAL;
    //判断打开的是fb设备时,再做操作
    if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
        /* 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;
        //这里是在处理映射地址,将fb映射到当前进程地址空间
        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)
                         ? (m->info.red.offset ? HAL_PIXEL_FORMAT_BGRA_8888 : 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;
        } else {
            free(dev);
        }
    }
    return status;
}

​ mapFrameBuffer通过锁结构最终申请了一块区域后初始化:

int mapFrameBufferLocked(struct private_module_t* module, int format)
{
    // already initialized...
    if (module->framebuffer) {
        return 0;
    }
        
    char const * const device_template[] = {
            "/dev/graphics/fb%u",
            "/dev/fb%u",
            0 };

    int fd = -1;
    int i=0;
    char name[64];

    while ((fd==-1) && device_template[i]) {
        snprintf(name, 64, device_template[i], 0);
        fd = open(name, O_RDWR, 0);
        i++;
    }
    if (fd < 0)
        return -errno;

    struct fb_fix_screeninfo finfo;
    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
        return -errno;

    struct fb_var_screeninfo info;
    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
        return -errno;

    info.reserved[0] = 0;
    info.reserved[1] = 0;
    info.reserved[2] = 0;
    info.xoffset = 0;
    info.yoffset = 0;
    info.activate = FB_ACTIVATE_NOW;

    /*
     * Request NUM_BUFFERS screens
     * To enable page flipping, NUM_BUFFERS should be at least 2.
     */
    info.yres_virtual = info.yres * NUM_BUFFERS;

    switch (format) {
    case HAL_PIXEL_FORMAT_RGBA_8888:
        info.bits_per_pixel = 32;
        info.red.offset = 0;
        info.red.length = 8;
        info.green.offset = 8;
        info.green.length = 8;
        info.blue.offset = 16;
        info.blue.length = 8;
        break;
    default:
        ALOGW("unknown format: %d", format);
        break;
    }

    uint32_t flags = PAGE_FLIP;
#if USE_PAN_DISPLAY
    if (ioctl(fd, FBIOPAN_DISPLAY, &info) == -1) {
        ALOGW("FBIOPAN_DISPLAY failed, page flipping not supported");
#else
    if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
        ALOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
#endif
        info.yres_virtual = info.yres;
        flags &= ~PAGE_FLIP;
    }

    if (info.yres_virtual < info.yres * 2) {
        // we need at least 2 for page-flipping
        info.yres_virtual = info.yres;
        flags &= ~PAGE_FLIP;
        ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
                info.yres_virtual, info.yres*2);
    }

    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
        return -errno;

    uint64_t  refreshQuotient =
    (
            uint64_t( info.upper_margin + info.lower_margin + info.yres )
            * ( info.left_margin  + info.right_margin + info.xres )
            * info.pixclock
    );

    /* Beware, info.pixclock might be 0 under emulation, so avoid a
     * division-by-0 here (SIGFPE on ARM) */
    int refreshRate = refreshQuotient > 0 ? (int)(1000000000000000LLU / refreshQuotient) : 0;

    //刷新频率
    if (refreshRate == 0) {
        // bleagh, bad info from the driver
        refreshRate = 60*1000;  // 60 Hz
    }

    if (int(info.width) <= 0 || int(info.height) <= 0) {
        // the driver doesn't return that information
        // default to 160 dpi
        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
    }

    float xdpi = (info.xres * 25.4f) / info.width;
    float ydpi = (info.yres * 25.4f) / info.height;
    float fps  = refreshRate / 1000.0f;

    ALOGI(   "using (fd=%d)\n"
            "id           = %s\n"
            "xres         = %d px\n"
            "yres         = %d px\n"
            "xres_virtual = %d px\n"
            "yres_virtual = %d px\n"
            "bpp          = %d\n"
            "r            = %2u:%u\n"
            "g            = %2u:%u\n"
            "b            = %2u:%u\n",
            fd,
            finfo.id,
            info.xres,
            info.yres,
            info.xres_virtual,
            info.yres_virtual,
            info.bits_per_pixel,
            info.red.offset, info.red.length,
            info.green.offset, info.green.length,
            info.blue.offset, info.blue.length
    );

    ALOGI(   "width        = %d mm (%f dpi)\n"
            "height       = %d mm (%f dpi)\n"
            "refresh rate = %.2f Hz\n",
            info.width,  xdpi,
            info.height, ydpi,
            fps
    );


    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
        return -errno;

    if (finfo.smem_len <= 0)
        return -errno;


    module->flags = flags;
    module->info = info;
    module->finfo = finfo;
    module->xdpi = xdpi;
    module->ydpi = ydpi;
    module->fps = fps;//帧率

    /*
     * map the framebuffer
     */

    size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);
    module->framebuffer = new private_handle_t(dup(fd), fbSize, 0);

    //设置pagerFlip的缓存数量
    module->numBuffers = info.yres_virtual / info.yres;
    module->bufferMask = 0;

    //通过mmap映射得到一个地址
    void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if (vaddr == MAP_FAILED) {
        ALOGE("Error mapping the framebuffer (%s)", strerror(errno));
        return -errno;
    }
    //把地址赋值过去
    module->framebuffer->base = intptr_t(vaddr);
    //最终把这里空间全部置为0
    memset(vaddr, 0, fbSize);
    return 0;
}
2.2.2GPU打开流程

​ GPU的打开流程在上面已经大概描述过,也是通过gralloc_device_open打开的。函数主要是用来创建一个gralloc_context_t结构体,并且对它的成员变量device进行初始化。结构体gralloc_context_t的成员变量device的类型为gralloc_device_t,它用来描述一个gralloc设备。前面提到,gralloc设备是用来分配和释放图形缓冲区的,这是通过调用它的成员函数alloc和free来实现的。函数gralloc_device_open所打开的gralloc设备的成员函数alloc和free分别被设置为Gralloc模块中的函数gralloc_alloc和gralloc_free。

参考:(133条消息) Android图形显示之硬件抽象层Gralloc_android gralloc_快乐安卓的博客-CSDN博客

Q1: YUV存储图像格式的方式?

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐