关于Android下gralloc,hwcompoer以及surface模块的重新认识

这篇具有很好参考价值的文章主要介绍了关于Android下gralloc,hwcompoer以及surface模块的重新认识。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

关于Android下gralloc,hwcompoer以及surface模块的重新认识



引言

欠债还钱天经地义,知识的债也是如此!这不必须得将我前面欠下来的债给补上!对于任何复杂的知识点,我们都可以采用庖丁解牛的学习方式,一步步的分解。将知识由大到小吃透。虽说Android的graphics图形栈是一个非常负责的模块,但是完事开头难,我们先从基本面入手!



一. allocator service的实现

这里我只能无力的吐糟下Android为了所谓的system,vendor隔离,搞了一个HIDL,这可苦了我们这些搞Android的。这里我以最简单的alloctaor 2.0来作为参考,简单介绍其实现!


1.1 . allocator 2.0 service代码结构

这个比较简单,我们直接上代码!

//hardware/interfaces/graphics/allocator/2.0
├── Android.bp
├── default
│   ├── Android.bp
│   ├── android.hardware.graphics.allocator@2.0-service.rc
│   ├── OWNERS
│   ├── passthrough.cpp
│   └── service.cpp
├── IAllocator.hal
└── utils
    ├── gralloc1-adapter
    │   ├── Android.bp
    │   ├── gralloc1-adapter.cpp
    │   ├── gralloc1-adapter.h
    │   ├── Gralloc1On0Adapter.cpp
    │   └── Gralloc1On0Adapter.h
    ├── hal
    │   ├── Android.bp
    │   └── include
    │       └── allocator-hal
    │           └── 2.0
    │               ├── Allocator.h
    │               └── AllocatorHal.h
    ├── OWNERS
    └── passthrough
        ├── Android.bp
        └── include
            └── allocator-passthrough
                └── 2.0
                    ├── Gralloc0Hal.h
                    ├── Gralloc1Hal.h
                    └── GrallocLoader.h

11 directories, 20 files


1.2 allocator 2.0 service passthrough方式的实现

这里我们不对细节,做过多的纠缠,我们只梳理其大体框架!


/**
 * The id of this module
 */
#define GRALLOC_HARDWARE_MODULE_ID "gralloc"
/**
 * Name of the graphics device to open
 */

#define GRALLOC_HARDWARE_GPU0 "gpu0"

//[passthrough.cpp]
HIDL_FETCH_IAllocator(...)
    GrallocLoader::load()   //GrallocLoader.h
        loadModule()//核心是这个,加载HAL MODLE
            hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module)
        createHal(module)//这里无论是Gralloc1Hal还是Gralloc0Hal最终都会调用 gralloc_open(module, &mDevice)
             gralloc_open(module, &mDevice)
                module->methods->open(module, 
            GRALLOC_HARDWARE_GPU0, TO_HW_DEVICE_T_OPEN(device)) //注意这里传递的id为GRALLOC_HARDWARE_GPU0
        createAllocator(std::move(hal))

这里我们重点需要关心的是,这里hw_get_modul传递的id是GRALLOC_HARDWARE_MODULE_ID!


1.3 allocator HAL的实现

通过前面分析可知,hw_get_module会加载HAL模块,这里我们以Android默认的gralloc实现来说明:

//[hardware/libhardware/modules/gralloc]

├── Android.mk
├── framebuffer.cpp
├── gralloc.cpp
├── gralloc_priv.h
├── gr.h
└── mapper.cpp



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,//注意这里的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,
};


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)) {//allocator的gralloc加载会走次分支
        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;
}

这里需要注意的是,此时allocator service调用open时候传递下来的id为GRALLOC_HARDWARE_GPU0,这个地方要和后面的composer的open对比来看


1.4 allocator HAL alloc的实现

上面的都是常规操作,下面我们接下来看下 allocator HAL alloc的实现!

//[gralloc.cpp]
static int gralloc_alloc(alloc_device_t* dev,
        int width, int height, int format, int usage,
        buffer_handle_t* pHandle, int* pStride)
{
    ...
    if (usage & GRALLOC_USAGE_HW_FB) {
        err = gralloc_alloc_framebuffer(dev, size, format, usage, pHandle);
    } else {
        err = gralloc_alloc_buffer(dev, size, usage, pHandle);
    }

    if (err < 0) {
        return err;
    }

    *pStride = stride;
    return 0;
}

