【Android】Android(安卓)SurfaceFlinger之BufferQueue
在Android中,BufferQueue是Surface实现本地窗口的关键,驻留在SurfaceFlinger进程中进行服务,下面从BufferQueue的结构开始分析。
1、BufferQueue模式
BufferQueue相关的源码在frameworks/native/libs/gui/,涉及以下几个重要的数据结构:
class BufferQueue;class BufferQueueCore;class BufferQueueProducer;class BufferQueueConsumer;
BufferQueue属于典型的生产者-消费者模式,还有个表示buffer状态的BufferState,共五种状态,分别为FREE、DEQUEUED、QUEUED、ACQUIRED和SHARED。FREE表示buffer可以被Producer进行dequeue,此时buffer属于BufferQueue,当dequeue buffer时,状态变为DEQUEUED;DEQUEUED表示buffer已经被Producer dequeued,但还没有被queued和canceled,当收到相关的release fence通知时,Producer还可以修改buffer的数据,此时buffer属于Producer,当queue或attach buffer时,状态变为QUEUED,当cancel或detach buffer时,状态又变回FREE;QUEUED表示Producer填充了buffer且被Consumer queued,buffer数据仍有可能被修改,与fence信号相关,此时buffer属于BufferQueue,当acquire buffer时,状态变为ACQUIRED,当其它的异步buffer变为QUEUED时,这个buffer则变为FREE;ACQUIRED表示buffer被Consumer acquired,buffer数据仍有可能被修改,与fence信号相关,此时buffer属于Consumer,当release或detach buffer时,状态变为FREE,如果buffer datach后又进行了attach,其状态又会变为ACQUIRED;SHARED表示buffer为共享模式,同时可以是除FREE之外的其它任何状态,还可以被多次dequeud、queued和acquired。
在buffer的几个状态中,涉及Producer和Consumer,而它们的交互必须通过BufferQueue这个管理者或中介才能完成。Producer一般为应用程序,会不断地给buffer填充数据,不过首先要向BufferQueue进行dequeue以申请一块buffer,此时buffer为其所有,填充好数据之后再向BufferQueue进行queue,把控制权还给BufferQueue,这些操作都是由Producer主动发起的。而Consumer是被动的,当buffer数据准备好后才被通知进行消费,这个通知是被BufferQueue发起的,BufferQueue就是一个服务机构,其内部有个ProxyConsumerListener,当buffer数据就绪后就会通知Consumer进行消费。
2、BufferQueue缓冲分配过程
全局上下并无BufferQueue实例,只是声明了private BufferQueue构造函数而没有实现,其实也用不到,通过其static函数createBufferQueue实现,分别创建了BufferQueueCore、BufferQueueProducer和BufferQueueConsumer,其中BufferQueueCore作为参数传给了BufferQueueProducer和BufferQueueConsumer,如下所示:
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;}
BufferQueueCore是管理BufferQueue的核心类,有如下两个重要的成员变量,mAllocator与SurfaceFlinger关联,用来创建GraphicBuffer,mSlots用于存储buffer数据,支持64个buffer,其中的BufferSlot存储了GraphicBuffer和BufferState。
sp mAllocator;BufferQueueDefs::SlotsType mSlots;namespace BufferQueueDefs { enum { NUM_BUFFER_SLOTS = 64 }; typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];} 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 mGraphicBuffer; EGLDisplay mEglDisplay; BufferState mBufferState; bool mRequestBufferCalled; uint64_t mFrameNumber; EGLSyncKHR mEglFence; sp mFence; bool mAcquireCalled; bool mNeedsReallocation;};
上面提到了buffer分配由生产者发起,即BufferQueueProducer的deququeBuffer操作,函数原型如下:
status_t BufferQueueProducer::dequeueBuffer(int *outSlot, sp *outFence, uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) { ATRACE_CALL(); { // Autolock scope 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; } } // Autolock scope BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#x", 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; { // Autolock scope Mutex::Autolock lock(mCore->mMutex); mCore->waitWhileAllocatingLocked(); if (format == 0) { format = mCore->mDefaultBufferFormat; } // Enable the usage bits the consumer requested 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; } // This should not happen if (found == BufferQueueCore::INVALID_BUFFER_SLOT) { BQ_LOGE("dequeueBuffer: no available buffer slots"); return -EBUSY; } const sp& buffer(mSlots[found].mGraphicBuffer); // If we are not allowed to allocate new buffers, // waitForFreeSlotThenRelock must have returned a slot containing a // buffer. If this buffer would require reallocation to meet the // requested attributes, we free it and attempt to get another one. if (!mCore->mAllowAllocation) { if (buffer->needsReallocation(width, height, format, usage)) { if (mCore->mSharedBufferSlot == found) { BQ_LOGE("dequeueBuffer: cannot re-allocate a shared" "buffer"); return BAD_VALUE; } mCore->mFreeSlots.insert(found); mCore->clearBufferSlotLocked(found); found = BufferItem::INVALID_BUFFER_SLOT; continue; } } } const sp& buffer(mSlots[found].mGraphicBuffer); if (mCore->mSharedBufferSlot == found && buffer->needsReallocation(width, height, format, 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, 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 { // We add 1 because that will be the frame number when this buffer // is queued 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; // Don't return a fence in shared buffer mode, except for the first // frame. *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 shared buffer mode has just been enabled, cache the slot of the // first buffer that is dequeued and mark it as the shared buffer. if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == BufferQueueCore::INVALID_BUFFER_SLOT) { mCore->mSharedBufferSlot = found; mSlots[found].mBufferState.mShared = true; } } // Autolock scope if (returnFlags & BUFFER_NEEDS_REALLOCATION) { status_t error; BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot); sp graphicBuffer(mCore->mAllocator->createGraphicBuffer( width, height, format, usage, {mConsumerName.string(), mConsumerName.size()}, &error)); { // Autolock scope Mutex::Autolock lock(mCore->mMutex); if (graphicBuffer != NULL && !mCore->mIsAbandoned) { graphicBuffer->setGenerationNumber(mCore->mGenerationNumber); mSlots[*outSlot].mGraphicBuffer = graphicBuffer; } mCore->mIsAllocating = false; mCore->mIsAllocatingCondition.broadcast(); if (graphicBuffer == NULL) { 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(); } // Autolock scope } if (attachedByConsumer) { returnFlags |= BUFFER_NEEDS_REALLOCATION; } if (eglFence != EGL_NO_SYNC_KHR) { EGLint result = eglClientWaitSyncKHR(eglDisplay, eglFence, 0, 1000000000); // If something goes wrong, log the error, but return the buffer without // synchronizing access to it. It's too late at this point to abort the // dequeue operation. 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); return returnFlags;}
deququeBuffer的目的就是给Producer申请一个可用的buffer,最终获取的是buffer slots数组索引,通过outSlot参数返回,outFence是一种同步形式,当使用Fence时,必须等待Fence信号才能修改buffer,width和height参数有一定的限制,最大值不能超过GL_MAX_VIEWPORT_DIMS和GL_MAX_TEXTURE_SIZE的最小值,这个值可通过glGetIntegerv获取,与updateTexImage有关,width和height都为0时就使用默认值1,如果其中一个为0将出错,format和usage用来指定buffer的格式和用途,format为0时使用默认的mDefaultBufferFormat,即PIXEL_FORMAT_RGBA_8888。
在deququeBuffer函数中,首先会检查BufferQueue是否可用,BufferQueue是否连接了Producer,width和height参数是否合法,失败时出错返回。然后进入while循环查找可用的buffer slot,不过在此之前还要处理一下width、height、format和usage变量,如果有其它的buffer分配操作还要等待其结束,使用的是pthread条件变量。在while循环中查找可用的buffer slot时,首先会进入waitForFreeSlotThenRelock,从名字就可以看出是用来获取FREE状态的buffer slot,同时还会统计buffer的DEQUEUEED和ACQUIRED状态的个数,不能超过限制的最大值,而且还不能频繁地disconect后马上connect,这可能会用尽内存,在等待buffer期间,是否阻塞、延时效果都将影响buffer查询结果。在获取buffer slot成功后,实际上是buffer slot的数组索引,这时还没有真正地分配内存,当我们没有权限分配新的buffer时,这一步通常会返回一个可用的buffer,但是需要注意的是,这个buffer有时候还不是最优的,还需要进行重分配,在这种清空下,这个buffer就会被free掉然后等待后面的重分配。while循环之后,若buffer需要重新分配,就通过createGraphicBuffer完成,至此,dequeueBuffer完成。
dequeueBuffer时获取到的是一个buffer slot索引,那么如何保证属于不同进程的服务端和客户端访问的是同一块内存呢,这就用到了Android中的Binder机制,涉及下面几个相关的类:
class BufferQueueProducer : public BnGraphicBufferProducer, private IBinder::DeathRecipientclass BnGraphicBufferProducer : public BnInterfaceclass BpGraphicBufferProducer : public BpInterface
下面是BpGraphicBufferProducer的dequeueBuffer实现,关键是通过remote调用transact,这时就会走到native的BnGraphicBufferProducer的onTransact。
virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); data.writeUint32(width); data.writeUint32(height); data.writeInt32(static_cast<int32_t>(format)); data.writeUint32(usage); status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply); if (result != NO_ERROR) { return result; } *buf = reply.readInt32(); bool nonNull = reply.readInt32(); if (nonNull) { *fence = new Fence(); result = reply.read(**fence); if (result != NO_ERROR) { fence->clear(); return result; } } result = reply.readInt32(); return result; }
下面是BnGraphicBufferProducer的onTransact的部分代码,在DEQUEUE_BUFFER时,从data获取参数,然后调用buffer生产者的dequeueBuffer,随后把结果回传到reply参数。
status_t BnGraphicBufferProducer::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ switch(code) { case DEQUEUE_BUFFER: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); uint32_t width = data.readUint32(); uint32_t height = data.readUint32(); PixelFormat format = static_cast<PixelFormat>(data.readInt32()); uint32_t usage = data.readUint32(); int buf = 0; sp<Fence> fence; int result = dequeueBuffer(&buf, &fence, width, height, format, usage); reply->writeInt32(buf); reply->writeInt32(fence != NULL); if (fence != NULL) { reply->write(*fence); } reply->writeInt32(result); return NO_ERROR; } } return BBinder::onTransact(code, data, reply, flags);}
在IGraphicBufferProducer中,还有两个struct,QueueBufferInput和QueueBufferOutput如下所示,其中QueueBufferInput使用了Flattenable协议,用于对一个对象即buffer进形数字化。
struct QueueBufferInput : public Flattenablestruct QueueBufferOutput
3、应用程序与BufferQueue
前面介绍了BufferQueue的基本原理,那么它是如何与应用程序联系起来的呢?以frameworks/base/cmds/bootanimation/这个系统开机动画为例,bootanimation和SurfaceFlinger都是使用OpenGL ES来完成UI显示的,当一个Android设备上电后,可能会显示几个不同的开机画面,如BootLoader画面、Kernel画面、Android画面等,bootanim.rc启动脚本内容如下:
service bootanim /system/bin/bootanimation class core user graphics group graphics audio disabled oneshot writepid /dev/stune/top-app/tasks
bootanimation启动后,首先进入如下的main函数,通过属性debug.sf.nobootanimation判断有无启动动画,有动画时,启动一个线程池,然后创建一个BootAnimation对象并加入线程池。
int main(){ setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY); char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.nobootanimation", value, "0"); int noBootAnimation = atoi(value); ALOGI_IF(noBootAnimation, "boot animation disabled"); if (!noBootAnimation) { sp proc(ProcessState::self()); ProcessState::self()->startThreadPool(); // create the boot animation object sp boot = new BootAnimation(); IPCThreadState::self()->joinThreadPool(); } return 0;}
BootAnimation是启动动画的实现类,继承了Thread和Binder,在构造函数中创建了SurfaceComposerClient对象,即mSession,从而建立与SurfaceFlinger的连接通道,而前面提到的IGraphicBufferProducer则是应用程序与BufferQueue的传输通道,BufferQueue负责每个应用程序的绘画过程,SurfaceFlinger把所有应用程序的最终绘图结果混合后统一显示到物理屏幕上。
class BootAnimation : public Thread, public IBinder::DeathRecipientBootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), mTimeCheckThread(NULL) { mSession = new SurfaceComposerClient(); // If the system has already booted, the animation is not being used for a boot. mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0);}
BootAnimation继承子RefBase,当其指针被第一次引用时触发onFirstRef函数,与远程Binder服务建立连接后还要处理Binder服务挂掉的清空,通过重装binderDied函数完成,然后调用run启动BootAnimation线程。
void BootAnimation::onFirstRef() { status_t err = mSession->linkToComposerDeath(this); ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err)); if (err == NO_ERROR) { run("BootAnimation", PRIORITY_DISPLAY); }}void BootAnimation::binderDied(const wp<IBinder>&){ // woah, surfaceflinger died! ALOGD("SurfaceFlinger died, exiting..."); // calling requestExit() is not enough here because the Surface code // might be blocked on a condition variable that will never be updated. kill( getpid(), SIGKILL ); requestExit(); audioplay::destroy();}
接下来便是readyToRun,关键两步是通过SurfaceComposerClient创建buffer和EGL配置,如下代码所示:
status_t BootAnimation::readyToRun() { mAssets.addDefaultAssets(); sp dtoken(SurfaceComposerClient::getBuiltInDisplay( ISurfaceComposer::eDisplayIdMain)); DisplayInfo dinfo; status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo); if (status) return -1; // create the native surface sp control = session()->createSurface(String8("BootAnimation"), dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565); SurfaceComposerClient::openGlobalTransaction(); control->setLayer(0x40000000); SurfaceComposerClient::closeGlobalTransaction(); sp s = control->getSurface(); // initialize opengl and egl const EGLint attribs[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 0, EGL_NONE }; EGLint w, h; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, 0, 0); eglChooseConfig(display, attribs, &config, 1, &numConfigs); surface = eglCreateWindowSurface(display, config, s.get(), NULL); context = eglCreateContext(display, config, NULL, NULL); eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) return NO_INIT; mDisplay = display; mContext = context; mSurface = surface; mWidth = w; mHeight = h; mFlingerSurfaceControl = control; mFlingerSurface = s; // If the device has encryption turned on or is in process // of being encrypted we show the encrypted boot animation. char decrypt[PROPERTY_VALUE_MAX]; property_get("vold.decrypt", decrypt, ""); bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt); if (encryptedAnimation && (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) { mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE; } else if (access(OEM_BOOTANIMATION_FILE, R_OK) == 0) { mZipFileName = OEM_BOOTANIMATION_FILE; } else if (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) { mZipFileName = SYSTEM_BOOTANIMATION_FILE; } return NO_ERROR;}
SurfaceComposerClient的createSurface,在SurfaceFlinger端的实现便是Client中的createSurface,如下:
status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp* handle, sp* gbp){ /* * createSurface must be called from the GL thread so that it can * have access to the GL context. */ class MessageCreateLayer : public MessageBase { SurfaceFlinger* flinger; Client* client; sp* handle; sp* gbp; status_t result; const String8& name; uint32_t w, h; PixelFormat format; uint32_t flags; public: MessageCreateLayer(SurfaceFlinger* flinger, const String8& name, Client* client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp* handle, sp* gbp) : flinger(flinger), client(client), handle(handle), gbp(gbp), result(NO_ERROR), name(name), w(w), h(h), format(format), flags(flags) { } status_t getResult() const { return result; } virtual bool handler() { result = flinger->createLayer(name, client, w, h, format, flags, handle, gbp); return true; } }; sp msg = new MessageCreateLayer(mFlinger.get(), name, this, w, h, format, flags, handle, gbp); mFlinger->postMessageSync(msg); return static_cast( msg.get() )->getResult();}
Client::createSurface中,以同步方式把消息post到SurfaceFlinger,期间还创建了Layer,如下的createNormalLayer:
status_t SurfaceFlinger::createLayer( const String8& name, const sp& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp* handle, sp* gbp){ //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string()); 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; switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceNormal: result = createNormalLayer(client, name, w, h, flags, format, handle, gbp, &layer); break; case ISurfaceComposerClient::eFXSurfaceDim: result = createDimLayer(client, name, w, h, flags, handle, gbp, &layer); break; default: result = BAD_VALUE; break; } if (result != NO_ERROR) { return result; } result = addClientLayer(client, *handle, *gbp, layer); if (result != NO_ERROR) { return result; } setTransactionFlags(eTransactionNeeded); return result;}
从SurfaceFlinger::createNormalLayer可以看出,在这里真正的创建了一个Layer对象,同时创建了BufferQueue和SurfaceFlingerConsumer以及MonitorProducer,这样Buffer中介、生产者、消费者创建完成,Layer就像是许多画面中的一层,最后通过SurfaceFlinger进行处理以显示到屏幕上。
status_t SurfaceFlinger::createNormalLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, sp* handle, sp* gbp, sp* 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; } *outLayer = new Layer(this, client, name, w, h, flags); status_t err = (*outLayer)->setBuffers(w, h, format, flags); if (err == NO_ERROR) { *handle = (*outLayer)->getHandle(); *gbp = (*outLayer)->getProducer(); } ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err)); return err;}
至此,buffer创建完成,EGL配置完成,然后进入threadLoop,接着可能为android或movie,里面全是一些OpenGL操作以显示动画,最后通过EGL释放资源,退出线程池。
bool BootAnimation::threadLoop(){ bool r; // We have no bootanimation file, so we use the stock android logo // animation. if (mZipFileName.isEmpty()) { r = android(); } else { r = movie(); } eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(mDisplay, mContext); eglDestroySurface(mDisplay, mSurface); mFlingerSurface.clear(); mFlingerSurfaceControl.clear(); eglTerminate(mDisplay); eglReleaseThread(); IPCThreadState::self()->stopProcess(); return r;}
更多相关文章
- Android(安卓)SharedPreferences保存登录状态
- android shape的使用
- Android(安卓)Weekly Notes Issue #232
- LGame(Android及J2SE游戏引擎)入门示例——如何构建一个游戏
- Android的电话功能介绍
- android应用 小试牛刀 开发自己的应用程序就是这么简单
- Android(安卓)Power Management
- Gsensor的整个系统架构
- 箭头函数的基础使用