Android6.0 图像合成过程详解(一) setUpHWComposer函数
http://blog.csdn.net/kc58236582/article/details/52856341
上一篇博客分析了,用户进程如何申请一个GraphicBuffer的过程。这篇博客我们进一步分析图像合成过程,其中也解答之前的一些疑惑:
1. 之前碰到的不支持硬件模块
2. DisplayDevice类
3. 消费者的onFrameAvailable函数
我们直接分析合成的过程,具体的流程我们http://blog.csdn.net/kc58236582/article/details/52778333这篇博客分析了,这篇博客我们增加了一些以前没理解的点。
一、handleTransactionLocked函数
1.1 Layer的doTransaction函数
这里我直接从handleTransactionLocked函数开始分析,这个函数先会调用每个Layer对象的doTransaction函数,我们先来看看这个函数。
- uint32_t Layer::doTransaction(uint32_t flags) {
- ATRACE_CALL();
- const Layer::State& s(getDrawingState());//上次绘制的State对象
- const Layer::State& c(getCurrentState());//当前使用的State对象
- const bool sizeChanged = (c.requested.w != s.requested.w) ||//如果两个对象的大小不相等,说明Layer的尺寸发生变化
- (c.requested.h != s.requested.h);
- if (sizeChanged) {//如果Layer的尺寸发生变化,就要改变Surface的缓冲区的尺寸
- mSurfaceFlingerConsumer->setDefaultBufferSize(
- c.requested.w, c.requested.h);
- }
- if (!isFixedSize()) {
- //如果Layer不是固定尺寸的类型,比较它的实际大小和要求的改变大小
- const bool resizePending = (c.requested.w != c.active.w) ||
- (c.requested.h != c.active.h);
- if (resizePending && mSidebandStream == NULL) {//如果两者不一样,flags加上不更新Geometry标志
- flags |= eDontUpdateGeometryState;
- }
- }
- if (flags & eDontUpdateGeometryState) {
- } else {
- //如果没有eDontUpdateGeometryState标志,更新active的值为request
- Layer::State& editCurrentState(getCurrentState());
- editCurrentState.active = c.requested;
- }
- if (s.active != c.active) {
- // 如果当前state的active和以前的State的active不等,设置更新标志
- flags |= Layer::eVisibleRegion;
- }
- if (c.sequence != s.sequence) {
- //如果当前state的sequence和以前state的sequence不等,设置更新标志
- flags |= eVisibleRegion;
- this->contentDirty = true;
- const uint8_t type = c.transform.getType();
- mNeedsFiltering = (!c.transform.preserveRects() ||
- (type >= Transform::SCALE));
- }
- // Commit the transaction
- commitTransaction();//将mCurrentState的值赋给mDrawingState
- return flags;
- }
这个函数之前博客也分析过,这里我们看看其中最重要的一个flag就是eVisibleRegion代表这个Layer是否要更新。而这里如果要更新Layer,也只是大小,sequence(也就是属性)变化才会更新这个flag。而Layer内容(buffer)的更新不在这里。这里使用了mDrawingState,mCurrentState两个变量。这两个变量主要是一些属性值。
最后会把mCurrentState的值赋给mDrawingState。而mCurrentState是在下面一些函数中变化的:
- bool Layer::setPosition(float x, float y) {
- if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
- return false;
- mCurrentState.sequence++;
- mCurrentState.transform.set(x, y);
- setTransactionFlags(eTransactionNeeded);
- return true;
- }
- bool Layer::setLayer(uint32_t z) {
- if (mCurrentState.z == z)
- return false;
- mCurrentState.sequence++;
- mCurrentState.z = z;
- setTransactionFlags(eTransactionNeeded);
- return true;
- }
- bool Layer::setSize(uint32_t w, uint32_t h) {
- if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
- return false;
- mCurrentState.requested.w = w;
- mCurrentState.requested.h = h;
- setTransactionFlags(eTransactionNeeded);
- return true;
- }
- bool Layer::setAlpha(uint8_t alpha) {
- if (mCurrentState.alpha == alpha)
- return false;
- mCurrentState.sequence++;
- mCurrentState.alpha = alpha;
- setTransactionFlags(eTransactionNeeded);
- return true;
- }
我们下面开始看handleTransactionLocked函数。
先看下处理layer的事务,遍历每个Layer的doTransaction来更新状态,以及根据flags是否要更新layer。
- void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
- {
- const LayerVector& currentLayers(mCurrentState.layersSortedByZ);//所有的Layer
- const size_t count = currentLayers.size();
- /*
- * Traversal of the children
- * (perform the transaction for each of them if needed)
- */
- if (transactionFlags & eTraversalNeeded) {
- for (size_t i=0 ; i<count ; i++) {
- const sp<Layer>& layer(currentLayers[i]);
- uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
- if (!trFlags) continue;
- const uint32_t flags = layer->doTransaction(0);//遍历每个layer,更新mDrawingState状态
- if (flags & Layer::eVisibleRegion)
- mVisibleRegionsDirty = true;//有需要更新的layer,把该变量置为true
- }
- }
1.2 处理显示设备的变化
下面是handleTransactionLocked中处理显示设备的变化的
- if (transactionFlags & eDisplayTransactionNeeded) {
- //得到当前显示设备列表和之前使用的显示设备列表
- const KeyedVector< wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
- const KeyedVector< wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
- if (!curr.isIdenticalTo(draw)) {
- mVisibleRegionsDirty = true;
- const size_t cc = curr.size();//现在显示设备的数量
- size_t dc = draw.size();//以前显示设备的数量
- for (size_t i=0 ; i<dc ; i++) {
- const ssize_t j = curr.indexOfKey(draw.keyAt(i));
- if (j < 0) {//j< 0代表当前设备列表中找不到以前设备列表中的某个设备,设备被删除了
- if (!draw[i].isMainDisplay()) {
- ......
- //如果不是主设备移除它
- mDisplays.removeItem(draw.keyAt(i));
- } else {
- ALOGW("trying to remove the main display");
- }
- } else {//j>0代表这个设备两个列表中都存在,再检查有没有其他变化
- // this display is in both lists. see if something changed.
- const DisplayDeviceState& state(curr[j]);
- const wp<IBinder>& display(curr.keyAt(j));
- const sp<IBinder> state_binder = IInterface::asBinder(state.surface);
- const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface);
- if (state_binder != draw_binder) {
- //设备的Surface已经发生了变化(Surface对象不是一个了),旧的设备必须先删除掉
- sp<DisplayDevice> hw(getDisplayDevice(display));
- if (hw != NULL)
- hw->disconnect(getHwComposer());
- mDisplays.removeItem(display);
- mDrawingState.displays.removeItemsAt(i);
- dc--; i--;
- // at this point we must loop to the next item
- continue;
- }
- const sp<DisplayDevice> disp(getDisplayDevice(display));
- if (disp != NULL) {
- //两个对象的layerStack不相等,使用当前对象的
- if (state.layerStack != draw[i].layerStack) {
- disp->setLayerStack(state.layerStack);
- }
- //如果两个对象的方向、viewport、frame不相等,使用当前对象的
- if ((state.orientation != draw[i].orientation)
- || (state.viewport != draw[i].viewport)
- || (state.frame != draw[i].frame))
- {
- disp->setProjection(state.orientation,
- state.viewport, state.frame);
- }
- if (state.width != draw[i].width || state.height != draw[i].height) {
- disp->setDisplaySize(state.width, state.height);
- }
- }
- }
- }
- // 处理显示设备增加的情况
- for (size_t i=0 ; i<cc ; i++) {
- if (draw.indexOfKey(curr.keyAt(i)) < 0) {
- //当前列表中某个设备在以前列表中没有找到,说明是增加的设备
- //创建DisplayDevice对象,把它加入到mDisplays列表中
- ......
- const wp<IBinder>& display(curr.keyAt(i));
- if (dispSurface != NULL) {
- sp<DisplayDevice> hw = new DisplayDevice(this,
- state.type, hwcDisplayId,
- mHwc->getFormat(hwcDisplayId), state.isSecure,
- display, dispSurface, producer,
- mRenderEngine->getEGLConfig());
- ......
- mDisplays.add(display, hw);
- ......
- }
- }
- }
- }
- }
这段代码的作用是处理显示设备的变化,分成3种情况:
1.显示设备减少了,需要把显示设备对应的DisplayDevice移除
2.显示设备发生了变化,例如用户设置了Surface、重新设置了layerStack、旋转了屏幕等,这就需要重新设置显示对象的属性
3.显示设备增加了,创建新的DisplayDevice加入系统中。
这些在之前博客都分析过,我们主要看下几个变量mCurrentState.displays, mDrawingState.displays。代表之前的设备和现在的设备。
这些displays是State的一个变量,是每个display的一个唯一码对应一个DisplayDeviceState(状态)。
- struct State {
- LayerVector layersSortedByZ;
- DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays;
- };
而mDisplays是一个Display的唯一码 对应一个DisplayDevice。
- DefaultKeyedVector< wp<IBinder>, sp<DisplayDevice> > mDisplays;
而这里主要用mCurrentState.displays, mDrawingState.displays中的Display的唯一码看哪个DisplayDevice增加了或者删除了,再去根据这个唯一码来对应在mDisplays中的DisplayDevice增加或者删除或者一些状态的修改。
1.3 设置TransformHint
- if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
- sp<const DisplayDevice> disp;
- uint32_t currentlayerStack = 0;
- for (size_t i=0; i<count; i++) {
- // NOTE: we rely on the fact that layers are sorted by
- // layerStack first (so we don't have to traverse the list
- // of displays for every layer).
- const sp<Layer>& layer(currentLayers[i]);
- uint32_t layerStack = layer->getDrawingState().layerStack;
- if (i==0 || currentlayerStack != layerStack) {
- currentlayerStack = layerStack;
- // figure out if this layerstack is mirrored
- // (more than one display) if so, pick the default display,
- // if not, pick the only display it's on.
- disp.clear();//清除disp
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- if (hw->getLayerStack() == currentlayerStack) {
- if (disp == NULL) {
- disp = hw;//找到了一个layerStacker相同的显示设备
- } else {
- disp = NULL;//如果有两个显示设备的layerStacker相同,都不用
- break;
- }
- }
- }
- }
- if (disp == NULL) {
- // 没有找到具有相同layerStack的显示设备,使用缺省设备
- disp = getDefaultDisplayDevice();
- }
- layer->updateTransformHint(disp);//设置Layer对象的TransformHint
- }
- }
这段代码的作用是根据每种显示设备的不同,设置和显示设备关联在一起的Layer(主要看Layer的layerStack是否和DisplayDevice的layerStack)的TransformHint(主要指设备的显示方向orientation)。
1.4 处理Layer增加情况
- const LayerVector& layers(mDrawingState.layersSortedByZ);
- if (currentLayers.size() > layers.size()) {
- // 如果有Layer加入,设置需要更新
- mVisibleRegionsDirty = true;
- }
- // 处理有Layer删除的情况
- if (mLayersRemoved) {
- mLayersRemoved = false;
- mVisibleRegionsDirty = true;
- const size_t count = layers.size();
- for (size_t i=0 ; i<count ; i++) {
- const sp<Layer>& layer(layers[i]);
- if (currentLayers.indexOf(layer) < 0) {
- //如果这个Layer已经不存在了,把它的所在区域设置为需要更新的区域
- const Layer::State& s(layer->getDrawingState());
- Region visibleReg = s.transform.transform(
- Region(Rect(s.active.w, s.active.h)));
- invalidateLayerStack(s.layerStack, visibleReg);
- }
- }
- }
这段代码处理Layer的增加情况,如果Layer增加了,需要重新计算设备的更新区域,因此把mVisibleRegionsDirty设为true,如果Layer删除了,需要把Layer的可见区域加入到系统需要更新的区域中。
而这里mVisibleRegionsDirty设为true代表Layer需要更新,如果Layer不需要更新的话后面的rebuildLayerStack函数的执行就是空的了。
1.5 设置mDrawingState
- commitTransaction();
- updateCursorAsync();
1.6 小结
handleTransaction函数的作用的就是处理系统在两次刷新期间的各种变化。SurfaceFlinger模块中不管是SurfaceFlinger类还是Layer类,都采用了双缓冲的方式来保存他们的属性,这样的好处是刚改变SurfaceFlinger对象或者Layer类对象的属性是,不需要上锁,大大的提高了系统效率。只有在最后的图像输出是,才进行一次上锁,并进行内存的属性变化处理。正因此,应用进程必须收到VSync信号才开始改变Surface的内容。
二、handlePageFlip函数
代码如下,这个函数就是更新Layer中的buffer(内容),遍历每个Layer看这个Layer是否有内容更新,就看其hasQueuedFrame函数是否返回true。之前分析过当有更新的话,mQueuedFrames的值会加1.而hasQueuedFrame函数就是看这个值是否为0
- bool SurfaceFlinger::handlePageFlip()
- {
- Region dirtyRegion;
- bool visibleRegions = false;
- const LayerVector& layers(mDrawingState.layersSortedByZ);
- bool frameQueued = false;
- Vector<Layer*> layersWithQueuedFrames;
- //查找需要更新的Layer
- for (size_t i = 0, count = layers.size(); i<count ; i++) {
- const sp<Layer>& layer(layers[i]);
- if (layer->hasQueuedFrame()) {
- frameQueued = true;
- if (layer->shouldPresentNow(mPrimaryDispSync)) {
- layersWithQueuedFrames.push_back(layer.get());
- } else {
- layer->useEmptyDamage();
- }
- } else {
- layer->useEmptyDamage();
- }
- }
- for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
- Layer* layer = layersWithQueuedFrames[i];
- const Region dirty(layer->latchBuffer(visibleRegions));
- layer->useSurfaceDamage();
- const Layer::State& s(layer->getDrawingState());
- invalidateLayerStack(s.layerStack, dirty);
- }
- mVisibleRegionsDirty |= visibleRegions;
- if (frameQueued && layersWithQueuedFrames.empty()) {
- signalLayerUpdate();
- }
- return !layersWithQueuedFrames.empty();
- }
hasQueuedFrame函数如下。
- bool hasQueuedFrame() const { return mQueuedFrames > 0 || mSidebandStreamChanged; }
调用每个Layer的latchBuffer函数根据返回的更新区域调用invalidateLayerStack来设置更新设备对象的更新区域。
我们先来看看invalidateLayerStack函数,在SurfaceFlinger.cpp中的invalidateLayerStack。先是遍历所有的设备,找到和Layer的layerStack一样的设备,然后调用了DisplayDevice的dirtyRegion.orSelf方法
- void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack,
- const Region& dirty) {
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- const sp<DisplayDevice>& hw(mDisplays[dpy]);
- if (hw->getLayerStack() == layerStack) {
- hw->dirtyRegion.orSelf(dirty);
- }
- }
- }
- Region& Region::orSelf(const Rect& r) {
- return operationSelf(r, op_or);
- }
最后我们再来看看latchBuffer函数
- Region Layer::latchBuffer(bool& recomputeVisibleRegions)
- {
- ATRACE_CALL();
- if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) {
- // mSidebandStreamChanged was true
- mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream();
- if (mSidebandStream != NULL) {
- setTransactionFlags(eTransactionNeeded);
- mFlinger->setTransactionFlags(eTraversalNeeded);
- }
- recomputeVisibleRegions = true;
- const State& s(getDrawingState());
- return s.transform.transform(Region(Rect(s.active.w, s.active.h)));
- }
- Region outDirtyRegion;
- if (mQueuedFrames > 0) { //mQueuedFrames大于0代表有Surface更新的要求
- if (mRefreshPending) {
- return outDirtyRegion;
- }
- // Capture the old state of the layer for comparisons later
- const State& s(getDrawingState());//注意这是使用的DrawingState
- const bool oldOpacity = isOpaque(s);
- sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
- struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
- ......//定义Reject结构体
- };
- Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
- getProducerStickyTransform() != 0);
- uint64_t maxFrameNumber = 0;
- {
- Mutex::Autolock lock(mQueueItemLock);
- maxFrameNumber = mLastFrameNumberReceived;
- }
- status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,//更新纹理
- mFlinger->mPrimaryDispSync, maxFrameNumber);
- if (updateResult == BufferQueue::PRESENT_LATER) {
- mFlinger->signalLayerUpdate();//如果结果是推迟处理,发送Invalidate消息
- return outDirtyRegion;
- } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
- // If the buffer has been rejected, remove it from the shadow queue
- // and return early
- Mutex::Autolock lock(mQueueItemLock);
- mQueueItems.removeAt(0);
- android_atomic_dec(&mQueuedFrames);
- return outDirtyRegion;
- } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
- // This can occur if something goes wrong when trying to create the
- // EGLImage for this buffer. If this happens, the buffer has already
- // been released, so we need to clean up the queue and bug out
- // early.
- {
- Mutex::Autolock lock(mQueueItemLock);
- mQueueItems.clear();
- android_atomic_and(0, &mQueuedFrames);
- }
- // Once we have hit this state, the shadow queue may no longer
- // correctly reflect the incoming BufferQueue's contents, so even if
- // updateTexImage starts working, the only safe course of action is
- // to continue to ignore updates.
- mUpdateTexImageFailed = true;
- return outDirtyRegion;
- }
- { // Autolock scope
- auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
- Mutex::Autolock lock(mQueueItemLock);
- // Remove any stale buffers that have been dropped during
- // updateTexImage
- while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
- mQueueItems.removeAt(0);
- android_atomic_dec(&mQueuedFrames);
- }
- mQueueItems.removeAt(0);
- }
- // Decrement the queued-frames count. Signal another event if we
- // have more frames pending.
- if (android_atomic_dec(&mQueuedFrames) > 1) {//减少mQueuedFrames的值
- mFlinger->signalLayerUpdate();//如果还有更多frame需要处理,要发消息
- }
- if (updateResult != NO_ERROR) {
- // something happened!
- recomputeVisibleRegions = true;
- return outDirtyRegion;
- }
- //更新mActiveBuffer,得到现在需要输出的图像数据
- mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
- if (mActiveBuffer == NULL) {
- return outDirtyRegion;//出错
- }
- mRefreshPending = true;
- mFrameLatencyNeeded = true;
- //下面根据各种情况是否重新计算更新区域
- if (oldActiveBuffer == NULL) {
- // the first time we receive a buffer, we need to trigger a
- // geometry invalidation.
- recomputeVisibleRegions = true;
- }
- Rect crop(mSurfaceFlingerConsumer->getCurrentCrop());
- const uint32_t transform(mSurfaceFlingerConsumer->getCurrentTransform());
- const uint32_t scalingMode(mSurfaceFlingerConsumer->getCurrentScalingMode());
- if ((crop != mCurrentCrop) ||
- (transform != mCurrentTransform) ||
- (scalingMode != mCurrentScalingMode))
- {
- mCurrentCrop = crop;
- mCurrentTransform = transform;
- mCurrentScalingMode = scalingMode;
- recomputeVisibleRegions = true;
- }
- if (oldActiveBuffer != NULL) {
- uint32_t bufWidth = mActiveBuffer->getWidth();
- uint32_t bufHeight = mActiveBuffer->getHeight();
- if (bufWidth != uint32_t(oldActiveBuffer->width) ||
- bufHeight != uint32_t(oldActiveBuffer->height)) {
- recomputeVisibleRegions = true;
- }
- }
- mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
- if (oldOpacity != isOpaque(s)) {
- recomputeVisibleRegions = true;
- }
- // FIXME: postedRegion should be dirty & bounds
- Region dirtyRegion(Rect(s.active.w, s.active.h));
- // transform the dirty region to window-manager space
- outDirtyRegion = (s.transform.transform(dirtyRegion));//返回Layer的更新区域
- }
- return outDirtyRegion;
- }
这里我们来看mSurfaceFlingerConsumer->updateTexImage更新纹理
- status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
- const DispSync& dispSync, uint64_t maxFrameNumber)
- {
- ATRACE_CALL();
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ALOGE("updateTexImage: GLConsumer is abandoned!");
- return NO_INIT;
- }
- // Make sure the EGL state is the same as in previous calls.
- status_t err = checkAndUpdateEglStateLocked();
- if (err != NO_ERROR) {
- return err;
- }
- BufferItem item;
- // 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),//消费者端取数据
- maxFrameNumber);
- 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 BUFFER_REJECTED;
- }
- // Release the previous buffer.
- err = updateAndReleaseLocked(item);
- if (err != NO_ERROR) {
- return err;
- }
- if (!SyncFeatures::getInstance().useNativeFenceSync()) {
- // Bind the new buffer to the GL texture.
- //
- // Older devices require the "implicit" synchronization provided
- // by glEGLImageTargetTexture2DOES, which this method calls. Newer
- // devices will either call this in Layer::onDraw, or (if it's not
- // a GL-composited layer) not at all.
- err = bindTextureImageLocked();
- }
- return err;
- }
- status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item)
- {
- status_t err = NO_ERROR;
- int buf = item.mBuf;
- if (!mAttached) {
- releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
- mEglDisplay, EGL_NO_SYNC_KHR);
- return INVALID_OPERATION;
- }
- err = checkAndUpdateEglStateLocked();
- ......
- err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
- ......
- err = syncForReleaseLocked(mEglDisplay);
- ......
- //释放buffer
- if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
- status_t status = releaseBufferLocked(
- mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
- mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
- if (status < NO_ERROR) {
- GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
- strerror(-status), status);
- err = status;
- // keep going, with error raised [?]
- }
- }
- // 更新状态
- mCurrentTexture = buf;
- mCurrentTextureImage = mEglSlots[buf].mEglImage;
- mCurrentCrop = item.mCrop;
- mCurrentTransform = item.mTransform;
- mCurrentScalingMode = item.mScalingMode;
- mCurrentTimestamp = item.mTimestamp;
- mCurrentFence = item.mFence;
- mCurrentFrameNumber = item.mFrameNumber;
- computeCurrentTransformMatrixLocked();
- return err;
- }
- sp<GraphicBuffer> GLConsumer::getCurrentBuffer() const {
- Mutex::Autolock lock(mMutex);
- return (mCurrentTextureImage == NULL) ?
- NULL : mCurrentTextureImage->graphicBuffer();
- }
LatchBuffer函数调用updateTextImage来得到需要的图像。这里参数r是Reject对象,其作用是判断在缓冲区的尺寸是否符合要求。调用updateTextImage函数如果得到的结果是PRESENT_LATER,表示推迟处理,然后调用signalLayerUpdate函数来发送invalidate消息,这次绘制过程就不处理这个Surface的图像了。
如果不需要推迟处理,把mQueuedFrames的值减1.
最后LatchBuffer函数调用mSurfaceFlingerConsumer的getCurrentBuffer来取回当前的图像缓冲区指针,保存在mActiveBuffer中。
这样经过handleTransaction handlePageFlip两个函数处理,SurfaceFlinger中无论是Layer属性的变化还是图像的变化都处理好了,只等VSync信号到来就可以输出了。
三、rebuildLayerStack函数
VSync信号来了之后先是调用的这个函数,前面分析handleTransactionLocked的时候,当mVisibleRegionsDirty为 true代表是要更新Layer,这里上来就是看这个变量是否为true。
- void SurfaceFlinger::rebuildLayerStacks() {
- // rebuild the visible layer list per screen
- if (CC_UNLIKELY(mVisibleRegionsDirty)) {//mVisibleRegionsDirty是否为true
- ATRACE_CALL();
- mVisibleRegionsDirty = false;
- invalidateHwcGeometry();
- //计算每个显示设备上可见的Layer
- const LayerVector& layers(mDrawingState.layersSortedByZ);
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- Region opaqueRegion;
- Region dirtyRegion;
- Vector< sp<Layer> > layersSortedByZ;
- const sp<DisplayDevice>& hw(mDisplays[dpy]);
- const Transform& tr(hw->getTransform());
- const Rect bounds(hw->getBounds());
- if (hw->isDisplayOn()) {
- //计算每个layer的可见区域,确定设备需要重新绘制的区域
- SurfaceFlinger::computeVisibleRegions(layers,
- hw->getLayerStack(), dirtyRegion, opaqueRegion);
- const size_t count = layers.size();
- for (size_t i=0 ; i<count ; i++) {
- const sp<Layer>& layer(layers[i]);
- const Layer::State& s(layer->getDrawingState());
- if (s.layerStack == hw->getLayerStack()) {
- //只需要和显示设备的LayerStack相同的layer
- Region drawRegion(tr.transform(
- layer->visibleNonTransparentRegion));
- drawRegion.andSelf(bounds);
- if (!drawRegion.isEmpty()) {
- //如果Layer的显示区域和显示设备的窗口有交集
- //把Layer加入列表中
- layersSortedByZ.add(layer);
- }
- }
- }
- }
- //设置显示设备的可见Layer列表
- hw->setVisibleLayersSortedByZ(layersSortedByZ);
- hw->undefinedRegion.set(bounds);
- hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
- hw->dirtyRegion.orSelf(dirtyRegion);//设置每个DisplayDevice的drawRegions 加上dirtyRegion区域
- }
- }
- }
rebuildLayerStacks函数的作用是重建每个显示设备的可见layer对象列表。其他的说明还是看另一篇博客http://write.blog.csdn.net/postedit?ref=toolbar&ticket=ST-83533-ejxpwYJbCoASdBlu6Tpr-passport.csdn.net
四、setUpHWComposer函数
HWComposer中有一个类型为DisplayData结构的数组mDisplayData[],维护每个显示设备的信息。我们先来看在HWComposer构造函数中有下面这段代码,我们这里mFbDev为空,因此我们遍历每个设备,调用queryDisplayProperties函数。
- if (mFbDev) {
- ALOGD("chenchen mFbDev end");
- ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
- "should only have fbdev if no hwc or hwc is 1.0");
- DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
- disp.connected = true;
- disp.format = mFbDev->format;
- DisplayConfig config = DisplayConfig();
- config.width = mFbDev->width;
- config.height = mFbDev->height;
- config.xdpi = mFbDev->xdpi;
- config.ydpi = mFbDev->ydpi;
- config.refresh = nsecs_t(1e9 / mFbDev->fps);
- disp.configs.push_back(config);
- disp.currentConfig = 0;
- } else if (mHwc) {
- // here we're guaranteed to have at least HWC 1.1
- for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
- queryDisplayProperties(i);
- }
- }
下面我们来看queryDisplayProperties函数,通过hwc模块的getDisplayConfigs和getDisplayAttributes方法来获取configs,最后把格式和connect设置为true。
- status_t HWComposer::queryDisplayProperties(int disp) {
- LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
- // use zero as default value for unspecified attributes
- int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
- memset(values, 0, sizeof(values));
- const size_t MAX_NUM_CONFIGS = 128;
- uint32_t configs[MAX_NUM_CONFIGS] = {0};
- size_t numConfigs = MAX_NUM_CONFIGS;
- status_t err = mHwc->getDisplayConfigs(mHwc, disp, configs, &numConfigs);
- if (err != NO_ERROR) {
- // this can happen if an unpluggable display is not connected
- mDisplayData[disp].connected = false;
- return err;
- }
- mDisplayData[disp].currentConfig = 0;
- for (size_t c = 0; c < numConfigs; ++c) {
- err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
- DISPLAY_ATTRIBUTES, values);
- // If this is a pre-1.5 HWC, it may not know about color transform, so
- // try again with a smaller set of attributes
- if (err != NO_ERROR) {
- err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
- PRE_HWC15_DISPLAY_ATTRIBUTES, values);
- }
- if (err != NO_ERROR) {
- // we can't get this display's info. turn it off.
- mDisplayData[disp].connected = false;
- return err;
- }
- DisplayConfig config = DisplayConfig();
- for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
- switch (DISPLAY_ATTRIBUTES[i]) {
- case HWC_DISPLAY_VSYNC_PERIOD:
- config.refresh = nsecs_t(values[i]);//设置config
- break;
- case HWC_DISPLAY_WIDTH:
- config.width = values[i];
- break;
- case HWC_DISPLAY_HEIGHT:
- config.height = values[i];
- break;
- case HWC_DISPLAY_DPI_X:
- config.xdpi = values[i] / 1000.0f;
- break;
- case HWC_DISPLAY_DPI_Y:
- config.ydpi = values[i] / 1000.0f;
- break;
- case HWC_DISPLAY_COLOR_TRANSFORM:
- config.colorTransform = values[i];
- break;
- default:
- ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
- i, DISPLAY_ATTRIBUTES[i]);
- break;
- }
- }
- if (config.xdpi == 0.0f || config.ydpi == 0.0f) {
- float dpi = getDefaultDensity(config.width, config.height);
- config.xdpi = dpi;
- config.ydpi = dpi;
- }
- mDisplayData[disp].configs.push_back(config);
- }
- // FIXME: what should we set the format to?
- mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;//格式
- mDisplayData[disp].connected = true;//已连接
- return NO_ERROR;
- }
我们再来看SurfaceFlinger中init函数,后面创建DisplayDevice过程。
- for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
- DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
- // set-up the displays that are already connected
- if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {//当前设备连接了,或者是默认设备(即使没有连接)
- // All non-virtual displays are currently considered secure.
- bool isSecure = true;
- createBuiltinDisplayLocked(type);//分配一个token
- wp<IBinder> token = mBuiltinDisplays[i];
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer,//创建producer consumer
- new GraphicBufferAlloc());
- sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
- consumer);
- int32_t hwcId = allocateHwcDisplayId(type);
- sp<DisplayDevice> hw = new DisplayDevice(this,//创建DisplayDevice
- type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
- fbs, producer,
- mRenderEngine->getEGLConfig());
- if (i > DisplayDevice::DISPLAY_PRIMARY) {
- // FIXME: currently we don't get blank/unblank requests
- // for displays other than the main display, so we always
- // assume a connected display is unblanked.
- ALOGD("marking display %zu as acquired/unblanked", i);
- hw->setPowerMode(HWC_POWER_MODE_NORMAL);
- }
- mDisplays.add(token, hw);//放入mDisplays中
- }
- }
setUpHWComposer函数的作用是更新HWComposer对象中图层对象列表以及图层属性。下面函数先会遍历各个设备DisplayDevice,然后根据可见layer数量,调用createWorkList创建hwc_layer_list_t列表,然后在每个设备上遍历可见layer,将layer的mActiveBuffer设置到HWComposer中去,最后调用了HWComposer的prepare函数。
- void SurfaceFlinger::setUpHWComposer() {
- ......
- HWComposer& hwc(getHwComposer());
- if (hwc.initCheck() == NO_ERROR) {
- // build the h/w work list
- if (CC_UNLIKELY(mHwWorkListDirty)) {
- mHwWorkListDirty = false;
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {//遍历mDisplays
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- const int32_t id = hw->getHwcDisplayId();
- if (id >= 0) {
- const Vector< sp<Layer> >& currentLayers(//遍历DisplayDevice所有可见layer
- hw->getVisibleLayersSortedByZ());
- const size_t count = currentLayers.size();
- if (hwc.createWorkList(id, count) == NO_ERROR) {//根据layer数量调用createWorkList创建hwc_layer_list_t列表
- HWComposer::LayerListIterator cur = hwc.begin(id);
- const HWComposer::LayerListIterator end = hwc.end(id);
- for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
- const sp<Layer>& layer(currentLayers[i]);
- layer->setGeometry(hw, *cur);
- if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
- cur->setSkip(true);
- }
- }
- }
- }
- }
- }
- // set the per-frame data
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- const int32_t id = hw->getHwcDisplayId();
- if (id >= 0) {
- const Vector< sp<Layer> >& currentLayers(
- hw->getVisibleLayersSortedByZ());
- const size_t count = currentLayers.size();
- HWComposer::LayerListIterator cur = hwc.begin(id);
- const HWComposer::LayerListIterator end = hwc.end(id);
- for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
- //将layer的mActiveBuffer设置到HWComposer中去
- const sp<Layer>& layer(currentLayers[i]);
- layer->setPerFrameData(hw, *cur);
- }
- }
- }
- // If possible, attempt to use the cursor overlay on each display.
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- const int32_t id = hw->getHwcDisplayId();
- if (id >= 0) {
- const Vector< sp<Layer> >& currentLayers(
- hw->getVisibleLayersSortedByZ());
- const size_t count = currentLayers.size();
- HWComposer::LayerListIterator cur = hwc.begin(id);
- const HWComposer::LayerListIterator end = hwc.end(id);
- for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
- const sp<Layer>& layer(currentLayers[i]);
- if (layer->isPotentialCursor()) {
- cur->setIsCursorLayerHint();
- break;
- }
- }
- }
- }
- status_t err = hwc.prepare();
- ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- hw->prepareFrame(hwc);
- }
- }
- }
- status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
- return BAD_INDEX;
- }
- if (mHwc) {
- DisplayData& disp(mDisplayData[id]);
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // we need space for the HWC_FRAMEBUFFER_TARGET
- numLayers++;//注意到这个细节没有,当支持egl合成的时候,会把numLayers加1
- }
- if (disp.capacity < numLayers || disp.list == NULL) {//当DisplayData中的list为空,我们就要malloc
- size_t size = sizeof(hwc_display_contents_1_t)
- + numLayers * sizeof(hwc_layer_1_t);//整个申请内存长度,hwc_display_contents_1_t结构体本身的长度加上后面hwc_layer_1_t个数的长度
- free(disp.list);
- disp.list = (hwc_display_contents_1_t*)malloc(size);//malloc
- disp.capacity = numLayers;
- }
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
- memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));//DisplayData的framebufferTarget清0
- const DisplayConfig& currentConfig =
- disp.configs[disp.currentConfig];
- const hwc_rect_t r = { 0, 0,
- (int) currentConfig.width, (int) currentConfig.height };
- disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
- disp.framebufferTarget->hints = 0;
- disp.framebufferTarget->flags = 0;
- disp.framebufferTarget->handle = disp.fbTargetHandle;
- disp.framebufferTarget->transform = 0;
- disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
- disp.framebufferTarget->sourceCropf.left = 0;
- disp.framebufferTarget->sourceCropf.top = 0;
- disp.framebufferTarget->sourceCropf.right =
- currentConfig.width;
- disp.framebufferTarget->sourceCropf.bottom =
- currentConfig.height;
- } else {
- disp.framebufferTarget->sourceCrop = r;
- }
- disp.framebufferTarget->displayFrame = r;
- disp.framebufferTarget->visibleRegionScreen.numRects = 1;
- disp.framebufferTarget->visibleRegionScreen.rects =
- &disp.framebufferTarget->displayFrame;
- disp.framebufferTarget->acquireFenceFd = -1;
- disp.framebufferTarget->releaseFenceFd = -1;
- disp.framebufferTarget->planeAlpha = 0xFF;
- }
- disp.list->retireFenceFd = -1;
- disp.list->flags = HWC_GEOMETRY_CHANGED;
- disp.list->numHwLayers = numLayers;//DisplayData中list中layer的个数
- }
- return NO_ERROR;
- }
下面我们来看下DisplayData的数据结构
- struct DisplayData {
- DisplayData();
- ~DisplayData();
- Vector<DisplayConfig> configs;
- size_t currentConfig;
- uint32_t format; // pixel format from FB hal, for pre-hwc-1.1
- bool connected;
- bool hasFbComp;
- bool hasOvComp;
- size_t capacity;
- hwc_display_contents_1* list;
- hwc_layer_1* framebufferTarget;
- buffer_handle_t fbTargetHandle;
- sp<Fence> lastRetireFence; // signals when the last set op retires
- sp<Fence> lastDisplayFence; // signals when the last set op takes
- // effect on screen
- buffer_handle_t outbufHandle;
- sp<Fence> outbufAcquireFence;
- // protected by mEventControlLock
- int32_t events;
- };
再来看下hwc_display_contents_1。保留了原始的注释,我们先看hwc_display_contents_1,我们先看联合体union,第一个hwc_display_t dpy hwc_surface_t sur这个是EGL使用的,而如果是普通的就使用另外一个联合体outbuf什么的,后面还保存了layer的个数和hwc_layer_1_t 数组的起始地址hwLayers[0]
- typedef struct hwc_display_contents_1 {
- /* File descriptor referring to a Sync HAL fence object which will signal
- * when this composition is retired. For a physical display, a composition
- * is retired when it has been replaced on-screen by a subsequent set. For
- * a virtual display, the composition is retired when the writes to
- * outputBuffer are complete and can be read. The fence object is created
- * and returned by the set call; this field will be -1 on entry to prepare
- * and set. SurfaceFlinger will close the returned file descriptor.
- */
- int retireFenceFd;
- union {
- /* Fields only relevant for HWC_DEVICE_VERSION_1_0. */
- struct {
- /* (dpy, sur) is the target of SurfaceFlinger's OpenGL ES
- * composition for HWC_DEVICE_VERSION_1_0. They aren't relevant to
- * prepare. The set call should commit this surface atomically to
- * the display along with any overlay layers.
- */
- hwc_display_t dpy;
- hwc_surface_t sur;
- };
- /* These fields are used for virtual displays when the h/w composer
- * version is at least HWC_DEVICE_VERSION_1_3. */
- struct {
- /* outbuf is the buffer that receives the composed image for
- * virtual displays. Writes to the outbuf must wait until
- * outbufAcquireFenceFd signals. A fence that will signal when
- * writes to outbuf are complete should be returned in
- * retireFenceFd.
- *
- * This field is set before prepare(), so properties of the buffer
- * can be used to decide which layers can be handled by h/w
- * composer.
- *
- * If prepare() sets all layers to FRAMEBUFFER, then GLES
- * composition will happen directly to the output buffer. In this
- * case, both outbuf and the FRAMEBUFFER_TARGET layer's buffer will
- * be the same, and set() has no work to do besides managing fences.
- *
- * If the TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS board config
- * variable is defined (not the default), then this behavior is
- * changed: if all layers are marked for FRAMEBUFFER, GLES
- * composition will take place to a scratch framebuffer, and
- * h/w composer must copy it to the output buffer. This allows the
- * h/w composer to do format conversion if there are cases where
- * that is more desirable than doing it in the GLES driver or at the
- * virtual display consumer.
- *
- * If some or all layers are marked OVERLAY, then the framebuffer
- * and output buffer will be different. As with physical displays,
- * the framebuffer handle will not change between frames if all
- * layers are marked for OVERLAY.
- */
- buffer_handle_t outbuf;
- /* File descriptor for a fence that will signal when outbuf is
- * ready to be written. The h/w composer is responsible for closing
- * this when no longer needed.
- *
- * Will be -1 whenever outbuf is NULL, or when the outbuf can be
- * written immediately.
- */
- int outbufAcquireFenceFd;
- };
- };
- /* List of layers that will be composed on the display. The buffer handles
- * in the list will be unique. If numHwLayers is 0, all composition will be
- * performed by SurfaceFlinger.
- */
- uint32_t flags;
- size_t numHwLayers;//layer个数
- hwc_layer_1_t hwLayers[0];//layer起始地址
- } hwc_display_contents_1_t;
再来看下每个layer的数据结构体hwc_layer_1 ,其主要数据在buffer_handle_t handle中,buffer_handle_t 其实就是native_handle_t之前分析过,里面有共享内存的fd和地址。
- typedef struct hwc_layer_1 {
- /*
- * compositionType is used to specify this layer's type and is set by either
- * the hardware composer implementation, or by the caller (see below).
- *
- * This field is always reset to HWC_BACKGROUND or HWC_FRAMEBUFFER
- * before (*prepare)() is called when the HWC_GEOMETRY_CHANGED flag is
- * also set, otherwise, this field is preserved between (*prepare)()
- * calls.
- *
- * HWC_BACKGROUND
- * Always set by the caller before calling (*prepare)(), this value
- * indicates this is a special "background" layer. The only valid field
- * is backgroundColor.
- * The HWC can toggle this value to HWC_FRAMEBUFFER to indicate it CANNOT
- * handle the background color.
- *
- *
- * HWC_FRAMEBUFFER_TARGET
- * Always set by the caller before calling (*prepare)(), this value
- * indicates this layer is the framebuffer surface used as the target of
- * OpenGL ES composition. If the HWC sets all other layers to HWC_OVERLAY
- * or HWC_BACKGROUND, then no OpenGL ES composition will be done, and
- * this layer should be ignored during set().
- *
- * This flag (and the framebuffer surface layer) will only be used if the
- * HWC version is HWC_DEVICE_API_VERSION_1_1 or higher. In older versions,
- * the OpenGL ES target surface is communicated by the (dpy, sur) fields
- * in hwc_compositor_device_1_t.
- *
- * This value cannot be set by the HWC implementation.
- *
- *
- * HWC_FRAMEBUFFER
- * Set by the caller before calling (*prepare)() ONLY when the
- * HWC_GEOMETRY_CHANGED flag is also set.
- *
- * Set by the HWC implementation during (*prepare)(), this indicates
- * that the layer will be drawn into the framebuffer using OpenGL ES.
- * The HWC can toggle this value to HWC_OVERLAY to indicate it will
- * handle the layer.
- *
- *
- * HWC_OVERLAY
- * Set by the HWC implementation during (*prepare)(), this indicates
- * that the layer will be handled by the HWC (ie: it must not be
- * composited with OpenGL ES).
- *
- *
- * HWC_SIDEBAND
- * Set by the caller before calling (*prepare)(), this value indicates
- * the contents of this layer come from a sideband video stream.
- *
- * The h/w composer is responsible for receiving new image buffers from
- * the stream at the appropriate time (e.g. synchronized to a separate
- * audio stream), compositing them with the current contents of other
- * layers, and displaying the resulting image. This happens
- * independently of the normal prepare/set cycle. The prepare/set calls
- * only happen when other layers change, or when properties of the
- * sideband layer such as position or size change.
- *
- * If the h/w composer can't handle the layer as a sideband stream for
- * some reason (e.g. unsupported scaling/blending/rotation, or too many
- * sideband layers) it can set compositionType to HWC_FRAMEBUFFER in
- * (*prepare)(). However, doing so will result in the layer being shown
- * as a solid color since the platform is not currently able to composite
- * sideband layers with the GPU. This may be improved in future
- * versions of the platform.
- *
- *
- * HWC_CURSOR_OVERLAY
- * Set by the HWC implementation during (*prepare)(), this value
- * indicates the layer's composition will now be handled by the HWC.
- * Additionally, the client can now asynchronously update the on-screen
- * position of this layer using the setCursorPositionAsync() api.
- */
- int32_t compositionType;
- /*
- * hints is bit mask set by the HWC implementation during (*prepare)().
- * It is preserved between (*prepare)() calls, unless the
- * HWC_GEOMETRY_CHANGED flag is set, in which case it is reset to 0.
- *
- * see hwc_layer_t::hints
- */
- uint32_t hints;
- /* see hwc_layer_t::flags */
- uint32_t flags;
- union {
- /* color of the background. hwc_color_t.a is ignored */
- hwc_color_t backgroundColor;
- struct {
- union {
- /* When compositionType is HWC_FRAMEBUFFER, HWC_OVERLAY,
- * HWC_FRAMEBUFFER_TARGET, this is the handle of the buffer to
- * compose. This handle is guaranteed to have been allocated
- * from gralloc using the GRALLOC_USAGE_HW_COMPOSER usage flag.
- * If the layer's handle is unchanged across two consecutive
- * prepare calls and the HWC_GEOMETRY_CHANGED flag is not set
- * for the second call then the HWComposer implementation may
- * assume that the contents of the buffer have not changed. */
- buffer_handle_t handle;
- /* When compositionType is HWC_SIDEBAND, this is the handle
- * of the sideband video stream to compose. */
- const native_handle_t* sidebandStream;
- };
- /* transformation to apply to the buffer during composition */
- uint32_t transform;
- /* blending to apply during composition */
- int32_t blending;
- /* area of the source to consider, the origin is the top-left corner of
- * the buffer. As of HWC_DEVICE_API_VERSION_1_3, sourceRect uses floats.
- * If the h/w can't support a non-integer source crop rectangle, it should
- * punt to OpenGL ES composition.
- */
- union {
- // crop rectangle in integer (pre HWC_DEVICE_API_VERSION_1_3)
- hwc_rect_t sourceCropi;
- hwc_rect_t sourceCrop; // just for source compatibility
- // crop rectangle in floats (as of HWC_DEVICE_API_VERSION_1_3)
- hwc_frect_t sourceCropf;
- };
- /* where to composite the sourceCrop onto the display. The sourceCrop
- * is scaled using linear filtering to the displayFrame. The origin is the
- * top-left corner of the screen.
- */
- hwc_rect_t displayFrame;
- /* visible region in screen space. The origin is the
- * top-left corner of the screen.
- * The visible region INCLUDES areas overlapped by a translucent layer.
- */
- hwc_region_t visibleRegionScreen;
- /* Sync fence object that will be signaled when the buffer's
- * contents are available. May be -1 if the contents are already
- * available. This field is only valid during set(), and should be
- * ignored during prepare(). The set() call must not wait for the
- * fence to be signaled before returning, but the HWC must wait for
- * all buffers to be signaled before reading from them.
- *
- * HWC_FRAMEBUFFER layers will never have an acquire fence, since
- * reads from them are complete before the framebuffer is ready for
- * display.
- *
- * HWC_SIDEBAND layers will never have an acquire fence, since
- * synchronization is handled through implementation-defined
- * sideband mechanisms.
- *
- * The HWC takes ownership of the acquireFenceFd and is responsible
- * for closing it when no longer needed.
- */
- int acquireFenceFd;
- /* During set() the HWC must set this field to a file descriptor for
- * a sync fence object that will signal after the HWC has finished
- * reading from the buffer. The field is ignored by prepare(). Each
- * layer should have a unique file descriptor, even if more than one
- * refer to the same underlying fence object; this allows each to be
- * closed independently.
- *
- * If buffer reads can complete at significantly different times,
- * then using independent fences is preferred. For example, if the
- * HWC handles some layers with a blit engine and others with
- * overlays, then the blit layers can be reused immediately after
- * the blit completes, but the overlay layers can't be reused until
- * a subsequent frame has been displayed.
- *
- * Since HWC doesn't read from HWC_FRAMEBUFFER layers, it shouldn't
- * produce a release fence for them. The releaseFenceFd will be -1
- * for these layers when set() is called.
- *
- * Since HWC_SIDEBAND buffers don't pass through the HWC client,
- * the HWC shouldn't produce a release fence for them. The
- * releaseFenceFd will be -1 for these layers when set() is called.
- *
- * The HWC client taks ownership of the releaseFenceFd and is
- * responsible for closing it when no longer needed.
- */
- int releaseFenceFd;
- /*
- * Availability: HWC_DEVICE_API_VERSION_1_2
- *
- * Alpha value applied to the whole layer. The effective
- * value of each pixel is computed as:
- *
- * if (blending == HWC_BLENDING_PREMULT)
- * pixel.rgb = pixel.rgb * planeAlpha / 255
- * pixel.a = pixel.a * planeAlpha / 255
- *
- * Then blending proceeds as usual according to the "blending"
- * field above.
- *
- * NOTE: planeAlpha applies to YUV layers as well:
- *
- * pixel.rgb = yuv_to_rgb(pixel.yuv)
- * if (blending == HWC_BLENDING_PREMULT)
- * pixel.rgb = pixel.rgb * planeAlpha / 255
- * pixel.a = planeAlpha
- *
- *
- * IMPLEMENTATION NOTE:
- *
- * If the source image doesn't have an alpha channel, then
- * the h/w can use the HWC_BLENDING_COVERAGE equations instead of
- * HWC_BLENDING_PREMULT and simply set the alpha channel to
- * planeAlpha.
- *
- * e.g.:
- *
- * if (blending == HWC_BLENDING_PREMULT)
- * blending = HWC_BLENDING_COVERAGE;
- * pixel.a = planeAlpha;
- *
- */
- uint8_t planeAlpha;
- /* Pad to 32 bits */
- uint8_t _pad[3];
- /*
- * Availability: HWC_DEVICE_API_VERSION_1_5
- *
- * This defines the region of the source buffer that has been
- * modified since the last frame.
- *
- * If surfaceDamage.numRects > 0, then it may be assumed that any
- * portion of the source buffer not covered by one of the rects has
- * not been modified this frame. If surfaceDamage.numRects == 0,
- * then the whole source buffer must be treated as if it had been
- * modified.
- *
- * If the layer's contents are not modified relative to the prior
- * prepare/set cycle, surfaceDamage will contain exactly one empty
- * rect ([0, 0, 0, 0]).
- *
- * The damage rects are relative to the pre-transformed buffer, and
- * their origin is the top-left corner.
- */
- hwc_region_t surfaceDamage;
- };
- };
- #ifdef __LP64__
- /*
- * For 64-bit mode, this struct is 120 bytes (and 8-byte aligned), and needs
- * to be padded as such to maintain binary compatibility.
- */
- uint8_t reserved[120 - 112];
- #else
- /*
- * For 32-bit mode, this struct is 96 bytes, and needs to be padded as such
- * to maintain binary compatibility.
- */
- uint8_t reserved[96 - 84];
- #endif
- } hwc_layer_1_t;
回到setUpHWComposer函数,下面是变量所有的设备上的layer调用其setPerFrameData函数。
在分析setPerFrameData之前我们先分析下setUpHWComposer中的遍历Layer时候用到的cur和end。我把这段代码单独拿出来。
- HWComposer::LayerListIterator cur = hwc.begin(id);
- const HWComposer::LayerListIterator end = hwc.end(id);
- for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
- /*
- * update the per-frame h/w composer data for each layer
- * and build the transparent region of the FB
- */
- const sp<Layer>& layer(currentLayers[i]);
- layer->setPerFrameData(hw, *cur);
- }
- HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
- return getLayerIterator(id, 0);
- }
再来看下getLayerIterator函数,正常应该是最后一个分支。注意这个时候index是0
- HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
- if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
- return LayerListIterator();
- }
- const DisplayData& disp(mDisplayData[id]);
- if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
- return LayerListIterator();
- }
- return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index);
- }
- class LayerListIterator {
- friend class HWComposer;
- HWCLayer* const mLayerList;
- size_t mIndex;
- LayerListIterator() : mLayerList(NULL), mIndex(0) { }
- LayerListIterator(HWCLayer* layer, size_t index)
- : mLayerList(layer), mIndex(index) { }
- // we don't allow assignment, because we don't need it for now
- LayerListIterator& operator = (const LayerListIterator& rhs);
- public:
- // copy operators
- LayerListIterator(const LayerListIterator& rhs)
- : mLayerList(HWCLayer::copy(rhs.mLayerList)), mIndex(rhs.mIndex) {
- }
- ~LayerListIterator() { delete mLayerList; }
- // pre-increment
- LayerListIterator& operator++() {
- mLayerList->setLayer(++mIndex);
- return *this;
- }
- // dereference
- HWCLayerInterface& operator * () { return *mLayerList; }
- HWCLayerInterface* operator -> () { return mLayerList; }
- // comparison
- bool operator == (const LayerListIterator& rhs) const {
- return mIndex == rhs.mIndex;
- }
- bool operator != (const LayerListIterator& rhs) const {
- return !operator==(rhs);
- }
- };
而我们再来看看下HWComposer中的end函数,end函数和begin很像只是在调用getLayerIterator的时候,begin传入0,end传入layer的最后一位。最后就是mIndex成员变量不一样
- HWComposer::LayerListIterator HWComposer::end(int32_t id) {
- size_t numLayers = 0;
- if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
- const DisplayData& disp(mDisplayData[id]);
- if (mHwc && disp.list) {
- numLayers = disp.list->numHwLayers;//获取到list中laye的个数
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
- // which we ignore when iterating through the layer list.
- ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id);
- if (numLayers) {
- numLayers--;//变成最后一位
- }
- }
- }
- }
- return getLayerIterator(id, numLayers);//和上面一样,只是传入的index不一样。
- }
我们再来看LayerListIterator操作符++的重载,会调用mLayerList->setLayer函数
- LayerListIterator& operator++() {
- mLayerList->setLayer(++mIndex);
- return *this;
- }
- virtual status_t setLayer(size_t index) {
- mCurrentLayer = &mLayerList[index];
- return NO_ERROR;
- }
- void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
- HWComposer::HWCLayerInterface& layer) {
- // we have to set the visible region on every frame because
- // we currently free it during onLayerDisplayed(), which is called
- // after HWComposer::commit() -- every frame.
- // Apply this display's projection's viewport to the visible region
- // before giving it to the HWC HAL.
- const Transform& tr = hw->getTransform();
- Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
- layer.setVisibleRegionScreen(visible);
- layer.setSurfaceDamage(surfaceDamageRegion);
- if (mSidebandStream.get()) {
- layer.setSidebandStream(mSidebandStream);
- } else {
- // NOTE: buffer can be NULL if the client never drew into this
- // layer yet, or if we ran out of memory
- layer.setBuffer(mActiveBuffer);
- }
- }
- virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
- if (buffer == 0 || buffer->handle == 0) {
- getLayer()->compositionType = HWC_FRAMEBUFFER;
- getLayer()->flags |= HWC_SKIP_LAYER;
- getLayer()->handle = 0;
- } else {
- if (getLayer()->compositionType == HWC_SIDEBAND) {
- // If this was a sideband layer but the stream was removed, reset
- // it to FRAMEBUFFER. The HWC can change it to OVERLAY in prepare.
- getLayer()->compositionType = HWC_FRAMEBUFFER;
- }
- getLayer()->handle = buffer->handle;
- }
- }
- status_t HWComposer::prepare() {
- Mutex::Autolock _l(mDisplayLock);
- for (size_t i=0 ; i<mNumDisplays ; i++) {
- DisplayData& disp(mDisplayData[i]);
- if (disp.framebufferTarget) {//这里其实就是disp.list中最后一个layer
- // make sure to reset the type to HWC_FRAMEBUFFER_TARGET
- // DO NOT reset the handle field to NULL, because it's possible
- // that we have nothing to redraw (eg: eglSwapBuffers() not called)
- // in which case, we should continue to use the same buffer.
- LOG_FATAL_IF(disp.list == NULL);
- disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
- }
- if (!disp.connected && disp.list != NULL) {
- ALOGW("WARNING: disp %zu: connected, non-null list, layers=%zu",
- i, disp.list->numHwLayers);
- }
- mLists[i] = disp.list;//DisplayData的list就是mList的一个组员
- if (mLists[i]) {
- if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
- mLists[i]->outbuf = disp.outbufHandle;
- mLists[i]->outbufAcquireFenceFd = -1;
- } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
- // garbage data to catch improper use
- mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;
- mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;
- } else {
- mLists[i]->dpy = EGL_NO_DISPLAY;
- mLists[i]->sur = EGL_NO_SURFACE;
- }
- }
- }
- int err = mHwc->prepare(mHwc, mNumDisplays, mLists);//调用Hwc模块的prepare函数
- ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));
- if (err == NO_ERROR) {
- // here we're just making sure that "skip" layers are set
- // to HWC_FRAMEBUFFER and we're also counting how many layers
- // we have of each type.
- //
- // If there are no window layers, we treat the display has having FB
- // composition, because SurfaceFlinger will use GLES to draw the
- // wormhole region.
- for (size_t i=0 ; i<mNumDisplays ; i++) {
- DisplayData& disp(mDisplayData[i]);
- disp.hasFbComp = false;
- disp.hasOvComp = false;
- if (disp.list) {
- for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
- hwc_layer_1_t& l = disp.list->hwLayers[i];
- //ALOGD("prepare: %d, type=%d, handle=%p",
- // i, l.compositionType, l.handle);
- if (l.flags & HWC_SKIP_LAYER) {
- l.compositionType = HWC_FRAMEBUFFER;
- }
- if (l.compositionType == HWC_FRAMEBUFFER) {
- disp.hasFbComp = true;
- }
- if (l.compositionType == HWC_OVERLAY) {
- disp.hasOvComp = true;
- }
- if (l.compositionType == HWC_CURSOR_OVERLAY) {
- disp.hasOvComp = true;
- }
- }
- if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
- disp.hasFbComp = true;
- }
- } else {
- disp.hasFbComp = true;
- }
- }
- }
- return (status_t)err;
- }