描述图形缓冲区,可能在系统帧缓冲区中分配(数组),也可能在共享内存中分配
struct private_handle_t {
struct native_handle nativeHandle;
enum {
PRIV_FLAGS_FRAMEBUFFER = 0x00000001
};
int fd;
int magic;
int flags;
int size;
int offset;
int base;
int pid;
};
typedef struct native_handle
{
int version;
int numFds;
int numInts;
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wzero-length-array"
#endif
int data[0];
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} native_handle_t;
typedef const native_handle_t* buffer_handle_t;
// native_handle.cpp
static const int kMaxNativeFds = 1024
static const int kMaxNativeInts = 1024
native_handle_t* native_handle_init(char* storage, int numFds, int numInts) {
if ((uintptr_t) storage % alignof(native_handle_t)) {
errno = EINVAL
return NULL
}
native_handle_t* handle = (native_handle_t*) storage
handle->version = sizeof(native_handle_t)
handle->numFds = numFds
handle->numInts = numInts
return handle
}
native_handle_t* native_handle_create(int numFds, int numInts) {
if (numFds < 0 || numInts < 0 || numFds > kMaxNativeFds || numInts > kMaxNativeInts) {
errno = EINVAL
return NULL
}
size_t mallocSize = sizeof(native_handle_t) + (sizeof(int) * (numFds + numInts))
native_handle_t* h = static_cast<native_handle_t*>(malloc(mallocSize))
if (h) {
h->version = sizeof(native_handle_t)
h->numFds = numFds
h->numInts = numInts
}
return h
}
native_handle_t* native_handle_clone(const native_handle_t* handle) {
native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts)
if (clone == NULL) return NULL
for (int i = 0
clone->data[i] = dup(handle->data[i])
if (clone->data[i] == -1) {
clone->numFds = i
native_handle_close(clone)
native_handle_delete(clone)
return NULL
}
}
memcpy(&clone->data[handle->numFds], &handle->data[handle->numFds],
sizeof(int) * handle->numInts)
return clone
}
int native_handle_delete(native_handle_t* h) {
if (h) {
if (h->version != sizeof(native_handle_t)) return -EINVAL
free(h)
}
return 0
}
int native_handle_close(const native_handle_t* h) {
if (h->version != sizeof(native_handle_t)) return -EINVAL
int saved_errno = errno
const int numFds = h->numFds
for (int i = 0
close(h->data[i])
}
errno = saved_errno
return 0
}
gralloc设备和一个fb设备,gralloc设备(申请分配/释放一块图形缓冲区) fb设备(将前面已经准备好了的图形缓冲区渲染到帧缓冲区)
应用进程(SurfaceFlinger)mmap映射gralloc设备分配的图形缓冲区地址,往里填充内容

