BufferQueue 是 Android 中所有图形处理操作的核心。它的作用很简单:将生成图形数据缓冲区的一方(生产者)连接到接受数据以显示或进一步处理的一方(消费者)。几乎所有在系统中移动图形数据缓冲区的内容都依赖于 BufferQueue。

Android 定义了一个类 BufferQueue,用于创建 BufferQueue、生产者和消费者。该类定义(位于frameworks/native/include/gui/BufferQueue.h)如下:

namespace android {class BufferQueue {
public:// BufferQueue will keep track of at most this value of buffers.// Attempts at runtime to increase the number of buffers past this will fail.enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };// Used as a placeholder slot# when the value isn't pointing to an existing buffer.enum { INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT };// Alias to <IGraphicBufferConsumer.h> -- please scope from there in future code!enum {NO_BUFFER_AVAILABLE = IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,PRESENT_LATER = IGraphicBufferConsumer::PRESENT_LATER,};// When in async mode we reserve two slots in order to guarantee that the// producer and consumer can run asynchronously.enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 };// for backward source compatibilitytypedef ::android::ConsumerListener ConsumerListener;// ProxyConsumerListener is a ConsumerListener implementation that keeps a weak// reference to the actual consumer object.  It forwards all calls to that// consumer object so long as it exists.//// This class exists to avoid having a circular reference between the// BufferQueue object and the consumer object.  The reason this can't be a weak// reference in the BufferQueue class is because we're planning to expose the// consumer side of a BufferQueue as a binder interface, which doesn't support// weak references.class ProxyConsumerListener : public BnConsumerListener {public:ProxyConsumerListener(const wp<ConsumerListener>& consumerListener);virtual ~ProxyConsumerListener();virtual void onFrameAvailable(const BufferItem& item) override;virtual void onFrameReplaced(const BufferItem& item) override;virtual void onBuffersReleased() override;virtual void onSidebandStreamChanged() override;virtual bool getFrameTimestamps(uint64_t frameNumber,FrameTimestamps* outTimestamps) const override;private:// mConsumerListener is a weak reference to the IConsumerListener.  This is// the raison d'etre of ProxyConsumerListener.wp<ConsumerListener> mConsumerListener;};// BufferQueue manages a pool of gralloc memory slots to be used by// producers and consumers. allocator is used to allocate all the// needed gralloc buffers.static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,sp<IGraphicBufferConsumer>* outConsumer,const sp<IGraphicBufferAlloc>& allocator = NULL);private:BufferQueue(); // Create through createBufferQueue
};// ----------------------------------------------------------------------------
}; // namespace android

BufferQueue 定义了一个类 ProxyConsumerListener 用于方便 ConsumerListener 的 IPC,它会把所有对它的调用,都转发给实际的 consumer 对象。

BufferQueue 类只有一个静态成员函数 createBufferQueue() 用于创建 BufferQueue,该函数定义(位于 frameworks/native/libs/gui/BufferQueueCore.cpp)如下:

void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,sp<IGraphicBufferConsumer>* outConsumer,const sp<IGraphicBufferAlloc>& allocator) {LOG_ALWAYS_FATAL_IF(outProducer == NULL,"BufferQueue: outProducer must not be NULL");LOG_ALWAYS_FATAL_IF(outConsumer == NULL,"BufferQueue: outConsumer must not be NULL");sp<BufferQueueCore> core(new BufferQueueCore(allocator));LOG_ALWAYS_FATAL_IF(core == NULL,"BufferQueue: failed to create BufferQueueCore");sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));LOG_ALWAYS_FATAL_IF(producer == NULL,"BufferQueue: failed to create BufferQueueProducer");sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));LOG_ALWAYS_FATAL_IF(consumer == NULL,"BufferQueue: failed to create BufferQueueConsumer");*outProducer = producer;*outConsumer = consumer;
}

createBufferQueue()函数基于 IGraphicBufferAlloc 创建 BufferQueueCore,并基于后者创建 BufferQueueProducerBufferQueueConsumer 返回给调用者。Android 图形系统的核心在 BufferQueue,BufferQueue 的核心则在 BufferQueueCore 类,而不是 BufferQueue 类。

图形缓冲区分配器 IGraphicBufferAlloc

BufferQueueConsumer 管理的图形缓冲区均由 BufferQueueProducer 通过 IGraphicBufferAlloc 分配。创建 BufferQueue 时,传入的 allocator 通常为空值,此时 BufferQueueCore 通过如下方式(位于
frameworks/native/libs/gui/BufferQueueCore.cpp)获得 IGraphicBufferAlloc

    if (allocator == NULL) {sp<ISurfaceComposer> composer(ComposerService::getComposerService());mAllocator = composer->createGraphicBufferAlloc();if (mAllocator == NULL) {BQ_LOGE("createGraphicBufferAlloc failed");}}

BufferQueueCoreIGraphicBufferAlloc 来自于 ComposerServiceComposerService 定义(位于frameworks/native/include/private/gui/ComposerService.h)如下:

class ComposerService : public Singleton<ComposerService>
{sp<ISurfaceComposer> mComposerService;sp<IBinder::DeathRecipient> mDeathObserver;Mutex mLock;ComposerService();void connectLocked();void composerServiceDied();friend class Singleton<ComposerService>;
public:// Get a connection to the Composer Service.  This will block until// a connection is established.static sp<ISurfaceComposer> getComposerService();
};

ComposerService 类本身仅仅持有到 composer service,如 SurfaceFlinger 的连接,即 ISurfaceComposer。如果远程服务挂掉了,这个类通过 Binder 的 linkToDeath 机制得到通知,并将重新建立连接。

ComposerService 类的成员函数定义(位于 frameworks/native/libs/gui/SurfaceComposerClient.cpp)如下:

ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService);ComposerService::ComposerService()
: Singleton<ComposerService>() {Mutex::Autolock _l(mLock);connectLocked();
}void ComposerService::connectLocked() {const String16 name("SurfaceFlinger");while (getService(name, &mComposerService) != NO_ERROR) {usleep(250000);}assert(mComposerService != NULL);// Create the death listener.class DeathObserver : public IBinder::DeathRecipient {ComposerService& mComposerService;virtual void binderDied(const wp<IBinder>& who) {ALOGW("ComposerService remote (surfaceflinger) died [%p]",who.unsafe_get());mComposerService.composerServiceDied();}public:DeathObserver(ComposerService& mgr) : mComposerService(mgr) { }};mDeathObserver = new DeathObserver(*const_cast<ComposerService*>(this));IInterface::asBinder(mComposerService)->linkToDeath(mDeathObserver);
}/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {ComposerService& instance = ComposerService::getInstance();Mutex::Autolock _l(instance.mLock);if (instance.mComposerService == NULL) {ComposerService::getInstance().connectLocked();assert(instance.mComposerService != NULL);ALOGD("ComposerService reconnected");}return instance.mComposerService;
}

实际的 composer service 是 SurfaceFlinger。SurfaceFlinger 中是这样创建 IGraphicBufferAlloc 的(配置使用 HWC2 的情况,位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp):

sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
{sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());return gba;
}

IGraphicBufferAlloc 实际为 GraphicBufferAlloc,该类定义(位于 frameworks/native/include/gui/GraphicBufferAlloc.h)如下:

namespace android {
// ---------------------------------------------------------------------------class GraphicBuffer;class GraphicBufferAlloc : public BnGraphicBufferAlloc {
public:GraphicBufferAlloc();virtual ~GraphicBufferAlloc();virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width,uint32_t height, PixelFormat format, uint32_t usage,std::string requestorName, status_t* error) override;
};// ---------------------------------------------------------------------------
}; // namespace android

GraphicBufferAlloc 继承自 BnGraphicBufferAlloc,后者定义(位于 frameworks/native/include/gui/IGraphicBufferAlloc.h)如下:

class IGraphicBufferAlloc : public IInterface
{
public:DECLARE_META_INTERFACE(GraphicBufferAlloc);/* Create a new GraphicBuffer for the client to use.*/virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,PixelFormat format, uint32_t usage, std::string requestorName,status_t* error) = 0;sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,PixelFormat format, uint32_t usage, status_t* error) {return createGraphicBuffer(w, h, format, usage, "<Unknown>", error);}
};// ----------------------------------------------------------------------------class BnGraphicBufferAlloc : public BnInterface<IGraphicBufferAlloc>
{
public:virtual status_t onTransact(uint32_t code,const Parcel& data,Parcel* reply,uint32_t flags = 0);
};// ----------------------------------------------------------------------------}; // namespace android

GraphicBufferAlloc 只有一个成员函数,该函数定义(frameworks/native/libs/gui/GraphicBufferAlloc.cpp)如下:

namespace android {
// ----------------------------------------------------------------------------GraphicBufferAlloc::GraphicBufferAlloc() {
}GraphicBufferAlloc::~GraphicBufferAlloc() {
}sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width,uint32_t height, PixelFormat format, uint32_t usage,std::string requestorName, status_t* error) {sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(width, height, format, usage, std::move(requestorName)));status_t err = graphicBuffer->initCheck();*error = err;if (err != 0 || graphicBuffer->handle == 0) {if (err == NO_MEMORY) {GraphicBuffer::dumpAllocationsToSystemLog();}ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) ""failed (%s), handle=%p",width, height, strerror(-err), graphicBuffer->handle);return 0;}return graphicBuffer;
}// ----------------------------------------------------------------------------
}; // namespace android

BufferQueueCoreGraphicBuffer 的容器,IGraphicBufferAlloc 仅仅用于创建 GraphicBuffer 对象。但对于实际的图形内存块的管理,还不在 IGraphicBufferAlloc 这一层。

图形缓冲区 GraphicBuffer

GraphicBuffer 类是更底层 操作系统/硬件 层图形内存块的封装,该类的定义如下:

