Android6.0 图像合成过程详解(二) doComposition函数汇总(2)

2018-11-24 18:28

return (status_t)err; }

我们继续看doComposeSurfaces函数,下面这个函数当cur!=end代表起码有两个以上图层,然后遍历图层,当layer是HWC_FRAMEBUFFER代表是需要egl合成的,而HWC_FRAMEBUFFER_TARGET是egl合成后使用的直接就跳了,HWC_CURSOR_OVERLAY和HWC_OVERLAY是用HWC模块(硬件合成)的,也就不用调用Layer的draw方法。而如果图层只要1个或者没有,那么直接使用egl合成。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片 HWComposer::LayerListIterator cur = hwc.begin(id); const HWComposer::LayerListIterator end = hwc.end(id); ......

const Vector< sp >& layers(hw->getVisibleLayersSortedByZ()); const size_t count = layers.size();

const Transform& tr = hw->getTransform(); if (cur != end) { //代表起码有两个以上图层 // we're using h/w composer

for (size_t i=0 ; i& layer(layers[i]);

const Region clip(dirty.intersect(tr.transform(layer->visibleRegion))); if (!clip.isEmpty()) {

switch (cur->getCompositionType()) { case HWC_CURSOR_OVERLAY: case HWC_OVERLAY: {

const Layer::State& state(layer->getDrawingState()); if ((cur->getHints() & HWC_HINT_CLEAR_FB) && i

&& layer->isOpaque(state) && (state.alpha == 0xFF) && hasGlesComposition) {

// never clear the very first layer since we're // guaranteed the FB is already cleared layer->clearWithOpenGL(hw, clip); }

break; }

case HWC_FRAMEBUFFER: {

layer->draw(hw, clip);//只有是HWC_FRAMEBUFFER才会调用Layer的draw合成

break; }

case HWC_FRAMEBUFFER_TARGET: {

// this should not happen as the iterator shouldn't // let us get there.

ALOGW(\found in hwc list

(index=%zu)\

break; } } }

layer->setAcquireFence(hw, *cur); } } else {

// we're not using h/w composer

for (size_t i=0 ; i

const sp& layer(layers[i]); const Region clip(dirty.intersect(

tr.transform(layer->visibleRegion))); if (!clip.isEmpty()) {

layer->draw(hw, clip); } } }

// disable scissor at the end of the frame engine.disableScissor(); return true; }

Layer的draw我们就不看了主要是使用egl合成纹理,但是有一点疑问,我们从来没有把layer中的mActiveBuffer放到egl中去,那么egl又是怎么合成各个layer的呢,我想肯定客户进程在绘制各个layer的时候,也是用egl绘制的,所有后面合成的时候egl有各个layer的buffer。

后面我们再来看下DisplayDevice::swapBuffers函数,是使用eglSwapBuffers来把egl合成的数据放到mSurface中去。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 void DisplayDevice::swapBuffers(HWComposer& hwc) const { // We need to call eglSwapBuffers() if:

// (1) we don't have a hardware composer, or

// (2) we did GLES composition this frame, and either

// (a) we have framebuffer target support (not present on legacy // devices, where HWComposer::commit() handles things); or // (b) this is a virtual display if (hwc.initCheck() != NO_ERROR ||

(hwc.hasGlesComposition(mHwcDisplayId) &&

(hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) { EGLBoolean success = eglSwapBuffers(mDisplay, mSurface); if (!success) {

EGLint error = eglGetError();

if (error == EGL_CONTEXT_LOST ||

mType == DisplayDevice::DISPLAY_PRIMARY) {

LOG_ALWAYS_FATAL(\ mDisplay, mSurface, error); } else {

ALOGE(\ mDisplay, mSurface, error); } } }

else if(hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL) {

EGLBoolean success = eglSwapBuffersVIV(mDisplay, mSurface); if (!success) {

EGLint error = eglGetError();

ALOGE(\ mDisplay, mSurface, error); } }

status_t result = mDisplaySurface->advanceFrame(); if (result != NO_ERROR) {

ALOGE(\ mDisplayName.string(), result); } }

二、FramebufferSurface收到egl合成数据

之前分析DisplayDevice时候,还分析了FramebufferSurface,我们这里再来看下。 在SurfaceFlinger.cpp中的init函数,在创建DisplayDevice之前,我们先调用createBufferQueue来创建了一个buffer的生产者和消费者,然后把消费者放入了FramebufferSurface,生产者放入了DisplayDevice中。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 sp producer; sp consumer;

BufferQueue::createBufferQueue(&producer, &consumer, new GraphicBufferAlloc());

sp fbs = new FramebufferSurface(*mHwc, i, consumer);

int32_t hwcId = allocateHwcDisplayId(type);

sp hw = new DisplayDevice(this,

type, hwcId, mHwc->getFormat(hwcId), isSecure, token,

fbs, producer,

mRenderEngine->getEGLConfig());

我们先来看生产者,下面是DisplayDevice的构造函数,生产者作为参数直接新建了一个Surface,然后把这个Surface作为参数调用eglCreateWindowSurface返回的就是mSurface,之前我们分析最后egl合成的数据时调用eglSwapBuffers并且把数据放到mSurface,这样最后肯定就到消费者(FramebufferSurface)去了。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 mNativeWindow = new Surface(producer, false);

ANativeWindow* const window = mNativeWindow.get(); /*

* Create our display's surface */

EGLSurface surface;

EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (config == EGL_NO_CONFIG) {

config = RenderEngine::chooseEglConfig(display, format); }

surface = eglCreateWindowSurface(display, config, window, NULL);

最后到消费者那端的onFrameAvailable,也就是FramebufferSurface的onFrameAvailable中,我们现在来分析下这个过程,也就解答了一个onFrameAvailable的疑惑。

FramebufferSurface的父类是ConsumerBase类,我们来看其构造函数。先是构造了mConsumer,这里其实就是BufferQueueConsumer类,后面调用了其consumerConnect方法。 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片

ConsumerBase::ConsumerBase(const sp& bufferQueue, bool controlledByApp) :

mAbandoned(false),

mConsumer(bufferQueue) {

mName = String8::format(\

wp listener = static_cast(this);

sp proxy = new BufferQueue::ProxyConsumerListener(listener);

status_t err = mConsumer->consumerConnect(proxy, controlledByApp); if (err != NO_ERROR) {

CB_LOGE(\ strerror(-err), err); } else {

mConsumer->setConsumerName(mName); } }

我们来看下BufferQueueConsumer类的consumerConnect方法,就是调用了connect方法。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片

virtual status_t consumerConnect(const sp& consumer, bool controlledByApp) {

return connect(consumer, controlledByApp); }

这个方法中将mCore->mConsumerListener = consumerListener,这个mCore就是BufferQueueCore类。我们再从ConsumerBase的构造函数看这个consumerListener参数其实就是FrameBufferSurface对象本身。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 status_t BufferQueueConsumer::connect(

const sp& consumerListener, bool controlledByApp) { ATRACE_CALL();

if (consumerListener == NULL) {

BQ_LOGE(\ return BAD_VALUE; }

BQ_LOGV(\ controlledByApp ? \

Mutex::Autolock lock(mCore->mMutex);

if (mCore->mIsAbandoned) {

BQ_LOGE(\ return NO_INIT; }

mCore->mConsumerListener = consumerListener;//设置回调 mCore->mConsumerControlledByApp = controlledByApp;

return NO_ERROR; }

我们再看BufferQueueProducer::queueBuffer函数,这个函数应该是生产者已经使用好buffer了,这个使用会调用如下代码这个listener就是BufferQueueCore的mConsumerListener,传输的数据时BufferItem。再传之前把BufferItem的mGraphicBuffer清了,因为消费者可以自己获取buffer,不用通过BufferItem传。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 item.mGraphicBuffer.clear();

item.mSlot = BufferItem::INVALID_BUFFER_SLOT;

// Call back without the main BufferQueue lock held, but with the callback // lock held so we can ensure that callbacks occur in order


Android6.0 图像合成过程详解(二) doComposition函数汇总(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:以作业改革 促学生发展

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: