Android中的GraphicBuffer的分配

Android中的GraphicBuffer的分配,Android中圖像緩沖區的分配是由單例類GraphicBufferAllocator實現的。

[frameworks/native/include/ui/GraphicBufferAllocator.h]

#ifndef ANDROID_BUFFER_ALLOCATOR_H
#define ANDROID_BUFFER_ALLOCATOR_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

namespace android {
class String8;

class GraphicBufferAllocator : public Singleton
{
public:
    enum {
        USAGE_SW_READ_NEVER     = GRALLOC_USAGE_SW_READ_NEVER, //0x00000000
        USAGE_SW_READ_RARELY    = GRALLOC_USAGE_SW_READ_RARELY, //0x00000002
        USAGE_SW_READ_OFTEN     = GRALLOC_USAGE_SW_READ_OFTEN, //0x00000003
        USAGE_SW_READ_MASK      = GRALLOC_USAGE_SW_READ_MASK, //0x0000000F

        USAGE_SW_WRITE_NEVER    = GRALLOC_USAGE_SW_WRITE_NEVER, //0x00000000
        USAGE_SW_WRITE_RARELY   = GRALLOC_USAGE_SW_WRITE_RARELY, //0x00000020
        USAGE_SW_WRITE_OFTEN    = GRALLOC_USAGE_SW_WRITE_OFTEN, //0x00000030
        USAGE_SW_WRITE_MASK     = GRALLOC_USAGE_SW_WRITE_MASK, //0x000000F0

        USAGE_SOFTWARE_MASK     = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK,

        USAGE_HW_TEXTURE        = GRALLOC_USAGE_HW_TEXTURE, //0x00000100
        USAGE_HW_RENDER         = GRALLOC_USAGE_HW_RENDER, //0x0000020
        USAGE_HW_2D             = GRALLOC_USAGE_HW_2D, //0x00000400
        USAGE_HW_MASK           = GRALLOC_USAGE_HW_MASK //0x00071F00
    };

    //獲取單例實例。
    static inline GraphicBufferAllocator& get() { return getInstance(); }

    status_t alloc(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
            buffer_handle_t* handle, uint32_t* stride);

    status_t free(buffer_handle_t handle);

    void dump(String8& res) const;
    static void dumpToSystemLog();

private:
    struct alloc_rec_t {
        uint32_t width;
        uint32_t height;
        uint32_t stride;
        PixelFormat format;
        uint32_t usage;
        size_t size;
    };

    //靜態變量
    static Mutex sLock;
    static KeyedVector sAllocList;

    //父類聲明為友元類,原因是?不清楚。
    friend class Singleton;

    //構造和析構函數均為private。
    GraphicBufferAllocator();
    ~GraphicBufferAllocator();

    alloc_device_t  *mAllocDev;
};
}; // namespace android

#endif // ANDROID_BUFFER_ALLOCATOR_H

具體的實現思路是:
1. 在構造函數中打開gralloc模塊,在析構函數中關閉打開的gralloc文件描述符;

GraphicBufferAllocator::GraphicBufferAllocator()
    : mAllocDev(0)
{
    hw_module_t const* module;
    /* GRALLOC_HARDWARE_MODULE_ID值為字符串"gralloc",在hardware/gralloc.h中定義。 */
    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
    ALOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);
    if (err == 0) {
        /* gralloc_open與gralloc_close的實現位於hardware/gralloc.h中。*/
        gralloc_open(module, &mAllocDev);
    }
}

GraphicBufferAllocator::~GraphicBufferAllocator()
{
    gralloc_close(mAllocDev);
}

alloc()函數執行成功後,會插入到GraphicBufferAllocator類的靜態變量sAllocList中,每次操作需要加鎖sLock。在free時,會刪除Key為handle的Key-Value對。

[frameworks/native/libs/ui/GraphicBufferAllocator.cpp]
Mutex GraphicBufferAllocator::sLock;
KeyedVector GraphicBufferAllocator::sAllocList;

status_t GraphicBufferAllocator::alloc(uint32_t width, uint32_t height,
        PixelFormat format, uint32_t usage, buffer_handle_t* handle,
        uint32_t* stride)
{
    ATRACE_CALL();

    // make sure to not allocate a N x 0 or 0 x N buffer, since this is
    // allowed from an API stand-point, allocate a 1x1 buffer instead.
    if (!width || !height)
        width = height = 1;

    // we have a h/w allocator and h/w buffer is requested
    status_t err;

    // Filter out any usage bits that should not be passed to the gralloc module
    usage &= GRALLOC_USAGE_ALLOC_MASK;

    int outStride = 0;
    err = mAllocDev->alloc(mAllocDev, static_cast(width),
            static_cast(height), format, static_cast(usage), handle,
            &outStride);
    *stride = static_cast(outStride);

    ALOGW_IF(err, "alloc(%u, %u, %d, %08x, ...) failed %d (%s)",
            width, height, format, usage, err, strerror(-err));

    if (err == NO_ERROR) {
        Mutex::Autolock _l(sLock);
        KeyedVector& list(sAllocList);
        uint32_t bpp = bytesPerPixel(format);
        alloc_rec_t rec;
        rec.width = width;
        rec.height = height;
        rec.stride = *stride;
        rec.format = format;
        rec.usage = usage;
        rec.size = static_cast(height * (*stride) * bpp);
        list.add(*handle, rec);
    }

    return err;
}

status_t GraphicBufferAllocator::free(buffer_handle_t handle)
{
    ATRACE_CALL();
    status_t err;

    err = mAllocDev->free(mAllocDev, handle);

    ALOGW_IF(err, "free(...) failed %d (%s)", err, strerror(-err));
    if (err == NO_ERROR) {
        Mutex::Autolock _l(sLock);
        KeyedVector& list(sAllocList);
        list.removeItem(handle);
    }

    return err;
}

You May Also Like