上一篇博客分析了,用户进程如何申请一个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();
调用commitTransaction和updateCursorAsync函数 commitTransaction函数作用是把mDrawingState的值设置成mCurrentState的值。而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放在layersWithQueuedFrames,然后调用每个Layer的latchBuffer函数。
调用每个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);
}
}
}
orSelf方法,就是把Layer的更新区域 加到 DisplayDevice的dirtyRegion区域上。
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;
}
我们再来看看updateAndReleaseLocked函数,这个函数释放了buffer,然后更新了mCurrentTexture mCurrentTextureImage等。
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;
}
最后Layer的mActiveBuffer是从mSurfaceFlingerConsumer->getCurrentBuffer(),而就是mCurrentTextureImage变量。
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);
}
}
}
我们先来看下createWorkList函数,我们先为DisplayData的list申请内存,这个内存要先hwc_display_contents_1_t结构体本身的长度加上后面hwc_layer_1_t个数的长度。后面用DisplayData中list中hwLayers最后一个作为DisplayData中的framebufferTarget。
注意到这个细节没有,当支持egl合成的时候,会把numLayers加1,这是因为如果支持egl合成list最后一个layer是egl合成后的buffer用的,所以要增加一个layer,而前面都是普通的layer。
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中的begin函数
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);
}
新建了一个LayerListIterator,这里面HWCLayerVersion1就是mLayerList, index就是mIndex. 我们看下*符号的重载,因为我们后面用到了,就是mLayerList。
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);
}
};
而上面的mLayerList就是HWCLayerVersion1对象。
而我们再来看看下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;
}
setLayer会从mLayerList中设置当前的mCurrentLayer,通过mLayerList, 这个变量就是disp.list->hwLayers
virtual status_t setLayer(size_t index) {
mCurrentLayer = &mLayerList[index];
return NO_ERROR;
}
这样准备工作就好了,我们再来分析Layer的setPerFrameData函数,主要就是调用了HWCLayerVersion1的setBuffer函数
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);
}
}
再来看HWCLayerVersion1的setBuffer函数,调用getLayer函数设置其handle,而getLayer就是mCurrentLayer。之前mCurrentLayer会一个个遍历各个Layer,这样就把所有的layer都设置其handle,就是hwc_layer_1_t中的handle。
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;
}
}
最后会调用HWComposer的prepare函数,我们再来看下这个函数。这里我们先将DisplayData的framebufferTarget的composition设置为HWC_FRAMEBUFFER_TARGET,然后将每个DisplayData的list放入mList中。最后调用了mHwc的prepare函数。
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;
}
mHwc的prepare主要将每个Layer的composition设置为HWC_FRAMEBUFFER。