前言
經(jīng)過前兩篇文章的解析,我們徹底的理解GraphicBuffer的生產(chǎn)端究竟做了什么胎挎。本文就來討論GraphicBuffer是怎么消費。
整個圖元的消費到合成,最后到通過hwc發(fā)送到fb谆趾。由于整個流程十分長,中間有許多細節(jié)叛本,我將會挑出核心的思想來和大家聊聊其中的原理沪蓬。
還記得,我在GraphicBuffer的誕生里面具體了聊了queuebuffer最后會通過IConsumerListener的回調(diào)通知消費者進行消費来候。
我們接著繼續(xù)看看接下來的邏輯跷叉。
如果遇到問題,可以到本文討論http://www.reibang.com/p/67c1e350fe0d
正文
讓我們先來回憶一下营搅,在圖元緩沖隊列初始化一文中曾經(jīng)總結(jié)的UML圖云挟。
文件:frameworks/native/libs/gui/BufferQueueProducer.cpp
frameAvailableListener = mCore->mConsumerListener;
}
Mutex::Autolock lock(mCallbackMutex);
while (callbackTicket != mCurrentCallbackTicket) {
mCallbackCondition.wait(mCallbackMutex);
}
if (frameAvailableListener != NULL) {
frameAvailableListener->onFrameAvailable(item);
} else if (frameReplacedListener != NULL) {
frameReplacedListener->onFrameReplaced(item);
}
frameAvailableListener就是ProxyConsumerListener。這個對象持有ConsumeBase转质。當進行回調(diào)時候就會回調(diào)到ConsumeBase的mFrameAvailableListener园欣。
void ConsumerBase::onFrameAvailable(const BufferItem& item) {
sp<FrameAvailableListener> listener;
{ // scope for the lock
Mutex::Autolock lock(mFrameAvailableMutex);
listener = mFrameAvailableListener.promote();
}
if (listener != NULL) {
listener-> (item);
}
}
而ConsumeBase的mFrameAvailableListener是BufferLayer注冊進來的。到這里倒在緩沖隊列的初始化聊過休蟹。
BufferLayer onFrameAvailable
文件:/frameworks/native/services/surfaceflinger/BufferLayer.cpp
void BufferLayer::onFrameAvailable(const BufferItem& item) {
// Add this buffer from our internal queue tracker
{ // Autolock scope
Mutex::Autolock lock(mQueueItemLock);
mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
item.mGraphicBuffer->getHeight(),
item.mFrameNumber);
if (item.mFrameNumber == 1) {
mLastFrameNumberReceived = 0;
}
// Ensure that callbacks are handled in order
while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
ms2ns(500));
...
}
mQueueItems.push_back(item);
android_atomic_inc(&mQueuedFrames);
mLastFrameNumberReceived = item.mFrameNumber;
mQueueItemCondition.broadcast();
}
mFlinger->signalLayerUpdate();
}
這里做的事情很簡單沸枯,增加mQueuedFrames的計數(shù),mQueueItems添加一個BufferItem赂弓,并喚醒其他線程入隊的阻塞绑榴。接著調(diào)用SF的signalLayerUpdate。
SurfaceFlinger signalLayerUpdate
文件:rameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::signalLayerUpdate() {
mEventQueue->invalidate();
}
接著調(diào)用到MessageQueue的invalidate
void MessageQueue::invalidate() {
mEvents->requestNextVsync();
}
在MessageQueue中請求下一個同步信號
EventThread::Connection::requestNextVsync
void EventThread::Connection::requestNextVsync() {
mEventThread->requestNextVsync(this);
}
void EventThread::requestNextVsync(const sp<EventThread::Connection>& connection) {
std::lock_guard<std::mutex> lock(mMutex);
if (mResyncWithRateLimitCallback) {
mResyncWithRateLimitCallback();
}
if (connection->count < 0) {
connection->count = 0;
mCondition.notify_all();
}
}
EventThread::Connection的count的標志位實際上是指vysnc事件是每隔幾個事件通知盈魁。此時是count在初始化的時候是-1.此時強制設(shè)置為0彭沼,說明只有調(diào)用requestNextVsync強制喚醒才會返回vysnc通知。
整體設(shè)計可以看我寫第一篇SurfaceFlinger 的初始化备埃。mResyncWithRateLimitCallback這個方法用于調(diào)整DispSync的時間戳姓惑。假如是第一次初始化,因此count還是-1.因此直接喚醒waitForEventLocked中的等待按脚。
if (!timestamp && !eventPending) {
// wait for something to happen
if (waitForVSync) {
bool softwareSync = mUseSoftwareVSync;
auto timeout = softwareSync ? 16ms : 1000ms;
if (mCondition.wait_for(*lock, timeout) == std::cv_status::timeout) {
if (!softwareSync) {
ALOGW("Timed out waiting for hw vsync; faking it");
}
// FIXME: how do we decide which display id the fake
// vsync came from ?
mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
mVSyncEvent[0].vsync.count++;
}
} else {
mCondition.wait(*lock);
}
此時timestamp一開始是0于毙,當設(shè)置了時間戳,將不會直接等待跳出死循環(huán)辅搬,為0則會唯沮。eventPending是由接進來的屏幕的mPendingEvents判斷是否為空脖旱,不為空則是true。 如果EventThread有Connection接進來進行監(jiān)聽將會設(shè)置為waitForVSync為true介蛉。
當我們進行初始化的時候萌庆,由于沒有屏幕接進來。因此第一個信號是DISPLAY_EVENT_VSYNC币旧。進行刷新践险。
MessageQueue的回調(diào)
int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
for (int i = 0; i < n; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
mHandler->dispatchInvalidate();
break;
}
}
}
return 1;
}
能看到整個MessageQueue的回調(diào)只接受DISPLAY_EVENT_VSYNC,進行刷新吹菱。
void MessageQueue::Handler::dispatchInvalidate() {
if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
}
}
void MessageQueue::Handler::handleMessage(const Message& message) {
switch (message.what) {
case INVALIDATE:
android_atomic_and(~eventMaskInvalidate, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
case REFRESH:
android_atomic_and(~eventMaskRefresh, &mEventMask);
mQueue.mFlinger->onMessageReceived(message.what);
break;
}
}
發(fā)送了一個INVALIDATE消息交給SF的onMessageReceive處理巍虫。
SF onMessageReceive 處理 INVALIDATE消息
void SurfaceFlinger::onMessageReceived(int32_t what) {
ATRACE_CALL();
switch (what) {
case MessageQueue::INVALIDATE: {
bool frameMissed = !mHadClientComposition &&
mPreviousPresentFence != Fence::NO_FENCE &&
(mPreviousPresentFence->getSignalTime() ==
Fence::SIGNAL_TIME_PENDING);
if (frameMissed) {
mTimeStats.incrementMissedFrames();
if (mPropagateBackpressure) {
signalLayerUpdate();
break;
}
}
updateVrFlinger();
bool refreshNeeded = handleMessageTransaction();
refreshNeeded |= handleMessageInvalidate();
refreshNeeded |= mRepaintEverything;
if (refreshNeeded) {
signalRefresh();
}
break;
}
case MessageQueue::REFRESH: {
handleMessageRefresh();
break;
}
}
}
MessageQueue的消息處理函數(shù)中SF處理了兩種消息一種是INVALIDATE校驗無效的區(qū)域。校驗方式兩個步驟:
- 1.handleMessageTransaction 處理事務(wù)鳍刷,如交換繪制mDrawState和mCurrentState的焦點狀態(tài)占遥,記錄每一個Layer當前需要繪制的各自的Layer,如果判斷到已經(jīng)添加了Layer進來输瓜,則需要打開判斷可視區(qū)域標志位瓦胎。發(fā)現(xiàn)Layer被移除了需要更新臟(已經(jīng)變動)區(qū)域
- 2.handleMessageInvalidate 核心就是latch每一個Layer中的圖元進行acquire的操作。一旦判斷到每一Layer中有l(wèi)atch了圖元尤揣,說有新的圖元需要消費凛捏,或者還有圖元沒有消費的,則需要主動調(diào)用signalLayerUpdate()進行下一個循環(huán)的INVALIDATE發(fā)送芹缔。
最后是否需要調(diào)用signalRefresh坯癣,handleMessageTransaction需要處理事務(wù)或者handleMessageInvalidate判斷到有新圖元。則會通過signalRefresh進入下一個循環(huán)進行Refresh消息的發(fā)送最欠。
void SurfaceFlinger::signalRefresh() {
mRefreshPending = true;
mEventQueue->refresh();
}
知道核心思想示罗,我們再來每一個步驟中做了什么。
handleMessageTransaction
uint32_t SurfaceFlinger::peekTransactionFlags() {
return android_atomic_release_load(&mTransactionFlags);
}
bool SurfaceFlinger::handleMessageTransaction() {
uint32_t transactionFlags = peekTransactionFlags();
if (transactionFlags) {
handleTransaction(transactionFlags);
return true;
}
return false;
}
我們先討論打開了mTransactionFlags事務(wù)的標志位芝硬。一旦Layer蚜点,Display等和顯示相關(guān)的數(shù)據(jù)結(jié)構(gòu)發(fā)生變化都需要打開這個標志位。
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
State drawingState(mDrawingState);
Mutex::Autolock _l(mStateLock);
const nsecs_t now = systemTime();
...
mVsyncModulator.onTransactionHandled();
transactionFlags = getTransactionFlags(eTransactionMask);
handleTransactionLocked(transactionFlags);
mLastTransactionTime = systemTime() - now;
invalidateHwcGeometry();
}
void SurfaceFlinger::invalidateHwcGeometry()
{
mGeometryInvalid = true;
}
核心是handleTransactionLocked拌阴。
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
// 通知所有的Layer可以進行合成
mCurrentState.traverseInZOrder([](Layer* layer) {
layer->notifyAvailableFrames();
});
if (transactionFlags & eTraversalNeeded) {
mCurrentState.traverseInZOrder([&](Layer* layer) {
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
if (!trFlags) return;
const uint32_t flags = layer->doTransaction(0);
if (flags & Layer::eVisibleRegion)
mVisibleRegionsDirty = true;
});
}
/*
* Perform display own transactions if needed
*/
if (transactionFlags & eDisplayTransactionNeeded) {
processDisplayChangesLocked();
processDisplayHotplugEventsLocked();
}
if (transactionFlags & (eDisplayLayerStackChanged|eDisplayTransactionNeeded)) {
sp<const DisplayDevice> disp;
uint32_t currentlayerStack = 0;
bool first = true;
mCurrentState.traverseInZOrder([&](Layer* layer) {
uint32_t layerStack = layer->getLayerStack();
if (first || currentlayerStack != layerStack) {
currentlayerStack = layerStack;
disp.clear();
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) {
if (disp == nullptr) {
disp = std::move(hw);
} else {
disp = nullptr;
break;
}
}
}
}
if (disp == nullptr) {
disp = getDefaultDisplayDeviceLocked();
}
if (disp != nullptr) {
layer->updateTransformHint(disp);
}
first = false;
});
}
if (mLayersAdded) {
mLayersAdded = false;
mVisibleRegionsDirty = true;
}
if (mLayersRemoved) {
mLayersRemoved = false;
mVisibleRegionsDirty = true;
mDrawingState.traverseInZOrder([&](Layer* layer) {
if (mLayersPendingRemoval.indexOf(layer) >= 0) {
Region visibleReg;
visibleReg.set(layer->computeScreenBounds());
invalidateLayerStack(layer, visibleReg);
}
});
}
commitTransaction();
updateCursorAsync();
}
- 1.第一個從底部向頂部循環(huán)遍歷mCurrentState中的Layer绍绘,通知每一個被SyncPoint完成了doTransaction步驟而阻塞的Layer。讓Layer可以進行合成的準備迟赃。
void BufferLayer::notifyAvailableFrames() {
auto headFrameNumber = getHeadFrameNumber();
bool headFenceSignaled = headFenceHasSignaled();
Mutex::Autolock lock(mLocalSyncPointMutex);
for (auto& point : mLocalSyncPoints) {
if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled) {
point->setFrameAvailable();
}
}
}
- 2.從底部遍歷每一個Layer的doTransaction方法陪拘。處理可視區(qū)域。
- 3.檢查每一個Layer中的所對應(yīng)的顯示屏id類型纤壁,同時更新里面的變換矩陣左刽。
- 4.如果通過Client添加過Layer就會打上mLayersAdded,此時將會關(guān)閉這個標志位酌媒,同時打開mVisibleRegionsDirty欠痴,讓后續(xù)的步驟檢測變動的可視區(qū)域迄靠。
- 5.如果Layer有移除,則調(diào)用invalidateLayerStack更新DisplayDevice中原有的可視臟區(qū)喇辽。
void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
const sp<DisplayDevice>& hw(mDisplays[dpy]);
if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) {
hw->dirtyRegion.orSelf(dirty);
}
}
}
讓我們看看doTransaction核心方法掌挚。
Layer doTransaction
文件:/frameworks/native/services/surfaceflinger/Layer.cpp
uint32_t Layer::doTransaction(uint32_t flags) {
pushPendingState();
Layer::State c = getCurrentState();
if (!applyPendingStates(&c)) {
return 0;
}
const Layer::State& s(getDrawingState());
const bool sizeChanged = (c.requested.w != s.requested.w) || (c.requested.h != s.requested.h);
if (sizeChanged) {
...
setDefaultBufferSize(c.requested.w, c.requested.h);
}
const bool resizePending = ((c.requested.w != c.active.w) || (c.requested.h != c.active.h)) &&
(getBE().compositionInfo.mBuffer != nullptr);
if (!isFixedSize()) {
if (resizePending && getBE().compositionInfo.hwc.sidebandStream == nullptr) {
flags |= eDontUpdateGeometryState;
}
}
if (!(flags & eDontUpdateGeometryState)) {
Layer::State& editCurrentState(getCurrentState());
if (mFreezeGeometryUpdates) {
float tx = c.active.transform.tx();
float ty = c.active.transform.ty();
c.active = c.requested;
c.active.transform.set(tx, ty);
editCurrentState.active = c.active;
} else {
editCurrentState.active = editCurrentState.requested;
c.active = c.requested;
}
}
if (s.active != c.active) {
flags |= Layer::eVisibleRegion;
}
if (c.sequence != s.sequence) {
// invalidate and recompute the visible regions if needed
flags |= eVisibleRegion;
this->contentDirty = true;
const uint8_t type = c.active.transform.getType();
mNeedsFiltering = (!c.active.transform.preserveRects() || (type >= Transform::SCALE));
}
if (c.flags & layer_state_t::eLayerHidden) {
clearSyncPoints();
}
// Commit the transaction
commitTransaction(c);
return flags;
}
void Layer::commitTransaction(const State& stateToCommit) {
mDrawingState = stateToCommit;
}
- 1.就是檢測BufferLayer中的mCurrentState和上一幀已經(jīng)繪制了的mDrawState的差距。如果發(fā)現(xiàn)兩者的requested的區(qū)域發(fā)生了變動菩咨,則會調(diào)用setDefaultBufferSize吠式,重新定義圖元消費BufferLayerConsumer的默認寬高。
void BufferLayer::setDefaultBufferSize(uint32_t w, uint32_t h) {
mConsumer->setDefaultBufferSize(w, h);
}
- 檢測mCurrentState中requested和active之間的幾何寬高旦委。在每一個Layer::State中都會存在兩個幾何結(jié)構(gòu)體requested和active。當我們設(shè)置了Surface了postion等在屏幕上顯示的幾何參數(shù)會先設(shè)置到mCurrentState.requested中雏亚。也就是說requested等待繪制的參數(shù)缨硝。active則是顯示中的幾何參數(shù)。一旦發(fā)生變化則設(shè)resizePending為true罢低。
- isFixedSize則是判斷當前對應(yīng)的Layer是否被凍結(jié)不允許變化大小查辩,假設(shè)此時是關(guān)閉的,且sidebandStream是空的网持。此時不會立即更新requested和active的區(qū)域宜岛。回到后面acquire步驟時候進行處理功舀。
- 最后更新mCurrentState為mDrawState萍倡。
這里需要注意,和SF的State不一樣辟汰。Layer::State將會記錄Layer顯示相關(guān)的參數(shù)列敲。
SF commitTransaction
void SurfaceFlinger::commitTransaction()
{
if (!mLayersPendingRemoval.isEmpty()) {
// Notify removed layers now that they can't be drawn from
for (const auto& l : mLayersPendingRemoval) {
recordBufferingStats(l->getName().string(),
l->getOccupancyHistory(true));
l->onRemoved();
}
mLayersPendingRemoval.clear();
}
mAnimCompositionPending = mAnimTransactionPending;
mDrawingState = mCurrentState;
mCurrentState.colorMatrixChanged = false;
mDrawingState.traverseInZOrder([](Layer* layer) {
layer->commitChildList();
});
mTransactionPending = false;
mAnimTransactionPending = false;
mTransactionCV.broadcast();
}
此時也會更新SF中的mDrawingState,同時會更新每一個Layer中對應(yīng)處理完的事務(wù)狀態(tài)帖汞。
BufferLayer commitChildList
void Layer::commitChildList() {
for (size_t i = 0; i < mCurrentChildren.size(); i++) {
const auto& child = mCurrentChildren[i];
child->commitChildList();
}
mDrawingChildren = mCurrentChildren;
mDrawingParent = mCurrentParent;
}
對應(yīng)的每一個Layer同時會更新之后需要繪制的父Layer和子Layer戴而。
handleMessageInvalidate 檢測變動區(qū)域
文件:/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
bool SurfaceFlinger::handleMessageInvalidate() {
return handlePageFlip();
}
bool SurfaceFlinger::handlePageFlip()
{
nsecs_t latchTime = systemTime();
bool visibleRegions = false;
bool frameQueued = false;
bool newDataLatched = false;
mDrawingState.traverseInZOrder([&](Layer* layer) {
if (layer->hasQueuedFrame()) {
frameQueued = true;
if (layer->shouldPresentNow(mPrimaryDispSync)) {
mLayersWithQueuedFrames.push_back(layer);
} else {
layer->useEmptyDamage();
}
} else {
layer->useEmptyDamage();
}
});
for (auto& layer : mLayersWithQueuedFrames) {
const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
layer->useSurfaceDamage();
invalidateLayerStack(layer, dirty);
if (layer->isBufferLatched()) {
newDataLatched = true;
}
}
mVisibleRegionsDirty |= visibleRegions;
if (frameQueued && (mLayersWithQueuedFrames.empty() || !newDataLatched)) {
signalLayerUpdate();
}
return !mLayersWithQueuedFrames.empty() && newDataLatched;
}
首先要注意,在這個方法開始SF需要正式消費圖元翩蘸。此時會有一個問題所意,比如有個Layer.此時線程1通知了Layer有了一個新的圖元進來了,還沒來的消費又進來了一個圖元催首。此時我們需要再進行消費扶踊?假如出現(xiàn)了寬高變化怎么辦?那不就浪費了doTransaction步驟的寬高變化記錄嗎郎任。因此我們需要一個latch方法姻檀,鎖住圖元。
一旦檢測到圖元還有沒有消費的或者還沒有到了需要顯示時候涝滴,就會調(diào)用signalLayerUpdate绣版,讓下一個循環(huán)回來消費胶台。
這個方法判斷是否需要refresh的依據(jù),其實就是判斷兩個情況同時成立杂抽,第一個是mLayersWithQueuedFrames不為空诈唬,有需要顯示的Layer。同時latch上鎖圖元成功了缩麸。
BufferLayer shouldPresentNow
文件:/frameworks/native/services/surfaceflinger/BufferLayer.cpp
bool BufferLayer::shouldPresentNow(const DispSync& dispSync) const {
if (mSidebandStreamChanged || mAutoRefresh) {
return true;
}
Mutex::Autolock lock(mQueueItemLock);
if (mQueueItems.empty()) {
return false;
}
auto timestamp = mQueueItems[0].mTimestamp;
nsecs_t expectedPresent = mConsumer->computeExpectedPresent(dispSync);
// Ignore timestamps more than a second in the future
bool isPlausible = timestamp < (expectedPresent + s2ns(1));
bool isDue = timestamp < expectedPresent;
return isDue || !isPlausible;
}
該方法會通過computeExpectedPresent通過DispSync計算這一幀應(yīng)該是什么顯示铸磅。是否顯示由下面的公式?jīng)Q定:
預(yù)期顯示 - 入隊時間 < 1s && 入隊時間<預(yù)期時間
一旦允許顯示則往mLayersWithQueuedFrames添加Layer。這個Layer集合就是需要繪制的圖層杭朱。
BufferLayer latchBuffer
接著會遍歷mLayersWithQueuedFrames每一層的Layer阅仔,并且調(diào)用latchBuffer進行圖元鎖定。
接下來這個方法很長弧械。我把它拆開2部分來聊
Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
...
Region outDirtyRegion;
if (mQueuedFrames <= 0 && !mAutoRefresh) {
return outDirtyRegion;
}
//已經(jīng)latch過了就不需要了
if (mRefreshPending) {
return outDirtyRegion;
}
//fence已經(jīng)喚醒了八酒,也不需要了
if (!headFenceHasSignaled()) {
mFlinger->signalLayerUpdate();
return outDirtyRegion;
}
const State& s(getDrawingState());
const bool oldOpacity = isOpaque(s);
sp<GraphicBuffer> oldBuffer = getBE().compositionInfo.mBuffer;
if (!allTransactionsSignaled()) {
mFlinger->signalLayerUpdate();
return outDirtyRegion;
}
bool queuedBuffer = false;
LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
getProducerStickyTransform() != 0, mName.string(),
mOverrideScalingMode, mFreezeGeometryUpdates);
//核心
status_t updateResult =
mConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync,
&mAutoRefresh, &queuedBuffer,
mLastFrameNumberReceived);
//根據(jù)消費返回的狀態(tài)做處理
if (updateResult == BufferQueue::PRESENT_LATER) {
mFlinger->signalLayerUpdate();
return outDirtyRegion;
} else if (updateResult == BufferLayerConsumer::BUFFER_REJECTED) {
if (queuedBuffer) {
Mutex::Autolock lock(mQueueItemLock);
mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber);
mQueueItems.removeAt(0);
android_atomic_dec(&mQueuedFrames);
}
return outDirtyRegion;
} else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
if (queuedBuffer) {
Mutex::Autolock lock(mQueueItemLock);
mQueueItems.clear();
android_atomic_and(0, &mQueuedFrames);
mTimeStats.clearLayerRecord(getName().c_str());
}
mUpdateTexImageFailed = true;
return outDirtyRegion;
}
//從入隊到這里的queuedBuffer 都為true
if (queuedBuffer) {
// Autolock scope
auto currentFrameNumber = mConsumer->getFrameNumber();
Mutex::Autolock lock(mQueueItemLock);
while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
mTimeStats.removeTimeRecord(getName().c_str(), mQueueItems[0].mFrameNumber);
mQueueItems.removeAt(0);
android_atomic_dec(&mQueuedFrames);
}
const std::string layerName(getName().c_str());
mTimeStats.setAcquireFence(layerName, currentFrameNumber, mQueueItems[0].mFenceTime);
mTimeStats.setLatchTime(layerName, currentFrameNumber, latchTime);
mQueueItems.removeAt(0);
}
if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) ||
mAutoRefresh) {
mFlinger->signalLayerUpdate();
}
//把已經(jīng)消費的圖元保存到SurfaceFlingerBE里面
getBE().compositionInfo.mBuffer =
mConsumer->getCurrentBuffer(&getBE().compositionInfo.mBufferSlot);
mActiveBuffer = getBE().compositionInfo.mBuffer;
if (getBE().compositionInfo.mBuffer == nullptr) {
// this can only happen if the very first buffer was rejected.
return outDirtyRegion;
}
mBufferLatched = true;
...
}
整個核心就是updateTexImage方法。在這里面經(jīng)過判斷刃唐,latch過的Layer就不會再進行l(wèi)atch羞迷。
經(jīng)過updateTexImage處理后,會判斷返回的狀態(tài)碼画饥。如果需要延遲顯示則直接返回空的臟區(qū)域衔瓮。如果發(fā)現(xiàn)需要拒絕顯示這個幀,將會丟棄mQueueItem中對應(yīng)的圖元參數(shù)和索引抖甘。如果消費失敗了热鞍,則會處理清除mQueueItem中所有等待消費的圖元。最后返回空臟區(qū)衔彻。
成功消費后碍现,如果是從queueBuffer的步驟到這里的,將會移除mQueueItem第一項圖元數(shù)據(jù)米奸。剩下的圖元還有剩下的昼接,則需要進行下一輪invalidate消息。
最后會把消費后的圖元悴晰,作為當前需要顯示的圖元保存在getBE().compositionInfo.mBuffer和mActiveBuffer慢睡,并且設(shè)置mBufferLatched。
核心的updateTexImage方法我們稍后注重考究铡溪。
//記錄上一幀序列
mPreviousFrameNumber = mCurrentFrameNumber;
//記錄當前這一幀的序列
mCurrentFrameNumber = mConsumer->getFrameNumber();
{
//記錄上鎖時間
Mutex::Autolock lock(mFrameEventHistoryMutex);
mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
}
mRefreshPending = true;
mFrameLatencyNeeded = true;
if (oldBuffer == nullptr) {
recomputeVisibleRegions = true;
}
//記錄DataSpace
ui::Dataspace dataSpace = mConsumer->getCurrentDataSpace();
switch (dataSpace) {
case ui::Dataspace::V0_SRGB:
dataSpace = ui::Dataspace::SRGB;
break;
case ui::Dataspace::V0_SRGB_LINEAR:
dataSpace = ui::Dataspace::SRGB_LINEAR;
break;
case ui::Dataspace::V0_JFIF:
dataSpace = ui::Dataspace::JFIF;
break;
case ui::Dataspace::V0_BT601_625:
dataSpace = ui::Dataspace::BT601_625;
break;
case ui::Dataspace::V0_BT601_525:
dataSpace = ui::Dataspace::BT601_525;
break;
case ui::Dataspace::V0_BT709:
dataSpace = ui::Dataspace::BT709;
break;
default:
break;
}
mCurrentDataSpace = dataSpace;
Rect crop(mConsumer->getCurrentCrop());
const uint32_t transform(mConsumer->getCurrentTransform());
const uint32_t scalingMode(mConsumer->getCurrentScalingMode());
if ((crop != mCurrentCrop) ||
(transform != mCurrentTransform) ||
(scalingMode != mCurrentScalingMode)) {
mCurrentCrop = crop;
mCurrentTransform = transform;
mCurrentScalingMode = scalingMode;
recomputeVisibleRegions = true;
}
if (oldBuffer != nullptr) {
uint32_t bufWidth = getBE().compositionInfo.mBuffer->getWidth();
uint32_t bufHeight = getBE().compositionInfo.mBuffer->getHeight();
if (bufWidth != uint32_t(oldBuffer->width) ||
bufHeight != uint32_t(oldBuffer->height)) {
recomputeVisibleRegions = true;
}
}
//記錄透明參數(shù)
mCurrentOpacity = getOpacityForFormat(getBE().compositionInfo.mBuffer->format);
if (oldOpacity != isOpaque(s)) {
recomputeVisibleRegions = true;
}
//移除mLocalSyncPoints中的阻塞
{
Mutex::Autolock lock(mLocalSyncPointMutex);
auto point = mLocalSyncPoints.begin();
while (point != mLocalSyncPoints.end()) {
if (!(*point)->frameIsAvailable() || !(*point)->transactionIsApplied()) {
// This sync point must have been added since we started
// latching. Don't drop it yet.
++point;
continue;
}
if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
point = mLocalSyncPoints.erase(point);
} else {
++point;
}
}
}
// FIXME: postedRegion should be dirty & bounds
Region dirtyRegion(Rect(s.active.w, s.active.h));
// transform the dirty region to window-manager space
outDirtyRegion = (getTransform().transform(dirtyRegion));
return outDirtyRegion;
- 1.設(shè)置相關(guān)的參數(shù)漂辐,如幀數(shù),裁剪參數(shù)棕硫,DataSpace髓涯,透明參數(shù)等。并且移除了代表當幀數(shù)之前mLocalSyncPoints。
- 2.計算臟區(qū)是由mDrawState對應(yīng)的active參數(shù)確定(此時requested和active已經(jīng)交換了)拱礁。最后調(diào)用transform轉(zhuǎn)化轉(zhuǎn)化為臟區(qū)
Transform Layer::getTransform() const {
Transform t;
const auto& p = mDrawingParent.promote();
if (p != nullptr) {
t = p->getTransform();
if (p->isFixedSize() && p->getBE().compositionInfo.mBuffer != nullptr) {
int bufferWidth;
int bufferHeight;
if ((p->mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) == 0) {
bufferWidth = p->getBE().compositionInfo.mBuffer->getWidth();
bufferHeight = p->getBE().compositionInfo.mBuffer->getHeight();
} else {
bufferHeight = p->getBE().compositionInfo.mBuffer->getWidth();
bufferWidth = p->getBE().compositionInfo.mBuffer->getHeight();
}
float sx = p->getDrawingState().active.w / static_cast<float>(bufferWidth);
float sy = p->getDrawingState().active.h / static_cast<float>(bufferHeight);
Transform extraParentScaling;
extraParentScaling.set(sx, 0, 0, sy);
t = t * extraParentScaling;
}
}
return t * getDrawingState().active.transform;
}
其實這個轉(zhuǎn)化是查找每一個Layer的父Layer,并且根據(jù)父Layer的寬高和當前Layer比進行一次等比例縮小一姿。
換句話說包各,實際上臟區(qū)的計算摘仅,從App進程角度來看是以Surface為一個單位進行計算。
BufferLayerConsumer updateTexImage
文件:/frameworks/native/services/surfaceflinger/BufferLayerConsumer.cpp
status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
bool* autoRefresh, bool* queuedBuffer,
uint64_t maxFrameNumber) {
ATRACE_CALL();
Mutex::Autolock lock(mMutex);
if (mAbandoned) {
return NO_INIT;
}
// Make sure RenderEngine is current
if (!mRE.isCurrent()) {
return INVALID_OPERATION;
}
BufferItem item;
status_t 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 {
BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
}
return err;
}
if (autoRefresh) {
*autoRefresh = item.mAutoRefresh;
}
if (queuedBuffer) {
*queuedBuffer = item.mQueuedBuffer;
}
int slot = item.mSlot;
if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
return BUFFER_REJECTED;
}
// Release the previous buffer.
err = updateAndReleaseLocked(item, &mPendingRelease);
if (err != NO_ERROR) {
return err;
}
if (!SyncFeatures::getInstance().useNativeFenceSync()) {
err = bindTextureImageLocked();
}
return err;
}
在這個方法中有兩個核心:
- 1.acquireBufferLocked消費圖元问畅。
- 2.LayerReject 判斷是否需要拒絕顯示當前已經(jīng)消費的圖元娃属。
- 3.updateAndReleaseLocked更新當前Layer中需要顯示的圖元,同時釋放之前的圖元為Free狀態(tài)护姆。
- 4.最后判斷OpenGL es是否攜帶EGL_KHR_fence_sync標志位矾端,代表OpenGL es的同步柵。如果是卵皂,則提前通過OpenGL es繪制Image秩铆。
BufferLayerConsumer acquireBufferLocked
文件:meworks/native/services/surfaceflinger/BufferLayerConsumer.cpp
status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
uint64_t maxFrameNumber) {
status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, maxFrameNumber);
if (err != NO_ERROR) {
return err;
}
if (item->mGraphicBuffer != nullptr) {
mImages[item->mSlot] = new Image(item->mGraphicBuffer, mRE);
}
return NO_ERROR;
}
- 1.ConsumerBase::acquireBufferLocked 從基類還是處理圖元消費。
- 2.通過GraphicBuffer生成Image對象保存在mImages數(shù)組中渐裂。
先來看看image對象對應(yīng)的頭文件:
class Image : public LightRefBase<Image> {
public:
Image(sp<GraphicBuffer> graphicBuffer, RE::RenderEngine& engine);
Image(const Image& rhs) = delete;
Image& operator=(const Image& rhs) = delete;
status_t createIfNeeded(const Rect& imageCrop);
const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
const native_handle* graphicBufferHandle() {
return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
}
const RE::Image& image() const { return *mImage; }
private:
friend class LightRefBase<Image>;
virtual ~Image();
// mGraphicBuffer is the buffer that was used to create this image.
sp<GraphicBuffer> mGraphicBuffer;
std::unique_ptr<RE::Image> mImage;
bool mCreated;
int32_t mCropWidth;
int32_t mCropHeight;
};
其實很簡單豺旬,核心是持有了GraphicBuffer和RE::Image兩個對象钠惩。GraphicBuffer圖元柒凉,我們?nèi)タ纯碦E::Image對象是怎么生成的。
BufferLayerConsumer::Image::Image(sp<GraphicBuffer> graphicBuffer, RE::RenderEngine& engine)
: mGraphicBuffer(graphicBuffer),
mImage{engine.createImage()},
mCreated(false),
mCropWidth(0),
mCropHeight(0) {}
std::unique_ptr<RE::Image> RenderEngine::createImage() {
return std::make_unique<Image>(*this);
}
class Image {
public:
virtual ~Image() = 0;
virtual bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected,
int32_t cropWidth, int32_t cropHeight) = 0;
};
namespace impl {
class RenderEngine;
class Image : public RE::Image {
public:
explicit Image(const RenderEngine& engine);
~Image() override;
Image(const Image&) = delete;
Image& operator=(const Image&) = delete;
bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected, int32_t cropWidth,
int32_t cropHeight) override;
private:
friend class RenderEngine;
EGLSurface getEGLImage() const { return mEGLImage; }
EGLDisplay mEGLDisplay;
EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR;
};
} // namespace impl
其實Image對象實際上就是控制NativeBuffer篓跛,EGLDisplay膝捞,EGLSurface對象。這些對象實際上都是OpenGL es繪制的核心對象愧沟。所有的操作都是透過這個Image繪制蔬咬。
ConsumerBase acquireBufferLocked
文件:/frameworks/native/libs/gui/ConsumerBase.cpp
status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
nsecs_t presentWhen, uint64_t maxFrameNumber) {
...
status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
...
if (item->mGraphicBuffer != NULL) {
if (mSlots[item->mSlot].mGraphicBuffer != NULL) {
freeBufferLocked(item->mSlot);
}
mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
}
mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
mSlots[item->mSlot].mFence = item->mFence;
return OK;
}
這里調(diào)用了BufferQueueConsumer的acquireBuffer。并且把消費的值賦值到新的item對應(yīng)的mSlots下標中沐寺。因為這個過程可能會選擇一些丟幀或者跳幀處理林艘。
BufferQueueConsumer acquireBuffer
文件:/frameworks/native/libs/gui/BufferQueueConsumer.cpp
status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
nsecs_t expectedPresent, uint64_t maxFrameNumber) {
ATRACE_CALL();
int numDroppedBuffers = 0;
sp<IProducerListener> listener;
{
Mutex::Autolock lock(mCore->mMutex);
int numAcquiredBuffers = 0;
for (int s : mCore->mActiveBuffers) {
if (mSlots[s].mBufferState.isAcquired()) {
++numAcquiredBuffers;
}
}
if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
return INVALID_OPERATION;
}
bool sharedBufferAvailable = mCore->mSharedBufferMode &&
mCore->mAutoRefresh && mCore->mSharedBufferSlot !=
BufferQueueCore::INVALID_BUFFER_SLOT;
if (mCore->mQueue.empty() && !sharedBufferAvailable) {
return NO_BUFFER_AVAILABLE;
}
BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
if (expectedPresent != 0 && !mCore->mQueue.empty()) {
const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
const BufferItem& bufferItem(mCore->mQueue[1]);
if (maxFrameNumber && bufferItem.mFrameNumber > maxFrameNumber) {
break;
}
nsecs_t desiredPresent = bufferItem.mTimestamp;
if (desiredPresent < expectedPresent - MAX_REASONABLE_NSEC ||
desiredPresent > expectedPresent) {
break;
}
if (!front->mIsStale) {
// Front buffer is still in mSlots, so mark the slot as free
mSlots[front->mSlot].mBufferState.freeQueued();
if (!mCore->mSharedBufferMode &&
mSlots[front->mSlot].mBufferState.isFree()) {
mSlots[front->mSlot].mBufferState.mShared = false;
}
// Don't put the shared buffer on the free list
if (!mSlots[front->mSlot].mBufferState.isShared()) {
mCore->mActiveBuffers.erase(front->mSlot);
mCore->mFreeBuffers.push_back(front->mSlot);
}
listener = mCore->mConnectedProducerListener;
++numDroppedBuffers;
}
mCore->mQueue.erase(front);
front = mCore->mQueue.begin();
}
nsecs_t desiredPresent = front->mTimestamp;
bool bufferIsDue = desiredPresent <= expectedPresent ||
desiredPresent > expectedPresent + MAX_REASONABLE_NSEC;
bool consumerIsReady = maxFrameNumber > 0 ?
front->mFrameNumber <= maxFrameNumber : true;
if (!bufferIsDue || !consumerIsReady) {
return PRESENT_LATER;
}
}
int slot = BufferQueueCore::INVALID_BUFFER_SLOT;
if (sharedBufferAvailable && mCore->mQueue.empty()) {
....
} else {
slot = front->mSlot;
*outBuffer = *front;
}
if (!outBuffer->mIsStale) {
mSlots[slot].mAcquireCalled = true;
if (mCore->mQueue.empty()) {
mSlots[slot].mBufferState.acquireNotInQueue();
} else {
mSlots[slot].mBufferState.acquire();
}
mSlots[slot].mFence = Fence::NO_FENCE;
}
if (outBuffer->mAcquireCalled) {
outBuffer->mGraphicBuffer = NULL;
}
mCore->mQueue.erase(front);
mCore->mDequeueCondition.broadcast();
mCore->mOccupancyTracker.registerOccupancyChange(mCore->mQueue.size());
VALIDATE_CONSISTENCY();
}
if (listener != NULL) {
for (int i = 0; i < numDroppedBuffers; ++i) {
listener->onBufferReleased();
}
}
return NO_ERROR;
}
- 處理圖元之前,首先檢測mActiveBuffers中活躍的圖元究竟有多少個混坞。如果超出mMaxAcquiredBufferCount限制狐援,則不允許繼續(xù)。
- 獲取之前入隊到mQueue的第一項front進行循環(huán)處理究孕。首先獲取之前計算出來的期待顯示時間和當前入隊的時間比較啥酱,找出和當前時間最接近的入隊圖元。如果入隊的時間比期待的小一秒厨诸,并且入隊的時間比期待的時間小镶殷。這樣就會直接跳出mQueue處理的處理循環(huán)。
如果front.mIsStale為false說明這個圖元已經(jīng)過期了微酬。將把mSlot的索引從mActiveBuffers轉(zhuǎn)移到mFreeBuffer绘趋。同時計算為一個numDroppedBuffers丟幀計數(shù)處理颤陶。獲取mQueue的下一項圖元。
最后把當前的front圖元返回埋心,并且釋放那些已經(jīng)丟幀的圖元指郁。
LayerRejecter 判斷是否需要拒絕顯示當前已經(jīng)消費的圖元
文件:/frameworks/native/services/surfaceflinger/LayerRejecter.cpp
bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
if (buf == nullptr) {
return false;
}
uint32_t bufWidth = buf->getWidth();
uint32_t bufHeight = buf->getHeight();
if (item.mTransform & Transform::ROT_90) {
swap(bufWidth, bufHeight);
}
int actualScalingMode = mOverrideScalingMode >= 0 ? mOverrideScalingMode : item.mScalingMode;
bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
if (mFront.active != mFront.requested) {
if (isFixedSize || (bufWidth == mFront.requested.w && bufHeight == mFront.requested.h)) {
mFront.active = mFront.requested;
mCurrent.active = mFront.active;
mCurrent.modified = true;
mRecomputeVisibleRegions = true;
mFreezeGeometryUpdates = false;
if (mFront.crop != mFront.requestedCrop) {
mFront.crop = mFront.requestedCrop;
mCurrent.crop = mFront.requestedCrop;
mRecomputeVisibleRegions = true;
}
if (mFront.finalCrop != mFront.requestedFinalCrop) {
mFront.finalCrop = mFront.requestedFinalCrop;
mCurrent.finalCrop = mFront.requestedFinalCrop;
mRecomputeVisibleRegions = true;
}
}
}
if (!isFixedSize && !mStickyTransformSet) {
if (mFront.active.w != bufWidth || mFront.active.h != bufHeight) {
return true;
}
}
if (!mFront.activeTransparentRegion.isTriviallyEqual(mFront.requestedTransparentRegion)) {
mFront.activeTransparentRegion = mFront.requestedTransparentRegion;
mCurrent.activeTransparentRegion = mFront.activeTransparentRegion;
mRecomputeVisibleRegions = true;
}
return false;
}
拒絕檢測圖元顯示。mFront其實就是上文通過doTransaction的mDrawState拷呆,此時已經(jīng)進行交換闲坎,所以mDrawState是這一幀的內(nèi)容。一旦發(fā)現(xiàn)requested和active的幾何不一致茬斧。如果此時不是NATIVE_WINDOW_SCALING_MODE_FREEZE(凍結(jié)屏幕)腰懂。同時圖元的寬高和requested相同,才會進行requested和active的交換项秉。
如果是NATIVE_WINDOW_SCALING_MODE_FREEZE(凍結(jié)屏幕)绣溜,則但是發(fā)現(xiàn)requested的寬高和圖元需要的寬高不一致就會拒絕繪制,丟掉當前幀娄蔼。其實思想很簡單怖喻,實際上就這種NATIVE_WINDOW_SCALING_MODE_FREEZE模式下就是只繪制和當前窗口一樣大小的圖元。其他都不設(shè)置岁诉。
updateAndReleaseLocked更新當前Layer中需要顯示的圖元锚沸,同時釋放之前的圖元為Free狀態(tài)
status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
PendingRelease* pendingRelease) {
status_t err = NO_ERROR;
int slot = item.mSlot;
if (slot != mCurrentTexture) {
err = syncForReleaseLocked();
if (err != NO_ERROR) {
releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
return err;
}
}
sp<Image> nextTextureImage = mImages[slot];
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (pendingRelease == nullptr) {
status_t status =
releaseBufferLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer());
if (status < NO_ERROR) {
err = status;
}
} else {
pendingRelease->currentTexture = mCurrentTexture;
pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
pendingRelease->isPending = true;
}
}
// Update the BufferLayerConsumer state.
mCurrentTexture = slot;
mCurrentTextureImage = nextTextureImage;
mCurrentCrop = item.mCrop;
mCurrentTransform = item.mTransform;
mCurrentScalingMode = item.mScalingMode;
mCurrentTimestamp = item.mTimestamp;
mCurrentDataSpace = static_cast<ui::Dataspace>(item.mDataSpace);
mCurrentHdrMetadata = item.mHdrMetadata;
mCurrentFence = item.mFence;
mCurrentFenceTime = item.mFenceTime;
mCurrentFrameNumber = item.mFrameNumber;
mCurrentTransformToDisplayInverse = item.mTransformToDisplayInverse;
mCurrentSurfaceDamage = item.mSurfaceDamage;
mCurrentApi = item.mApi;
computeCurrentTransformMatrixLocked();
return err;
}
- 1.syncForReleaseLocked 實際上是一次Fence阻塞,等待所有的Fence的監(jiān)聽都達到了NO_ERROR,返回Signal狀態(tài)涕癣。就進行下一步哗蜈,同時進行釋放上一幀的圖元,進入到free狀態(tài)坠韩。
- 2.記錄上一幀的數(shù)據(jù)到pendingRelease距潘,以及本次準備渲染的幀數(shù)中相關(guān)的參數(shù),如DataSpace只搁,mSlot插槽中對應(yīng)的index音比,以及攜帶GraphicBuffer的Image。
DataSpace小知識的記錄
有了RGB氢惋,Ycbcr這些顏色format洞翩,為什么還需要DataSpace,色彩的數(shù)據(jù)空間呢明肮?這里需要借助一篇文章
菱农,這里稍作總結(jié)。
在現(xiàn)實世界中柿估,當光強一倍循未,則亮度也會提升一倍,是一個線性關(guān)系。但是由于最早的顯示器(陰極射線管)顯示圖像的時候的妖,輸出亮度和電壓并不是成線性關(guān)系的绣檬,而是亮度等于電壓的2.2次冪的非線性關(guān)系:.
這個2.2也叫做Gama值。為了盡可能的達到現(xiàn)實世界的效果嫂粟。因此需要一個Gama的糾正娇未。也就是去除2.2次冪,因此會在處理之前先進行一次0.45次冪的處理星虹,抵消這個2.2次冪的造成的異常零抬。
而我們常用的sRGB的色彩空間也是這么一回事,就是指的是0.45次冪宽涌。而在上文中所有記錄的DataSpace也是這個意思平夜。
總結(jié)
bool refreshNeeded = handleMessageTransaction();
refreshNeeded |= handleMessageInvalidate();
refreshNeeded |= mRepaintEverything;
if (refreshNeeded) {
signalRefresh();
}
此時我們已經(jīng)分析接收到Invalidate消息之后判斷是否需要刷新的判斷處理。
- 1.handleMessageTransaction將會處理每一個Layer的事務(wù)卸亮,最核心的事情就是把每一個Layer中的上一幀的mDrawState被當前幀的mCurrentState替代忽妒。一旦有事務(wù)需要處理,說明有Surface發(fā)生了狀態(tài)的變化兼贸,如寬高如位置段直。此時就必須重新刷新整個界面。
- 2.handleMessageInvalidate處理的核心:
- 首先檢測哪一些圖元需要顯示溶诞,需要的則會添加到mLayersWithQueuedFrames鸯檬。條件是入隊時間不能超過預(yù)期時間的一秒,也能不能超過預(yù)期時間(mQueueItems是onFrameAvailable回調(diào)添加)很澄。
- 遍歷每一個需要顯示的Layer京闰,調(diào)用latchBuffer方法颜及。這個方法核心是updateTexImage甩苛。這個方法分為3個步驟:
acquireBufferLocked 本質(zhì)上是獲取mQueue的第一個加進來的圖元作為即將顯示的圖元。但是如果遇到顯示的時間和預(yù)期時間差大于1秒俏站,同時發(fā)現(xiàn)這個圖元已經(jīng)過期了(free狀態(tài)),則會跳幀讯蒲,直到找到最近時間的一幀。
LayerRejecter 判斷是否有打開凍結(jié)窗口模式肄扎,打開了但是發(fā)現(xiàn)圖元的大小不對則拒絕顯示墨林。相反,則會mDrawState的requested賦值給active犯祠。
updateAndReleaseLocked 釋放前一幀的圖元旭等,同時準備設(shè)置當前消費的圖元作為準備繪制的畫面。
我們回頭來看看handleMessageInvalidate衡载,它其實也是判斷是否需要全局刷新搔耕。如果發(fā)現(xiàn)圖元鎖定之后有Layer消費了圖元,則會決定進行調(diào)用refresh頁面痰娱。發(fā)送Refresh消息弃榨。最后dirty區(qū)域?qū)蕾嚫窵ayer 的寬高菩收。mVisibleRegions標志位最后是依賴latchBuffer返回的臟區(qū)和Layer是否有添加過。
我們最后來看看Refresh做了什么鲸睛?
case MessageQueue::REFRESH: {
handleMessageRefresh();
break;
}
void SurfaceFlinger::handleMessageRefresh() {
mRefreshPending = false;
nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
preComposition(refreshStartTime);
rebuildLayerStacks();
setUpHWComposer();
doDebugFlashRegions();
doTracing("handleRefresh");
logLayerStats();
doComposition();
postComposition(refreshStartTime);
...
mLayersWithQueuedFrames.clear();
}
大致上娜饵,刷新屏幕分為7步驟:
- 1.preComposition 預(yù)處理合成
- 2.rebuildLayerStacks 重新構(gòu)建Layer棧
- 3.setUpHWComposer HWC的渲染或者準備
- 4.doDebugFlashRegions 打開debug繪制模式
- 5.doTracing 跟蹤打印
- 6.doComposition 合成圖元
- 7.postComposition 圖元合成后的vysnc等收尾工作。
下一篇文章將會和大家聊聊官辈。