class GraphicBuffer: public ANativeObjectBase< ANativeWindowBuffer, GraphicBuffer, RefBase >,public Flattenable<GraphicBuffer>
{friend class Flattenable<GraphicBuffer>;
public:
. . . . . .GraphicBuffer();// creates w * h bufferGraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,uint32_t inUsage, std::string requestorName = "<Unknown>");// create a buffer from an existing handleGraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,uint32_t inUsage, uint32_t inStride, native_handle_t* inHandle,bool keepOwnership);// create a buffer from an existing ANativeWindowBufferGraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership);// return statusstatus_t initCheck() const;uint32_t getWidth() const           { return static_cast<uint32_t>(width); }uint32_t getHeight() const          { return static_cast<uint32_t>(height); }uint32_t getStride() const          { return static_cast<uint32_t>(stride); }uint32_t getUsage() const           { return static_cast<uint32_t>(usage); }PixelFormat getPixelFormat() const  { return format; }Rect getBounds() const              { return Rect(width, height); }uint64_t getId() const              { return mId; }uint32_t getGenerationNumber() const { return mGenerationNumber; }void setGenerationNumber(uint32_t generation) {mGenerationNumber = generation;}status_t reallocate(uint32_t inWidth, uint32_t inHeight,PixelFormat inFormat, uint32_t inUsage);bool needsReallocation(uint32_t inWidth, uint32_t inHeight,PixelFormat inFormat, uint32_t inUsage);status_t lock(uint32_t inUsage, void** vaddr);status_t lock(uint32_t inUsage, const Rect& rect, void** vaddr);// For HAL_PIXEL_FORMAT_YCbCr_420_888status_t lockYCbCr(uint32_t inUsage, android_ycbcr *ycbcr);status_t lockYCbCr(uint32_t inUsage, const Rect& rect,android_ycbcr *ycbcr);status_t unlock();status_t lockAsync(uint32_t inUsage, void** vaddr, int fenceFd);status_t lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr,int fenceFd);status_t lockAsyncYCbCr(uint32_t inUsage, android_ycbcr *ycbcr,int fenceFd);status_t lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,android_ycbcr *ycbcr, int fenceFd);status_t unlockAsync(int *fenceFd);ANativeWindowBuffer* getNativeBuffer() const;// for debuggingstatic void dumpAllocationsToSystemLog();// Flattenable protocolsize_t getFlattenedSize() const;size_t getFdCount() const;status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);private:~GraphicBuffer();enum {ownNone   = 0,ownHandle = 1,ownData   = 2,};inline const GraphicBufferMapper& getBufferMapper() const {return mBufferMapper;}inline GraphicBufferMapper& getBufferMapper() {return mBufferMapper;}uint8_t mOwner;private:friend class Surface;friend class BpSurface;friend class BnSurface;friend class LightRefBase<GraphicBuffer>;GraphicBuffer(const GraphicBuffer& rhs);GraphicBuffer& operator = (const GraphicBuffer& rhs);const GraphicBuffer& operator = (const GraphicBuffer& rhs) const;status_t initSize(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,uint32_t inUsage, std::string requestorName);void free_handle();GraphicBufferMapper& mBufferMapper;ssize_t mInitCheck;// If we're wrapping another buffer then this reference will make sure it// doesn't get freed.sp<ANativeWindowBuffer> mWrappedBuffer;uint64_t mId;// Stores the generation number of this buffer. If this number does not// match the BufferQueue's internal generation number (set through// IGBP::setGenerationNumber), attempts to attach the buffer will fail.uint32_t mGenerationNumber;
};

ANativeObjectBase 模板的声明(位于 frameworks/native/include/ui/ANativeObjectBase.h)是这样的:

template <typename NATIVE_TYPE, typename TYPE, typename REF>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{
public:// Disambiguate between the incStrong in REF and NATIVE_TYPEvoid incStrong(const void* id) const {REF::incStrong(id);}void decStrong(const void* id) const {REF::decStrong(id);}protected:typedef ANativeObjectBase<NATIVE_TYPE, TYPE, REF> BASE;ANativeObjectBase() : NATIVE_TYPE(), REF() {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));}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);}
};} // namespace android
#endif // __cplusplus

以此来看,GraphicBuffer 也将继承 ANativeWindowBufferANativeWindowBuffer 定义(位于 system/core/include/system/window.h)如下:

typedef const native_handle_t* buffer_handle_t;
. . . . . .
typedef struct ANativeWindowBuffer
{
#ifdef __cplusplusANativeWindowBuffer() {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));}
#endifstruct 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;

这个结构体描述了更底层 操作系统/硬件 层图形内存块的信息,包括图形内存块的句柄 handle,图像的宽度、高度,像素格式等。图形内存块的句柄类型 buffer_handle_tconst native_handle_t* 的别名,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;

可以看到 GraphicBuffer 类的主要职责主要有三块:
1. 主要通过继承自 ANativeWindowBuffer 结构体的成员,来描述图形内存块的信息。
2. 分配释放图形内存块。这主要通过 initSize() / reallocate() / free_handle() 等操作完成。
3. 分配的图形内存块未必已经映射到应用程序的虚拟地址空间了。应用程序要想像访问普通内存那样访问图形内存块,还需要通过 lockXXX 操作将图形内存块映射到应用程序进程的虚拟地址空间内。应用程序在把图形内存块还回去的时候则需要 unlockXXX 操作。

此外 GraphicBuffermInitCheck 用于记录图形缓冲区的状态;mGenerationNumber 用于记录 generation number;mId 用于标识图形缓冲区,它通过如下方式计算得到:

static uint64_t getUniqueId() {static volatile int32_t nextId = 0;uint64_t id = static_cast<uint64_t>(getpid()) << 32;id |= static_cast<uint32_t>(android_atomic_inc(&nextId));return id;
}

mID 通过进程的 PID 和一个不断递增的整数计算获得。

GraphicBuffer 依赖于 GraphicBufferAllocator 完成图形内存块的分配和释放,依赖于 GraphicBufferMapper 执行图形内存块的 lock/unlock 操作。

GraphicBuffer 的图形内存块分配和释放操作实现(位于 frameworks/native/libs/ui/GraphicBuffer.cpp)如下:

GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,PixelFormat inFormat, uint32_t inUsage, std::string requestorName): BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
{width  =height =stride =format =usage  = 0;handle = NULL;mInitCheck = initSize(inWidth, inHeight, inFormat, inUsage,std::move(requestorName));
}GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,PixelFormat inFormat, uint32_t inUsage, uint32_t inStride,native_handle_t* inHandle, bool keepOwnership): BASE(), mOwner(keepOwnership ? ownHandle : ownNone),mBufferMapper(GraphicBufferMapper::get()),mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
{width  = static_cast<int>(inWidth);height = static_cast<int>(inHeight);stride = static_cast<int>(inStride);format = inFormat;usage  = static_cast<int>(inUsage);handle = inHandle;
}GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership): BASE(), mOwner(keepOwnership ? ownHandle : ownNone),mBufferMapper(GraphicBufferMapper::get()),mInitCheck(NO_ERROR), mWrappedBuffer(buffer), mId(getUniqueId()),mGenerationNumber(0)
{width  = buffer->width;height = buffer->height;stride = buffer->stride;format = buffer->format;usage  = buffer->usage;handle = buffer->handle;
}GraphicBuffer::~GraphicBuffer()
{if (handle) {free_handle();}
}void GraphicBuffer::free_handle()
{if (mOwner == ownHandle) {mBufferMapper.unregisterBuffer(handle);native_handle_close(handle);native_handle_delete(const_cast<native_handle*>(handle));} else if (mOwner == ownData) {GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());allocator.free(handle);}handle = NULL;mWrappedBuffer = 0;
}
. . . . . .
status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight,PixelFormat inFormat, uint32_t inUsage)
{if (mOwner != ownData)return INVALID_OPERATION;if (handle &&static_cast<int>(inWidth) == width &&static_cast<int>(inHeight) == height &&inFormat == format &&static_cast<int>(inUsage) == usage)return NO_ERROR;if (handle) {GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());allocator.free(handle);handle = 0;}return initSize(inWidth, inHeight, inFormat, inUsage, "[Reallocation]");
}
. . . . . .
status_t GraphicBuffer::initSize(uint32_t inWidth, uint32_t inHeight,PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
{GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();uint32_t outStride = 0;status_t err = allocator.allocate(inWidth, inHeight, inFormat, inUsage,&handle, &outStride, mId, std::move(requestorName));if (err == NO_ERROR) {width = static_cast<int>(inWidth);height = static_cast<int>(inHeight);format = inFormat;usage = static_cast<int>(inUsage);stride = static_cast<int>(outStride);}return err;
}

GraphicBuffer 的图形内存块的 lock/unlock 操作实现(位于 frameworks/native/libs/ui/GraphicBuffer.cpp)如下:

status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr)
{const Rect lockBounds(width, height);status_t res = lock(inUsage, lockBounds, vaddr);return res;
}status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr)
{if (rect.left < 0 || rect.right  > width ||rect.top  < 0 || rect.bottom > height) {ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",rect.left, rect.top, rect.right, rect.bottom,width, height);return BAD_VALUE;}status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr);return res;
}status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr)
{const Rect lockBounds(width, height);status_t res = lockYCbCr(inUsage, lockBounds, ycbcr);return res;
}status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect,android_ycbcr* ycbcr)
{if (rect.left < 0 || rect.right  > width ||rect.top  < 0 || rect.bottom > height) {ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",rect.left, rect.top, rect.right, rect.bottom,width, height);return BAD_VALUE;}status_t res = getBufferMapper().lockYCbCr(handle, inUsage, rect, ycbcr);return res;
}status_t GraphicBuffer::unlock()
{status_t res = getBufferMapper().unlock(handle);return res;
}status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd)
{const Rect lockBounds(width, height);status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd);return res;
}status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect,void** vaddr, int fenceFd)
{if (rect.left < 0 || rect.right  > width ||rect.top  < 0 || rect.bottom > height) {ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",rect.left, rect.top, rect.right, rect.bottom,width, height);return BAD_VALUE;}status_t res = getBufferMapper().lockAsync(handle, inUsage, rect, vaddr,fenceFd);return res;
}status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr,int fenceFd)
{const Rect lockBounds(width, height);status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd);return res;
}status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,android_ycbcr* ycbcr, int fenceFd)
{if (rect.left < 0 || rect.right  > width ||rect.top  < 0 || rect.bottom > height) {ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",rect.left, rect.top, rect.right, rect.bottom,width, height);return BAD_VALUE;}status_t res = getBufferMapper().lockAsyncYCbCr(handle, inUsage, rect,ycbcr, fenceFd);return res;
}status_t GraphicBuffer::unlockAsync(int *fenceFd)
{status_t res = getBufferMapper().unlockAsync(handle, fenceFd);return res;
}

这些操作基本上都是比较直接的委托。

GraphicBufferAllocator 和 GraphicBufferMapper

GraphicBufferAllocatorGraphicBufferMapper 则依赖于 Gralloc1::Loader
Gralloc1::Device 完成图形内存的分配释放和 lock / unlock 操作,其中 Gralloc1::Loader 用于加载 HAL 层的 gralloc 模块并创建 Gralloc1::DeviceGralloc1::Device 则用于执行最终的图形内存的分配释放和 lock / unlock 操作。

GraphicBufferAllocator 类定义(位于 frameworks/native/include/ui/GraphicBufferAllocator.h)如下:

namespace android {class Gralloc1Loader;
class String8;class GraphicBufferAllocator : public Singleton<GraphicBufferAllocator>
{
public:enum {USAGE_SW_READ_NEVER     = GRALLOC1_CONSUMER_USAGE_CPU_READ_NEVER,USAGE_SW_READ_RARELY    = GRALLOC1_CONSUMER_USAGE_CPU_READ,USAGE_SW_READ_OFTEN     = GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN,USAGE_SW_READ_MASK      = GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN,USAGE_SW_WRITE_NEVER    = GRALLOC1_PRODUCER_USAGE_CPU_WRITE_NEVER,USAGE_SW_WRITE_RARELY   = GRALLOC1_PRODUCER_USAGE_CPU_WRITE,USAGE_SW_WRITE_OFTEN    = GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN,USAGE_SW_WRITE_MASK     = GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN,USAGE_SOFTWARE_MASK     = USAGE_SW_READ_MASK|USAGE_SW_WRITE_MASK,USAGE_HW_TEXTURE        = GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE,USAGE_HW_RENDER         = GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET,USAGE_HW_2D             = 0x00000400, // DeprecatedUSAGE_HW_MASK           = 0x00071F00, // Deprecated};static inline GraphicBufferAllocator& get() { return getInstance(); }status_t allocate(uint32_t w, uint32_t h, PixelFormat format,uint32_t usage, buffer_handle_t* handle, uint32_t* stride,uint64_t graphicBufferId, std::string requestorName);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;std::string requestorName;};static Mutex sLock;static KeyedVector<buffer_handle_t, alloc_rec_t> sAllocList;friend class Singleton<GraphicBufferAllocator>;GraphicBufferAllocator();~GraphicBufferAllocator();std::unique_ptr<Gralloc1::Loader> mLoader;std::unique_ptr<Gralloc1::Device> mDevice;
};// ---------------------------------------------------------------------------
}; // namespace android

GraphicBufferAllocator 主要定义了分配图形内存块的 allocate() 和释放图形内存块的 free() 两个函数,这两个函数的实现(位于 frameworks/native/libs/ui/GraphicBufferAllocator.cpp)如下:

ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferAllocator )Mutex GraphicBufferAllocator::sLock;
KeyedVector<buffer_handle_t,GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;GraphicBufferAllocator::GraphicBufferAllocator(): mLoader(std::make_unique<Gralloc1::Loader>()),mDevice(mLoader->getDevice()) {}GraphicBufferAllocator::~GraphicBufferAllocator() {}
. . . . . .
status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,PixelFormat format, uint32_t usage, buffer_handle_t* handle,uint32_t* stride, uint64_t graphicBufferId, std::string requestorName)
{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;// Filter out any usage bits that should not be passed to the gralloc moduleusage &= GRALLOC_USAGE_ALLOC_MASK;auto descriptor = mDevice->createDescriptor();auto error = descriptor->setDimensions(width, height);if (error != GRALLOC1_ERROR_NONE) {ALOGE("Failed to set dimensions to (%u, %u): %d", width, height, error);return BAD_VALUE;}error = descriptor->setFormat(static_cast<android_pixel_format_t>(format));if (error != GRALLOC1_ERROR_NONE) {ALOGE("Failed to set format to %d: %d", format, error);return BAD_VALUE;}error = descriptor->setProducerUsage(static_cast<gralloc1_producer_usage_t>(usage));if (error != GRALLOC1_ERROR_NONE) {ALOGE("Failed to set producer usage to %u: %d", usage, error);return BAD_VALUE;}error = descriptor->setConsumerUsage(static_cast<gralloc1_consumer_usage_t>(usage));if (error != GRALLOC1_ERROR_NONE) {ALOGE("Failed to set consumer usage to %u: %d", usage, error);return BAD_VALUE;}error = mDevice->allocate(descriptor, graphicBufferId, handle);if (error != GRALLOC1_ERROR_NONE) {ALOGE("Failed to allocate (%u x %u) format %d usage %u: %d",width, height, format, usage, error);return NO_MEMORY;}error = mDevice->getStride(*handle, stride);if (error != GRALLOC1_ERROR_NONE) {ALOGW("Failed to get stride from buffer: %d", error);}if (error == NO_ERROR) {Mutex::Autolock _l(sLock);KeyedVector<buffer_handle_t, alloc_rec_t>& 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<size_t>(height * (*stride) * bpp);rec.requestorName = std::move(requestorName);list.add(*handle, rec);}return NO_ERROR;
}status_t GraphicBufferAllocator::free(buffer_handle_t handle)
{ATRACE_CALL();auto error = mDevice->release(handle);if (error != GRALLOC1_ERROR_NONE) {ALOGE("Failed to free buffer: %d", error);}Mutex::Autolock _l(sLock);KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);list.removeItem(handle);return NO_ERROR;
}

