经过前面两篇的介绍,现在可以分析surfaceflinger 的处理UI buffer的流程了
目录
一、onMessageReceived
1、handleMessageTransaction()
2、handleMessageInvalidate():
3、 signalRefresh();
① preComposition():
② rebuildLayerStacks():
③setUpHWComposer
④doComposition
一、onMessageReceived
通过vsync机制知道,最终会跑到onMessageReceived函数 ::INVALIDATE这里,进行图像输出的准备工作。
void SurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL();
switch (what) {
case MessageQueue::TRANSACTION:
handleMessageTransaction();
break;
case MessageQueue::INVALIDATE:
handleMessageTransaction();
handleMessageInvalidate();
signalRefresh();
break;
case MessageQueue::REFRESH:
handleMessageRefresh();
break;
}
}
case MessageQueue::INVALIDATE:会调用三个方法,分别看一下:
1、handleMessageTransaction()
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
.....
/*1、
* Traversal of the children
* (perform the transaction for each of them if needed)
*/
if (transactionFlags & eTraversalNeeded) {
for (size_t i=0 ; i<count ; i++) {//这里遍历每一个Layer,根据eTraversalNeeded标志来决定是否要检查Layer对象。如果Layer中有eTransactionNeeded标志,则返回非0值,然后调用它的doTransaction函数
const sp<Layer>& layer(currentLayers[i]);
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
if (!trFlags) continue;
const uint32_t flags = layer->doTransaction(0);
if (flags & Layer::eVisibleRegion)//Layer的doTransaction函数返回的flags如果有eVisibleRegion,则说明该Layer需要更新,mVisibleRegionsDirty设置为true
mVisibleRegionsDirty = true;
}
}
/*2、
* Perform display own transactions if needed
*/
if (transactionFlags & eDisplayTransactionNeeded) {
// here we take advantage of Vector's copy-on-write semantics to
// improve performance by skipping the transaction entirely when
// know that the lists are identical
//得到当前显示设备列表和之前使用的显示设备列表
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();//以前显示设备的数量
// find the displays that were removed
// (ie: in drawing state but not in current state)
// also handle displays that changed
// (ie: displays that are in both lists)
for (size_t i=0 ; i<dc ; i++) {
const ssize_t j = curr.indexOfKey(draw.keyAt(i));
if (j < 0) {//设备被删除
// in drawing state but not in current state
if (!draw[i].isMainDisplay()) {
// Call makeCurrent() on the primary display so we can
// be sure that nothing associated with this display
// is current.
const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
if (hw != NULL)
hw->disconnect(getHwComposer());
if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
mEventThread->onHotplugReceived(draw[i].type, false);
mDisplays.removeItem(draw.keyAt(i));//如果不是主设备移除它
} else {
ALOGW("trying to remove the main display");
}
} else {//设备还在,再检查有没有其他变化
// this display is in both lists. see if something changed.
const DisplayDeviceState& state(curr[j]);
const wp<IBinder>& display(curr.keyAt(j));
if (state.surface->asBinder() != draw[i].surface->asBinder()) {
// changing the surface is like destroying and
// recreating the DisplayDevice, so we just remove it
// from the drawing state, so that it get re-added
// below.
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) {
if (state.layerStack != draw[i].layerStack) {//两个对象layerStack不等,使用当前对象的
disp->setLayerStack(state.layerStack);
}
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);
}
}
}
}
//处理显示设备增加的情况。。。
// find displays that were added
// (ie: in current state but not in drawing state)
for (size_t i=0 ; i<cc ; i++) {
...............................
}
3、
//这段代码根据每种显示设备的不同,设置和显示设备关联在一起的Layer(主要看Layer的layerStack是否和DisplayDevice的layerStack一致)的TransformHint(主要指设备的显示方向orientation)
if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
// The transform hint might have changed for some layers
// (either because a display has changed, or because a layer
// as changed).
..............................
layer->updateTransformHint(disp);//设置Layer对象的TransformHint
}
/*4、
* Perform our own transaction if needed
*/
const LayerVector& layers(mDrawingState.layersSortedByZ);
if (currentLayers.size() > layers.size()) {//如果有Layer加入,设置需要更新
// layers have been added
mVisibleRegionsDirty = true;
}
// some layers might have been removed, so
// we need to update the regions they're exposing.
if (mLayersRemoved) {//有Layer删除
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不存在,则把它的所在区域设置为需要更新的区域
// this layer is not visible anymore
// TODO: we could traverse the tree from front to back and
// compute the actual visible region
// TODO: we could cache the transformed region
const Layer::State& s(layer->getDrawingState());
Region visibleReg = s.transform.transform(
Region(Rect(s.active.w, s.active.h)));
invalidateLayerStack(s.layerStack, visibleReg);
}
}
}
commitTransaction();//commitTransaction函数最关键的作用是把mDrawingState的值设置成mCurrentState的值。
}
handleTransactionLocked 做了下面几件事:
①在 handleTransactionLocked 函数里面遍历每一个children,调用 layer->doTransaction(0),查看layer是否发生改变,如果是就把 mVisibleRegionsDirty 置为 true 。
②处理显示设备相关的事务,add、remove、change等。
- 移除不需要的显示设备,将其对应的DisplayDevice移除
- 对于发生变化的显示设备(设置Surface、重置layerStack、旋转。。。),就需要重置显示对象的属性
- 对于新增加的显示设备,创建DisplayDevice并加入到系统
③layer的角度发生变化处理。
④surfaceflinger 本身的事务处理,如layer的添加、删除等。
- 如果有Layer增加,需要重新计算设备的更新区域,mVisibleRegionsDirty设置为true
- 如果有Layer被删除,需要把Layer的可见区域加入到系统需要更新的区域中
①.1 分析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) ||
(c.requested.h != s.requested.h);
if (sizeChanged) {//如果两个对象的大小不相等,说明Layer的尺寸发生变化
// the size changed, we need to ask our client to request a new buffer
// record the new size, form this point on, when the client request
// a buffer, it'll get the new size.
mSurfaceFlingerConsumer->setDefaultBufferSize(
c.requested.w, c.requested.h);
}
if (!isFixedSize()) {
const bool resizePending = (c.requested.w != c.active.w) ||
(c.requested.h != c.active.h);
if (resizePending) {
// don't let Layer::doTransaction update the drawing state
// if we have a pending resize, unless we are in fixed-size mode.
// the drawing state will be updated only once we receive a buffer
// with the correct size.
//
// in particular, we want to make sure the clip (which is part
// of the geometry state) is latched together with the size but is
// latched immediately when no resizing is involved.
flags |= eDontUpdateGeometryState;
}
}
// always set active to requested, unless we're asked not to
// this is used by Layer, which special cases resizes.
if (flags & eDontUpdateGeometryState) {
} else {如果没有eDontUpdateGeometryState标志,更新active的值为request
Layer::State& editCurrentState(getCurrentState());
editCurrentState.active = c.requested;
}
if (s.active != c.active) {// 如果当前state的active和以前的State的active不等,设置更新标志
// invalidate and recompute the visible regions if needed
flags |= Layer::eVisibleRegion;
}
if (c.sequence != s.sequence) {//如果当前state的sequence和以前state的sequence不等,设置更新标志
// invalidate and recompute the visible regions if needed
flags |= eVisibleRegion;
this->contentDirty = true;
// we may use linear filtering, if the matrix scales us
const uint8_t type = c.transform.getType();
mNeedsFiltering = (!c.transform.preserveRects() ||
(type >= Transform::SCALE));
}
// Commit the transaction
commitTransaction();//将mCurrentState的值赋给mDrawingState
return flags;
}
其中Layer::State 是啥?
struct State {
Geometry active;//实际大小
Geometry requested;//用户大小
uint32_t z;//Z轴值
uint32_t layerStack;//和显示设备的关联值
uint8_t alpha;
uint8_t flags;
uint8_t reserved[2];
int32_t sequence; // changes when visible regions can change
Transform transform;//序列值,Layer的属性变化一次,这个值就加1
// the transparentRegion hint is a bit special, it's latched only
// when we receive a buffer -- this is because it's "content"
// dependent.
Region activeTransparentRegion;//实际的透明区域
Region requestedTransparentRegion;//用户层的透明区域
};
Layer对象在绘制图形时,使用的是mDrawingState变量,用户调用接口设置Layer对象属性是,设置的值保存在mCurrentState对象中,这样就不会因为用户的操作而干扰Layer对象的绘制了。所以这里有两个对象。
接下来对State 结构体中的一些变量进行说明:
- Geometry字段:State的结构中有两个Geometry字段,active和requested。他们表示layer的尺寸,其中requested保存是用户设置的尺寸,而active保存的值通过计算后的实际尺寸。
- layerStack字段:它是用户指定的一个值,用户可以给DisplayDevice也指定一个layerStack值,只有Layer对象和DisplayDevice对象的layerStack相等,这个Layer才能在这个显示设备上输出,这样的好处是可以让显示设备只显示某个Surface的内容。例如,可以让HDMI显示设备只显示手机上播放视频的Surface窗口,但不显示Activity窗口。
- sequence字段:它是一个序列值,每当用户调用了Layer的接口,例如setAlpha、setSize或者setLayer等改变Layer对象属性的哈数,这个值都会加1。因此在doTransaction函数中能通过比较sequence值来判断Layer的属性值有没有变化。
可以看到Layer::State中的layerStack中会对比DisplayDeviceState对象的layerStack,所以分析下DisplayDeviceState,定义在surfaceFlinger.h里面 ,代码如下:
struct DisplayDeviceState {
DisplayDeviceState();
DisplayDeviceState(DisplayDevice::DisplayType type);
bool isValid() const { return type >= 0; }
bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
DisplayDevice::DisplayType type;
sp<IGraphicBufferProducer> surface;
uint32_t layerStack;
Rect viewport;
Rect frame;
uint8_t orientation;
uint32_t width, height;
String8 displayName;
bool isSecure;
};
DisplayDeviceState的layerStack和Layer的State中的layerStack如果相等,则Layer可以在该State对应的DisplayDevice中显示。
总结下,虽然处理了很多事物,但主要是设置一些flag,但并未对相关的Buffer进行实际的操作。handleTransaction函数的作用的就是处理系统在两次刷新期间的各种变化。SurfaceFlinger模块 中不管是SurfaceFlinger类还是Layer类,都采用了双缓冲的方式来保存他们的属性,这样的好处是刚改变SurfaceFlinger对象或者Layer类对象的属性时不需要上锁,这很大程度上提高了系统效率。只有在最后的图像输出才会进行一次上锁,并将内存的属性变化进行处理。正因此,应用进程必须收到VSync信号才开始改变Surface中Buffer的内容。
2、handleMessageInvalidate():
handleMessageInvalidate 里面主要干的事情是,让原来的图像数据失效,准备好新的图像数据,主要是在SurfaceFlingerConsumer 的那几步,也就是updateTextImage里面做的那几步。
这里解释一下UML里面几个重要的函数:
void SurfaceFlinger::handlePageFlip()
{
Region dirtyRegion;
bool visibleRegions = false;
const LayerVector& layers(mDrawingState.layersSortedByZ);
// Store the set of layers that need updates. This set must not change as
// buffers are being latched, as this could result in a deadlock.
// Example: Two producers share the same command stream and:
// 1.) Layer 0 is latched
// 2.) Layer 0 gets a new frame
// 2.) Layer 1 gets a new frame
// 3.) Layer 1 is latched.
// Display is now waiting on Layer 1's frame, which is behind layer 0's
// second frame. But layer 0's second frame could be waiting on display.
Vector<Layer*> layersWithQueuedFrames;
for (size_t i = 0, count = layers.size(); i<count ; i++) {
const sp<Layer>& layer(layers[i]);
if (layer->hasQueuedFrame())//确定这个Layer对象是否有需要更新的图层
layersWithQueuedFrames.push_back(layer.get());//把需要更新的Layer对象放到layersWithQueuedFrames中
}
for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
Layer* layer = layersWithQueuedFrames[i];
//更新Layer对象的latchBuffer函数
const Region dirty(layer->latchBuffer(visibleRegions));
const Layer::State& s(layer->getDrawingState());
//设置更新设备对象的更新区域
invalidateLayerStack(s.layerStack, dirty);
}
mVisibleRegionsDirty |= visibleRegions;
}
layer的hasQueuedFrame()的代码实现如下:
bool hasQueuedFrame() const { return mQueuedFrames > 0 || mSidebandStreamChanged; }
只要Surface有数据写入,就会调用Layer的onFrameAvailable函数,然后mQueuedFrames值加1。
latchBuffer:
Region Layer::latchBuffer(bool& recomputeVisibleRegions)
{
...
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());
const bool oldOpacity = isOpaque(s);
sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
//定义Reject结构体...
};
Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
getProducerStickyTransform() != 0);
//更新纹理,得到需要的图像
status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
mFlinger->mPrimaryDispSync);
//如果结果是推迟处理,发送Invalidate消息
if (updateResult == BufferQueue::PRESENT_LATER) {
mFlinger->signalLayerUpdate();
return outDirtyRegion;
}
{ // Autolock scope
Mutex::Autolock lock(mQueueItemLock);
mQueueItems.removeAt(0);
}
//减少mQueuedFrames的值
if (android_atomic_dec(&mQueuedFrames) > 1) {
//如果还有更多frame需要处理,要发消息
mFlinger->signalLayerUpdate();
}
if (updateResult != NO_ERROR) {
recomputeVisibleRegions = true;
return outDirtyRegion;
}
//更新mActiveBuffer,得到现在需要输出的图像数据
mActiveBuffer = mSurfaceFlingerConsumer->getCurrentBuffer();
if (mActiveBuffer == NULL) {
return outDirtyRegion;//出错
}
mRefreshPending = true;
mFrameLatencyNeeded = true;
//下面根据各种情况是否重新计算更新区域
if (oldActiveBuffer == NULL) {
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;
}
Region dirtyRegion(Rect(s.active.w, s.active.h));
outDirtyRegion = (s.transform.transform(dirtyRegion));
}
return outDirtyRegion;
}
latchBuffer函数调用updateTextImage来得到需要的图像纹理。这里参数r是Reject对象,其作用是判断在缓冲区的尺寸是否符合要求。updateTextImage的代码实现如下:
status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter)
{
ATRACE_CALL();
ALOGV("updateTexImage");
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;
}
BufferQueue::BufferItem item;
// 1、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());
if (err != NO_ERROR) {
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
err = NO_ERROR;
} else if (err == BufferQueue::PRESENT_LATER) {
// return the error, without logging
} else {
ALOGE("updateTexImage: acquire failed: %s (%d)",
strerror(-err), err);
}
return err;
}
// We call the rejecter here, in case the caller has a reason to
// not accept this buffer. This is used by SurfaceFlinger to
// reject buffers which have the wrong size
int buf = item.mBuf;
if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR);
return NO_ERROR;
}
//2、 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.
//3、
err = bindTextureImageLocked();
}
return err;
}
在看 bindTextureImageLocked 之前,先看看acquireBufferLocked、releaseBufferLocked两函数:
但是在这之前还要了解一下Android 的buffer状态图画 :
APP 作为我们的生产者,他会从FREE状态里面的buffer,dequeue 一个出来,向其填充数据,但APP 调用surface->unlock,的时候,DEQUEUED状态的buffer会变成QUEUED转态的buffer,当执行到updateTextImage 函数时,我们的消费者,会从QUEUED状态里面的buffer acquire 一个出来,变成ACQUIRED状态,当消费完之后会调用releaseBufferLocked,将ACQUIRED转态的buffer release掉,又变回FREE状态。下次生产者又可以拿来用了。
PS 注: QueueBuffer 的使用过程的4种状态:
( 1)FREE表示该Buffer没有被使用,且内容为空
( 2 ) DEQUEUED表示该Buffer正在被内容生产者绘制
( 3 ) QUEUED表示该Buffer已经被绘制了内容,放入BufferQueue,等待被显示(或者下一步处理)
( 4 ) ACQUIRED表示该Buffer正在被消费者拿去做显示(或者下一步处理)
acquireBufferLocked 会调用到 ConsumerBase::acquireBufferLocked 函数如下:
status_t ConsumerBase::acquireBufferLocked(BufferQueue::BufferItem *item,
nsecs_t presentWhen) {
status_t err = mConsumer->acquireBuffer(item, presentWhen);
if (err != NO_ERROR) {
return err;
}
if (item->mGraphicBuffer != NULL) {
mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
}
mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
mSlots[item->mBuf].mFence = item->mFence;
CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
item->mBuf, item->mFrameNumber);
return OK;
}
可以看见 这个函数里面调用了 mConsumer->acquireBuffer(item, presentWhen); mConsumer 是谁?mConsumer 就是 BufferQueueConsumer 类的对象,怎么来的看下:
void Layer::onFirstRef() {
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
mProducer = new MonitoredProducer(producer, mFlinger);
mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mSurfaceFlingerConsumer->setContentsChangedListener(this);
mSurfaceFlingerConsumer->setName(mName);
#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
#warning "disabling triple buffering"
mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
#else
mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
#endif
const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
updateTransformHint(hw);
}
即是在创建 SurfaceControl 的时候,触发 Layer::onFirstRef ()时,mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);传进去的consumer,最终复制给了mConsumer,所以mConsumer 就是BufferQueueConsumer。所以mConsumerr->acquireBuffer(item, presentWhen)最终会调用到BufferQueueConsumer::acquireBuffer()
status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
nsecs_t expectedPresent) {
ATRACE_CALL();
Mutex::Autolock lock(mCore->mMutex);
// Check that the consumer doesn't currently have the maximum number of
// buffers acquired. We allow the max buffer count to be exceeded by one
// buffer so that the consumer can successfully set up the newly acquired
// buffer before releasing the old one.
int numAcquiredBuffers = 0;
for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
++numAcquiredBuffers;
}
}
if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
BQ_LOGE("acquireBuffer: max acquired buffer count reached: %d (max %d)",
numAcquiredBuffers, mCore->mMaxAcquiredBufferCount);
return INVALID_OPERATION;
}
// Check if the queue is empty.
// In asynchronous mode the list is guaranteed to be one buffer deep,
// while in synchronous mode we use the oldest buffer.
if (mCore->mQueue.empty()) {
return NO_BUFFER_AVAILABLE;
}
BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
// If expectedPresent is specified, we may not want to return a buffer yet.
// If it's specified and there's more than one buffer queued, we may want
// to drop a buffer.
if (expectedPresent != 0) {
const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
// The 'expectedPresent' argument indicates when the buffer is expected
// to be presented on-screen. If the buffer's desired present time is
// earlier (less) than expectedPresent -- meaning it will be displayed
// on time or possibly late if we show it as soon as possible -- we
// acquire and return it. If we don't want to display it until after the
// expectedPresent time, we return PRESENT_LATER without acquiring it.
//
// To be safe, we don't defer acquisition if expectedPresent is more
// than one second in the future beyond the desired present time
// (i.e., we'd be holding the buffer for a long time).
//
// NOTE: Code assumes monotonic time values from the system clock
// are positive.
// Start by checking to see if we can drop frames. We skip this check if
// the timestamps are being auto-generated by Surface. If the app isn't
// generating timestamps explicitly, it probably doesn't want frames to
// be discarded based on them.
while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
// If entry[1] is timely, drop entry[0] (and repeat). We apply an
// additional criterion here: we only drop the earlier buffer if our
// desiredPresent falls within +/- 1 second of the expected present.
// Otherwise, bogus desiredPresent times (e.g., 0 or a small
// relative timestamp), which normally mean "ignore the timestamp
// and acquire immediately", would cause us to drop frames.
//
// We may want to add an additional criterion: don't drop the
// earlier buffer if entry[1]'s fence hasn't signaled yet.
const BufferItem& bufferItem(mCore->mQueue[1]);
nsecs_t desiredPresent = bufferItem.mTimestamp;
if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
desiredPresent > expectedPresent) {
// This buffer is set to display in the near future, or
// desiredPresent is garbage. Either way we don't want to drop
// the previous buffer just to get this on the screen sooner.
BQ_LOGV("acquireBuffer: nodrop desire=%" PRId64 " expect=%"
PRId64 " (%" PRId64 ") now=%" PRId64,
desiredPresent, expectedPresent,
desiredPresent - expectedPresent,
systemTime(CLOCK_MONOTONIC));
break;
}
BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
" size=%zu",
desiredPresent, expectedPresent, mCore->mQueue.size());
if (mCore->stillTracking(front)) {
// Front buffer is still in mSlots, so mark the slot as free
mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
}
mCore->mQueue.erase(front);
front = mCore->mQueue.begin();
}
// See if the front buffer is due
nsecs_t desiredPresent = front->mTimestamp;
if (desiredPresent > expectedPresent &&
desiredPresent < expectedPresent + MAX_REASONABLE_NSEC) {
BQ_LOGV("acquireBuffer: defer desire=%" PRId64 " expect=%" PRId64
" (%" PRId64 ") now=%" PRId64,
desiredPresent, expectedPresent,
desiredPresent - expectedPresent,
systemTime(CLOCK_MONOTONIC));
return PRESENT_LATER;
}
BQ_LOGV("acquireBuffer: accept desire=%" PRId64 " expect=%" PRId64 " "
"(%" PRId64 ") now=%" PRId64, desiredPresent, expectedPresent,
desiredPresent - expectedPresent,
systemTime(CLOCK_MONOTONIC));
}
int slot = front->mSlot;
*outBuffer = *front;
ATRACE_BUFFER_INDEX(slot);
BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
slot, front->mFrameNumber, front->mGraphicBuffer->handle);
// If the front buffer is still being tracked, update its slot state
if (mCore->stillTracking(front)) {
mSlots[slot].mAcquireCalled = true;
mSlots[slot].mNeedsCleanupOnRelease = false;
mSlots[slot].mBufferState = BufferSlot::ACQUIRED;
mSlots[slot].mFence = Fence::NO_FENCE;
}
// If the buffer has previously been acquired by the consumer, set
// mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
// on the consumer side
if (outBuffer->mAcquireCalled) {
outBuffer->mGraphicBuffer = NULL;
}
mCore->mQueue.erase(front);
// We might have freed a slot while dropping old buffers, or the producer
// may be blocked waiting for the number of buffers in the queue to
// decrease.
mCore->mDequeueCondition.broadcast();
ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
return NO_ERROR;
}
其实就是从mCore->mQueue 队列中取出第一个构造好的buffer。
同理如此分析releaseBufferLocked 函数。
回过头看一下 bindTextureImageLocked函数 : 作用就是将新的缓冲区绑定到GL纹理,OpenGL 相关了。
status_t GLConsumer::bindTextureImageLocked() {
............
glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
..........
return doGLFenceWaitLocked();
}
Region 了解
对于我们桌面上的图像,他是按照Layer 一层一层的铺上的,若是Layer 的Z值比较到,那么他就越在其他Layer的上层。
对于个每一个Layer 都有透明度的概念:
①、opaque:不透明,如果这个layer的某个区域设置的是不透明,那么这个Layer层的下面的Layer 就不会被看见。
②、transparent : 全透明,可以完全看见下面层的Layer。
③、translucent : 半透明,还是可以看见下面层的Layer。
在程序中,通过Region 结构体来表述透明度。
Region 由一系列的Rect(矩形)组成,这些矩形从上到下,从左到右排列出来,并且各个矩形的Y轴坐标相同(对于Y轴坐标相同的矩形X轴无交叉)或者无交叉。
Span :一组Rect ,Y轴一样,X轴无交叉。
Region定义的文件:frameworks\native\include\ui\Region.h ,里面有一个 Vector<Rect> mStorage; 成员变量。mStorage的最后一项表示边界
- 如果Region只是一个简单的矩形区域,则mStorage只包含一个Rect类型的元素。
- 如果Region中包含多个矩形区域,则mStorage只包含多个Rect类型的元素+最后元素(这块区域的边界)。
3、 signalRefresh();
void SurfaceFlinger::signalRefresh() {
mEventQueue.refresh();
}
导致 case MessageQueue::REFRESH:下的 handleMessageRefresh();被调用。
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
preComposition(); //关键点1 合成前预处理
rebuildLayerStacks();//关键点2 计算可见区域,主要依据:z-order大的覆盖有重叠区域z-order小的
//关键点3 下面几个方法都是页面合成相关
setUpHWComposer();
doDebugFlashRegions();
doComposition();//关键点4 合成所有层的图像, 经过这一步后,就显示新的内容了
postComposition();//合成之后的工作
}
handleMessageRefresh
在handleMessageRefresh 函数里面,做的主要的工作是:
①计算各个Layer的显示区域
②合成并且显示,可以通过OpenGL的方式把每个layer的可视区域在一个内存里面描述出来;也可以通过硬件 HWComposer合成出来。
① preComposition():
处理一些标志位。
② rebuildLayerStacks():
显然rebuildLayerStacks()函数就是来处理各个Layer的显示区域。
在分析之前需要明确个基本概念:
- dirtyRegion:表示该区域是需要被刷新的。
- opaqueRegion:表示不透明区域。
- transparentRegion:表示完全透明区域。
- translucentRegion:表示半透明区域。
rebuildLayerStacks主要是做两件事:
- 重建每个显示设备的可见layer对象的列表。layer按照Z序排列,但每个Layer都有 透明区、不透明区、半透明区即下面的Layer某些区域也是有机会显示的
- 对每个显示设备,先计算和显示设备相同的layerStack值的layer对象在显示设备上的可见区域,然后将可见区域和显示设备的窗口有交集的layer组成一个新的列表,最后把这个列表设置到显示设备对象中。
void SurfaceFlinger::rebuildLayerStacks() {
// rebuild the visible layer list per screen
if (CC_UNLIKELY(mVisibleRegionsDirty)) {
ATRACE_CALL();
mVisibleRegionsDirty = false;
invalidateHwcGeometry();
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->canDraw()) {
SurfaceFlinger::computeVisibleRegions(layers,
hw->getLayerStack(), dirtyRegion, opaqueRegion);//计算每个Layer的可见区域,确定设备需要重新绘制的区域
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()) {//只需要和显示设备的layerStacek相同的Layer
Region drawRegion(tr.transform(
layer->visibleNonTransparentRegion));
drawRegion.andSelf(bounds);
if (!drawRegion.isEmpty()) {
//如果Layer的显示区域和显示设备的窗口有交集
//把Layer加入到列表中
layersSortedByZ.add(layer);
}
}
}
}
hw->setVisibleLayersSortedByZ(layersSortedByZ);//设置显示设备的可见Layer列表
hw->undefinedRegion.set(bounds);
hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
hw->dirtyRegion.orSelf(dirtyRegion);
}
}
}
SurfaceFlinger::computeVisibleRegions()比较核心重要,他的作用是记录各个Layer 的可视区域、被遮盖区域,并记录在layer中,汇总dirtyRegion, opaqueRegion形参中,即总的dirtyRegion 区域和总的opaqueRegion。最后回到rebuildLayerStacks,把得到的这些信息set到hw 对象里面去,用于接下来的合成。
先浏览一下computeVisibleRegions 函数吧:
void SurfaceFlinger::computeVisibleRegions(
const LayerVector& currentLayers, uint32_t layerStack,
Region& outDirtyRegion, Region& outOpaqueRegion)
{
Region aboveOpaqueLayers;//当前层之上累计的不透明区域
Region aboveCoveredLayers;//当前层之上累计的被覆盖区域,不透明+半透明
Region dirty;
outDirtyRegion.clear();总值
size_t i = currentLayers.size();//最上层layer的索引
while (i--) {//从Z轴 最上面的layer开始处理,由上到下
const sp<Layer>& layer = currentLayers[i];
const Layer::State& s(layer->getDrawingState());
// 只计算和layerstack相同的layer,其他忽略
if (s.layerStack != layerStack)
continue;
Region opaqueRegion; //不透明区域
Region visibleRegion; //可见区域,不透明区域+半透明区域
Region coveredRegion; //覆盖区域,可见区域覆盖的地方
Region transparentRegion; //完全透明区域
//stage1-start 得到当前Layer的原始可视区域 和 opaque区域
// handle hidden surfaces by setting the visible region to empty
if (CC_LIKELY(layer->isVisible())) {
const bool translucent = !layer->isOpaque(s);
Rect bounds(s.transform.transform(layer->computeBounds()));
visibleRegion.set(bounds);
if (!visibleRegion.isEmpty()) {
// Remove the transparent area from the visible region
if (translucent) {//计算透明区域
const Transform tr(s.transform);
if (tr.transformed()) {
if (tr.preserveRects()) {
// transform the transparent region
transparentRegion = tr.transform(s.activeTransparentRegion);
} else {
// transformation too complex, can't do the
// transparent region optimization.
transparentRegion.clear();
}
} else {
transparentRegion = s.activeTransparentRegion;
}
}
// 计算不透明区域
const int32_t layerOrientation = s.transform.getOrientation();
if (s.alpha==255 && !translucent &&
((layerOrientation & Transform::ROT_INVALID) == false)) {
opaqueRegion = visibleRegion;
}
}
}
//stage1-end
//当前Layer被遮盖区域:上层的覆盖区 和 layer所在区域的 交集
coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
// 扩大覆盖区域,为下次循环、即下层计算做准备
aboveCoveredLayers.orSelf(visibleRegion);
//可见区域 = 抠掉上层的不透明区域
visibleRegion.subtractSelf(aboveOpaqueLayers);
// 计算需要重绘的区域
if (layer->contentDirty) {
//内容变了,重绘整个可见区域
dirty = visibleRegion;
//以前的看见区域也要加进来,因为以前的内容需要抹掉
dirty.orSelf(layer->visibleRegion);
layer->contentDirty = false;
} else {
//暴露区域 = 可见区域-被覆盖区域
const Region newExposed = visibleRegion - coveredRegion;
const Region oldVisibleRegion = layer->visibleRegion;
const Region oldCoveredRegion = layer->coveredRegion;
const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
}
//layer的重绘区域 = 抠掉上层的不透明区域
dirty.subtractSelf(aboveOpaqueLayers);
//累计每层需要重绘的区域
outDirtyRegion.orSelf(dirty);
//更新aboveOpaqueLayers,为下层layer绘制做准备
aboveOpaqueLayers.orSelf(opaqueRegion);
//设置layer对象的区域
layer->setVisibleRegion(visibleRegion);
layer->setCoveredRegion(coveredRegion);
//设置可见的非透明区域
layer->setVisibleNonTransparentRegion(
visibleRegion.subtract(transparentRegion));
}
outOpaqueRegion = aboveOpaqueLayers;
}
总结下computeVisibleRegions的逻辑如下:
先计算每个layer在设备上的可见区域visibleRegion(不透明区域 + 半透明区域)。计算方法:整个Layer的区域-上层所有不透明区域aboveOpaqueLayers。而上层所有不透明区域的值 是一个逐层累积的过程,每层都把自己的不透明区域累加到aboveOpaqueLayers中。
每层的不透明区域的计算方法:如果layer的alpha值=255,并且layer的isOpaque = true,则本层的不透明区域 == layer所在区域。否则为0。这样一层层计算下来,就很容易得到每层的可见区域大小了。
这里以下图为例,解读下computeVisibleRegions这段逻辑:
假设有三个Layer,按照Z值从大到小,依次是Layer1->Layer2->Layer3,最后按照computeVisibleRegions的规则来合成Layer。有了这个图,看这段逻辑 便会更加直观。同时理解这段逻辑 最好的方法是将3个Layer带入到computeVisibleRegions方法中。
③setUpHWComposer
先不用管这个,这个这函数是硬件合成图像的(HWComposer),里面会有判断是否支持HWC,我们假设不支持,完全走egl ,gpu 合成,所以直接看doComposition函数。
④doComposition
在分析这个函数之前,先了解一下 DisplayDevice 类的作用。
先看一下两张图:
第一张图,表示我们的应用程序,获取surface,向surface请求buffer,这个buffer是android匿名内存里面分配出来的,这些buffer被surface这边的成员变量mSlots 管理着,当应用这边调用unlockAndPost 函数,提交已经绘制图像buffer以后,layer会通知surfaceflinger进程去处理新添加的buffer。surfaceflinger 经过文章前面一些流程处理后,就会把合成的buffer,提交给framebuffer,framebuffer是硬件分配的buffer,他们他们也是被surface类管理着,那么DisplayDevice的作用是啥呢?DisplayDevice类似于我们的应用进程,管理的是帧他可以请求硬件dequeuebuffer、queuebuffer,即lock、unlock的过程。
- 应用端的Buffer是向Ashmem申请的;DisplayDevice端的Buffer是向FrameBuffer申请的
- 应用端的Buffer是用来填充的;DisplayDevice端的Buffer是用来推给Framebuffer 渲染的
看一下DisplayDevice的创建过程:
DisplayDevice的创建过程在SurfaceFlinger::init()里面:
void SurfaceFlinger::init() {
//...
// initialize our non-virtual displays
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);
wp<IBinder> token = mBuiltinDisplays[i];
//BufferQueue相关
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer,
new GraphicBufferAlloc());
//关键点1:FramebufferSurface创建,定位为 消费者身份
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
consumer);
int32_t hwcId = allocateHwcDisplayId(type);
//关键点2:DisplayDevice创建,定位为 生产者身份
sp<DisplayDevice> hw = new DisplayDevice(this,
type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
fbs, producer,
mRenderEngine->getEGLConfig());
if (i > DisplayDevice::DISPLAY_PRIMARY) {
hw->setPowerMode(HWC_POWER_MODE_NORMAL);
}
mDisplays.add(token, hw);
}
}
//...
// start boot animation
startBootAnim();
}
FramebufferSurface构造函数实现如下:
FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp,
const sp<IGraphicBufferConsumer>& consumer) :
ConsumerBase(consumer),
mDisplayType(disp),
mCurrentBufferSlot(-1),
mCurrentBuffer(0),
mHwc(hwc)
{
mName = "FramebufferSurface";
mConsumer->setConsumerName(mName);
/*这里设置了标志位GRALLOC_USAGE_HW_FB,借此参数分辨
向Ashmem申请->APP;向Framebuffer申请->DisplayDevice
*/
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
GRALLOC_USAGE_HW_RENDER |
GRALLOC_USAGE_HW_COMPOSER);
mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
}
通过setConsumerUsageBits 函数,可以设置一个标志位,如果,表示向匿名共享内存申请buffer,为GRALLOC_USAGE_HW_FB,表示向显现驱动程序申请Framebuffer。
DisplayDevice的构造函数实现如下:
DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
//...各种初始化
{
//创建surface对象
mNativeWindow = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
//创建OpenGLES 使用的surface对象
EGLSurface surface;
EGLint w, h;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (config == EGL_NO_CONFIG) {
config = RenderEngine::chooseEglConfig(display, format);
}
surface = eglCreateWindowSurface(display, config, window, NULL);
eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);
eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
window->setSwapInterval(window, 0);//虚拟设备不支持 图像合成
mConfig = config;
mDisplay = display;
mSurface = surface;
mFormat = format;
mPageFlipCount = 0;
mViewport.makeInvalid();
mFrame.makeInvalid();
//虚拟设备的屏幕 默认不关闭
mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
// Name the display. The name will be replaced shortly if the display
// was created with createDisplay().
switch (mType) {
case DISPLAY_PRIMARY:
mDisplayName = "Built-in Screen";
break;
case DISPLAY_EXTERNAL:
mDisplayName = "HDMI Screen";
break;
default:
mDisplayName = "Virtual Screen"; // e.g. Overlay #n
break;
}
// initialize the display orientation transform.
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
}
该构造函数主要是 创建了Surface,也就是一个NativeWindow。
这里看下 surface的构造函数,代码如下:
Surface::Surface(
const sp<IGraphicBufferProducer>& bufferProducer,
bool controlledByApp)
: mGraphicBufferProducer(bufferProducer)
{
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = hook_setSwapInterval;
ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
ANativeWindow::cancelBuffer = hook_cancelBuffer;
ANativeWindow::queueBuffer = hook_queueBuffer;
ANativeWindow::query = hook_query;
ANativeWindow::perform = hook_perform;
//...
}
这里对其中的一个hook_queueBuffer进行分析,代码如下:
int Surface::hook_queueBuffer(ANativeWindow* window,
ANativeWindowBuffer* buffer, int fenceFd) {
Surface* c = getSelf(window);
return c->queueBuffer(buffer, fenceFd);
}
最后是调用回了Surface的queueBuffer方法,其他几个hook方法也是类似的。即NativeWindow 和Surface访问的方法是一样的。
同时通过上面的分析得出Buffer的流程:Surface->BufferQueue->FramebufferSurface->HWComposer->Gralloc->显示设备Framebuffer.
最后在看一下doComposition 的函数处理内容:
这个UML图中,我们看出来在doComposeSurfaces函数里面最后会调用 layer->draw(hw, clip)进而开始调用OpenGL的接口开始绘制合成图像了。完了之后,回到doDisplayComposition函数,调用hw->swapBuffers(getHwComposer()),进行framebuffer的切换,即把准备好的framebuffer和正在显示器上显示的buffer进行交换,显示器就显示刚刚合成的新画面。