fff

android Gui系统之SurfaceFlinger(5)

Joyfulmath 发布于2016-06-30 22:00

9.Vsync第二部分

在上一篇中我们讲到,视图的刷新需要很多步骤,

void SurfaceFlinger::handleMessageRefresh() {

   ATRACE_CALL();

   preComposition();  //合成前的准备

   rebuildLayerStacks();//重新建立layer堆栈

   setUpHWComposer();//HWComposer的设定

#ifdef QCOM_BSP

   setUpTiledDr();

#endif

   doDebugFlashRegions();

   doComposition();  //正式合成工作

   postComposition(); //合成的后期工作

}

本文将继续分析这些过程。

9.1 handlerMessageInvalidate

invalidate 字面意思就是使无效,更进一步就是当前的buffer已经无限,请刷新界面。

啥也没干,buffer已经无效,我换下一个,就是handlePageFlip

void SurfaceFlinger::handleMessageInvalidate() {

   ATRACE_CALL();

   handlePageFlip();

}

再来看这个函数:handlePageFlip

handlePageFlip

@step1:layer->latchBuffer(visibleRegions) 通过该函数锁定各layer的缓冲区。可以理解这个函数一定与BufferQueue有关。

status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,

               mFlinger->mPrimaryDispSync);

上面是latchBuffer的核心语句。SurfaceFlingerConsumer前文已经提过,是client端操作bufferqueue的一个端口。所以这个函数一定是操作bufferqueue的。

// Acquire the next buffer.

   // In asynchronous mode the list is guaranteed to be one buffer

   // deep, while in synchronous mode we use the oldest buffer.

   err = acquireBufferLocked(&item, computeExpectedPresent(dispSync));

   if (err != NO_ERROR) {

       if (err == BufferQueue::NO_BUFFER_AVAILABLE) {

           err = NO_ERROR;

       } else if (err == BufferQueue::PRESENT_LATER) {

           // return the error, without logging

       } else {

           ALOGE("updateTexImage: acquire failed: %s (%d)",

               strerror(-err), err);

       }

       return err;

   }

   // We call the rejecter here, in case the caller has a reason to

   // not accept this buffer.  This is used by SurfaceFlinger to

   // reject buffers which have the wrong size

   int buf = item.mBuf;

   if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {

       releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR);

       return NO_ERROR;

   }

   // Release the previous buffer.

   err = updateAndReleaseLocked(item);

   if (err != NO_ERROR) {

       return err;

   }

看了注释,基本解释了大体的过程。

1)  请求新的buffer

2)通过rejecter来判断申请的buffer是否满足surfaceflinger的要求。

3)释放之前的buffer

具体流程可以参考如下:

@step2:SurfaceFlinger:invalidateLayerStack来更新各个区域。

9.2 preComposition 合成前的准备

首先来看2个Vsync Rate相关的代码:

virtual void setVsyncRate(uint32_t count)

virtual void requestNextVsync()

当count为1时,表示每个信号都要报告,当count =2 时,表示信号 一个间隔一个报告,当count =0时,表示不自动报告,除非主动触发requestNextVsync

void SurfaceFlinger::preComposition()

{

bool needExtraInvalidate = false;

const LayerVector& layers(mDrawingState.layersSortedByZ);

const size_t count = layers.size();

for (size_t i=0 ; i

if (layers[i]->onPreComposition()) {

needExtraInvalidate = true;

}

}

if (needExtraInvalidate) {

signalLayerUpdate();

}

}

代码很简单,其实一共就3步,

1)获取全部的layer

2)每个layer onPrecomposition

3) layer update

bool Layer::onPreComposition() {

mRefreshPending = false;

return mQueuedFrames > 0 || mSidebandStreamChanged;

}

也就是说,当layer里存放被queue的frame以后,就会出发layer update.

void SurfaceFlinger::signalLayerUpdate() {

mEventQueue.invalidate();

}

最终会调用:

void EventThread::Connection::requestNextVsync() {

mEventThread->requestNextVsync(this);

}

void EventThread::requestNextVsync(

const sp& connection) {

Mutex::Autolock _l(mLock);

if (connection->count < 0) {

connection->count = 0;

mCondition.broadcast();//通知对vsync感兴趣的类

}

}

那么谁在等待这个broadcast呢?

还是EventThread

void EventThread::onVSyncEvent(nsecs_t timestamp) {

Mutex::Autolock _l(mLock);

mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;

mVSyncEvent[0].header.id = 0;

mVSyncEvent[0].header.timestamp = timestamp;

mVSyncEvent[0].vsync.count++;

mCondition.broadcast();

}

9.3可见区域rebuildlayerStack

rebuildLayerStacks

前文提到mVisibleRegionsDirty这个变量是标记要刷新的可见区域的,我们按字面意思解释下:脏的可见区域,顾名思义,这就是要刷新的区域,因为buffer已经“脏”了。

@step1:系统的display可能不止一个,存在与mDisplays中。

@step2:computeVisibleRegions这个函数根据所有的layer状态,得到2个重要的变量。opaqueRegion & dirtyRegion

dirtyRegion是需要被刷新的。 opaqueRegion 不透明区域,应为layer是按Z-order排序的,左右排在前面的opaqueRegion 会挡住后面的layer。

@step3:Region drawRegion(tr.transform( layer->visibleNonTransparentRegion));程序需要进一步得出每个layer 绘制的区域。

系统的display(显示器)可能不止一个,但是所有的layer都记录在layersSortedByZ里面。记录每个layer属于那个display的变量是 hw->getLayerStack()

@step4:将结果保存到hw中。