typedef struct gralloc_module_t {
......
int (*registerBuffer)(struct gralloc_module_t const* module,
buffer_handle_t handle);
int (*unregisterBuffer)(struct gralloc_module_t const* module,
buffer_handle_t handle);
int (*lock)(struct gralloc_module_t const* module,
buffer_handle_t handle, int usage,
int l, int t, int w, int h,
void** vaddr);
int (*unlock)(struct gralloc_module_t const* module,
buffer_handle_t handle);
......
}
gralloc设备
typedef struct alloc_device_t {
struct hw_device_t common;
int (*alloc)(struct alloc_device_t* dev,
int w, int h, int format, int usage,
buffer_handle_t* handle, int* stride);
int (*free)(struct alloc_device_t* dev,
buffer_handle_t handle);
} alloc_device_t;
fb设备描述屏幕设备 帧缓冲区
typedef struct framebuffer_device_t {
struct hw_device_t common;
const uint32_t flags;
const uint32_t width;
const uint32_t height;
const int stride;
const int format;
const float xdpi;
const float ydpi;
const float fps;
const int minSwapInterval;
const int maxSwapInterval;
int reserved[8];
int (*setSwapInterval)(struct framebuffer_device_t* window,
int interval);
int (*setUpdateRect)(struct framebuffer_device_t* window,
int left, int top, int width, int height);
int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer);
int (*compositionComplete)(struct framebuffer_device_t* dev);
void* reserved_proc[8];
} framebuffer_device_t;
SurfaceFlinger通过gralloc申请图形缓冲区(可能来自帧缓冲区的分配/可能来自gralloc共享内存的分配)都是通过mmap映射到SurfaceFlinger进程空间
帧缓冲区backbuffer-frontbuffer
static int gralloc_alloc_buffer(alloc_device_t* dev,
size_t size, int usage, buffer_handle_t* pHandle)
{
int err = 0;
int fd = -1;
size = roundUpToPageSize(size);
fd = ashmem_create_region("gralloc-buffer", size);
if (fd < 0) {
LOGE("couldn't create ashmem (%s)", strerror(-errno));
err = -errno;
}
if (err == 0) {
private_handle_t* hnd = new private_handle_t(fd, size, 0);
gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
dev->common.module);
err = mapBuffer(module, hnd);
if (err == 0) {
*pHandle = hnd;
}
}
LOGE_IF(err, "gralloc failed err=%s", strerror(-err));
return err;
}
int mapBuffer(gralloc_module_t const* module,
private_handle_t* hnd)
{
void* vaddr;
return gralloc_map(module, hnd, &vaddr);
}
int gralloc_register_buffer(gralloc_module_t const* module,
buffer_handle_t handle)
{
if (private_handle_t::validate(handle) < 0)
return -EINVAL;
int err = 0;
private_handle_t* hnd = (private_handle_t*)handle;
if (hnd->pid != getpid()) {
void *vaddr;
err = gralloc_map(module, handle, &vaddr);
}
return err;
}
static int gralloc_map(gralloc_module_t const* module,
buffer_handle_t handle,
void** vaddr)
{
private_handle_t* hnd = (private_handle_t*)handle;
if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
size_t size = hnd->size;
void* mappedAddress = mmap(0, size,
PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
if (mappedAddress == MAP_FAILED) {
LOGE("Could not mmap %s", strerror(errno));
return -errno;
}
hnd->base = intptr_t(mappedAddress) + hnd->offset;
}
*vaddr = (void*)hnd->base;
return 0;
}
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
{
if (private_handle_t::validate(buffer) < 0)
return -EINVAL;
fb_context_t* ctx = (fb_context_t*)dev;
private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
private_module_t* m = reinterpret_cast<private_module_t*>(
dev->common.module);
if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
const size_t offset = hnd->base - m->framebuffer->base;
m->info.activate = FB_ACTIVATE_VBL;
m->info.yoffset = offset / m->finfo.line_length;
if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
LOGE("FBIOPUT_VSCREENINFO failed");
m->base.unlock(&m->base, buffer);
return -errno;
}
m->currentBuffer = buffer;
} else {
void* fb_vaddr;
void* buffer_vaddr;
m->base.lock(&m->base, m->framebuffer,
GRALLOC_USAGE_SW_WRITE_RARELY,
0, 0, m->info.xres, m->info.yres,
&fb_vaddr);
m->base.lock(&m->base, buffer,
GRALLOC_USAGE_SW_READ_RARELY,
0, 0, m->info.xres, m->info.yres,
&buffer_vaddr);
memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
m->base.unlock(&m->base, buffer);
m->base.unlock(&m->base, m->framebuffer);
}
return 0;
}
每个应用可有多个surface,每个surface内容(图形缓冲区(像素内容),SurfaceFlinger负责合成多个应用的多个surface
GraphicBuffer 描述的是图形缓冲区native_handle_t handle
GraphicBuffer(const native_handle_t* handle, HandleWrapMethod method,
uint32_t width, uint32_t height,
PixelFormat format, uint32_t layerCount,
uint32_t usage, uint32_t stride)
: GraphicBuffer(handle, method, width, height, format, layerCount,
static_cast<uint64_t>(usage), stride) {}
核心点(应用如何将每个surface画面像素内容传输到SurfaceFlinger)
binder + mmap
class ISurfaceComposerClient : public IInterface
{
public:
......
virtual sp<ISurface> createSurface( surface_data_t* data,
int pid,
const String8& name,
DisplayID display,
uint32_t w,
uint32_t h,
PixelFormat format,
uint32_t flags) = 0;
......
};
应用创建本地层surface
sp<SurfaceControl> SurfaceComposerClient::createSurface(
const String8& name,
uint32_t w,
uint32_t h,
PixelFormat format,
uint32_t flags,
SurfaceControl* parent,
int32_t windowType,
int32_t ownerUid)
{
sp<SurfaceControl> s;
createSurfaceChecked(name, w, h, format, &s, flags, parent, windowType, ownerUid);
return s;
}
status_t SurfaceComposerClient::createSurfaceChecked(
const String8& name,
uint32_t w,
uint32_t h,
PixelFormat format,
sp<SurfaceControl>* outSurface,
uint32_t flags,
SurfaceControl* parent,
int32_t windowType,
int32_t ownerUid)
{
sp<SurfaceControl> sur;
status_t err = mStatus;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IBinder> parentHandle;
sp<IGraphicBufferProducer> gbp;
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
err = mClient->createSurface(name, w, h, format, flags, parentHandle,
windowType, ownerUid, &handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
*outSurface = new SurfaceControl(this, handle, gbp, true );
}
}
return err;
}
SurfaceControl::SurfaceControl(
const sp<SurfaceComposerClient>& client,
const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbp,
bool owned)
: mClient(client), mHandle(handle), mGraphicBufferProducer(gbp), mOwned(owned)
{
}
void SurfaceControl::writeToParcel(Parcel* parcel)
{
parcel->writeStrongBinder(ISurfaceComposerClient::asBinder(mClient->getClient()));
parcel->writeStrongBinder(mHandle);
parcel->writeStrongBinder(IGraphicBufferProducer::asBinder(mGraphicBufferProducer));
}
sp<Surface> SurfaceControl::generateSurfaceLocked() const
{
mSurfaceData = new Surface(mGraphicBufferProducer, false);
return mSurfaceData;
}
sp<Surface> SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
return generateSurfaceLocked();
}
return mSurfaceData;
}
SurfaceFlinger 提供给应用的本地binder服务 Client.cpp
status_t Client::createSurface(
const String8& name,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
const sp<IBinder>& parentHandle, int32_t windowType, int32_t ownerUid,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp)
{
sp<Layer> parent = nullptr;
if (parentHandle != nullptr) {
auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
parent = layerHandle->owner.promote();
if (parent == nullptr) {
return NAME_NOT_FOUND;
}
}
if (parent == nullptr) {
bool parentDied;
parent = getParentLayer(&parentDied);
if (parentDied) {
return NAME_NOT_FOUND;
}
}
class MessageCreateLayer : public MessageBase {
SurfaceFlinger* flinger;
Client* client;
sp<IBinder>* handle;
sp<IGraphicBufferProducer>* gbp;
status_t result;
const String8& name;
uint32_t w, h;
PixelFormat format;
uint32_t flags;
sp<Layer>* parent;
int32_t windowType;
int32_t ownerUid;
public:
MessageCreateLayer(SurfaceFlinger* flinger,
const String8& name, Client* client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle, int32_t windowType, int32_t ownerUid,
sp<IGraphicBufferProducer>* gbp,
sp<Layer>* parent)
: flinger(flinger), client(client),
handle(handle), gbp(gbp), result(NO_ERROR),
name(name), w(w), h(h), format(format), flags(flags),
parent(parent), windowType(windowType), ownerUid(ownerUid) {
}
status_t getResult() const { return result; }
virtual bool handler() {
result = flinger->createLayer(name, client, w, h, format, flags,
windowType, ownerUid, handle, gbp, parent);
return true;
}
};
sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
name, this, w, h, format, flags, handle,
windowType, ownerUid, gbp, &parent);
mFlinger->postMessageSync(msg);
return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}
status_t SurfaceFlinger::createLayer(
const String8& name,
const sp<Client>& client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
{
if (int32_t(w|h) < 0) {
ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
int(w), int(h));
return BAD_VALUE;
}
status_t result = NO_ERROR;
sp<Layer> layer;
String8 uniqueName = getUniqueLayerName(name);
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceColor:
result = createColorLayer(client,
uniqueName, w, h, flags,
handle, &layer);
break;
default:
result = BAD_VALUE;
break;
}
if (result != NO_ERROR) {
return result;
}
if (windowType == 441731) {
windowType = 2024;
layer->setPrimaryDisplayOnly();
}
layer->setInfo(windowType, ownerUid);
result = addClientLayer(client, *handle, *gbp, layer, *parent);
if (result != NO_ERROR) {
return result;
}
mInterceptor->saveSurfaceCreation(layer);
setTransactionFlags(eTransactionNeeded);
return result;
}
status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
// initialize the surfaces
switch (format) {
case PIXEL_FORMAT_TRANSPARENT:
case PIXEL_FORMAT_TRANSLUCENT:
format = PIXEL_FORMAT_RGBA_8888
break
case PIXEL_FORMAT_OPAQUE:
format = PIXEL_FORMAT_RGBX_8888
break
}
// 构建一个BufferLayer对象
sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags)
status_t err = layer->setBuffers(w, h, format, flags)
if (err == NO_ERROR) {
*handle = layer->getHandle()
*gbp = layer->getProducer()
*outLayer = layer
}
ALOGE_IF(err, "createBufferLayer() failed (%s)", strerror(-err))
return err
}
BufferLayer
void BufferLayer::onFirstRef() {
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
mConsumer = new BufferLayerConsumer(consumer,
mFlinger->getRenderEngine(), mTextureName, this);
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mConsumer->setContentsChangedListener(this);
mConsumer->setName(mName);
if (mFlinger->isLayerTripleBufferingDisabled()) {
mProducer->setMaxDequeuedBufferCount(2);
}
const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
updateTransformHint(hw);
}
sp<IBinder> Layer::getHandle() {
Mutex::Autolock _l(mLock);
return new Handle(mFlinger, this);
}
sp<IGraphicBufferProducer> BufferLayer::getProducer() const {
return mProducer;
}
BufferQueue