GraphicBufferAllocator 分配图形内存块时,步骤如下:
1. 通过 Gralloc1::Device 创建 Gralloc1::Descriptor,并为其设置要分配的图形内存块的规格,包括图像的长和宽,图像的像素格式,图形内存块的使用场景,其中图形内存块的使用场景参数主要用于性能优化。
2. 以 Gralloc1::Descriptor、图形内存块的标识 ID,和图形内存块句柄的指针作为参数,通过 Gralloc1::Deviceallocate() 分配图形内存块,分配的结果通过图形内存块句柄的指针返回。
3. 分配完成之后,可以通过Gralloc1::Device 图形内存块的步进,即单行像素数据占用的内存字节数。底层可能为了性能优化,内存对齐等,分配的内存块可能大于保存实际图像所需要的大小。
4. 对分配结果做记录。GraphicBufferAllocator 维护一个图形内存块句柄到图形内存块规格的映射。

GraphicBufferAllocator 释放图形内存块时的步骤则基本相反:
1. 通过 Gralloc1::Device 释放图形内存块句柄。
2. 移除分配记录。

GraphicBufferMapper 类提供了对图形内存块的 lock / unlock 操作。该类定义(位于 frameworks/native/include/ui/GraphicBufferMapper.h)如下:

class GraphicBufferMapper : public Singleton<GraphicBufferMapper>
{
public:static inline GraphicBufferMapper& get() { return getInstance(); }status_t registerBuffer(buffer_handle_t handle);status_t registerBuffer(const GraphicBuffer* buffer);status_t unregisterBuffer(buffer_handle_t handle);status_t lock(buffer_handle_t handle,uint32_t usage, const Rect& bounds, void** vaddr);status_t lockYCbCr(buffer_handle_t handle,uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr);status_t unlock(buffer_handle_t handle);status_t lockAsync(buffer_handle_t handle,uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd);status_t lockAsyncYCbCr(buffer_handle_t handle,uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr,int fenceFd);status_t unlockAsync(buffer_handle_t handle, int *fenceFd);private:friend class Singleton<GraphicBufferMapper>;GraphicBufferMapper();std::unique_ptr<Gralloc1::Loader> mLoader;std::unique_ptr<Gralloc1::Device> mDevice;
};