此时的你是不是蒙圈了!尼玛gralloc_alloc里面又有两个分支:

  • gralloc_alloc_framebuffer

    这个分支比较特殊,主要用于GPU合成时候FramebufferSurface使用!然后该buffer在后面就可以用于hwcompower合成使用了。

    并且这里注意这里的FramebufferSurface是消费者,当消费者设置了GRALLOC_USAGE_HW_FB后,这个值在其对应的生产者申请buffer类型的时候,会获取到这个usage,然后这个usage就会随着生产者allocat()的调用逻辑,传递到gralloc来了!

    //[frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp]
        FramebufferSurface::FramebufferSurface(HWComposer& hwc, DisplayId displayId,
                                               const sp<IGraphicBufferConsumer>& consumer,
                                               uint32_t maxWidth, uint32_t maxHeight)
              : ConsumerBase(consumer),
                mDisplayId(displayId),
                mMaxWidth(maxWidth),
                mMaxHeight(maxHeight),
                mCurrentBufferSlot(-1),
                mCurrentBuffer(),
                mCurrentFence(Fence::NO_FENCE),
                mHwc(hwc),
                mHasPendingRelease(false),
                mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
                mPreviousBuffer() {
            ALOGV("Creating for display %s", to_string(displayId).c_str());
        
            mName = "FramebufferSurface";
            mConsumer->setConsumerName(mName);
            mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |//注意这个地方
                                               GRALLOC_USAGE_HW_RENDER |
                                               GRALLOC_USAGE_HW_COMPOSER);
            ...
        }
    
    

    关于这块可以参考博客:
    图像显示系统 - SurfaceFlinger GPU合成/CLIENT合成方式

  • gralloc_alloc_buffer

    它是基本的,像App的渲染buffer啊,其它的通用buffer,都是通过它alloc的!




二. hwcomposer service的实现

这里我只能无力的吐糟下Android为了所谓的system,vendor隔离,搞了一个HIDL,这可苦了我们这些搞Android的。composer 2.1来作为参考,简单介绍其实现!


2.1 . composer 2.1 service代码结构

这个比较简单,我们直接上代码!

//[hardware/interfaces/graphics/composer/2.1]

├── Android.bp
├── default
│   ├── Android.bp
│   ├── android.hardware.graphics.composer@2.1-service.rc
│   ├── OWNERS
│   └── service.cpp
├── IComposerCallback.hal
├── IComposerClient.hal
├── IComposer.hal
├── types.hal
└── utils
    ├── command-buffer
    │   ├── Android.bp
    │   └── include
    │       └── composer-command-buffer
    │           └── 2.1
    │               └── ComposerCommandBuffer.h
    ├── hal
    │   ├── Android.bp
    │   └── include
    │       └── composer-hal
    │           └── 2.1
    │               ├── ComposerClient.h
    │               ├── ComposerCommandEngine.h
    │               ├── Composer.h
    │               └── ComposerHal.h
    ├── hwc2on1adapter
    │   ├── Android.bp
    │   ├── CleanSpec.mk
    │   ├── HWC2On1Adapter.cpp
    │   ├── include
    │   │   └── hwc2on1adapter
    │   │       ├── HWC2On1Adapter.h
    │   │       └── MiniFence.h
    │   └── MiniFence.cpp
    ├── hwc2onfbadapter
    │   ├── Android.bp
    │   ├── HWC2OnFbAdapter.cpp
    │   └── include
    │       └── hwc2onfbadapter
    │           └── HWC2OnFbAdapter.h
    ├── OWNERS
    ├── passthrough
    │   ├── Android.bp
    │   └── include
    │       └── composer-passthrough
    │           └── 2.1
    │               ├── HwcHal.h
    │               └── HwcLoader.h
    └── resources
        ├── Android.bp
        ├── ComposerResources.cpp
        └── include
            └── composer-resources
                └── 2.1
                    └── ComposerResources.h

24 directories, 32 files


