diff options
author | 2023-01-21 16:58:22 -0500 | |
---|---|---|
committer | 2023-01-30 13:44:19 -0500 | |
commit | 63f127947bcb0275d2c75fdb25fe7ba8f30fecbc (patch) | |
tree | 8389c657da64608fe012c518d7c96a962467f70f | |
parent | dff1554cc8c39f4a64e74a50c0371bd0b794239f (diff) |
SF: Bundle ftl::Flags for CompositionCoverage
...as they will later be passed to Scheduler via ICompositor. For now,
extract ICompositor to its own header, alongside CompositionCoverage.
Bug: 241285475
Bug: 241285191
Test: Frame misses are still traced.
Change-Id: I1562893c9357a02aa42516e775700065b9b17e4b
8 files changed, 131 insertions, 60 deletions
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp index 9b044977be..dec8f59ee9 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.cpp +++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp @@ -17,12 +17,12 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <binder/IPCThreadState.h> - +#include <gui/DisplayEventReceiver.h> #include <utils/Log.h> #include <utils/Timers.h> #include <utils/threads.h> -#include <gui/DisplayEventReceiver.h> +#include <scheduler/interface/ICompositor.h> #include "EventThread.h" #include "FrameTimeline.h" diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h index ad0ea72623..0d59337950 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.h +++ b/services/surfaceflinger/Scheduler/MessageQueue.h @@ -37,15 +37,7 @@ namespace android { -struct ICompositor { - virtual void configure() = 0; - virtual bool commit(TimePoint frameTime, VsyncId, TimePoint expectedVsyncTime) = 0; - virtual void composite(TimePoint frameTime, VsyncId) = 0; - virtual void sample() = 0; - -protected: - ~ICompositor() = default; -}; +struct ICompositor; template <typename F> class Task : public MessageHandler { diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 1fc1519982..1e97f352d1 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -34,6 +34,8 @@ #include <utils/Trace.h> #include <FrameTimeline/FrameTimeline.h> +#include <scheduler/interface/ICompositor.h> + #include <algorithm> #include <cinttypes> #include <cstdint> diff --git a/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositionCoverage.h b/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositionCoverage.h new file mode 100644 index 0000000000..3d0f1a9d33 --- /dev/null +++ b/services/surfaceflinger/Scheduler/include/scheduler/interface/CompositionCoverage.h @@ -0,0 +1,37 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <cstdint> + +#include <ftl/flags.h> + +namespace android { + +// Whether composition was covered by HWC and/or GPU. +enum class CompositionCoverage : std::uint8_t { + Hwc = 1 << 0, + + // Mutually exclusive: The composition either used the GPU, or reused a buffer that had been + // composited on the GPU. + Gpu = 1 << 1, + GpuReuse = 1 << 2, +}; + +using CompositionCoverageFlags = ftl::Flags<CompositionCoverage>; + +} // namespace android diff --git a/services/surfaceflinger/Scheduler/include/scheduler/interface/ICompositor.h b/services/surfaceflinger/Scheduler/include/scheduler/interface/ICompositor.h new file mode 100644 index 0000000000..cc419259ef --- /dev/null +++ b/services/surfaceflinger/Scheduler/include/scheduler/interface/ICompositor.h @@ -0,0 +1,43 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <scheduler/Time.h> +#include <scheduler/VsyncId.h> + +namespace android { + +struct ICompositor { + // Configures physical displays, processing hotplug and/or mode setting via the Composer HAL. + virtual void configure() = 0; + + // Commits transactions for layers and displays. Returns whether any state has been invalidated, + // i.e. whether a frame should be composited for each display. + virtual bool commit(TimePoint frameTime, VsyncId, TimePoint expectedVsyncTime) = 0; + + // Composites a frame for each display. CompositionEngine performs GPU and/or HAL composition + // via RenderEngine and the Composer HAL, respectively. + virtual void composite(TimePoint frameTime, VsyncId) = 0; + + // Samples the composited frame via RegionSamplingThread. + virtual void sample() = 0; + +protected: + ~ICompositor() = default; +}; + +} // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7d0dc93cf9..0dc8b05993 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -408,15 +408,8 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI mDebugFlashDelay = base::GetUintProperty("debug.sf.showupdates"s, 0u); - // DDMS debugging deprecated (b/120782499) - property_get("debug.sf.ddms", value, "0"); - int debugDdms = atoi(value); - ALOGI_IF(debugDdms, "DDMS debugging not supported"); - - property_get("debug.sf.enable_gl_backpressure", value, "1"); - mPropagateBackpressureClientComposition = atoi(value); - ALOGI_IF(mPropagateBackpressureClientComposition, - "Enabling backpressure propagation for Client Composition"); + mBackpressureGpuComposition = base::GetBoolProperty("debug.sf.enable_gl_backpressure"s, true); + ALOGI_IF(mBackpressureGpuComposition, "Enabling backpressure for GPU composition"); property_get("ro.surface_flinger.supports_background_blur", value, "0"); bool supportsBlurs = atoi(value); @@ -2155,11 +2148,11 @@ bool SurfaceFlinger::commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expe const Period vsyncPeriod = mScheduler->getVsyncSchedule().period(); const FenceTimePtr& previousPresentFence = getPreviousPresentFence(frameTime, vsyncPeriod); - // When Backpressure propagation is enabled we want to give a small grace period + // When backpressure propagation is enabled, we want to give a small grace period of 1ms // for the present fence to fire instead of just giving up on this frame to handle cases // where present fence is just about to get signaled. - const int graceTimeForPresentFenceMs = - (mPropagateBackpressureClientComposition || !mHadClientComposition) ? 1 : 0; + const int graceTimeForPresentFenceMs = static_cast<int>( + mBackpressureGpuComposition || !mCompositionCoverage.test(CompositionCoverage::Gpu)); // Pending frames may trigger backpressure propagation. const TracedOrdinal<bool> framePending = {"PrevFramePending", @@ -2182,9 +2175,14 @@ bool SurfaceFlinger::commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expe (lastScheduledPresentTime.ns() < previousPresentTime - frameMissedSlop))}; const TracedOrdinal<bool> hwcFrameMissed = {"PrevHwcFrameMissed", - mHadDeviceComposition && frameMissed}; + frameMissed && + mCompositionCoverage.test( + CompositionCoverage::Hwc)}; + const TracedOrdinal<bool> gpuFrameMissed = {"PrevGpuFrameMissed", - mHadClientComposition && frameMissed}; + frameMissed && + mCompositionCoverage.test( + CompositionCoverage::Gpu)}; if (frameMissed) { mFrameMissedCount++; @@ -2222,7 +2220,7 @@ bool SurfaceFlinger::commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expe } if (framePending) { - if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) { + if (mBackpressureGpuComposition || (hwcFrameMissed && !gpuFrameMissed)) { scheduleCommit(FrameHint::kNone); return false; } @@ -2459,29 +2457,43 @@ void SurfaceFlinger::composite(TimePoint frameTime, VsyncId vsyncId) postComposition(presentTime); - const bool prevFrameHadClientComposition = mHadClientComposition; + const bool hadGpuComposited = mCompositionCoverage.test(CompositionCoverage::Gpu); + mCompositionCoverage.clear(); - mHadClientComposition = mHadDeviceComposition = mReusedClientComposition = false; TimeStats::ClientCompositionRecord clientCompositionRecord; for (const auto& [_, display] : displays) { const auto& state = display->getCompositionDisplay()->getState(); - mHadClientComposition |= state.usesClientComposition && !state.reusedClientComposition; - mHadDeviceComposition |= state.usesDeviceComposition; - mReusedClientComposition |= state.reusedClientComposition; + + if (state.usesDeviceComposition) { + mCompositionCoverage |= CompositionCoverage::Hwc; + } + + if (state.reusedClientComposition) { + mCompositionCoverage |= CompositionCoverage::GpuReuse; + } else if (state.usesClientComposition) { + mCompositionCoverage |= CompositionCoverage::Gpu; + } + clientCompositionRecord.predicted |= (state.strategyPrediction != CompositionStrategyPredictionState::DISABLED); clientCompositionRecord.predictionSucceeded |= (state.strategyPrediction == CompositionStrategyPredictionState::SUCCESS); } - clientCompositionRecord.hadClientComposition = mHadClientComposition; - clientCompositionRecord.reused = mReusedClientComposition; - clientCompositionRecord.changed = prevFrameHadClientComposition != mHadClientComposition; + const bool hasGpuComposited = mCompositionCoverage.test(CompositionCoverage::Gpu); + + clientCompositionRecord.hadClientComposition = hasGpuComposited; + clientCompositionRecord.reused = mCompositionCoverage.test(CompositionCoverage::GpuReuse); + clientCompositionRecord.changed = hadGpuComposited != hasGpuComposited; + mTimeStats->pushCompositionStrategyState(clientCompositionRecord); - // TODO: b/160583065 Enable skip validation when SF caches all client composition layers - const bool usedGpuComposition = mHadClientComposition || mReusedClientComposition; - mScheduler->modulateVsync(&VsyncModulator::onDisplayRefresh, usedGpuComposition); + using namespace ftl::flag_operators; + + // TODO(b/160583065): Enable skip validation when SF caches all client composition layers. + const bool hasGpuUseOrReuse = + mCompositionCoverage.any(CompositionCoverage::Gpu | CompositionCoverage::GpuReuse); + mScheduler->modulateVsync(&VsyncModulator::onDisplayRefresh, hasGpuUseOrReuse); mLayersWithQueuedFrames.clear(); if (mLayerTracingEnabled && mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 207dfe2e96..ed09c3f2a8 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -57,6 +57,8 @@ #include <scheduler/PresentLatencyTracker.h> #include <scheduler/Time.h> #include <scheduler/TransactionSchedule.h> +#include <scheduler/interface/CompositionCoverage.h> +#include <scheduler/interface/ICompositor.h> #include <ui/FenceResult.h> #include "Display/DisplayMap.h" @@ -606,19 +608,9 @@ private: void onComposerHalVsyncIdle(hal::HWDisplayId) override; // ICompositor overrides: - - // Configures physical displays, processing hotplug and/or mode setting via the Composer HAL. void configure() override; - - // Commits transactions for layers and displays. Returns whether any state has been invalidated, - // i.e. whether a frame should be composited for each display. bool commit(TimePoint frameTime, VsyncId, TimePoint expectedVsyncTime) override; - - // Composites a frame for each display. CompositionEngine performs GPU and/or HAL composition - // via RenderEngine and the Composer HAL, respectively. void composite(TimePoint frameTime, VsyncId) override; - - // Samples the composited frame via RegionSamplingThread. void sample() override; // ISchedulerCallback overrides: @@ -1158,17 +1150,6 @@ private: // Tracks layers that need to update a display's dirty region. std::vector<sp<Layer>> mLayersPendingRefresh; - // 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. - // Note that it is possible for a frame to be composed via both client and device - // composition, for example in the case of overlays. - bool mHadDeviceComposition = false; - // True if in the previous frame, the client composition was skipped by reusing the buffer - // used in a previous composition. This can happed if the client composition requests - // did not change. - bool mReusedClientComposition = false; - BootStage mBootStage = BootStage::BOOTLOADER; struct HotplugEvent { @@ -1204,7 +1185,7 @@ private: std::atomic_bool mForceFullDamage = false; bool mLayerCachingEnabled = false; - bool mPropagateBackpressureClientComposition = false; + bool mBackpressureGpuComposition = false; LayerTracing mLayerTracing{*this}; bool mLayerTracingEnabled = false; @@ -1268,6 +1249,9 @@ private: std::atomic<int> mNumTrustedPresentationListeners = 0; std::unique_ptr<compositionengine::CompositionEngine> mCompositionEngine; + + CompositionCoverageFlags mCompositionCoverage; + // mMaxRenderTargetSize is only set once in init() so it doesn't need to be protected by // any mutex. size_t mMaxRenderTargetSize{1}; diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index 0cbfa63354..74885d8a78 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -16,11 +16,12 @@ #pragma once -#include <Scheduler/Scheduler.h> #include <ftl/fake_guard.h> #include <gmock/gmock.h> #include <gui/ISurfaceComposer.h> +#include <scheduler/interface/ICompositor.h> + #include "Scheduler/EventThread.h" #include "Scheduler/LayerHistory.h" #include "Scheduler/Scheduler.h" |