Merge "SurfaceFlinger: Fix check for ignoring a new color transform" into qt-dev
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 48cb620..efe4bdf 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -1311,7 +1311,9 @@
StringAppendF(&result, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
extensions.getVersion());
StringAppendF(&result, "%s\n", extensions.getExtensions());
- StringAppendF(&result, "RenderEngine is in protected context : %d\n", mInProtectedContext);
+ StringAppendF(&result, "RenderEngine supports protected context: %d\n",
+ supportsProtectedContent());
+ StringAppendF(&result, "RenderEngine is in protected context: %d\n", mInProtectedContext);
StringAppendF(&result, "RenderEngine program cache size for unprotected context: %zu\n",
cache.getSize(mEGLContext));
StringAppendF(&result, "RenderEngine program cache size for protected context: %zu\n",
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 5a67dc4..0861a1f 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -60,6 +60,15 @@
GraphicBufferAllocator::~GraphicBufferAllocator() {}
+size_t GraphicBufferAllocator::getTotalSize() const {
+ Mutex::Autolock _l(sLock);
+ size_t total = 0;
+ for (size_t i = 0; i < sAllocList.size(); ++i) {
+ total += sAllocList.valueAt(i).size;
+ }
+ return total;
+}
+
void GraphicBufferAllocator::dump(std::string& result) const {
Mutex::Autolock _l(sLock);
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
diff --git a/libs/ui/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h
index 3a547b6..25d4512 100644
--- a/libs/ui/include/ui/GraphicBufferAllocator.h
+++ b/libs/ui/include/ui/GraphicBufferAllocator.h
@@ -49,6 +49,8 @@
status_t free(buffer_handle_t handle);
+ size_t getTotalSize() const;
+
void dump(std::string& res) const;
static void dumpToSystemLog();
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 46ca0b6..cbe8b29 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -130,7 +130,7 @@
}
mFrameTracker.logAndResetStats(mName);
- mFlinger->onLayerDestroyed();
+ mFlinger->onLayerDestroyed(this);
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 16f6729..276bce1 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -65,6 +65,13 @@
property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "1000000");
const int highFpsLateSfOffsetNs = atoi(value);
+ // Below defines the threshold when an offset is considered to be negative, i.e. targeting
+ // for the N+2 vsync instead of N+1. This means that:
+ // For offset < threshold, SF wake up (vsync_duration - offset) before HW vsync.
+ // For offset >= threshold, SF wake up (2 * vsync_duration - offset) before HW vsync.
+ property_get("debug.sf.phase_offset_threshold_for_next_vsync_ns", value, "-1");
+ const int phaseOffsetThresholdForNextVsyncNs = atoi(value);
+
mDefaultRefreshRateOffsets.early = {earlySfOffsetNs != -1 ? earlySfOffsetNs
: sfVsyncPhaseOffsetNs,
earlyAppOffsetNs != -1 ? earlyAppOffsetNs
@@ -84,6 +91,10 @@
highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
: highFpsLateAppOffsetNs};
mHighRefreshRateOffsets.late = {highFpsLateSfOffsetNs, highFpsLateAppOffsetNs};
+
+ mOffsetThresholdForNextVsync = phaseOffsetThresholdForNextVsyncNs != -1
+ ? phaseOffsetThresholdForNextVsyncNs
+ : std::numeric_limits<nsecs_t>::max();
}
PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
index 08747a5..dc71e6e 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.h
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -46,6 +46,7 @@
RefreshRateConfigs::RefreshRateType refreshRateType) const = 0;
virtual Offsets getCurrentOffsets() const = 0;
virtual void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) = 0;
+ virtual nsecs_t getOffsetThresholdForNextVsync() const = 0;
virtual void dump(std::string& result) const = 0;
};
@@ -72,6 +73,8 @@
mRefreshRateType = refreshRateType;
}
+ nsecs_t getOffsetThresholdForNextVsync() const override { return mOffsetThresholdForNextVsync; }
+
// Returns current offsets in human friendly format.
void dump(std::string& result) const override;
@@ -84,6 +87,7 @@
Offsets mDefaultRefreshRateOffsets;
Offsets mHighRefreshRateOffsets;
+ nsecs_t mOffsetThresholdForNextVsync;
};
} // namespace impl
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index 1a0de08..81a7864 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -139,6 +139,19 @@
}
}
+ Offsets getOffsets() {
+ // Early offsets are used if we're in the middle of a refresh rate
+ // change, or if we recently begin a transaction.
+ if (mTransactionStart == Scheduler::TransactionStart::EARLY ||
+ mRemainingEarlyFrameCount > 0 || mRefreshRateChangePending) {
+ return mEarlyOffsets;
+ } else if (mLastFrameUsedRenderEngine) {
+ return mEarlyGlOffsets;
+ } else {
+ return mLateOffsets;
+ }
+ }
+
private:
void updateOffsets() {
const Offsets desired = getOffsets();
@@ -167,19 +180,6 @@
}
}
- Offsets getOffsets() {
- // Early offsets are used if we're in the middle of a refresh rate
- // change, or if we recently begin a transaction.
- if (mTransactionStart == Scheduler::TransactionStart::EARLY ||
- mRemainingEarlyFrameCount > 0 || mRefreshRateChangePending) {
- return mEarlyOffsets;
- } else if (mLastFrameUsedRenderEngine) {
- return mEarlyGlOffsets;
- } else {
- return mLateOffsets;
- }
- }
-
Offsets mLateOffsets;
Offsets mEarlyOffsets;
Offsets mEarlyGlOffsets;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d5a38e9..2ca5c02 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -977,8 +977,7 @@
bool SurfaceFlinger::performSetActiveConfig() {
ATRACE_CALL();
if (mCheckPendingFence) {
- if (mPreviousPresentFence != Fence::NO_FENCE &&
- (mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled)) {
+ if (previousFrameMissed()) {
// fence has not signaled yet. wait for the next invalidate
mEventQueue->invalidateForHWC();
return true;
@@ -1587,12 +1586,23 @@
setTransactionFlags(eDisplayTransactionNeeded);
}
+bool SurfaceFlinger::previousFrameMissed() NO_THREAD_SAFETY_ANALYSIS {
+ // We are storing the last 2 present fences. If sf's phase offset is to be
+ // woken up before the actual vsync but targeting the next vsync, we need to check
+ // fence N-2
+ const sp<Fence>& fence =
+ mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync()
+ ? mPreviousPresentFences[0]
+ : mPreviousPresentFences[1];
+
+ return fence != Fence::NO_FENCE && (fence->getStatus() == Fence::Status::Unsignaled);
+}
+
void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {
ATRACE_CALL();
switch (what) {
case MessageQueue::INVALIDATE: {
- bool frameMissed = mPreviousPresentFence != Fence::NO_FENCE &&
- (mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled);
+ bool frameMissed = previousFrameMissed();
bool hwcFrameMissed = mHadDeviceComposition && frameMissed;
bool gpuFrameMissed = mHadClientComposition && frameMissed;
ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
@@ -1982,9 +1992,11 @@
}
getBE().mDisplayTimeline.updateSignalTimes();
- mPreviousPresentFence = displayDevice ? getHwComposer().getPresentFence(*displayDevice->getId())
- : Fence::NO_FENCE;
- auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence);
+ mPreviousPresentFences[1] = mPreviousPresentFences[0];
+ mPreviousPresentFences[0] = displayDevice
+ ? getHwComposer().getPresentFence(*displayDevice->getId())
+ : Fence::NO_FENCE;
+ auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFences[0]);
getBE().mDisplayTimeline.push(presentFenceTime);
DisplayStatInfo stats;
@@ -2075,12 +2087,18 @@
}
}
- mTransactionCompletedThread.addPresentFence(mPreviousPresentFence);
+ mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
mTransactionCompletedThread.sendCallbacks();
if (mLumaSampling && mRegionSamplingThread) {
mRegionSamplingThread->notifyNewContent();
}
+
+ // Even though ATRACE_INT64 already checks if tracing is enabled, it doesn't prevent the
+ // side-effect of getTotalSize(), so we check that again here
+ if (ATRACE_ENABLED()) {
+ ATRACE_INT64("Total Buffer Size", GraphicBufferAllocator::get().getTotalSize());
+ }
}
void SurfaceFlinger::computeLayerBounds() {
@@ -2932,6 +2950,13 @@
if (l->isRemovedFromCurrentState()) {
latchAndReleaseBuffer(l);
}
+
+ // If the layer has been removed and has no parent, then it will not be reachable
+ // when traversing layers on screen. Add the layer to the offscreenLayers set to
+ // ensure we can copy its current to drawing state.
+ if (!l->getParent()) {
+ mOffscreenLayers.emplace(l.get());
+ }
}
mLayersPendingRemoval.clear();
}
@@ -2945,7 +2970,17 @@
// clear the "changed" flags in current state
mCurrentState.colorMatrixChanged = false;
- mDrawingState.traverseInZOrder([](Layer* layer) { layer->commitChildList(); });
+ mDrawingState.traverseInZOrder([&](Layer* layer) {
+ layer->commitChildList();
+
+ // If the layer can be reached when traversing mDrawingState, then the layer is no
+ // longer offscreen. Remove the layer from the offscreenLayer set.
+ if (mOffscreenLayers.count(layer)) {
+ mOffscreenLayers.erase(layer);
+ }
+ });
+
+ commitOffscreenLayers();
});
mTransactionPending = false;
@@ -2973,6 +3008,18 @@
}
}
+void SurfaceFlinger::commitOffscreenLayers() {
+ for (Layer* offscreenLayer : mOffscreenLayers) {
+ offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, [](Layer* layer) {
+ uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
+ if (!trFlags) return;
+
+ layer->doTransaction(0);
+ layer->commitChildList();
+ });
+ }
+}
+
void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
Region& outDirtyRegion, Region& outOpaqueRegion) {
ATRACE_CALL();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 72e2ff9..5871774 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -308,7 +308,10 @@
const sp<IGraphicBufferProducer>& bufferProducer) const;
inline void onLayerCreated() { mNumLayers++; }
- inline void onLayerDestroyed() { mNumLayers--; }
+ inline void onLayerDestroyed(Layer* layer) {
+ mNumLayers--;
+ mOffscreenLayers.erase(layer);
+ }
TransactionCompletedThread& getTransactionCompletedThread() {
return mTransactionCompletedThread;
@@ -563,6 +566,7 @@
uint32_t setTransactionFlags(uint32_t flags, Scheduler::TransactionStart transactionStart);
void latchAndReleaseBuffer(const sp<Layer>& layer);
void commitTransaction() REQUIRES(mStateLock);
+ void commitOffscreenLayers();
bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
const Vector<ComposerState>& states);
@@ -824,6 +828,8 @@
return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt;
}
+ bool previousFrameMissed();
+
/*
* Debugging & dumpsys
*/
@@ -956,7 +962,7 @@
std::vector<sp<Layer>> mLayersWithQueuedFrames;
// Tracks layers that need to update a display's dirty region.
std::vector<sp<Layer>> mLayersPendingRefresh;
- sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
+ std::array<sp<Fence>, 2> mPreviousPresentFences = {Fence::NO_FENCE, Fence::NO_FENCE};
// True if in the previous frame at least one layer was composed via the GPU.
bool mHadClientComposition = false;
// True if in the previous frame at least one layer was composed via HW Composer.
@@ -1150,6 +1156,12 @@
// Flag used to set override allowed display configs from backdoor
bool mDebugDisplayConfigSetByBackdoor = false;
+
+ // A set of layers that have no parent so they are not drawn on screen.
+ // Should only be accessed by the main thread.
+ // The Layer pointer is removed from the set when the destructor is called so there shouldn't
+ // be any issues with a raw pointer referencing an invalid object.
+ std::unordered_set<Layer*> mOffscreenLayers;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
index cfa8337..96121bb 100644
--- a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
+++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
@@ -49,6 +49,8 @@
// refresh rates, to properly update the offsets.
void setRefreshRateType(RefreshRateConfigs::RefreshRateType /*refreshRateType*/) override {}
+ nsecs_t getOffsetThresholdForNextVsync() const override { return FAKE_PHASE_OFFSET_NS; }
+
// Returns current offsets in human friendly format.
void dump(std::string& /*result*/) const override {}
};