2.2 composer 2.1 service passthrough方式的实现

这里我们不对细节,做过多的纠缠,我们只梳理其大体框架!

这里有一点需要注意,composer使用Android默认的实现,即不设置ro属性指定!

//[service.cpp]
android::sp<IComposer> composer = HwcLoader::load()//HwcLoader.h
    loadModule()
        hw_get_module(HWC_HARDWARE_MODULE_ID, &module)//默认使用,这个分支加载失败
        hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module)//加载这个分支,和gralloc使用的HAL是同一个模块
    createHalWithAdapter()
        openDeviceWithAdapter()
            adaptGrallocModule(...module->methods->open(module,
            GRALLOC_HARDWARE_FB0, TO_HW_DEVICE_T_OPEN(device));
    createComposer())
    



这里我需要重点注意的几点:

  • composer的默认实现,加载的HAL库的实现是gralloc.default
  • 调用HAL下open方法的时候,传递的ID的名称是GRALLOC_HARDWARE_FB0这个是需要和allocator实现区分开来的

2.3 composer 2.1 service HAL的实现

这里的实现,就很简单了。因为这里使用gralloc.default作为composer HAL的实现,只实现了其H2C 1.0。

//[hardware/libhardware/modules/gralloc]



├── Android.mk
├── framebuffer.cpp
├── gralloc.cpp
├── gralloc_priv.h
├── gr.h
└── mapper.cpp



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,//注意这里的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,
};


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)) {
        ....
    } else {
        status = fb_device_open(module, name, device);//composer的HAL加载会走次分支
    }
    return status;
}


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)) {//前面传递进来的id 那么就是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;
        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;
}



三. gralloc和hwcompoer中各种让人眼花缭乱的数据关系

这块之前的花式关系,真的是让人眼花缭乱,不知道是李鬼还是李逵。尼玛,让人不得不一吐为快啊!


3.1 native_handle_t*和buffer_handle_t

其它它们是一个东西,具体的定义如下:

//[system/core/libcutils/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] */
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wzero-length-array"
#endif
    int data[0];        /* numFds + numInts ints */
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} native_handle_t;

typedef const native_handle_t* buffer_handle_t;


它的源码目录比较奇特,在libcutils里面。这点大家需要注意。

native_handle/native_handle_t只是定义了一个描述buffer的结构体原型,这个原型是和平台无关的,方便buffer在各个进程之间传递,注意成员data是一个大小为0的数组,这意味着data指向紧挨着numInts后面的一个地址.我们可以把native_handle_t看成是一个纯虚的基类.

一般来说,我们描述一块buffer,需要知道它在kernel中对应的fd,虚拟地址/物理地址,offset,size等等信息,后面我们在private_handle_t中就可以看到这些字段.
android的gralloc模块负责从fb设备或者gpu中分配meomory,所以我们在gralloc中就可以找到native_handle的具体实现,gralloc中对buffer的描述就和具体的平台相关了,我们以aosp中最基本的gralloc为例,来看下gralloc中对native_handle是如何使用的.


3.2 private_handle_t

我们来看下,Android aosp为我们打样实现的一个private_handle_t,如下:

//[hardware/libhardware/modules/gralloc/gralloc_priv.h]
#ifdef __cplusplus  
//在c++编译环境下private_handle_t继承于native_handle  
struct private_handle_t : public native_handle {  
#else  
//在c编译环境下,private_handle_t的第一个成员是native_handle类型,其实和c++的继承是一个意思,  
//总之就是一个指向private_handle_t的指针同样也可以表示一个指向native_handle的指针.  
struct private_handle_t {  
    struct native_handle nativeHandle;  
#endif  
    // file-descriptors  
    int     fd;   
    // ints  
    int     magic;  
    int     flags;  
    int     size;  
    int     offset;  
    // 因为native_handle的data成员是一个大小为0的数组,所以data[0]其实就是指向了fd,data[1]指向magic,以此类推.  
    // 上面提到我们可以把native_handle看成是一个纯虚的基类,那么在private_handle_t这个派生类中,numFds=1 numInts=4.  
    ...  
}  

gralloc分配的buffer都可以用一个private_handle_T来描述(不一定是上面的实现,可以是私有的)同时也可以用一个native_handle来描述.在不同的平台的实现上,private_handle_t可能会有不同的定义,所以private_handle_t在各个模块之间传递的时候很不方便,而如果用native_handle的身份来传递,就可以消除平台的差异性.在HardwareComposer中,由SurfaceFlinger传给hwc的handle即是native_handle类型,而hwc作为平台相关的模块,他需要知道native_handle中各个字段的具体含义,所以hwc往往会将native_handle指针转化为private_handle_t指针来使用。


3.3 小结

对于native_handle和native_handle_t,以及private_handle_t这三个类型可以看作是同一个东西,而buffer_handle_t则是指向他们的指针.
那么android是如何使用这些struct的,gralloc分配的buffer如何和android联系起来呢?我们继续来看window.h


3.4 ANativeWindowBuffer和ANativeWindow

在具体分析ANativeWindowBuffer和ANativeWindow之前,我们先来看下和这两个类型都相关的另外一个结构体android_native_base_t。

[frameworks/native/libs/nativebase/include/nativebase/nativebase.h]

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;

这里的incRef和decRef是为了把派生类和android所有class的老祖宗RefBase联系起来所预留的函数指针,在后面我们在会看到指针具体会指向哪些函数.

好了,前面该说的也已经说了。是时候亮出看家本领了,我们直接来看ANativeWindowBuffer。

ANativeWindowBuffer:

    [frameworks/native/libs/nativebase/include/nativebase/nativebase.h]
    typedef struct ANativeWindowBuffer
    {
    #ifdef __cplusplus
        ANativeWindowBuffer() {
            // ANDROID_NATIVE_BUFFER_MAGIC的值是"_bfr"  
            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.
        // 调用common,也就是android_native_base_t的incRef和decRef函数
        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

       // common的incRef和decRef  
        struct android_native_base_t common;

        int width;
        int height;
        int stride;
        int format;
        int usage_deprecated;
        uintptr_t layerCount;

        void* reserved[1];

        const native_handle_t* handle;
        uint64_t usage;

        // we needed extra space for storing the 64-bits usage flags
        // the number of slots to use from reserved_proc depends on the
        // architecture.
        void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
    } ANativeWindowBuffer_t;

    typedef struct ANativeWindowBuffer ANativeWindowBuffer;

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

**==ANativeWindow==** 的定义如下:



[frameworks/native/libs/nativewindow/include/system/window.h]
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;


    const uint32_t flags;


    const int   minSwapInterval;


    const int   maxSwapInterval;


    const float xdpi;
    const float ydpi;


    intptr_t    oem[4];


    int     (*setSwapInterval)(struct ANativeWindow* window,
                int interval);


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


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


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


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


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


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


    int     (*dequeueBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer** buffer, int* fenceFd);


    int     (*queueBuffer)(struct ANativeWindow* window,
                struct ANativeWindowBuffer* buffer, int fenceFd);


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


//没有定义在这里,这里只是为了学习方便
[frameworks/native/libs/nativewindow/include/android/native_window.h]
typedef struct ANativeWindow ANativeWindow;

我们目前需要注意的是ANativeWindow的函数指针成员所指向的函数都需要一个struct ANativeWindowBuffer* buffer的参数.

ANativeWindowBuffer和ANativeWindow还是没有给android_native_base_t的incRef和decRef指针赋值,ANativeWindowBuffer和ANativeWindow两个还是可以理解为抽象类!



3.5 GraphicBuffer和Surface

前面我们认知了ANativeWindow和ANativeWindowBuffer,接下来也让我们揭开GraphicBuffer和Surface的庐山真面目。

frameworks/native/libs/ui/include/ui/GraphicBuffer.h]
class GraphicBuffer
    : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
      public Flattenable<GraphicBuffer>
{
    ...
}

GraphicBuffer继承于模板类模版类ANativeObjectBase,这个模版类有三个模版.它的定义如下:

[frameworks/native/libs/ui/include/ui/ANativeObjectBase.h]
// NATIVE_TYPE=ANativeWindowBuffer TYPE=GraphicBuffer REF=RefBase  
template <typename NATIVE_TYPE, typename TYPE, typename REF>  
// ANativeObjectBase多重继承于ANativeWindowBuffer和RefBase  
class ANativeObjectBase : public NATIVE_TYPE, public REF   
{  
public:  
    // Disambiguate between the incStrong in REF and NATIVE_TYPE  
    // incStrong和decStrong直接调用其中一个基类RefBase的对应函数  
    void incStrong(const void* id) const {  
        REF::incStrong(id);  
    }     
    void decStrong(const void* id) const {  
        REF::decStrong(id);  
    }     
  
protected:  
    // 给ANativeObjectBase取了个别名BASE  
    typedef ANativeObjectBase<NATIVE_TYPE, TYPE, REF> BASE;  
    ANativeObjectBase() : NATIVE_TYPE(), REF() {  
        // 构造函数中给ANativeWindowBuffer.common的两个函数指针赋值了!这两个指针就是我们之前在分析ANativeWindowBuffer的时候悬而未决的地方.  
        // incRef和decRef指针分别指向内部函数incRef和decRef  
        NATIVE_TYPE::common.incRef = incRef;  
        NATIVE_TYPE::common.decRef = decRef;  
    }     
    static inline TYPE* getSelf(NATIVE_TYPE* self) {  
        return static_cast<TYPE*>(self);  
    }     
    static inline TYPE const* getSelf(NATIVE_TYPE const* self) {  
        return static_cast<TYPE const *>(self);  
    }     
    static inline TYPE* getSelf(android_native_base_t* base) {  
        return getSelf(reinterpret_cast<NATIVE_TYPE*>(base));  
    }     
    static inline TYPE const * getSelf(android_native_base_t const* base) {  
        return getSelf(reinterpret_cast<NATIVE_TYPE const*>(base));  
    }  
    // 内部函数incRef和decRef调用上面的incStong和decStrong,也就是说ANativeWindowBuffer.common的两个函数指针最终会调用到RefBase的incStrong和decStrong.  
    static void incRef(android_native_base_t* base) {  
        ANativeObjectBase* self = getSelf(base);  
        self->incStrong(self);  
    }     
    static void decRef(android_native_base_t* base) {  
        ANativeObjectBase* self = getSelf(base);  
        self->decStrong(self);  
    }   
};  

搞了半天,原来GraphicBuffer就是ANativeWindowBuffer一种具体实现,把ANativeWindowBuffer的common成员的两个函数指针incRef decRef指向了GraphicBuffer的另一个基类RefBase的incStrong和decStrong,而ANativeWindowBuffer无非就是把buffer_handle_t包了一层.

我们看下另外一个从ANativeObjectBase派生的类,他就是大名鼎鼎的,Surface!它的定义如下:

class Surface  
    : public ANativeObjectBase<ANativeWindow, Surface, RefBase>  
{  
    enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };  
    ...  
    struct BufferSlot {  
        sp<GraphicBuffer> buffer;  
        Region dirtyRegion;  
    };  
    // mSlots stores the buffers that have been allocated for each buffer slot.  
    // It is initialized to null pointers, and gets filled in with the result of  
    // IGraphicBufferProducer::requestBuffer when the client dequeues a buffer from a  
    // slot that has not yet been used. The buffer allocated to a slot will also  
    // be replaced if the requested buffer usage or geometry differs from that  
    // of the buffer allocated to a slot.  
    BufferSlot mSlots[NUM_BUFFER_SLOTS];  
    ...  
}  

Surface和GraphicBuffer都继承自模版类ANativeObjectBase,他使用的三个模版是ANativeWindow, Surface, RefBase,关于incRef和decRef两个函数指针的指向问题和上面GraphicBuffer是完全相同的, 这里就不赘述了.我们需要注意的是Surface有一个BufferSlot类型的成员数组mSlots,BufferSlot是GraphicBuffer的包装,所以我们可以理解为每个Surface中都有一个大小为NUM_BUFFER_SLOTS的GraphicBuffer数组.

因为Surface继承自ANativeWindow,所以Surface需要实现ANativeWindow中定义的一些接口,这些实现在Surface的构造函数中,我们来看下它的实现:

[frameworks/native/libs/gui/Surface.cpp]
Surface::Surface(  
        const sp<IGraphicBufferProducer>& bufferProducer,  
        bool controlledByApp)  
    : mGraphicBufferProducer(bufferProducer)  
{  
    // Initialize the ANativeWindow function pointers.  
    ANativeWindow::setSwapInterval  = hook_setSwapInterval;  
    ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;  
    ANativeWindow::cancelBuffer     = hook_cancelBuffer;  
    ANativeWindow::queueBuffer      = hook_queueBuffer;  
    ANativeWindow::query            = hook_query;  
    ANativeWindow::perform          = hook_perform;  
  
    ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;  
    ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;  
    ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;  
    ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;  
  
    const_cast<int&>(ANativeWindow::minSwapInterval) = 0;  
    const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;  
}  

ANativeWindow定义的这些接口有什么用呢?谁会来call这些函数呢?举个例子来看.我们在EGL的api中可以找到eglCreateWindowSurface这个函数的定义:

[frameworks/native/opengl/libs/EGL/eglApi.cpp]

EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,  
                                    NativeWindowType window,  
                                    const EGLint *attrib_list)  
{  
    ...  
}

注意其中一个参数NativeWindowType window,这个NativeWindowType又是什么呢?

[frameworks/native/opengl/include/EGL/eglplatform.h]
typedef struct ANativeWindow*           EGLNativeWindowType;  
typedef EGLNativeWindowType  NativeWindowType;

原来NativeWindowType在Android环境下,就是ANativeWindow*,也就是Surface*!
总结一下:

  • native_handle/native_handle_t是private_handle_t的抽象表示方法,消除平台相关性,方便private_handle_t所表示的memory信息在android各个层次之间传递.而buffer_handle_t是指向他们的指针.

  • ANativeWindowBuffer将buffer_handle_t进行了包装,ANativeWindow和ANativeWindowBuffer都继承于android_native_base_t,定义了common.incRef和common.decRef两个函数指针,但是并没有为函数指针赋值,所以ANativeWindow和ANativeWindowBuffer仍然是抽象类.
    GraphicBuffer和Surface通过继承模版类ANativeObjectBase并指定其中一个模版是RefBase,为incRef和decRef两个指针分别赋值为RefBase的incStrong和decStrong,这样

  • GraphicBuffer继承了ANativeWindowBuffer,Surface继承了ANativeWindow,并且两者都具有的和RefBase同样的incStong decStrong成员函数.

  • Surface的成员BufferSlot mSlots[NUM_BUFFER_SLOTS];可以看作是sp类型的数组,也就是说每个Surface中都包含有NUM_BUFFER_SLOTS个sp.

关于ANativeWindow的使用方法,我们可以在SurfaceFlinger中找到一个很好的列子,就是SF的captureScreen接口。


3.6 关于GraphicBuffer和Surface牵涉的各种数据结构小结

通过上述的一通咔咔学习,我们在以后的SurfaceFlinger HardWare Composer以及gralloc相关代码的学习过程中,native_handle private_handle_t ANativeWindowBuffer ANativeWindow GraphicBuffer Surface等等一系列和memory相关的struct和class,他们相互之间到底是什么区别,又有什么联系呢,我们应该已经很清楚了。

概括来说native_handle,private_handle_t,ANativeWindowBuffer,GraphicBuffer这四个struct/class所描述的是一块memory。而ANativeWindow和Surface所描述的是一系列上述memeofy的组合和对buffer的操作方法,有的struct/class在比较低的level使用,和平台有关,而另外一些在比较高的level使用和平台无关,还有一些介于低/高level之间,用以消除平台相关性,让android可以方便运行在不同的平台上。

关于Android下gralloc,hwcompoer以及surface模块的重新认识,Android graphic深入分析,android,gralloc,hwcomposer,surface




写在最后

好了今天的博客关于Android下gralloc,hwcompoer以及surface模块的重新认识就到这里了。总之,青山不改绿水长流先到这里了。如果本博客对你有所帮助,麻烦关注或者点个赞,如果觉得很烂也可以踩一脚!谢谢各位了!!文章来源地址https://www.toymoban.com/news/detail-830704.html