GraphicBufferMapper 通过 Gralloc1::Device 提供对图形内存块的 lock / unlock 操作,这些操作的定义(位于 frameworks/native/libs/ui/GraphicBufferMapper.cpp)如下:

ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper )GraphicBufferMapper::GraphicBufferMapper(): mLoader(std::make_unique<Gralloc1::Loader>()),mDevice(mLoader->getDevice()) {}status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
{ATRACE_CALL();gralloc1_error_t error = mDevice->retain(handle);ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",handle, error);return error;
}status_t GraphicBufferMapper::registerBuffer(const GraphicBuffer* buffer)
{ATRACE_CALL();gralloc1_error_t error = mDevice->retain(buffer);ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",buffer->getNativeBuffer()->handle, error);return error;
}status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
{ATRACE_CALL();gralloc1_error_t error = mDevice->release(handle);ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",handle, error);return error;
}static inline gralloc1_rect_t asGralloc1Rect(const Rect& rect) {gralloc1_rect_t outRect{};outRect.left = rect.left;outRect.top = rect.top;outRect.width = rect.width();outRect.height = rect.height();return outRect;
}status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,const Rect& bounds, void** vaddr)
{return lockAsync(handle, usage, bounds, vaddr, -1);
}status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, uint32_t usage,const Rect& bounds, android_ycbcr *ycbcr)
{return lockAsyncYCbCr(handle, usage, bounds, ycbcr, -1);
}status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
{int32_t fenceFd = -1;status_t error = unlockAsync(handle, &fenceFd);if (error == NO_ERROR) {sync_wait(fenceFd, -1);close(fenceFd);}return error;
}status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle,uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd)
{ATRACE_CALL();gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);sp<Fence> fence = new Fence(fenceFd);gralloc1_error_t error = mDevice->lock(handle,static_cast<gralloc1_producer_usage_t>(usage),static_cast<gralloc1_consumer_usage_t>(usage),&accessRegion, vaddr, fence);ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lock(%p, ...) failed: %d", handle,error);return error;
}static inline bool isValidYCbCrPlane(const android_flex_plane_t& plane) {if (plane.bits_per_component != 8) {ALOGV("Invalid number of bits per component: %d",plane.bits_per_component);return false;}if (plane.bits_used != 8) {ALOGV("Invalid number of bits used: %d", plane.bits_used);return false;}bool hasValidIncrement = plane.h_increment == 1 ||(plane.component != FLEX_COMPONENT_Y && plane.h_increment == 2);hasValidIncrement = hasValidIncrement && plane.v_increment > 0;if (!hasValidIncrement) {ALOGV("Invalid increment: h %d v %d", plane.h_increment,plane.v_increment);return false;}return true;
}status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle,uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd)
{ATRACE_CALL();gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);sp<Fence> fence = new Fence(fenceFd);if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {gralloc1_error_t error = mDevice->lockYCbCr(handle,static_cast<gralloc1_producer_usage_t>(usage),static_cast<gralloc1_consumer_usage_t>(usage),&accessRegion, ycbcr, fence);ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lockYCbCr(%p, ...) failed: %d",handle, error);return error;}uint32_t numPlanes = 0;gralloc1_error_t error = mDevice->getNumFlexPlanes(handle, &numPlanes);if (error != GRALLOC1_ERROR_NONE) {ALOGV("Failed to retrieve number of flex planes: %d", error);return error;}if (numPlanes < 3) {ALOGV("Not enough planes for YCbCr (%u found)", numPlanes);return GRALLOC1_ERROR_UNSUPPORTED;}std::vector<android_flex_plane_t> planes(numPlanes);android_flex_layout_t flexLayout{};flexLayout.num_planes = numPlanes;flexLayout.planes = planes.data();error = mDevice->lockFlex(handle,static_cast<gralloc1_producer_usage_t>(usage),static_cast<gralloc1_consumer_usage_t>(usage),&accessRegion, &flexLayout, fence);if (error != GRALLOC1_ERROR_NONE) {ALOGW("lockFlex(%p, ...) failed: %d", handle, error);return error;}if (flexLayout.format != FLEX_FORMAT_YCbCr) {ALOGV("Unable to convert flex-format buffer to YCbCr");unlock(handle);return GRALLOC1_ERROR_UNSUPPORTED;}// Find planesauto yPlane = planes.cend();auto cbPlane = planes.cend();auto crPlane = planes.cend();for (auto planeIter = planes.cbegin(); planeIter != planes.cend();++planeIter) {if (planeIter->component == FLEX_COMPONENT_Y) {yPlane = planeIter;} else if (planeIter->component == FLEX_COMPONENT_Cb) {cbPlane = planeIter;} else if (planeIter->component == FLEX_COMPONENT_Cr) {crPlane = planeIter;}}if (yPlane == planes.cend()) {ALOGV("Unable to find Y plane");unlock(handle);return GRALLOC1_ERROR_UNSUPPORTED;}if (cbPlane == planes.cend()) {ALOGV("Unable to find Cb plane");unlock(handle);return GRALLOC1_ERROR_UNSUPPORTED;}if (crPlane == planes.cend()) {ALOGV("Unable to find Cr plane");unlock(handle);return GRALLOC1_ERROR_UNSUPPORTED;}// Validate planesif (!isValidYCbCrPlane(*yPlane)) {ALOGV("Y plane is invalid");unlock(handle);return GRALLOC1_ERROR_UNSUPPORTED;}if (!isValidYCbCrPlane(*cbPlane)) {ALOGV("Cb plane is invalid");unlock(handle);return GRALLOC1_ERROR_UNSUPPORTED;}if (!isValidYCbCrPlane(*crPlane)) {ALOGV("Cr plane is invalid");unlock(handle);return GRALLOC1_ERROR_UNSUPPORTED;}if (cbPlane->v_increment != crPlane->v_increment) {ALOGV("Cb and Cr planes have different step (%d vs. %d)",cbPlane->v_increment, crPlane->v_increment);unlock(handle);return GRALLOC1_ERROR_UNSUPPORTED;}if (cbPlane->h_increment != crPlane->h_increment) {ALOGV("Cb and Cr planes have different stride (%d vs. %d)",cbPlane->h_increment, crPlane->h_increment);unlock(handle);return GRALLOC1_ERROR_UNSUPPORTED;}// Pack plane data into android_ycbcr structycbcr->y = yPlane->top_left;ycbcr->cb = cbPlane->top_left;ycbcr->cr = crPlane->top_left;ycbcr->ystride = static_cast<size_t>(yPlane->v_increment);ycbcr->cstride = static_cast<size_t>(cbPlane->v_increment);ycbcr->chroma_step = static_cast<size_t>(cbPlane->h_increment);return error;
}status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd)
{ATRACE_CALL();sp<Fence> fence = Fence::NO_FENCE;gralloc1_error_t error = mDevice->unlock(handle, &fence);if (error != GRALLOC1_ERROR_NONE) {ALOGE("unlock(%p) failed: %d", handle, error);return error;}*fenceFd = fence->dup();return error;
}