void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) {
LOG_ALWAYS_FATAL_IF(outProducer == NULL,
"BufferQueue: outProducer must not be NULL")
LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
"BufferQueue: outConsumer must not be NULL")
// 建立bufferQueue核心对象BufferQueueCore
sp<BufferQueueCore> core(new BufferQueueCore())
LOG_ALWAYS_FATAL_IF(core == NULL,
"BufferQueue: failed to create BufferQueueCore")
// 图形缓冲区生产者BufferQueueProducer和BufferQueueCore绑定
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger))
LOG_ALWAYS_FATAL_IF(producer == NULL,
"BufferQueue: failed to create BufferQueueProducer")
// 图形缓冲区消费者BufferQueueConsumer和BufferQueueCore绑定
sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core))
LOG_ALWAYS_FATAL_IF(consumer == NULL,
"BufferQueue: failed to create BufferQueueConsumer")
*outProducer = producer
*outConsumer = consumer
}
BufferSlot, 一个bufferLayer 对应一个BufferQueueCore,有64个bufferSlot, 即64个图形缓冲区
namespace BufferQueueDefs {
static constexpr int NUM_BUFFER_SLOTS = 64;
}
namespace BufferQueueDefs {
typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
}
struct BufferState {
BufferState()
: mDequeueCount(0),
mQueueCount(0),
mAcquireCount(0),
mShared(false) {
}
uint32_t mDequeueCount;
uint32_t mQueueCount;
uint32_t mAcquireCount;
bool mShared;
inline bool isFree() const {
return !isAcquired() && !isDequeued() && !isQueued();
}
inline bool isDequeued() const {
return mDequeueCount > 0;
}
inline bool isQueued() const {
return mQueueCount > 0;
}
inline bool isAcquired() const {
return mAcquireCount > 0;
}
inline bool isShared() const {
return mShared;
}
inline void reset() {
*this = BufferState();
}
const char* string() const;
inline void dequeue() {
mDequeueCount++;
}
inline void detachProducer() {
if (mDequeueCount > 0) {
mDequeueCount--;
}
}
inline void attachProducer() {
mDequeueCount++;
}
inline void queue() {
if (mDequeueCount > 0) {
mDequeueCount--;
}
mQueueCount++;
}
inline void cancel() {
if (mDequeueCount > 0) {
mDequeueCount--;
}
}
inline void freeQueued() {
if (mQueueCount > 0) {
mQueueCount--;
}
}
inline void acquire() {
if (mQueueCount > 0) {
mQueueCount--;
}
mAcquireCount++;
}
inline void acquireNotInQueue() {
mAcquireCount++;
}
inline void release() {
if (mAcquireCount > 0) {
mAcquireCount--;
}
}
inline void detachConsumer() {
if (mAcquireCount > 0) {
mAcquireCount--;
}
}
inline void attachConsumer() {
mAcquireCount++;
}
};
struct BufferSlot {
BufferSlot()
: mGraphicBuffer(nullptr),
mEglDisplay(EGL_NO_DISPLAY),
mBufferState(),
mRequestBufferCalled(false),
mFrameNumber(0),
mEglFence(EGL_NO_SYNC_KHR),
mFence(Fence::NO_FENCE),
mAcquireCalled(false),
mNeedsReallocation(false) {
}
sp<GraphicBuffer> mGraphicBuffer;
EGLDisplay mEglDisplay;
BufferState mBufferState;
bool mRequestBufferCalled;
uint64_t mFrameNumber;
EGLSyncKHR mEglFence;
sp<Fence> mFence;
bool mAcquireCalled;
bool mNeedsReallocation;
};
BufferQueueProducer.cpp图形缓冲区生产者本地binder对象
status_t BufferQueueProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
ATRACE_CALL();
BQ_LOGV("requestBuffer: slot %d", slot);
Mutex::Autolock lock(mCore->mMutex);
if (mCore->mIsAbandoned) {
BQ_LOGE("requestBuffer: BufferQueue has been abandoned");
return NO_INIT;
}
if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
return NO_INIT;
}
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
return BAD_VALUE;
} else if (!mSlots[slot].mBufferState.isDequeued()) {
BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
"(state = %s)", slot, mSlots[slot].mBufferState.string());
return BAD_VALUE;
}
mSlots[slot].mRequestBufferCalled = true;
*buf = mSlots[slot].mGraphicBuffer;
return NO_ERROR;
}
status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
uint32_t width, uint32_t height, PixelFormat format,
uint64_t usage, uint64_t* outBufferAge,
FrameEventHistoryDelta* outTimestamps) {
ATRACE_CALL();
{
Mutex::Autolock lock(mCore->mMutex);
mConsumerName = mCore->mConsumerName;
if (mCore->mIsAbandoned) {
BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
return NO_INIT;
}
if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer");
return NO_INIT;
}
}
BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#" PRIx64, width, height, format, usage);
if ((width && !height) || (!width && height)) {
BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
return BAD_VALUE;
}
status_t returnFlags = NO_ERROR;
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
bool attachedByConsumer = false;
{
Mutex::Autolock lock(mCore->mMutex);
mCore->waitWhileAllocatingLocked();
if (format == 0) {
format = mCore->mDefaultBufferFormat;
}
usage |= mCore->mConsumerUsageBits;
const bool useDefaultSize = !width && !height;
if (useDefaultSize) {
width = mCore->mDefaultWidth;
height = mCore->mDefaultHeight;
}
int found = BufferItem::INVALID_BUFFER_SLOT;
while (found == BufferItem::INVALID_BUFFER_SLOT) {
status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue,
&found);
if (status != NO_ERROR) {
return status;
}
if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
BQ_LOGE("dequeueBuffer: no available buffer slots");
return -EBUSY;
}
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
if (!mCore->mAllowAllocation) {
if (buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
if (mCore->mSharedBufferSlot == found) {
BQ_LOGE("dequeueBuffer: cannot re-allocate a sharedbuffer");
return BAD_VALUE;
}
mCore->mFreeSlots.insert(found);
mCore->clearBufferSlotLocked(found);
found = BufferItem::INVALID_BUFFER_SLOT;
continue;
}
}
}
const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
if (mCore->mSharedBufferSlot == found &&
buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage)) {
BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
"buffer");
return BAD_VALUE;
}
if (mCore->mSharedBufferSlot != found) {
mCore->mActiveBuffers.insert(found);
}
*outSlot = found;
ATRACE_BUFFER_INDEX(found);
attachedByConsumer = mSlots[found].mNeedsReallocation;
mSlots[found].mNeedsReallocation = false;
mSlots[found].mBufferState.dequeue();
if ((buffer == NULL) ||
buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage))
{
mSlots[found].mAcquireCalled = false;
mSlots[found].mGraphicBuffer = NULL;
mSlots[found].mRequestBufferCalled = false;
mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
mSlots[found].mFence = Fence::NO_FENCE;
mCore->mBufferAge = 0;
mCore->mIsAllocating = true;
returnFlags |= BUFFER_NEEDS_REALLOCATION;
} else {
mCore->mBufferAge = mCore->mFrameCounter + 1 - mSlots[found].mFrameNumber;
}
BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
mCore->mBufferAge);
if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
"slot=%d w=%d h=%d format=%u",
found, buffer->width, buffer->height, buffer->format);
}
eglDisplay = mSlots[found].mEglDisplay;
eglFence = mSlots[found].mEglFence;
*outFence = (mCore->mSharedBufferMode &&
mCore->mSharedBufferSlot == found) ?
Fence::NO_FENCE : mSlots[found].mFence;
mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
mSlots[found].mFence = Fence::NO_FENCE;
if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
BufferQueueCore::INVALID_BUFFER_SLOT) {
mCore->mSharedBufferSlot = found;
mSlots[found].mBufferState.mShared = true;
}
}
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
width, height, format, BQ_LAYER_COUNT, usage,
{mConsumerName.string(), mConsumerName.size()});
status_t error = graphicBuffer->initCheck();
{
Mutex::Autolock lock(mCore->mMutex);
if (error == NO_ERROR && !mCore->mIsAbandoned) {
graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
}
mCore->mIsAllocating = false;
mCore->mIsAllocatingCondition.broadcast();
if (error != NO_ERROR) {
mCore->mFreeSlots.insert(*outSlot);
mCore->clearBufferSlotLocked(*outSlot);
BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
return error;
}
if (mCore->mIsAbandoned) {
mCore->mFreeSlots.insert(*outSlot);
mCore->clearBufferSlotLocked(*outSlot);
BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
return NO_INIT;
}
VALIDATE_CONSISTENCY();
}
}
if (attachedByConsumer) {
returnFlags |= BUFFER_NEEDS_REALLOCATION;
}
if (eglFence != EGL_NO_SYNC_KHR) {
EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0,
1000000000);
if (result == EGL_FALSE) {
BQ_LOGE("dequeueBuffer: error %#x waiting for fence",
eglGetError());
} else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
BQ_LOGE("dequeueBuffer: timeout waiting for fence");
}
eglDestroySyncKHR(eglDisplay, eglFence);
}
BQ_LOGV("dequeueBuffer: returning slot=%d/%" PRIu64 " buf=%p flags=%#x",
*outSlot,
mSlots[*outSlot].mFrameNumber,
mSlots[*outSlot].mGraphicBuffer->handle, returnFlags);
if (outBufferAge) {
*outBufferAge = mCore->mBufferAge;
}
addAndGetFrameTimestamps(nullptr, outTimestamps);
return returnFlags;
}
int BufferQueueProducer::getFreeBufferLocked() const {
if (mCore->mFreeBuffers.empty()) {
return BufferQueueCore::INVALID_BUFFER_SLOT;
}
int slot = mCore->mFreeBuffers.front();
mCore->mFreeBuffers.pop_front();
return slot;
}
应用层Surface.cpp
// 应用层申请buffer,应用层填充buffer数据
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
ATRACE_CALL()
ALOGV("Surface::dequeueBuffer")
uint32_t reqWidth
uint32_t reqHeight
PixelFormat reqFormat
uint64_t reqUsage
bool enableFrameTimestamps
{
Mutex::Autolock lock(mMutex)
if (mReportRemovedBuffers) {
mRemovedBuffers.clear()
}
reqWidth = mReqWidth ? mReqWidth : mUserWidth
reqHeight = mReqHeight ? mReqHeight : mUserHeight
reqFormat = mReqFormat
reqUsage = mReqUsage
enableFrameTimestamps = mEnableFrameTimestamps
if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot !=
BufferItem::INVALID_BUFFER_SLOT) {
sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer)
if (gbuf != NULL) {
*buffer = gbuf.get()
*fenceFd = -1
return OK
}
}
} // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer
int buf = -1
sp<Fence> fence
nsecs_t startTime = systemTime()
FrameEventHistoryDelta frameTimestamps
// graphicBufferProducer图形缓冲区生产者, 得到空闲bufferSlot数组下标buf
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth, reqHeight,
reqFormat, reqUsage, &mBufferAge,
enableFrameTimestamps ? &frameTimestamps
: nullptr)
mLastDequeueDuration = systemTime() - startTime
if (result < 0) {
ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
"(%d, %d, %d, %
reqWidth, reqHeight, reqFormat, reqUsage, result)
return result
}
if (buf < 0 || buf >= NUM_BUFFER_SLOTS) {
ALOGE("dequeueBuffer: IGraphicBufferProducer returned invalid slot number %d", buf)
android_errorWriteLog(0x534e4554, "36991414")
return FAILED_TRANSACTION
}
Mutex::Autolock lock(mMutex)
// Write this while holding the mutex
mLastDequeueStartTime = startTime
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer)
// this should never happen
ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf)
if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
freeAllBuffers()
}
if (enableFrameTimestamps) {
mFrameEventHistory->applyDelta(frameTimestamps)
}
if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
if (mReportRemovedBuffers && (gbuf != nullptr)) {
mRemovedBuffers.push_back(gbuf)
}
// 根据bufferslot数组下标buf,请求这块GraphicBuffer buffer,返回给gbuf对象
result = mGraphicBufferProducer->requestBuffer(buf, &gbuf)
if (result != NO_ERROR) {
ALOGE("dequeueBuffer: IGraphicBufferProducer::requestBuffer failed: %d", result)
mGraphicBufferProducer->cancelBuffer(buf, fence)
return result
}
}
if (fence->isValid()) {
*fenceFd = fence->dup()
if (*fenceFd == -1) {
ALOGE("dequeueBuffer: error duping fence: %d", errno)
// dup() should never fail
// and hope for the best
// visible corruption that lasts until the next frame.
}
} else {
*fenceFd = -1
}
// 申请获取到的空闲GraphicBuffer对应的android_native_buffer_t,应用层使用填充数据
*buffer = gbuf.get()
if (mSharedBufferMode && mAutoRefresh) {
mSharedBufferSlot = buf
mSharedBufferHasBeenQueued = false
} else if (mSharedBufferSlot == buf) {
mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT
mSharedBufferHasBeenQueued = false
}
return OK
}
status_t Surface::lock(
ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
{
if (mLockedBuffer != 0) {
ALOGE("Surface::lock failed, already locked");
return INVALID_OPERATION;
}
if (!mConnectedToCpu) {
int err = Surface::connect(NATIVE_WINDOW_API_CPU);
if (err) {
return err;
}
setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
}
ANativeWindowBuffer* out;
int fenceFd = -1;
status_t err = dequeueBuffer(&out, &fenceFd);
ALOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));
if (err == NO_ERROR) {
sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
const Rect bounds(backBuffer->width, backBuffer->height);
Region newDirtyRegion;
if (inOutDirtyBounds) {
newDirtyRegion.set(static_cast<Rect const&>(*inOutDirtyBounds));
newDirtyRegion.andSelf(bounds);
} else {
newDirtyRegion.set(bounds);
}
const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
const bool canCopyBack = (frontBuffer != 0 &&
backBuffer->width == frontBuffer->width &&
backBuffer->height == frontBuffer->height &&
backBuffer->format == frontBuffer->format);
if (canCopyBack) {
const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
if (!copyback.isEmpty()) {
copyBlt(backBuffer, frontBuffer, copyback, &fenceFd);
}
} else {
newDirtyRegion.set(bounds);
mDirtyRegion.clear();
Mutex::Autolock lock(mMutex);
for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
mSlots[i].dirtyRegion.clear();
}
}
{
Mutex::Autolock lock(mMutex);
int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
if (backBufferSlot >= 0) {
Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
mDirtyRegion.subtract(dirtyRegion);
dirtyRegion = newDirtyRegion;
}
}
mDirtyRegion.orSelf(newDirtyRegion);
if (inOutDirtyBounds) {
*inOutDirtyBounds = newDirtyRegion.getBounds();
}
void* vaddr;
status_t res = backBuffer->lockAsync(
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
newDirtyRegion.bounds(), &vaddr, fenceFd);
ALOGW_IF(res, "failed locking buffer (handle = %p)",
backBuffer->handle);
if (res != 0) {
err = INVALID_OPERATION;
} else {
mLockedBuffer = backBuffer;
outBuffer->width = backBuffer->width;
outBuffer->height = backBuffer->height;
outBuffer->stride = backBuffer->stride;
outBuffer->format = backBuffer->format;
outBuffer->bits = vaddr;
}
}
return err;
}
status_t Surface::unlockAndPost()
{
if (mLockedBuffer == 0) {
ALOGE("Surface::unlockAndPost failed, no locked buffer");
return INVALID_OPERATION;
}
int fd = -1;
status_t err = mLockedBuffer->unlockAsync(&fd);
ALOGE_IF(err, "failed unlocking buffer (%p)", mLockedBuffer->handle);
err = queueBuffer(mLockedBuffer.get(), fd);
ALOGE_IF(err, "queueBuffer (handle=%p) failed (%s)",
mLockedBuffer->handle, strerror(-err));
mPostedBuffer = mLockedBuffer;
mLockedBuffer = 0;
return err;
}
int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
ATRACE_CALL();
ALOGV("Surface::queueBuffer");
Mutex::Autolock lock(mMutex);
int64_t timestamp;
bool isAutoTimestamp = false;
if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
isAutoTimestamp = true;
ALOGV("Surface::queueBuffer making up timestamp: %.2f ms",
timestamp / 1000000.0);
} else {
timestamp = mTimestamp;
}
int i = getSlotFromBufferLocked(buffer);
if (i < 0) {
if (fenceFd >= 0) {
close(fenceFd);
}
return i;
}
if (mSharedBufferSlot == i && mSharedBufferHasBeenQueued) {
if (fenceFd >= 0) {
close(fenceFd);
}
return OK;
}
Rect crop(Rect::EMPTY_RECT);
mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
static_cast<android_dataspace>(mDataSpace), crop, mScalingMode,
mTransform ^ mStickyTransform, fence, mStickyTransform,
mEnableFrameTimestamps);
input.setHdrMetadata(mHdrMetadata);
if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
input.setSurfaceDamage(Region::INVALID_REGION);
} else {
int width = buffer->width;
int height = buffer->height;
bool rotated90 = (mTransform ^ mStickyTransform) &
NATIVE_WINDOW_TRANSFORM_ROT_90;
if (rotated90) {
std::swap(width, height);
}
Region flippedRegion;
for (auto rect : mDirtyRegion) {
int left = rect.left;
int right = rect.right;
int top = height - rect.bottom;
int bottom = height - rect.top;
switch (mTransform ^ mStickyTransform) {
case NATIVE_WINDOW_TRANSFORM_ROT_90: {
Rect flippedRect{top, width - right, bottom, width - left};
flippedRegion.orSelf(flippedRect);
break;
}
case NATIVE_WINDOW_TRANSFORM_ROT_180: {
Rect flippedRect{width - right, height - bottom,
width - left, height - top};
flippedRegion.orSelf(flippedRect);
break;
}
case NATIVE_WINDOW_TRANSFORM_ROT_270: {
Rect flippedRect{height - bottom, left,
height - top, right};
flippedRegion.orSelf(flippedRect);
break;
}
default: {
Rect flippedRect{left, top, right, bottom};
flippedRegion.orSelf(flippedRect);
break;
}
}
}
input.setSurfaceDamage(flippedRegion);
}
nsecs_t now = systemTime();
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
mLastQueueDuration = systemTime() - now;
if (err != OK) {
ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
}
if (mEnableFrameTimestamps) {
mFrameEventHistory->applyDelta(output.frameTimestamps);
mFrameEventHistory->updateAcquireFence(mNextFrameNumber,
std::make_shared<FenceTime>(std::move(fence)));
mFrameEventHistory->updateSignalTimes();
}
mLastFrameNumber = mNextFrameNumber;
mDefaultWidth = output.width;
mDefaultHeight = output.height;
mNextFrameNumber = output.nextFrameNumber;
if (mStickyTransform == 0) {
mTransformHint = output.transformHint;
}
mConsumerRunningBehind = (output.numPendingBuffers >= 2);
if (!mConnectedToCpu) {
mDirtyRegion = Region::INVALID_REGION;
}
if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot == i) {
mSharedBufferHasBeenQueued = true;
}
mQueueBufferCondition.broadcast();
return err;
}
native_window.h
typedef struct ANativeWindow_Buffer {
int32_t width;
int32_t height;
int32_t stride;
int32_t format;
void* bits;
uint32_t reserved[6];
} ANativeWindow_Buffer;
typedef struct ANativeWindowBuffer
{
#ifdef __cplusplus
ANativeWindowBuffer() {
common.magic = ANDROID_NATIVE_BUFFER_MAGIC;
common.version = sizeof(ANativeWindowBuffer);
memset(common.reserved, 0, sizeof(common.reserved));
}
void incStrong(const void* ) const {
common.incRef(const_cast<android_native_base_t*>(&common));
}
void decStrong(const void* ) const {
common.decRef(const_cast<android_native_base_t*>(&common));
}
#endif
struct android_native_base_t common;
int width;
int height;
int stride;
int format;
int usage_deprecated;
uintptr_t layerCount;
void* reserved[1];
const native_handle_t* handle;
uint64_t usage;
void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
} ANativeWindowBuffer_t;
typedef struct ANativeWindowBuffer ANativeWindowBuffer;
typedef ANativeWindowBuffer_t android_native_buffer_t;
```
// 代理请求接口
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
{
public:
explicit BpGraphicBufferProducer(const sp<IBinder>& impl)
: BpInterface<IGraphicBufferProducer>(impl)
{
}
~BpGraphicBufferProducer() override
virtual status_t requestBuffer(int bufferIdx, sp<GraphicBuffer>* buf) {
Parcel data, reply
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor())
data.writeInt32(bufferIdx)
status_t result =remote()->transact(REQUEST_BUFFER, data, &reply)
if (result != NO_ERROR) {
return result
}
bool nonNull = reply.readInt32()
if (nonNull) {
// 本地新建一个GraphicBuffer对象,reply内容填充该GraphicBuffer
*buf = new GraphicBuffer()
result = reply.read(**buf)
if(result != NO_ERROR) {
(*buf).clear()
return result
}
}
result = reply.readInt32()
return result
}
BufferQueueProducer.cpp 继承BnGraphicBufferProducer
status_t BnGraphicBufferProducer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case REQUEST_BUFFER: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply)
int bufferIdx = data.readInt32()
sp<GraphicBuffer> buffer
// binder端BufferQueueProducer请求到GraphicBuffer
int result = requestBuffer(bufferIdx, &buffer)
reply->writeInt32(buffer != 0)
if (buffer != 0) {
// 将该GraphicBuffer buffer写入parcel reply
reply->write(*buffer)
}
reply->writeInt32(result)
return NO_ERROR
}
case SET_MAX_DEQUEUED_BUFFER_COUNT: {
CHECK_INTERFACE(IGraphicBufferProducer, data, reply)
int maxDequeuedBuffers = data.readInt32()
int result = setMaxDequeuedBufferCount(maxDequeuedBuffers)
reply->writeInt32(result)
return NO_ERROR
}
```
```
class GraphicBuffer
: public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase>,
public Flattenable<GraphicBuffer>
// 写入reply parcel
status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
size_t sizeNeeded = GraphicBuffer::getFlattenedSize()
if (size < sizeNeeded) return NO_MEMORY
size_t fdCountNeeded = GraphicBuffer::getFdCount()
if (count < fdCountNeeded) return NO_MEMORY
int32_t* buf = static_cast<int32_t*>(buffer)
buf[0] = 'GB01'
buf[1] = width
buf[2] = height
buf[3] = stride
buf[4] = format
buf[5] = static_cast<int32_t>(layerCount)
buf[6] = int(usage)
buf[7] = static_cast<int32_t>(mId >> 32)
buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull)
buf[9] = static_cast<int32_t>(mGenerationNumber)
buf[10] = 0
buf[11] = 0
buf[12] = int(usage >> 32)
if (handle) {
buf[10] = int32_t(mTransportNumFds)
buf[11] = int32_t(mTransportNumInts)
memcpy(fds, handle->data, static_cast<size_t>(mTransportNumFds) * sizeof(int))
memcpy(buf + 13, handle->data + handle->numFds,
static_cast<size_t>(mTransportNumInts) * sizeof(int))
}
buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded)
size -= sizeNeeded
if (handle) {
fds += mTransportNumFds
count -= static_cast<size_t>(mTransportNumFds)
}
return NO_ERROR
}
// 应用进程读取数据,mBufferMapper.importBuffer映射地址到应用进程空间,从而共享一块物理内存
status_t GraphicBuffer::unflatten(
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
int const* buf = static_cast<int const*>(buffer)
// NOTE: it turns out that some media code generates a flattened GraphicBuffer manually!!!!!
// see H2BGraphicBufferProducer.cpp
uint32_t flattenWordCount = 0
if (buf[0] == 'GB01') {
// new version with 64-bits usage bits
flattenWordCount = 13
} else if (buf[0] == 'GBFR') {
// old version, when usage bits were 32-bits
flattenWordCount = 12
} else {
return BAD_TYPE
}
const size_t numFds = static_cast<size_t>(buf[10])
const size_t numInts = static_cast<size_t>(buf[11])
// Limit the maxNumber to be relatively small. The number of fds or ints
// should not come close to this number, and the number itself was simply
// chosen to be high enough to not cause issues and low enough to prevent
// overflow problems.
const size_t maxNumber = 4096
if (numFds >= maxNumber || numInts >= (maxNumber - flattenWordCount)) {
width = height = stride = format = usage_deprecated = 0
layerCount = 0
usage = 0
handle = NULL
ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts)
return BAD_VALUE
}
const size_t sizeNeeded = (flattenWordCount + numInts) * sizeof(int)
if (size < sizeNeeded) return NO_MEMORY
size_t fdCountNeeded = numFds
if (count < fdCountNeeded) return NO_MEMORY
if (handle) {
// free previous handle if any
free_handle()
}
if (numFds || numInts) {
width = buf[1]
height = buf[2]
stride = buf[3]
format = buf[4]
layerCount = static_cast<uintptr_t>(buf[5])
usage_deprecated = buf[6]
if (flattenWordCount == 13) {
usage = (uint64_t(buf[12]) << 32) | uint32_t(buf[6])
} else {
usage = uint64_t(usage_deprecated)
}
native_handle* h = native_handle_create(
static_cast<int>(numFds), static_cast<int>(numInts))
if (!h) {
width = height = stride = format = usage_deprecated = 0
layerCount = 0
usage = 0
handle = NULL
ALOGE("unflatten: native_handle_create failed")
return NO_MEMORY
}
memcpy(h->data, fds, numFds * sizeof(int))
memcpy(h->data + numFds, buf + flattenWordCount, numInts * sizeof(int))
handle = h
} else {
width = height = stride = format = usage_deprecated = 0
layerCount = 0
usage = 0
handle = NULL
}
mId = static_cast<uint64_t>(buf[7]) << 32
mId |= static_cast<uint32_t>(buf[8])
mGenerationNumber = static_cast<uint32_t>(buf[9])
mOwner = ownHandle
if (handle != 0) {
buffer_handle_t importedHandle
status_t err = mBufferMapper.importBuffer(handle, uint32_t(width), uint32_t(height),
uint32_t(layerCount), format, usage, uint32_t(stride), &importedHandle)
if (err != NO_ERROR) {
width = height = stride = format = usage_deprecated = 0
layerCount = 0
usage = 0
handle = NULL
ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err)
return err
}
native_handle_close(handle)
native_handle_delete(const_cast<native_handle_t*>(handle))
handle = importedHandle
mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts)
}
buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded)
size -= sizeNeeded
fds += numFds
count -= numFds
return NO_ERROR
}
应用层使用surface申请返回的graphicBuffer, 即如何填充ANativeWindow_Buffer.bits
static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
if (!isSurfaceValid(surface)) {
doThrowIAE(env);
return 0;
}
Rect dirtyRect(Rect::EMPTY_RECT);
Rect* dirtyRectPtr = NULL;
if (dirtyRectObj) {
dirtyRect.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
dirtyRect.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
dirtyRect.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
dirtyRectPtr = &dirtyRect;
}
ANativeWindow_Buffer outBuffer;
status_t err = surface->lock(&outBuffer, dirtyRectPtr);
if (err < 0) {
const char* const exception = (err == NO_MEMORY) ?
OutOfResourcesException :
"java/lang/IllegalArgumentException";
jniThrowException(env, exception, NULL);
return 0;
}
SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
convertPixelFormat(outBuffer.format),
outBuffer.format == PIXEL_FORMAT_RGBX_8888
? kOpaque_SkAlphaType : kPremul_SkAlphaType,
GraphicsJNI::defaultColorSpace());
SkBitmap bitmap;
ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
bitmap.setInfo(info, bpr);
if (outBuffer.width > 0 && outBuffer.height > 0) {
bitmap.setPixels(outBuffer.bits);
} else {
bitmap.setPixels(NULL);
}
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
nativeCanvas->setBitmap(bitmap);
if (dirtyRectPtr) {
nativeCanvas->clipRect(dirtyRect.left, dirtyRect.top,
dirtyRect.right, dirtyRect.bottom, SkClipOp::kIntersect);
}
if (dirtyRectObj) {
env->SetIntField(dirtyRectObj, gRectClassInfo.left, dirtyRect.left);
env->SetIntField(dirtyRectObj, gRectClassInfo.top, dirtyRect.top);
env->SetIntField(dirtyRectObj, gRectClassInfo.right, dirtyRect.right);
env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
}
sp<Surface> lockedSurface(surface);
lockedSurface->incStrong(&sRefBaseOwner);
return (jlong) lockedSurface.get();
}
static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject canvasObj) {
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
if (!isSurfaceValid(surface)) {
return;
}
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
nativeCanvas->setBitmap(SkBitmap());
status_t err = surface->unlockAndPost();
if (err < 0) {
doThrowIAE(env);
}
}