到了这里,关于关于Android下gralloc,hwcompoer以及surface模块的重新认识的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 探索Android Jetpack Compose的Surface组件

    随着声明性 UI 框架 Jetpack Compose 的出现,Android 开发变得更加简洁和直观。在这篇博客中,我们将深入探讨其中的一项基本构建块 —— Surface 组件,了解它如何影响 UI 的显示和设计。 一、Jetpack Compose和Surface组件 二、Surface组件的基本使用 三、影响Surface的属性 一、Jetpack Co

    2024年02月11日
    浏览(58)
  • Android UpdateEngine 模块分析(三)升级触发以及Action机制介绍

    前面分析了 UpdateEngine 模块的编译和启动流程,对于 UpdateEngine 模块已经有了初步的了解,接下来我们从升级的功能出发,分析 UpdateEngine 的升级过程,升级过程的内容非常的多,准备从 UpdateEngine 的 Action 机制开始分析,UpdateEngine 的升级过程有很多步骤,每一个步骤由一个

    2024年02月05日
    浏览(47)
  • Android开发之Compose基础学习-Surface容器的基本使用

    先上图 再看代码

    2024年02月15日
    浏览(44)
  • [Android] [ROOT] Magisk(魔术师/面具) 设置以及必装模块的安装

    当我们给手机刷入Magisk(面具)后,等于获得了安卓系统的最高管理员权限,也就是root权限。获取root权限后的设备相对于未root的设备,安全性会有一定的降低。也许是基于这个原因,现在大部分应用都会检测你的设备是否存在root,当检测到你的设备存在root,就会无法运行或者

    2023年04月10日
    浏览(63)
  • 关于Android Studio连接mysql数据库的过程和注册功能的实现(数据的插入)以及mysql环境变量的配置

    1.安装mysql数据库,安装的教程哔站有很多,版本尽量用mysql5.7的版本,用mysql8.0的版本与android studio进行连接的话可能会出现问题。 2.安装完成之后,给本机配置环境变量,步骤:如下图示 (1)通过搜索打开环境变量。 (2).点击环境变量。 (3).找到系统变量点击新建。

    2024年04月14日
    浏览(66)
  • Django 动态重新加载模块

    可以将对应的文件路径的具体的module传入 例如 我希望重新加载的模块的路径是:app01/myfile.py 那 file_path  对应就是【\\\'app01/myfile.py\\\'】 那 module 对应就是【\\\'myfile\\\'】 这样带入下面的代码就可以实现django动态重新加载某一模块

    2024年02月15日
    浏览(39)
  • Nginx重新编译并添加模块

            作用:一是检查所需模块是否已安装,二是将configure arguments: 后面的参数复制出来并保存,因为等会重新编译时还需将这些模块一同添加进去。         进入Nginx源码包目录下,执行make clean指令,清除历史编译。         使用./configure --help指令查询需要配置的参

    2024年02月05日
    浏览(39)
  • 关于安卓jar包修改并且重新发布

    背景: 对于某些jar包,其内部是存在bug的,解决的方法无外乎就有以下几种方法: (1)通过反射,修改其赋值逻辑 (2)通过继承,重写其方法 (3)修改jar包的源码,从根源上修复问题 对于改动量,难易程度,(1)和(2)都是比较适合的,但是,有些情况下,不能满足修

    2024年02月13日
    浏览(46)
  • 关于flink重新提交任务,重复消费kafka的坑

    按照以下方式设置backend目录和checkpoint目录,fsbackend目录有数据,checkpoint目录没数据 我以为checkpoint和fsbackend要同时设置,其实,1.14.3版本,setCheckpointStorage和stateBackend改成了分着设置 我上边代码这样设置,相当于首先指定了以下checkpoint按照默认的backend存储,然后又指定了按

    2024年02月03日
    浏览(55)
  • 关于VIVADO与VScode配置重启后,配置无效,需重新配置的问题

    问题:我想将VIVADO与VScode配置关联起来,实现在VIVADO中点击“设计文件”可以直接打开VScode进行代码编写的效果。问题在于,每次在VIVADO中配置完之后,再重启VIVADO,之前的配置都恢复了默认值,又得我重新配置,比较麻烦。经过数次研究,终于找到了解决办法,可以一劳永

    2024年02月09日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包