这里的不透明区域 是很有意义的一个概念,就是我们在Z-order 上,越靠近用户的时候,值越大,所以是递减操作。

9.4 setUpHWComposer 搭建环境

用于合成surface的功能模块可以有2个,OpenGL ES & HWC,它的管理实在HWC里面实现的。

setUpHWComposer 总的来说就干了3件事情。

1)构造Worklist,并且给DisplayData:list 申请空间

2)填充各layer数据

3)报告HWC(有其他地方决定使用那个)

9.5 doCompostion

关键地方来了,上面的setUpHWComposer 只是交给HWC来负责显示,真正显示的地方就在这里。

1)如何合成

2)如何显示到屏幕上

合成的流程大体如上图。

有了概念后,分析源码:

void SurfaceFlinger::doComposition() {

   ATRACE_CALL();

   const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);

   for (size_t dpy=0 ; dpy

       const sp& hw(mDisplays[dpy]);

       if (hw->isDisplayOn()) {

           // transform the dirty region into this screen's coordinate space

           const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));

           // repaint the framebuffer (if needed)

           doDisplayComposition(hw, dirtyRegion);

           ++mActiveFrameSequence;

           hw->dirtyRegion.clear();

           hw->flip(hw->swapRegion);

           hw->swapRegion.clear();

       }

       // inform the h/w that we're done compositing

       hw->compositionComplete();

   }

   postFramebuffer();

}

变量mRepaintEverything用于说明,是否需要全部重绘所有内容。如果为true的化,那么dirtyRegion就是displaydevice的 width & height构成的RECT。

否则由dirtyRegion转换而来。

doDisplayComposition是每个Display来处理,有可能会用到OpenGL 的接口来交换buffer。

hw->compositionComplete(); 通知HWC合成结束了。

postFramebuffer HWC的Set接口调用。

9.5.1 doDisplayComposition

doDisplayComposition

传入的参数inDirtyRegion,这就是要刷新的“脏”区域,but,我们的刷新机制,决定了必须是矩形的区域。

So,需要一个最小的矩形,能够包裹inDirtyRegion的区域。

SWAP_RECTANGLE:系统支持软件层面的部分刷新,就需要计算这个最小矩形。

PARTIAL_UPDATES:硬件层面的部分刷新,同理需要这个最小矩形。

最后就是重绘这个区域。

doComposeSurfaces

依次分析:hasGlesComposition需要Open GL来合成的layer,hasHwcComposition需要HWC来合成的layer。

这2各变量不是互斥的,有同时存在需要Open GL layer & HWC layer。

hasHwcComposition在2种情况下是true。

1)layer的类型是HWC_Framebuffer的时候,通常情况下是true。

2)cur ==end 核心实现layer->draw 来完成。

3)cur!=end, 将有hwc来实现。

{

ATRACE_CALL();

   if (CC_UNLIKELY(mActiveBuffer == 0)) {

       // the texture has not been created yet, this Layer has

       // in fact never been drawn into. This happens frequently with

       // SurfaceView because the WindowManager can't know when the client

       // has drawn the first time.

       // If there is nothing under us, we paint the screen in black, otherwise

       // we just skip this update.

       // figure out if there is something below us

       Region under;

       const SurfaceFlinger::LayerVector& drawingLayers(

               mFlinger->mDrawingState.layersSortedByZ);

       const size_t count = drawingLayers.size();

       for (size_t i=0 ; i

           const sp& layer(drawingLayers[i]);

           if (layer.get() == static_cast(this))

               break;

           under.orSelf( hw->getTransform().transform(layer->visibleRegion) );

       }

       // if not everything below us is covered, we plug the holes!

       Region holes(clip.subtract(under));

       if (!holes.isEmpty()) {

           clearWithOpenGL(hw, holes, 0, 0, 0, 1);

       }

       return;

   }

   // Bind the current buffer to the GL texture, and wait for it to be

   // ready for us to draw into.

   status_t err = mSurfaceFlingerConsumer->bindTextureImage();

   if (err != NO_ERROR) {

       ALOGW("onDraw: bindTextureImage failed (err=%d)", err);

       // Go ahead and draw the buffer anyway; no matter what we do the screen

       // is probably going to have something visibly wrong.

   }

   bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure());

   RenderEngine& engine(mFlinger->getRenderEngine());

   if (!blackOutLayer) {

       // TODO: we could be more subtle with isFixedSize()

       const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();

       // Query the texture matrix given our current filtering mode.

       float textureMatrix[16];

       mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering);

       mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);

       if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {

           /*

            * the code below applies the display's inverse transform to the texture transform

            */

           // create a 4x4 transform matrix from the display transform flags

           const mat4 flipH(-1,0,0,0,  0,1,0,0, 0,0,1,0, 1,0,0,1);

           const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1);

           const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1);

           mat4 tr;

           uint32_t transform = hw->getOrientationTransform();

           if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90)

               tr = tr * rot90;

           if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H)

               tr = tr * flipH;

           if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V)

               tr = tr * flipV;

           // calculate the inverse

           tr = inverse(tr);

           // and finally apply it to the original texture matrix

           const mat4 texTransform(mat4(static_cast(textureMatrix)) * tr);

           memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));

       }

       // Set things up for texturing.

       mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());

       mTexture.setFiltering(useFiltering);

       mTexture.setMatrix(textureMatrix);

       engine.setupLayerTexturing(mTexture);

   } else {

       engine.setupLayerBlackedOut();

   }

   drawWithOpenGL(hw, clip, useIdentityTransform);

   engine.disableTexturing();

}

里面关键就是drawwithOpenGL,可见是由Open GL来合成layer。

  

查看原文

你可能感兴趣的:(fff)