lock 时,需要以 Rect 的形式给 GraphicBufferMapper 传入 lock 的区域,这个区域会被做一个转换。GraphicBufferMapper 通过 Gralloc1::Device 执行 lock 操作。并将 lock 的结果,也就是映射到应用程序进程的虚拟地址空间的图形内存块的地址通过传入的 vaddr 返回给调用者。

像素数据格式有 RGB 和 YUV 之分,在 lock YUV 图形内存块时,如果设备支持 GRALLOC1_CAPABILITY_ON_ADAPTER,会直接通过 Gralloc1::Device 完成操作;否则,通过 Gralloc1::DevicelockFlex() 完成操作。

这里的 fence 是什么,用来做什么的?

Done.

Android OpenGL 图形系统分析系列文章

在 Android 中使用 OpenGL
Android 图形驱动初始化
EGL Context 创建
Android 图形系统之图形缓冲区分配
Android 图形系统之gralloc

Android 图形系统之图形缓冲区分配相关推荐

  1. Android 图形系统之gralloc

    Gralloc1::Loader 与 gralloc 模块加载 Gralloc1::Loader 用于加载 HAL gralloc 模块.其类定义(位于 frameworks/native/inclu ...

  2. Android图形系统之HWComposer

    Android图形系统之HWComposer 1.HWC 1.1 HWC作用 1.2 Overlay 1.3HWC实现 1.4 HWC功能 1.5 HWC效率 1.6 Compose方式 2.Fenc ...

  3. Android图形系统篇总结摘要

    Android图形系统学习框架:Android图形系统 简单总结下Activity启动后布局显示过程: SurfaceFlinger 是在init.rc解析的时候被创建的,执行其main方法,实例化了 ...

  4. Android 图形系统

    Android framework 为2D 和 3D 提供了各种各样的图形渲染 APIs 来与设备制造商的图形驱动实现交互,因此对于那些 API 在上层如何工作有一个好的理解非常重要.这一页介绍驱动基 ...

  5. 一篇文章看明白 Android 图形系统 Surface 与 SurfaceFlinger 之间的关系

    Android - SurfaceFlinger 图形系统 相关系列 一篇文章看明白 Android 系统启动时都干了什么 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制 一篇文 ...

  6. android studio 显示图形_显示服务器实现(一)

    在一个多窗口的图形化操作系统中,显示服务器的任务就是组织这些窗口展现给用户.实际的显示服务器有Linux世界基于X11协议的XServer或者Wayland协议的Weston,还有Android里的S ...

  7. Android 源码 图形系统概述

    Android 框架提供了各种用于 2D 和 3D 图形渲染的 API,可与制造商的图形驱动程序实现方法交互.应用开发者可通过三种方式将图像绘制到屏幕上:使用 Canvas.OpenGL ES 或 V ...

  8. 安卓高手之路之 图形系统之 图形框架(1)

    安卓图形系统理解起来并不容易.那是因为系统对于数据的封装非常多,图形模块与输入输出,应用程序管理等模块参杂在一起.让开发者很难摸清其中的脉络.下面先给出最简单的一张图.             这张图 ...

  9. android 特效绘图,Android绘图机制与处理技巧——Android图像处理之图形特效处理...

    Android变形矩阵--Matrix 对于图像的图形变换,Android系统是通过矩阵来进行处理的,每个像素点都表达了其坐标的X.Y信息.Android的图形变换矩阵是一个3x3的矩阵,如下图所示: ...

最新文章

  1. 美国本科计算机专业,美国本科计算机专业的最新排名介绍
  2. android图片的处理方法,android 处理图片到固定像素解决办法
  3. 什么是工装服_王俊凯穿连体工装亮相跨年晚会,中国风满满的设计,尽显帅气...
  4. JavaFX学习之道:JavaFX之TableView
  5. 调试JavaScript/VB Script脚本程序(ASP篇)
  6. c语言将字母的acsaii,C语言上机实验 答案
  7. 数学建模4 论文写作排版和技巧
  8. 入门机器学习(六)--课后作业解析-logistics回归(python实现)
  9. 【信仰充值中心】Firefox 96 后续更新一览
  10. “超人”助阵,IE静音很简单
  11. 反转链表 Reverse Linked List
  12. cnBlog的windows live writer 客户端配置
  13. android 合并数组
  14. Windows 10中检查已安装编解码器的几个方法
  15. Windows常用cmd命令总结
  16. MyBatis入门+概述
  17. 【数学模拟卷总结】2022李林四套卷数学二第一套
  18. js实现——鼠标单击事件-onclick和双击事件-ondblclick
  19. ps如何把自己的图与样机结合_如何利用PS制作贴图样机那
  20. 都 要 悠 着 点 呀~~

热门文章

  1. 格式化输出字符串变量
  2. 魔兽服务器状态页面,谁动了我的服务器 WOW大服务器优势何时展现
  3. 全国计算机一级d类考试内容,全国计算机一级考试WPS office复习题及答案2017
  4. redis(10)--RDB持久化
  5. ncbi查找目的基因序列_教你如何利用NCBI寻找目的基因
  6. error:cannot load driver JL2CM3.dll
  7. 全国首家工资总额负面清单管理试点企业获批
  8. mongo数据库单节点搭建
  9. 解决报错:import sun.misc.BASE64Decoder无法找到
  10. 阿里云容器服务与ASP.NET Core部署:用 docker secrets 保存 appsettings.Production.json