SF: Make message refresh loop over displays
Update message refresh handling to loop over the displays
at the top level and have each sub-function operate on the
passed in display. This will facilitate later updates that
allow for an SFBE per display.
Bug: 112259502
Test: cts -m CtsViewTestCases
SurfaceFlinger_test
vrflinger_test
Change-Id: I0284540563e532aa33a635c1642212eeb3f78bf4
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f5c0b74..2538945 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -259,8 +259,6 @@
mDebugDDMS(0),
mDebugDisableHWC(0),
mDebugDisableTransformHint(0),
- mDebugInSwapBuffers(0),
- mLastSwapBufferTime(0),
mDebugInTransaction(0),
mLastTransactionTime(0),
mForceFullDamage(false),
@@ -1444,25 +1442,26 @@
return false;
}
-bool SurfaceFlinger::handleMessageInvalidate() {
- ATRACE_CALL();
- return handlePageFlip();
-}
-
void SurfaceFlinger::handleMessageRefresh() {
ATRACE_CALL();
mRefreshPending = false;
+ const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
preComposition();
rebuildLayerStacks();
calculateWorkingSet();
- beginFrame();
- prepareFrame();
- doDebugFlashRegions();
+ for (const auto& [token, display] : mDisplays) {
+ beginFrame(display);
+ prepareFrame(display);
+ doDebugFlashRegions(display, repaintEverything);
+ doComposition(display, repaintEverything);
+ }
+
doTracing("handleRefresh");
logLayerStats();
- doComposition();
+
+ postFrame();
postComposition();
mHadClientComposition = false;
@@ -1470,11 +1469,18 @@
mHadClientComposition = mHadClientComposition ||
getBE().mHwc->hasClientComposition(display->getId());
}
+
mVsyncModulator.onRefreshed(mHadClientComposition);
mLayersWithQueuedFrames.clear();
}
+
+bool SurfaceFlinger::handleMessageInvalidate() {
+ ATRACE_CALL();
+ return handlePageFlip();
+}
+
void SurfaceFlinger::calculateWorkingSet() {
ATRACE_CALL();
ALOGV(__FUNCTION__);
@@ -1553,44 +1559,39 @@
mDrawingState.colorMatrixChanged = false;
}
-void SurfaceFlinger::doDebugFlashRegions()
+void SurfaceFlinger::doDebugFlashRegions(const sp<DisplayDevice>& display, bool repaintEverything)
{
// is debugging enabled
if (CC_LIKELY(!mDebugRegion))
return;
- const bool repaintEverything = mRepaintEverything;
- for (const auto& [token, display] : mDisplays) {
- if (display->isPoweredOn()) {
- // transform the dirty region into this screen's coordinate space
- const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
- if (!dirtyRegion.isEmpty()) {
- // redraw the whole screen
- doComposeSurfaces(display);
+ if (display->isPoweredOn()) {
+ // transform the dirty region into this screen's coordinate space
+ const Region dirtyRegion(display->getDirtyRegion(repaintEverything));
+ if (!dirtyRegion.isEmpty()) {
+ // redraw the whole screen
+ doComposeSurfaces(display);
- // and draw the dirty region
- const int32_t height = display->getHeight();
- auto& engine(getRenderEngine());
- engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
+ // and draw the dirty region
+ const int32_t height = display->getHeight();
+ auto& engine(getRenderEngine());
+ engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
- display->swapBuffers(getHwComposer());
- }
+ display->swapBuffers(getHwComposer());
}
}
- postFramebuffer();
+ postFramebuffer(display);
if (mDebugRegion > 1) {
usleep(mDebugRegion * 1000);
}
- for (const auto& [token, display] : mDisplays) {
- if (!display->isPoweredOn()) {
- continue;
- }
-
+ if (display->isPoweredOn()) {
status_t result = display->prepareFrame(*getBE().mHwc);
- ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)",
+ ALOGE_IF(result != NO_ERROR,
+ "prepareFrame for display %d failed:"
+ " %d (%s)",
display->getId(), result, strerror(-result));
}
}
@@ -1954,80 +1955,85 @@
display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent);
}
-void SurfaceFlinger::beginFrame()
+void SurfaceFlinger::beginFrame(const sp<DisplayDevice>& display)
{
- for (const auto& [token, display] : mDisplays) {
- bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty();
- bool empty = display->getVisibleLayersSortedByZ().size() == 0;
- bool wasEmpty = !display->lastCompositionHadVisibleLayers;
+ bool dirty = !display->getDirtyRegion(false).isEmpty();
+ bool empty = display->getVisibleLayersSortedByZ().size() == 0;
+ bool wasEmpty = !display->lastCompositionHadVisibleLayers;
- // If nothing has changed (!dirty), don't recompose.
- // If something changed, but we don't currently have any visible layers,
- // and didn't when we last did a composition, then skip it this time.
- // The second rule does two things:
- // - When all layers are removed from a display, we'll emit one black
- // frame, then nothing more until we get new layers.
- // - When a display is created with a private layer stack, we won't
- // emit any black frames until a layer is added to the layer stack.
- bool mustRecompose = dirty && !(empty && wasEmpty);
+ // If nothing has changed (!dirty), don't recompose.
+ // If something changed, but we don't currently have any visible layers,
+ // and didn't when we last did a composition, then skip it this time.
+ // The second rule does two things:
+ // - When all layers are removed from a display, we'll emit one black
+ // frame, then nothing more until we get new layers.
+ // - When a display is created with a private layer stack, we won't
+ // emit any black frames until a layer is added to the layer stack.
+ bool mustRecompose = dirty && !(empty && wasEmpty);
- ALOGV_IF(display->isVirtual(), "Display %d: %s composition (%sdirty %sempty %swasEmpty)",
- display->getId(), mustRecompose ? "doing" : "skipping", dirty ? "+" : "-",
- empty ? "+" : "-", wasEmpty ? "+" : "-");
+ ALOGV_IF(displayDevice->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
+ "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy,
+ mustRecompose ? "doing" : "skipping",
+ dirty ? "+" : "-",
+ empty ? "+" : "-",
+ wasEmpty ? "+" : "-");
- display->beginFrame(mustRecompose);
+ display->beginFrame(mustRecompose);
- if (mustRecompose) {
- display->lastCompositionHadVisibleLayers = !empty;
- }
+ if (mustRecompose) {
+ display->lastCompositionHadVisibleLayers = !empty;
}
}
-void SurfaceFlinger::prepareFrame()
+void SurfaceFlinger::prepareFrame(const sp<DisplayDevice>& display)
{
- for (const auto& [token, display] : mDisplays) {
- if (!display->isPoweredOn()) {
- continue;
- }
-
- status_t result = display->prepareFrame(*getBE().mHwc);
- ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)",
- display->getId(), result, strerror(-result));
+ if (!display->isPoweredOn()) {
+ return;
}
+
+ status_t result = display->prepareFrame(*getBE().mHwc);
+ ALOGE_IF(result != NO_ERROR,
+ "prepareFrame for display %d failed:"
+ " %d (%s)",
+ display->getId(), result, strerror(-result));
}
-void SurfaceFlinger::doComposition() {
+void SurfaceFlinger::doComposition(const sp<DisplayDevice>& display, bool repaintEverything) {
ATRACE_CALL();
ALOGV("doComposition");
- const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
- for (const auto& [token, display] : mDisplays) {
- if (display->isPoweredOn()) {
- // transform the dirty region into this screen's coordinate space
- const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
+ if (display->isPoweredOn()) {
+ // transform the dirty region into this screen's coordinate space
+ const Region dirtyRegion(display->getDirtyRegion(repaintEverything));
- // repaint the framebuffer (if needed)
- doDisplayComposition(display, dirtyRegion);
+ // repaint the framebuffer (if needed)
+ doDisplayComposition(display, dirtyRegion);
- display->dirtyRegion.clear();
- display->flip();
- }
+ display->dirtyRegion.clear();
+ display->flip();
}
- postFramebuffer();
+ postFramebuffer(display);
}
-void SurfaceFlinger::postFramebuffer()
+void SurfaceFlinger::postFrame()
+{
+ // |mStateLock| not needed as we are on the main thread
+ if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) {
+ uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount();
+ if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
+ logFrameStats();
+ }
+ }
+}
+
+void SurfaceFlinger::postFramebuffer(const sp<DisplayDevice>& display)
{
ATRACE_CALL();
ALOGV("postFramebuffer");
- const nsecs_t now = systemTime();
- mDebugInSwapBuffers = now;
+ mPostFramebufferTime = systemTime();
- for (const auto& [token, display] : mDisplays) {
- if (!display->isPoweredOn()) {
- continue;
- }
+ if (display->isPoweredOn()) {
const auto displayId = display->getId();
if (displayId >= 0) {
getBE().mHwc->presentAndGetReleaseFences(displayId);
@@ -2072,18 +2078,6 @@
getBE().mHwc->clearReleaseFences(displayId);
}
}
-
- mLastSwapBufferTime = systemTime() - now;
- mDebugInSwapBuffers = 0;
-
- // |mStateLock| not needed as we are on the main thread
- const auto display = getDefaultDisplayDeviceLocked();
- if (display && getHwComposer().isConnected(display->getId())) {
- const uint32_t flipCount = display->getPageFlipCount();
- if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
- logFrameStats();
- }
- }
}
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
@@ -4210,9 +4204,7 @@
// figure out if we're stuck somewhere
const nsecs_t now = systemTime();
- const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
const nsecs_t inTransaction(mDebugInTransaction);
- nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
/*
@@ -4320,11 +4312,8 @@
result.appendFormat(" orientation=%d, isPoweredOn=%d\n", display->getOrientation(),
display->isPoweredOn());
}
- result.appendFormat(" last eglSwapBuffers() time: %f us\n"
- " last transaction time : %f us\n"
- " transaction-flags : %08x\n"
+ result.appendFormat(" transaction-flags : %08x\n"
" gpu_to_cpu_unsupported : %d\n",
- mLastSwapBufferTime / 1000.0, mLastTransactionTime / 1000.0,
mTransactionFlags, !mGpuToCpuSupported);
if (display) {
@@ -4336,9 +4325,6 @@
activeConfig->getDpiY());
}
- result.appendFormat(" eglSwapBuffers time: %f us\n",
- inSwapBuffersDuration/1000.0);
-
result.appendFormat(" transaction time: %f us\n",
inTransactionDuration/1000.0);