xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <SurfaceFlingerProperties.sysprop.h>
18 #include <android-base/stringprintf.h>
19 #include <common/FlagManager.h>
20 #include <common/trace.h>
21 #include <compositionengine/CompositionEngine.h>
22 #include <compositionengine/CompositionRefreshArgs.h>
23 #include <compositionengine/DisplayColorProfile.h>
24 #include <compositionengine/LayerFE.h>
25 #include <compositionengine/LayerFECompositionState.h>
26 #include <compositionengine/RenderSurface.h>
27 #include <compositionengine/impl/HwcAsyncWorker.h>
28 #include <compositionengine/impl/Output.h>
29 #include <compositionengine/impl/OutputCompositionState.h>
30 #include <compositionengine/impl/OutputLayer.h>
31 #include <compositionengine/impl/OutputLayerCompositionState.h>
32 #include <compositionengine/impl/planner/Planner.h>
33 #include <ftl/algorithm.h>
34 #include <ftl/future.h>
35 #include <ftl/optional.h>
36 #include <scheduler/FrameTargeter.h>
37 #include <scheduler/Time.h>
38 
39 #include <com_android_graphics_libgui_flags.h>
40 
41 #include <optional>
42 #include <thread>
43 
44 #include "renderengine/ExternalTexture.h"
45 
46 // TODO(b/129481165): remove the #pragma below and fix conversion issues
47 #pragma clang diagnostic push
48 #pragma clang diagnostic ignored "-Wconversion"
49 
50 #include <renderengine/DisplaySettings.h>
51 #include <renderengine/RenderEngine.h>
52 
53 // TODO(b/129481165): remove the #pragma below and fix conversion issues
54 #pragma clang diagnostic pop // ignored "-Wconversion"
55 
56 #include <android-base/properties.h>
57 #include <ui/DebugUtils.h>
58 #include <ui/HdrCapabilities.h>
59 
60 #include "TracedOrdinal.h"
61 
62 using aidl::android::hardware::graphics::composer3::Composition;
63 
64 namespace android::compositionengine {
65 
66 Output::~Output() = default;
67 
68 namespace impl {
69 using CompositionStrategyPredictionState =
70         OutputCompositionState::CompositionStrategyPredictionState;
71 namespace {
72 
73 template <typename T>
74 class Reversed {
75 public:
Reversed(const T & container)76     explicit Reversed(const T& container) : mContainer(container) {}
begin()77     auto begin() { return mContainer.rbegin(); }
end()78     auto end() { return mContainer.rend(); }
79 
80 private:
81     const T& mContainer;
82 };
83 
84 // Helper for enumerating over a container in reverse order
85 template <typename T>
reversed(const T & c)86 Reversed<T> reversed(const T& c) {
87     return Reversed<T>(c);
88 }
89 
90 struct ScaleVector {
91     float x;
92     float y;
93 };
94 
95 // Returns a ScaleVector (x, y) such that from.scale(x, y) = to',
96 // where to' will have the same size as "to". In the case where "from" and "to"
97 // start at the origin to'=to.
getScale(const Rect & from,const Rect & to)98 ScaleVector getScale(const Rect& from, const Rect& to) {
99     return {.x = static_cast<float>(to.width()) / from.width(),
100             .y = static_cast<float>(to.height()) / from.height()};
101 }
102 
103 } // namespace
104 
createOutput(const compositionengine::CompositionEngine & compositionEngine)105 std::shared_ptr<Output> createOutput(
106         const compositionengine::CompositionEngine& compositionEngine) {
107     return createOutputTemplated<Output>(compositionEngine);
108 }
109 
110 Output::~Output() = default;
111 
isValid() const112 bool Output::isValid() const {
113     return mDisplayColorProfile && mDisplayColorProfile->isValid() && mRenderSurface &&
114             mRenderSurface->isValid();
115 }
116 
getDisplayId() const117 ftl::Optional<DisplayId> Output::getDisplayId() const {
118     return {};
119 }
120 
getName() const121 const std::string& Output::getName() const {
122     return mName;
123 }
124 
setName(const std::string & name)125 void Output::setName(const std::string& name) {
126     mName = name;
127     auto displayIdOpt = getDisplayId();
128     mNamePlusId = displayIdOpt ? base::StringPrintf("%s (%s)", mName.c_str(),
129                                      to_string(*displayIdOpt).c_str())
130                                : mName;
131 }
132 
setCompositionEnabled(bool enabled)133 void Output::setCompositionEnabled(bool enabled) {
134     auto& outputState = editState();
135     if (outputState.isEnabled == enabled) {
136         return;
137     }
138 
139     outputState.isEnabled = enabled;
140     dirtyEntireOutput();
141 }
142 
setLayerCachingEnabled(bool enabled)143 void Output::setLayerCachingEnabled(bool enabled) {
144     if (enabled == (mPlanner != nullptr)) {
145         return;
146     }
147 
148     if (enabled) {
149         mPlanner = std::make_unique<planner::Planner>(getCompositionEngine().getRenderEngine());
150         if (mRenderSurface) {
151             mPlanner->setDisplaySize(mRenderSurface->getSize());
152         }
153     } else {
154         mPlanner.reset();
155     }
156 
157     for (auto* outputLayer : getOutputLayersOrderedByZ()) {
158         if (!outputLayer) {
159             continue;
160         }
161 
162         outputLayer->editState().overrideInfo = {};
163     }
164 }
165 
setLayerCachingTexturePoolEnabled(bool enabled)166 void Output::setLayerCachingTexturePoolEnabled(bool enabled) {
167     if (mPlanner) {
168         mPlanner->setTexturePoolEnabled(enabled);
169     }
170 }
171 
setProjection(ui::Rotation orientation,const Rect & layerStackSpaceRect,const Rect & orientedDisplaySpaceRect)172 void Output::setProjection(ui::Rotation orientation, const Rect& layerStackSpaceRect,
173                            const Rect& orientedDisplaySpaceRect) {
174     auto& outputState = editState();
175 
176     outputState.displaySpace.setOrientation(orientation);
177     LOG_FATAL_IF(outputState.displaySpace.getBoundsAsRect() == Rect::INVALID_RECT,
178                  "The display bounds are unknown.");
179 
180     // Compute orientedDisplaySpace
181     ui::Size orientedSize = outputState.displaySpace.getBounds();
182     if (orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270) {
183         std::swap(orientedSize.width, orientedSize.height);
184     }
185     outputState.orientedDisplaySpace.setBounds(orientedSize);
186     outputState.orientedDisplaySpace.setContent(orientedDisplaySpaceRect);
187 
188     // Compute displaySpace.content
189     const uint32_t transformOrientationFlags = ui::Transform::toRotationFlags(orientation);
190     ui::Transform rotation;
191     if (transformOrientationFlags != ui::Transform::ROT_INVALID) {
192         const auto displaySize = outputState.displaySpace.getBoundsAsRect();
193         rotation.set(transformOrientationFlags, displaySize.width(), displaySize.height());
194     }
195     outputState.displaySpace.setContent(rotation.transform(orientedDisplaySpaceRect));
196 
197     // Compute framebufferSpace
198     outputState.framebufferSpace.setOrientation(orientation);
199     LOG_FATAL_IF(outputState.framebufferSpace.getBoundsAsRect() == Rect::INVALID_RECT,
200                  "The framebuffer bounds are unknown.");
201     const auto scale = getScale(outputState.displaySpace.getBoundsAsRect(),
202                                 outputState.framebufferSpace.getBoundsAsRect());
203     outputState.framebufferSpace.setContent(
204             outputState.displaySpace.getContent().scale(scale.x, scale.y));
205 
206     // Compute layerStackSpace
207     outputState.layerStackSpace.setContent(layerStackSpaceRect);
208     outputState.layerStackSpace.setBounds(
209             ui::Size(layerStackSpaceRect.getWidth(), layerStackSpaceRect.getHeight()));
210 
211     outputState.transform = outputState.layerStackSpace.getTransform(outputState.displaySpace);
212     outputState.needsFiltering = outputState.transform.needsBilinearFiltering();
213     dirtyEntireOutput();
214 }
215 
setNextBrightness(float brightness)216 void Output::setNextBrightness(float brightness) {
217     editState().displayBrightness = brightness;
218 }
219 
setDisplaySize(const ui::Size & size)220 void Output::setDisplaySize(const ui::Size& size) {
221     mRenderSurface->setDisplaySize(size);
222 
223     auto& state = editState();
224 
225     // Update framebuffer space
226     const ui::Size newBounds(size);
227     state.framebufferSpace.setBounds(newBounds);
228 
229     // Update display space
230     state.displaySpace.setBounds(newBounds);
231     state.transform = state.layerStackSpace.getTransform(state.displaySpace);
232 
233     // Update oriented display space
234     const auto orientation = state.displaySpace.getOrientation();
235     ui::Size orientedSize = size;
236     if (orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270) {
237         std::swap(orientedSize.width, orientedSize.height);
238     }
239     const ui::Size newOrientedBounds(orientedSize);
240     state.orientedDisplaySpace.setBounds(newOrientedBounds);
241 
242     if (mPlanner) {
243         mPlanner->setDisplaySize(size);
244     }
245 
246     dirtyEntireOutput();
247 }
248 
getTransformHint() const249 ui::Transform::RotationFlags Output::getTransformHint() const {
250     return static_cast<ui::Transform::RotationFlags>(getState().transform.getOrientation());
251 }
252 
setLayerFilter(ui::LayerFilter filter)253 void Output::setLayerFilter(ui::LayerFilter filter) {
254     editState().layerFilter = filter;
255     dirtyEntireOutput();
256 }
257 
setColorTransform(const compositionengine::CompositionRefreshArgs & args)258 void Output::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
259     auto& colorTransformMatrix = editState().colorTransformMatrix;
260     if (!args.colorTransformMatrix || colorTransformMatrix == args.colorTransformMatrix) {
261         return;
262     }
263 
264     colorTransformMatrix = *args.colorTransformMatrix;
265 
266     dirtyEntireOutput();
267 }
268 
setColorProfile(const ColorProfile & colorProfile)269 void Output::setColorProfile(const ColorProfile& colorProfile) {
270     auto& outputState = editState();
271     if (outputState.colorMode == colorProfile.mode &&
272         outputState.dataspace == colorProfile.dataspace &&
273         outputState.renderIntent == colorProfile.renderIntent) {
274         return;
275     }
276 
277     outputState.colorMode = colorProfile.mode;
278     outputState.dataspace = colorProfile.dataspace;
279     outputState.renderIntent = colorProfile.renderIntent;
280 
281     mRenderSurface->setBufferDataspace(colorProfile.dataspace);
282 
283     ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)",
284           decodeColorMode(colorProfile.mode).c_str(), colorProfile.mode,
285           decodeRenderIntent(colorProfile.renderIntent).c_str(), colorProfile.renderIntent);
286 
287     dirtyEntireOutput();
288 }
289 
setDisplayBrightness(float sdrWhitePointNits,float displayBrightnessNits)290 void Output::setDisplayBrightness(float sdrWhitePointNits, float displayBrightnessNits) {
291     auto& outputState = editState();
292     if (outputState.sdrWhitePointNits == sdrWhitePointNits &&
293         outputState.displayBrightnessNits == displayBrightnessNits) {
294         // Nothing changed
295         return;
296     }
297     outputState.sdrWhitePointNits = sdrWhitePointNits;
298     outputState.displayBrightnessNits = displayBrightnessNits;
299     dirtyEntireOutput();
300 }
301 
dump(std::string & out) const302 void Output::dump(std::string& out) const {
303     base::StringAppendF(&out, "Output \"%s\"", mName.c_str());
304     out.append("\n   Composition Output State:\n");
305 
306     dumpBase(out);
307 }
308 
dumpBase(std::string & out) const309 void Output::dumpBase(std::string& out) const {
310     dumpState(out);
311     out += '\n';
312 
313     if (mDisplayColorProfile) {
314         mDisplayColorProfile->dump(out);
315     } else {
316         out.append("    No display color profile!\n");
317     }
318 
319     out += '\n';
320 
321     if (mRenderSurface) {
322         mRenderSurface->dump(out);
323     } else {
324         out.append("    No render surface!\n");
325     }
326 
327     base::StringAppendF(&out, "\n   %zu Layers\n", getOutputLayerCount());
328     for (const auto* outputLayer : getOutputLayersOrderedByZ()) {
329         if (!outputLayer) {
330             continue;
331         }
332         outputLayer->dump(out);
333     }
334 }
335 
dumpPlannerInfo(const Vector<String16> & args,std::string & out) const336 void Output::dumpPlannerInfo(const Vector<String16>& args, std::string& out) const {
337     if (!mPlanner) {
338         out.append("Planner is disabled\n");
339         return;
340     }
341     base::StringAppendF(&out, "Planner info for display [%s]\n", mName.c_str());
342     mPlanner->dump(args, out);
343 }
344 
getDisplayColorProfile() const345 compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const {
346     return mDisplayColorProfile.get();
347 }
348 
setDisplayColorProfile(std::unique_ptr<compositionengine::DisplayColorProfile> mode)349 void Output::setDisplayColorProfile(std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
350     mDisplayColorProfile = std::move(mode);
351 }
352 
getReleasedLayersForTest() const353 const Output::ReleasedLayers& Output::getReleasedLayersForTest() const {
354     return mReleasedLayers;
355 }
356 
setDisplayColorProfileForTest(std::unique_ptr<compositionengine::DisplayColorProfile> mode)357 void Output::setDisplayColorProfileForTest(
358         std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
359     mDisplayColorProfile = std::move(mode);
360 }
361 
getRenderSurface() const362 compositionengine::RenderSurface* Output::getRenderSurface() const {
363     return mRenderSurface.get();
364 }
365 
setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface)366 void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
367     mRenderSurface = std::move(surface);
368     const auto size = mRenderSurface->getSize();
369     editState().framebufferSpace.setBounds(size);
370     if (mPlanner) {
371         mPlanner->setDisplaySize(size);
372     }
373     dirtyEntireOutput();
374 }
375 
cacheClientCompositionRequests(uint32_t cacheSize)376 void Output::cacheClientCompositionRequests(uint32_t cacheSize) {
377     if (cacheSize == 0) {
378         mClientCompositionRequestCache.reset();
379     } else {
380         mClientCompositionRequestCache = std::make_unique<ClientCompositionRequestCache>(cacheSize);
381     }
382 };
383 
setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface)384 void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface) {
385     mRenderSurface = std::move(surface);
386 }
387 
getDirtyRegion() const388 Region Output::getDirtyRegion() const {
389     const auto& outputState = getState();
390     return outputState.dirtyRegion.intersect(outputState.layerStackSpace.getContent());
391 }
392 
includesLayer(ui::LayerFilter filter) const393 bool Output::includesLayer(ui::LayerFilter filter) const {
394     return getState().layerFilter.includes(filter);
395 }
396 
includesLayer(const sp<LayerFE> & layerFE) const397 bool Output::includesLayer(const sp<LayerFE>& layerFE) const {
398     const auto* layerFEState = layerFE->getCompositionState();
399     return layerFEState && includesLayer(layerFEState->outputFilter);
400 }
401 
createOutputLayer(const sp<LayerFE> & layerFE) const402 std::unique_ptr<compositionengine::OutputLayer> Output::createOutputLayer(
403         const sp<LayerFE>& layerFE) const {
404     return impl::createOutputLayer(*this, layerFE);
405 }
406 
getOutputLayerForLayer(const sp<LayerFE> & layerFE) const407 compositionengine::OutputLayer* Output::getOutputLayerForLayer(const sp<LayerFE>& layerFE) const {
408     auto index = findCurrentOutputLayerForLayer(layerFE);
409     return index ? getOutputLayerOrderedByZByIndex(*index) : nullptr;
410 }
411 
findCurrentOutputLayerForLayer(const sp<compositionengine::LayerFE> & layer) const412 std::optional<size_t> Output::findCurrentOutputLayerForLayer(
413         const sp<compositionengine::LayerFE>& layer) const {
414     for (size_t i = 0; i < getOutputLayerCount(); i++) {
415         auto outputLayer = getOutputLayerOrderedByZByIndex(i);
416         if (outputLayer && &outputLayer->getLayerFE() == layer.get()) {
417             return i;
418         }
419     }
420     return std::nullopt;
421 }
422 
setReleasedLayers(Output::ReleasedLayers && layers)423 void Output::setReleasedLayers(Output::ReleasedLayers&& layers) {
424     mReleasedLayers = std::move(layers);
425 }
426 
prepare(const compositionengine::CompositionRefreshArgs & refreshArgs,LayerFESet & geomSnapshots)427 void Output::prepare(const compositionengine::CompositionRefreshArgs& refreshArgs,
428                      LayerFESet& geomSnapshots) {
429     SFTRACE_CALL();
430     ALOGV(__FUNCTION__);
431 
432     rebuildLayerStacks(refreshArgs, geomSnapshots);
433     uncacheBuffers(refreshArgs.bufferIdsToUncache);
434 }
435 
present(const compositionengine::CompositionRefreshArgs & refreshArgs)436 ftl::Future<std::monostate> Output::present(
437         const compositionengine::CompositionRefreshArgs& refreshArgs) {
438     const auto stringifyExpectedPresentTime = [this, &refreshArgs]() -> std::string {
439         return getDisplayId()
440                 .and_then(PhysicalDisplayId::tryCast)
441                 .and_then([&refreshArgs](PhysicalDisplayId id) {
442                     return refreshArgs.frameTargets.get(id);
443                 })
444                 .transform([](const auto& frameTargetPtr) {
445                     return frameTargetPtr.get()->expectedPresentTime();
446                 })
447                 .transform([](TimePoint expectedPresentTime) {
448                     return base::StringPrintf(" vsyncIn %.2fms",
449                                               ticks<std::milli, float>(expectedPresentTime -
450                                                                        TimePoint::now()));
451                 })
452                 .or_else([] {
453                     // There is no vsync for this output.
454                     return std::make_optional(std::string());
455                 })
456                 .value();
457     };
458     SFTRACE_FORMAT("%s for %s%s", __func__, mNamePlusId.c_str(),
459                    stringifyExpectedPresentTime().c_str());
460     ALOGV(__FUNCTION__);
461 
462     updateColorProfile(refreshArgs);
463     updateCompositionState(refreshArgs);
464     planComposition();
465     writeCompositionState(refreshArgs);
466     setColorTransform(refreshArgs);
467     beginFrame();
468 
469     if (isPowerHintSessionEnabled()) {
470         // always reset the flag before the composition prediction
471         setHintSessionRequiresRenderEngine(false);
472     }
473     GpuCompositionResult result;
474     const bool predictCompositionStrategy = canPredictCompositionStrategy(refreshArgs);
475     if (predictCompositionStrategy) {
476         result = prepareFrameAsync();
477     } else {
478         prepareFrame();
479     }
480 
481     devOptRepaintFlash(refreshArgs);
482     finishFrame(std::move(result));
483     ftl::Future<std::monostate> future;
484     const bool flushEvenWhenDisabled = !refreshArgs.bufferIdsToUncache.empty();
485     if (mOffloadPresent) {
486         future = presentFrameAndReleaseLayersAsync(flushEvenWhenDisabled);
487 
488         // Only offload for this frame. The next frame will determine whether it
489         // needs to be offloaded. Leave the HwcAsyncWorker in place. For one thing,
490         // it is currently presenting. Further, it may be needed next frame, and
491         // we don't want to churn.
492         mOffloadPresent = false;
493     } else {
494         presentFrameAndReleaseLayers(flushEvenWhenDisabled);
495         future = ftl::yield<std::monostate>({});
496     }
497     renderCachedSets(refreshArgs);
498     return future;
499 }
500 
offloadPresentNextFrame()501 void Output::offloadPresentNextFrame() {
502     mOffloadPresent = true;
503     updateHwcAsyncWorker();
504 }
505 
rebuildLayerStacks(const compositionengine::CompositionRefreshArgs & refreshArgs,LayerFESet & layerFESet)506 void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& refreshArgs,
507                                 LayerFESet& layerFESet) {
508     auto& outputState = editState();
509 
510     // Do nothing if this output is not enabled or there is no need to perform this update
511     if (!outputState.isEnabled || CC_LIKELY(!refreshArgs.updatingOutputGeometryThisFrame)) {
512         return;
513     }
514     SFTRACE_CALL();
515     ALOGV(__FUNCTION__);
516 
517     // Process the layers to determine visibility and coverage
518     compositionengine::Output::CoverageState coverage{layerFESet};
519     coverage.aboveCoveredLayersExcludingOverlays = refreshArgs.hasTrustedPresentationListener
520             ? std::make_optional<Region>()
521             : std::nullopt;
522     collectVisibleLayers(refreshArgs, coverage);
523 
524     // Compute the resulting coverage for this output, and store it for later
525     const ui::Transform& tr = outputState.transform;
526     Region undefinedRegion{outputState.displaySpace.getBoundsAsRect()};
527     undefinedRegion.subtractSelf(tr.transform(coverage.aboveOpaqueLayers));
528 
529     outputState.undefinedRegion = undefinedRegion;
530     outputState.dirtyRegion.orSelf(coverage.dirtyRegion);
531 }
532 
collectVisibleLayers(const compositionengine::CompositionRefreshArgs & refreshArgs,compositionengine::Output::CoverageState & coverage)533 void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArgs& refreshArgs,
534                                   compositionengine::Output::CoverageState& coverage) {
535     // Evaluate the layers from front to back to determine what is visible. This
536     // also incrementally calculates the coverage information for each layer as
537     // well as the entire output.
538     for (auto layer : reversed(refreshArgs.layers)) {
539         // Incrementally process the coverage for each layer
540         ensureOutputLayerIfVisible(layer, coverage);
541 
542         // TODO(b/121291683): Stop early if the output is completely covered and
543         // no more layers could even be visible underneath the ones on top.
544     }
545 
546     setReleasedLayers(refreshArgs);
547 
548     finalizePendingOutputLayers();
549 }
550 
ensureOutputLayerIfVisible(sp<compositionengine::LayerFE> & layerFE,compositionengine::Output::CoverageState & coverage)551 void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE,
552                                         compositionengine::Output::CoverageState& coverage) {
553     // Ensure we have a snapshot of the basic geometry layer state. Limit the
554     // snapshots to once per frame for each candidate layer, as layers may
555     // appear on multiple outputs.
556     if (!coverage.latchedLayers.count(layerFE)) {
557         coverage.latchedLayers.insert(layerFE);
558     }
559 
560     // Only consider the layers on this output
561     if (!includesLayer(layerFE)) {
562         return;
563     }
564 
565     // Obtain a read-only pointer to the front-end layer state
566     const auto* layerFEState = layerFE->getCompositionState();
567     if (CC_UNLIKELY(!layerFEState)) {
568         return;
569     }
570 
571     // handle hidden surfaces by setting the visible region to empty
572     if (CC_UNLIKELY(!layerFEState->isVisible)) {
573         return;
574     }
575 
576     bool computeAboveCoveredExcludingOverlays = coverage.aboveCoveredLayersExcludingOverlays &&
577             !layerFEState->outputFilter.toInternalDisplay;
578 
579     /*
580      * opaqueRegion: area of a surface that is fully opaque.
581      */
582     Region opaqueRegion;
583 
584     /*
585      * visibleRegion: area of a surface that is visible on screen and not fully
586      * transparent. This is essentially the layer's footprint minus the opaque
587      * regions above it. Areas covered by a translucent surface are considered
588      * visible.
589      */
590     Region visibleRegion;
591 
592     /*
593      * coveredRegion: area of a surface that is covered by all visible regions
594      * above it (which includes the translucent areas).
595      */
596     Region coveredRegion;
597 
598     /*
599      * transparentRegion: area of a surface that is hinted to be completely
600      * transparent.
601      * This is used to tell when the layer has no visible non-transparent
602      * regions and can be removed from the layer list. It does not affect the
603      * visibleRegion of this layer or any layers beneath it. The hint may not
604      * be correct if apps don't respect the SurfaceView restrictions (which,
605      * sadly, some don't).
606      *
607      * In addition, it is used on DISPLAY_DECORATION layers to specify the
608      * blockingRegion, allowing the DPU to skip it to save power. Once we have
609      * hardware that supports a blockingRegion on frames with AFBC, it may be
610      * useful to use this for other layers, too, so long as we can prevent
611      * regressions on b/7179570.
612      */
613     Region transparentRegion;
614 
615     /*
616      * shadowRegion: Region cast by the layer's shadow.
617      */
618     Region shadowRegion;
619 
620     /**
621      * covered region above excluding internal display overlay layers
622      */
623     std::optional<Region> coveredRegionExcludingDisplayOverlays = std::nullopt;
624 
625     const ui::Transform& tr = layerFEState->geomLayerTransform;
626 
627     // Get the visible region
628     // TODO(b/121291683): Is it worth creating helper methods on LayerFEState
629     // for computations like this?
630     const Rect visibleRect(tr.transform(layerFEState->geomLayerBounds));
631     visibleRegion.set(visibleRect);
632 
633     if (layerFEState->shadowSettings.length > 0.0f) {
634         // if the layer casts a shadow, offset the layers visible region and
635         // calculate the shadow region.
636         const auto inset = static_cast<int32_t>(ceilf(layerFEState->shadowSettings.length) * -1.0f);
637         Rect visibleRectWithShadows(visibleRect);
638         visibleRectWithShadows.inset(inset, inset, inset, inset);
639         visibleRegion.set(visibleRectWithShadows);
640         shadowRegion = visibleRegion.subtract(visibleRect);
641     }
642 
643     if (visibleRegion.isEmpty()) {
644         return;
645     }
646 
647     // Remove the transparent area from the visible region
648     if (!layerFEState->isOpaque) {
649         if (tr.preserveRects()) {
650             // Clip the transparent region to geomLayerBounds first
651             // The transparent region may be influenced by applications, for
652             // instance, by overriding ViewGroup#gatherTransparentRegion with a
653             // custom view. Once the layer stack -> display mapping is known, we
654             // must guard against very wrong inputs to prevent underflow or
655             // overflow errors. We do this here by constraining the transparent
656             // region to be within the pre-transform layer bounds, since the
657             // layer bounds are expected to play nicely with the full
658             // transform.
659             const Region clippedTransparentRegionHint =
660                     layerFEState->transparentRegionHint.intersect(
661                             Rect(layerFEState->geomLayerBounds));
662 
663             if (clippedTransparentRegionHint.isEmpty()) {
664                 if (!layerFEState->transparentRegionHint.isEmpty()) {
665                     ALOGD("Layer: %s had an out of bounds transparent region",
666                           layerFE->getDebugName());
667                     layerFEState->transparentRegionHint.dump("transparentRegionHint");
668                 }
669                 transparentRegion.clear();
670             } else {
671                 transparentRegion = tr.transform(clippedTransparentRegionHint);
672             }
673         } else {
674             // transformation too complex, can't do the
675             // transparent region optimization.
676             transparentRegion.clear();
677         }
678     }
679 
680     // compute the opaque region
681     const auto layerOrientation = tr.getOrientation();
682     if (layerFEState->isOpaque && ((layerOrientation & ui::Transform::ROT_INVALID) == 0)) {
683         // If we one of the simple category of transforms (0/90/180/270 rotation
684         // + any flip), then the opaque region is the layer's footprint.
685         // Otherwise we don't try and compute the opaque region since there may
686         // be errors at the edges, and we treat the entire layer as
687         // translucent.
688         opaqueRegion.set(visibleRect);
689     }
690 
691     // Clip the covered region to the visible region
692     coveredRegion = coverage.aboveCoveredLayers.intersect(visibleRegion);
693 
694     // Update accumAboveCoveredLayers for next (lower) layer
695     coverage.aboveCoveredLayers.orSelf(visibleRegion);
696 
697     if (CC_UNLIKELY(computeAboveCoveredExcludingOverlays)) {
698         coveredRegionExcludingDisplayOverlays =
699                 coverage.aboveCoveredLayersExcludingOverlays->intersect(visibleRegion);
700         coverage.aboveCoveredLayersExcludingOverlays->orSelf(visibleRegion);
701     }
702 
703     // subtract the opaque region covered by the layers above us
704     visibleRegion.subtractSelf(coverage.aboveOpaqueLayers);
705 
706     if (visibleRegion.isEmpty()) {
707         return;
708     }
709 
710     // Get coverage information for the layer as previously displayed,
711     // also taking over ownership from mOutputLayersorderedByZ.
712     auto prevOutputLayerIndex = findCurrentOutputLayerForLayer(layerFE);
713     auto prevOutputLayer =
714             prevOutputLayerIndex ? getOutputLayerOrderedByZByIndex(*prevOutputLayerIndex) : nullptr;
715 
716     //  Get coverage information for the layer as previously displayed
717     // TODO(b/121291683): Define kEmptyRegion as a constant in Region.h
718     const Region kEmptyRegion;
719     const Region& oldVisibleRegion =
720             prevOutputLayer ? prevOutputLayer->getState().visibleRegion : kEmptyRegion;
721     const Region& oldCoveredRegion =
722             prevOutputLayer ? prevOutputLayer->getState().coveredRegion : kEmptyRegion;
723 
724     // compute this layer's dirty region
725     Region dirty;
726     if (layerFEState->contentDirty) {
727         // we need to invalidate the whole region
728         dirty = visibleRegion;
729         // as well, as the old visible region
730         dirty.orSelf(oldVisibleRegion);
731     } else {
732         /* compute the exposed region:
733          *   the exposed region consists of two components:
734          *   1) what's VISIBLE now and was COVERED before
735          *   2) what's EXPOSED now less what was EXPOSED before
736          *
737          * note that (1) is conservative, we start with the whole visible region
738          * but only keep what used to be covered by something -- which mean it
739          * may have been exposed.
740          *
741          * (2) handles areas that were not covered by anything but got exposed
742          * because of a resize.
743          *
744          */
745         const Region newExposed = visibleRegion - coveredRegion;
746         const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
747         dirty = (visibleRegion & oldCoveredRegion) | (newExposed - oldExposed);
748     }
749     dirty.subtractSelf(coverage.aboveOpaqueLayers);
750 
751     // accumulate to the screen dirty region
752     coverage.dirtyRegion.orSelf(dirty);
753 
754     // Update accumAboveOpaqueLayers for next (lower) layer
755     coverage.aboveOpaqueLayers.orSelf(opaqueRegion);
756 
757     // Compute the visible non-transparent region
758     Region visibleNonTransparentRegion = visibleRegion.subtract(transparentRegion);
759 
760     // Perform the final check to see if this layer is visible on this output
761     // TODO(b/121291683): Why does this not use visibleRegion? (see outputSpaceVisibleRegion below)
762     const auto& outputState = getState();
763     Region drawRegion(outputState.transform.transform(visibleNonTransparentRegion));
764     drawRegion.andSelf(outputState.displaySpace.getBoundsAsRect());
765     if (drawRegion.isEmpty()) {
766         return;
767     }
768 
769     Region visibleNonShadowRegion = visibleRegion.subtract(shadowRegion);
770 
771     // The layer is visible. Either reuse the existing outputLayer if we have
772     // one, or create a new one if we do not.
773     auto outputLayer = ensureOutputLayer(prevOutputLayerIndex, layerFE);
774 
775     // Store the layer coverage information into the layer state as some of it
776     // is useful later.
777     auto& outputLayerState = outputLayer->editState();
778     outputLayerState.visibleRegion = visibleRegion;
779     outputLayerState.visibleNonTransparentRegion = visibleNonTransparentRegion;
780     outputLayerState.coveredRegion = coveredRegion;
781     outputLayerState.outputSpaceVisibleRegion = outputState.transform.transform(
782             visibleNonShadowRegion.intersect(outputState.layerStackSpace.getContent()));
783     outputLayerState.shadowRegion = shadowRegion;
784     outputLayerState.outputSpaceBlockingRegionHint =
785             layerFEState->compositionType == Composition::DISPLAY_DECORATION
786             ? outputState.transform.transform(
787                       transparentRegion.intersect(outputState.layerStackSpace.getContent()))
788             : Region();
789     if (CC_UNLIKELY(computeAboveCoveredExcludingOverlays)) {
790         outputLayerState.coveredRegionExcludingDisplayOverlays =
791                 std::move(coveredRegionExcludingDisplayOverlays);
792     }
793 }
794 
uncacheBuffers(std::vector<uint64_t> const & bufferIdsToUncache)795 void Output::uncacheBuffers(std::vector<uint64_t> const& bufferIdsToUncache) {
796     if (bufferIdsToUncache.empty()) {
797         return;
798     }
799     for (auto outputLayer : getOutputLayersOrderedByZ()) {
800         outputLayer->uncacheBuffers(bufferIdsToUncache);
801     }
802 }
803 
commitPictureProfilesToCompositionState()804 void Output::commitPictureProfilesToCompositionState() {
805     if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
806         return;
807     }
808     if (!hasPictureProcessing()) {
809         return;
810     }
811     auto compare = [](const ::android::compositionengine::OutputLayer* lhs,
812                       const ::android::compositionengine::OutputLayer* rhs) {
813         return lhs->getPictureProfilePriority() > rhs->getPictureProfilePriority();
814     };
815     std::priority_queue<::android::compositionengine::OutputLayer*,
816                         std::vector<::android::compositionengine::OutputLayer*>, decltype(compare)>
817             layersWithProfiles;
818     for (auto outputLayer : getOutputLayersOrderedByZ()) {
819         if (outputLayer->getPictureProfileHandle()) {
820             layersWithProfiles.push(outputLayer);
821         }
822     }
823 
824     // TODO(b/337330263): Use the default display picture profile from SurfaceFlinger
825     editState().pictureProfileHandle = PictureProfileHandle::NONE;
826 
827     // When layer-specific picture processing is supported, apply as many high priority profiles as
828     // possible to the layers, and ignore the low priority layers.
829     if (getMaxLayerPictureProfiles() > 0) {
830         for (int i = 0; i < getMaxLayerPictureProfiles() && !layersWithProfiles.empty();
831              layersWithProfiles.pop(), ++i) {
832             layersWithProfiles.top()->commitPictureProfileToCompositionState();
833             layersWithProfiles.top()->getLayerFE().onPictureProfileCommitted();
834         }
835         // No layer-specific picture processing, so apply the highest priority picture profile to
836         // the entire display.
837     } else if (!layersWithProfiles.empty()) {
838         editState().pictureProfileHandle = layersWithProfiles.top()->getPictureProfileHandle();
839         layersWithProfiles.top()->getLayerFE().onPictureProfileCommitted();
840     }
841 }
842 
setReleasedLayers(const compositionengine::CompositionRefreshArgs &)843 void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) {
844     // The base class does nothing with this call.
845 }
846 
updateCompositionState(const compositionengine::CompositionRefreshArgs & refreshArgs)847 void Output::updateCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) {
848     SFTRACE_CALL();
849     ALOGV(__FUNCTION__);
850 
851     if (!getState().isEnabled) {
852         return;
853     }
854 
855     mLayerRequestingBackgroundBlur = findLayerRequestingBackgroundComposition();
856     bool forceClientComposition = mLayerRequestingBackgroundBlur != nullptr;
857 
858     auto* properties = getOverlaySupport();
859 
860     for (auto* layer : getOutputLayersOrderedByZ()) {
861         layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame,
862                                       refreshArgs.devOptForceClientComposition ||
863                                               forceClientComposition,
864                                       refreshArgs.internalDisplayRotationFlags,
865                                       properties ? properties->lutProperties : std::nullopt);
866 
867         if (mLayerRequestingBackgroundBlur == layer) {
868             forceClientComposition = false;
869         }
870     }
871     commitPictureProfilesToCompositionState();
872 }
873 
planComposition()874 void Output::planComposition() {
875     if (!mPlanner || !getState().isEnabled) {
876         return;
877     }
878 
879     SFTRACE_CALL();
880     ALOGV(__FUNCTION__);
881 
882     mPlanner->plan(getOutputLayersOrderedByZ());
883 }
884 
writeCompositionState(const compositionengine::CompositionRefreshArgs & refreshArgs)885 void Output::writeCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) {
886     SFTRACE_CALL();
887     ALOGV(__FUNCTION__);
888 
889     if (!getState().isEnabled) {
890         return;
891     }
892 
893     if (auto frameTargetPtrOpt = getDisplayId()
894                                          .and_then(PhysicalDisplayId::tryCast)
895                                          .and_then([&refreshArgs](PhysicalDisplayId id) {
896                                              return refreshArgs.frameTargets.get(id);
897                                          })) {
898         editState().earliestPresentTime = frameTargetPtrOpt->get()->earliestPresentTime();
899         editState().expectedPresentTime = frameTargetPtrOpt->get()->expectedPresentTime().ns();
900         const auto debugPresentDelay = frameTargetPtrOpt->get()->debugPresentDelay();
901         if (debugPresentDelay) {
902             SFTRACE_FORMAT_INSTANT("DEBUG delaying presentation by %.2fms",
903                                    debugPresentDelay->ns() / 1e6f);
904             editState().expectedPresentTime += debugPresentDelay->ns();
905         }
906     }
907     editState().frameInterval = refreshArgs.frameInterval;
908     editState().powerCallback = refreshArgs.powerCallback;
909 
910     applyPictureProfile();
911 
912     compositionengine::OutputLayer* peekThroughLayer = nullptr;
913     sp<GraphicBuffer> previousOverride = nullptr;
914     bool includeGeometry = refreshArgs.updatingGeometryThisFrame;
915     uint32_t z = 0;
916     bool overrideZ = false;
917     uint64_t outputLayerHash = 0;
918     for (auto* layer : getOutputLayersOrderedByZ()) {
919         if (layer == peekThroughLayer) {
920             // No longer needed, although it should not show up again, so
921             // resetting it is not truly needed either.
922             peekThroughLayer = nullptr;
923 
924             // peekThroughLayer was already drawn ahead of its z order.
925             continue;
926         }
927         bool skipLayer = false;
928         const auto& overrideInfo = layer->getState().overrideInfo;
929         if (overrideInfo.buffer != nullptr) {
930             if (previousOverride && overrideInfo.buffer->getBuffer() == previousOverride) {
931                 ALOGV("Skipping redundant buffer");
932                 skipLayer = true;
933             } else {
934                 // First layer with the override buffer.
935                 if (overrideInfo.peekThroughLayer) {
936                     peekThroughLayer = overrideInfo.peekThroughLayer;
937 
938                     // Draw peekThroughLayer first.
939                     overrideZ = true;
940                     includeGeometry = true;
941                     constexpr bool isPeekingThrough = true;
942                     peekThroughLayer->writeStateToHWC(includeGeometry, false, z++, overrideZ,
943                                                       isPeekingThrough);
944                     outputLayerHash ^= android::hashCombine(
945                             reinterpret_cast<uint64_t>(&peekThroughLayer->getLayerFE()),
946                             z, includeGeometry, overrideZ, isPeekingThrough,
947                             peekThroughLayer->requiresClientComposition());
948                 }
949 
950                 previousOverride = overrideInfo.buffer->getBuffer();
951             }
952         }
953 
954         constexpr bool isPeekingThrough = false;
955         layer->writeStateToHWC(includeGeometry, skipLayer, z++, overrideZ, isPeekingThrough);
956         if (!skipLayer) {
957             outputLayerHash ^= android::hashCombine(
958                     reinterpret_cast<uint64_t>(&layer->getLayerFE()),
959                     z, includeGeometry, overrideZ, isPeekingThrough,
960                     layer->requiresClientComposition());
961         }
962     }
963     editState().outputLayerHash = outputLayerHash;
964 }
965 
findLayerRequestingBackgroundComposition() const966 compositionengine::OutputLayer* Output::findLayerRequestingBackgroundComposition() const {
967     compositionengine::OutputLayer* layerRequestingBgComposition = nullptr;
968     for (auto* layer : getOutputLayersOrderedByZ()) {
969         const auto* compState = layer->getLayerFE().getCompositionState();
970 
971         // If any layer has a sideband stream, we will disable blurs. In that case, we don't
972         // want to force client composition because of the blur.
973         if (compState->sidebandStream != nullptr) {
974             return nullptr;
975         }
976 
977         // If RenderEngine cannot render protected content, we cannot blur.
978         if (compState->hasProtectedContent &&
979             !getCompositionEngine().getRenderEngine().supportsProtectedContent()) {
980             return nullptr;
981         }
982         if (compState->isOpaque) {
983             continue;
984         }
985         if (compState->backgroundBlurRadius > 0 || compState->blurRegions.size() > 0) {
986             layerRequestingBgComposition = layer;
987         }
988     }
989     return layerRequestingBgComposition;
990 }
991 
updateColorProfile(const compositionengine::CompositionRefreshArgs & refreshArgs)992 void Output::updateColorProfile(const compositionengine::CompositionRefreshArgs& refreshArgs) {
993     setColorProfile(pickColorProfile(refreshArgs));
994 }
995 
996 // Returns a data space that fits all visible layers.  The returned data space
997 // can only be one of
998 //  - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced)
999 //  - Dataspace::DISPLAY_P3
1000 //  - Dataspace::DISPLAY_BT2020
1001 // The returned HDR data space is one of
1002 //  - Dataspace::UNKNOWN
1003 //  - Dataspace::BT2020_HLG
1004 //  - Dataspace::BT2020_PQ
getBestDataspace(ui::Dataspace * outHdrDataSpace,bool * outIsHdrClientComposition) const1005 ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace,
1006                                        bool* outIsHdrClientComposition) const {
1007     ui::Dataspace bestDataSpace = ui::Dataspace::V0_SRGB;
1008     *outHdrDataSpace = ui::Dataspace::UNKNOWN;
1009 
1010     // An Output's layers may be stale when it is disabled. As a consequence, the layers returned by
1011     // getOutputLayersOrderedByZ may not be in a valid state and it is not safe to access their
1012     // properties. Return a default dataspace value in this case.
1013     if (!getState().isEnabled) {
1014         return ui::Dataspace::V0_SRGB;
1015     }
1016 
1017     for (const auto* layer : getOutputLayersOrderedByZ()) {
1018         switch (layer->getLayerFE().getCompositionState()->dataspace) {
1019             case ui::Dataspace::V0_SCRGB:
1020             case ui::Dataspace::V0_SCRGB_LINEAR:
1021             case ui::Dataspace::BT2020:
1022             case ui::Dataspace::BT2020_ITU:
1023             case ui::Dataspace::BT2020_LINEAR:
1024             case ui::Dataspace::DISPLAY_BT2020:
1025                 bestDataSpace = ui::Dataspace::DISPLAY_BT2020;
1026                 break;
1027             case ui::Dataspace::DISPLAY_P3:
1028                 bestDataSpace = ui::Dataspace::DISPLAY_P3;
1029                 break;
1030             case ui::Dataspace::BT2020_PQ:
1031             case ui::Dataspace::BT2020_ITU_PQ:
1032                 bestDataSpace = ui::Dataspace::DISPLAY_P3;
1033                 *outHdrDataSpace = ui::Dataspace::BT2020_PQ;
1034                 *outIsHdrClientComposition =
1035                         layer->getLayerFE().getCompositionState()->forceClientComposition;
1036                 break;
1037             case ui::Dataspace::BT2020_HLG:
1038             case ui::Dataspace::BT2020_ITU_HLG:
1039                 bestDataSpace = ui::Dataspace::DISPLAY_P3;
1040                 // When there's mixed PQ content and HLG content, we set the HDR
1041                 // data space to be BT2020_HLG and convert PQ to HLG.
1042                 if (*outHdrDataSpace == ui::Dataspace::UNKNOWN) {
1043                     *outHdrDataSpace = ui::Dataspace::BT2020_HLG;
1044                 }
1045                 break;
1046             default:
1047                 break;
1048         }
1049     }
1050 
1051     return bestDataSpace;
1052 }
1053 
pickColorProfile(const compositionengine::CompositionRefreshArgs & refreshArgs) const1054 compositionengine::Output::ColorProfile Output::pickColorProfile(
1055         const compositionengine::CompositionRefreshArgs& refreshArgs) const {
1056     if (refreshArgs.outputColorSetting == OutputColorSetting::kUnmanaged) {
1057         return ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
1058                             ui::RenderIntent::COLORIMETRIC};
1059     }
1060 
1061     ui::Dataspace hdrDataSpace;
1062     bool isHdrClientComposition = false;
1063     ui::Dataspace bestDataSpace = getBestDataspace(&hdrDataSpace, &isHdrClientComposition);
1064 
1065     switch (refreshArgs.forceOutputColorMode) {
1066         case ui::ColorMode::SRGB:
1067             bestDataSpace = ui::Dataspace::V0_SRGB;
1068             break;
1069         case ui::ColorMode::DISPLAY_P3:
1070             bestDataSpace = ui::Dataspace::DISPLAY_P3;
1071             break;
1072         default:
1073             break;
1074     }
1075 
1076     // respect hdrDataSpace only when there is no legacy HDR support
1077     const bool isHdr = hdrDataSpace != ui::Dataspace::UNKNOWN &&
1078             !mDisplayColorProfile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition;
1079     if (isHdr) {
1080         bestDataSpace = hdrDataSpace;
1081     }
1082 
1083     ui::RenderIntent intent;
1084     switch (refreshArgs.outputColorSetting) {
1085         case OutputColorSetting::kManaged:
1086         case OutputColorSetting::kUnmanaged:
1087             intent = isHdr ? ui::RenderIntent::TONE_MAP_COLORIMETRIC
1088                            : ui::RenderIntent::COLORIMETRIC;
1089             break;
1090         case OutputColorSetting::kEnhanced:
1091             intent = isHdr ? ui::RenderIntent::TONE_MAP_ENHANCE : ui::RenderIntent::ENHANCE;
1092             break;
1093         default: // vendor display color setting
1094             intent = static_cast<ui::RenderIntent>(refreshArgs.outputColorSetting);
1095             break;
1096     }
1097 
1098     ui::ColorMode outMode;
1099     ui::Dataspace outDataSpace;
1100     ui::RenderIntent outRenderIntent;
1101     mDisplayColorProfile->getBestColorMode(bestDataSpace, intent, &outDataSpace, &outMode,
1102                                            &outRenderIntent);
1103 
1104     return ColorProfile{outMode, outDataSpace, outRenderIntent};
1105 }
1106 
beginFrame()1107 void Output::beginFrame() {
1108     auto& outputState = editState();
1109     const bool dirty = !getDirtyRegion().isEmpty();
1110     const bool empty = getOutputLayerCount() == 0;
1111     const bool wasEmpty = !outputState.lastCompositionHadVisibleLayers;
1112 
1113     // If nothing has changed (!dirty), don't recompose.
1114     // If something changed, but we don't currently have any visible layers,
1115     //   and didn't when we last did a composition, then skip it this time.
1116     // The second rule does two things:
1117     // - When all layers are removed from a display, we'll emit one black
1118     //   frame, then nothing more until we get new layers.
1119     // - When a display is created with a private layer stack, we won't
1120     //   emit any black frames until a layer is added to the layer stack.
1121     mMustRecompose = dirty && !(empty && wasEmpty);
1122 
1123     const char flagPrefix[] = {'-', '+'};
1124     static_cast<void>(flagPrefix);
1125     ALOGV("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __func__,
1126           mMustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty],
1127           flagPrefix[empty], flagPrefix[wasEmpty]);
1128 
1129     mRenderSurface->beginFrame(mMustRecompose);
1130 
1131     if (mMustRecompose) {
1132         outputState.lastCompositionHadVisibleLayers = !empty;
1133     }
1134 }
1135 
prepareFrame()1136 void Output::prepareFrame() {
1137     SFTRACE_CALL();
1138     ALOGV(__FUNCTION__);
1139 
1140     auto& outputState = editState();
1141     if (!outputState.isEnabled) {
1142         return;
1143     }
1144 
1145     std::optional<android::HWComposer::DeviceRequestedChanges> changes;
1146     bool success = chooseCompositionStrategy(&changes);
1147     resetCompositionStrategy();
1148     outputState.strategyPrediction = CompositionStrategyPredictionState::DISABLED;
1149     outputState.previousDeviceRequestedChanges = changes;
1150     outputState.previousDeviceRequestedSuccess = success;
1151     if (success) {
1152         applyCompositionStrategy(changes);
1153     }
1154     finishPrepareFrame();
1155 }
1156 
presentFrameAndReleaseLayersAsync(bool flushEvenWhenDisabled)1157 ftl::Future<std::monostate> Output::presentFrameAndReleaseLayersAsync(bool flushEvenWhenDisabled) {
1158     return ftl::Future<bool>(mHwComposerAsyncWorker->send([this, flushEvenWhenDisabled]() {
1159                presentFrameAndReleaseLayers(flushEvenWhenDisabled);
1160                return true;
1161            }))
1162             .then([](bool) { return std::monostate{}; });
1163 }
1164 
chooseCompositionStrategyAsync(std::optional<android::HWComposer::DeviceRequestedChanges> * changes)1165 std::future<bool> Output::chooseCompositionStrategyAsync(
1166         std::optional<android::HWComposer::DeviceRequestedChanges>* changes) {
1167     return mHwComposerAsyncWorker->send(
1168             [&, changes]() { return chooseCompositionStrategy(changes); });
1169 }
1170 
prepareFrameAsync()1171 GpuCompositionResult Output::prepareFrameAsync() {
1172     SFTRACE_CALL();
1173     ALOGV(__FUNCTION__);
1174     auto& state = editState();
1175     const auto& previousChanges = state.previousDeviceRequestedChanges;
1176     std::optional<android::HWComposer::DeviceRequestedChanges> changes;
1177     resetCompositionStrategy();
1178     auto hwcResult = chooseCompositionStrategyAsync(&changes);
1179     if (state.previousDeviceRequestedSuccess) {
1180         applyCompositionStrategy(previousChanges);
1181     }
1182     finishPrepareFrame();
1183 
1184     base::unique_fd bufferFence;
1185     std::shared_ptr<renderengine::ExternalTexture> buffer;
1186     updateProtectedContentState();
1187     const bool dequeueSucceeded = dequeueRenderBuffer(&bufferFence, &buffer);
1188     GpuCompositionResult compositionResult;
1189     if (dequeueSucceeded) {
1190         std::optional<base::unique_fd> optFd =
1191                 composeSurfaces(Region::INVALID_REGION, buffer, bufferFence);
1192         if (optFd) {
1193             compositionResult.fence = std::move(*optFd);
1194         }
1195     }
1196 
1197     auto chooseCompositionSuccess = hwcResult.get();
1198     const bool predictionSucceeded = dequeueSucceeded && changes == previousChanges;
1199     state.strategyPrediction = predictionSucceeded ? CompositionStrategyPredictionState::SUCCESS
1200                                                    : CompositionStrategyPredictionState::FAIL;
1201     if (!predictionSucceeded) {
1202         SFTRACE_NAME("CompositionStrategyPredictionMiss");
1203         resetCompositionStrategy();
1204         if (chooseCompositionSuccess) {
1205             applyCompositionStrategy(changes);
1206         }
1207         finishPrepareFrame();
1208         // Track the dequeued buffer to reuse so we don't need to dequeue another one.
1209         compositionResult.buffer = buffer;
1210     } else {
1211         SFTRACE_NAME("CompositionStrategyPredictionHit");
1212     }
1213     state.previousDeviceRequestedChanges = std::move(changes);
1214     state.previousDeviceRequestedSuccess = chooseCompositionSuccess;
1215     return compositionResult;
1216 }
1217 
devOptRepaintFlash(const compositionengine::CompositionRefreshArgs & refreshArgs)1218 void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
1219     if (CC_LIKELY(!refreshArgs.devOptFlashDirtyRegionsDelay)) {
1220         return;
1221     }
1222 
1223     if (getState().isEnabled) {
1224         if (const auto dirtyRegion = getDirtyRegion(); !dirtyRegion.isEmpty()) {
1225             base::unique_fd bufferFence;
1226             std::shared_ptr<renderengine::ExternalTexture> buffer;
1227             updateProtectedContentState();
1228             dequeueRenderBuffer(&bufferFence, &buffer);
1229             static_cast<void>(composeSurfaces(dirtyRegion, buffer, bufferFence));
1230             mRenderSurface->queueBuffer(base::unique_fd(), getHdrSdrRatio(buffer));
1231         }
1232     }
1233 
1234     constexpr bool kFlushEvenWhenDisabled = false;
1235     presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
1236 
1237     std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay);
1238 
1239     prepareFrame();
1240 }
1241 
finishFrame(GpuCompositionResult && result)1242 void Output::finishFrame(GpuCompositionResult&& result) {
1243     SFTRACE_CALL();
1244     ALOGV(__FUNCTION__);
1245     const auto& outputState = getState();
1246     if (!outputState.isEnabled) {
1247         return;
1248     }
1249 
1250     std::optional<base::unique_fd> optReadyFence;
1251     std::shared_ptr<renderengine::ExternalTexture> buffer;
1252     base::unique_fd bufferFence;
1253     if (outputState.strategyPrediction == CompositionStrategyPredictionState::SUCCESS) {
1254         optReadyFence = std::move(result.fence);
1255     } else {
1256         if (result.bufferAvailable()) {
1257             buffer = std::move(result.buffer);
1258             bufferFence = std::move(result.fence);
1259         } else {
1260             updateProtectedContentState();
1261             if (!dequeueRenderBuffer(&bufferFence, &buffer)) {
1262                 return;
1263             }
1264         }
1265         // Repaint the framebuffer (if needed), getting the optional fence for when
1266         // the composition completes.
1267         optReadyFence = composeSurfaces(Region::INVALID_REGION, buffer, bufferFence);
1268     }
1269     if (!optReadyFence) {
1270         return;
1271     }
1272     if (isPowerHintSessionEnabled() && !isPowerHintSessionGpuReportingEnabled()) {
1273         // get fence end time to know when gpu is complete in display
1274         setHintSessionGpuFence(
1275                 std::make_unique<FenceTime>(sp<Fence>::make(dup(optReadyFence->get()))));
1276     }
1277     // swap buffers (presentation)
1278     mRenderSurface->queueBuffer(std::move(*optReadyFence), getHdrSdrRatio(buffer));
1279 }
1280 
updateProtectedContentState()1281 void Output::updateProtectedContentState() {
1282     const auto& outputState = getState();
1283     auto& renderEngine = getCompositionEngine().getRenderEngine();
1284     const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
1285 
1286     bool isProtected;
1287     if (FlagManager::getInstance().display_protected()) {
1288         isProtected = outputState.isProtected;
1289     } else {
1290         isProtected = outputState.isSecure;
1291     }
1292 
1293     // We need to set the render surface as protected (DRM) if all the following conditions are met:
1294     // 1. The display is protected (in legacy, check if the display is secure)
1295     // 2. Protected content is supported
1296     // 3. At least one layer has protected content.
1297     if (isProtected && supportsProtectedContent) {
1298         auto layers = getOutputLayersOrderedByZ();
1299         bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
1300             return layer->getLayerFE().getCompositionState()->hasProtectedContent &&
1301                     (!FlagManager::getInstance().protected_if_client() ||
1302                      layer->requiresClientComposition());
1303         });
1304         if (needsProtected != mRenderSurface->isProtected()) {
1305             mRenderSurface->setProtected(needsProtected);
1306         }
1307     }
1308 }
1309 
dequeueRenderBuffer(base::unique_fd * bufferFence,std::shared_ptr<renderengine::ExternalTexture> * tex)1310 bool Output::dequeueRenderBuffer(base::unique_fd* bufferFence,
1311                                  std::shared_ptr<renderengine::ExternalTexture>* tex) {
1312     const auto& outputState = getState();
1313 
1314     // If we aren't doing client composition on this output, but do have a
1315     // flipClientTarget request for this frame on this output, we still need to
1316     // dequeue a buffer.
1317     if (outputState.usesClientComposition || outputState.flipClientTarget) {
1318         *tex = mRenderSurface->dequeueBuffer(bufferFence);
1319         if (*tex == nullptr) {
1320             ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
1321                   "client composition for this frame",
1322                   mName.c_str());
1323             return false;
1324         }
1325     }
1326     return true;
1327 }
1328 
composeSurfaces(const Region & debugRegion,std::shared_ptr<renderengine::ExternalTexture> tex,base::unique_fd & fd)1329 std::optional<base::unique_fd> Output::composeSurfaces(
1330         const Region& debugRegion, std::shared_ptr<renderengine::ExternalTexture> tex,
1331         base::unique_fd& fd) {
1332     SFTRACE_CALL();
1333     ALOGV(__FUNCTION__);
1334 
1335     const auto& outputState = getState();
1336     const TracedOrdinal<bool> hasClientComposition = {
1337         base::StringPrintf("hasClientComposition %s", mNamePlusId.c_str()),
1338         outputState.usesClientComposition};
1339     if (!hasClientComposition) {
1340         setExpensiveRenderingExpected(false);
1341         return base::unique_fd();
1342     }
1343 
1344     if (tex == nullptr) {
1345         ALOGW("Buffer not valid for display [%s], bailing out of "
1346               "client composition for this frame",
1347               mName.c_str());
1348         return {};
1349     }
1350 
1351     ALOGV("hasClientComposition");
1352 
1353     renderengine::DisplaySettings clientCompositionDisplay =
1354             generateClientCompositionDisplaySettings(tex);
1355 
1356     // Generate the client composition requests for the layers on this output.
1357     auto& renderEngine = getCompositionEngine().getRenderEngine();
1358     const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
1359     std::vector<LayerFE*> clientCompositionLayersFE;
1360     std::vector<LayerFE::LayerSettings> clientCompositionLayers =
1361             generateClientCompositionRequests(supportsProtectedContent,
1362                                               clientCompositionDisplay.outputDataspace,
1363                                               clientCompositionLayersFE);
1364     appendRegionFlashRequests(debugRegion, clientCompositionLayers);
1365 
1366     OutputCompositionState& outputCompositionState = editState();
1367     // Check if the client composition requests were rendered into the provided graphic buffer. If
1368     // so, we can reuse the buffer and avoid client composition.
1369     if (mClientCompositionRequestCache) {
1370         if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(),
1371                                                    clientCompositionDisplay,
1372                                                    clientCompositionLayers)) {
1373             SFTRACE_NAME("ClientCompositionCacheHit");
1374             outputCompositionState.reusedClientComposition = true;
1375             setExpensiveRenderingExpected(false);
1376             // b/239944175 pass the fence associated with the buffer.
1377             return base::unique_fd(std::move(fd));
1378         }
1379         SFTRACE_NAME("ClientCompositionCacheMiss");
1380         mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay,
1381                                             clientCompositionLayers);
1382     }
1383 
1384     // We boost GPU frequency here because there will be color spaces conversion
1385     // or complex GPU shaders and it's expensive. We boost the GPU frequency so that
1386     // GPU composition can finish in time. We must reset GPU frequency afterwards,
1387     // because high frequency consumes extra battery.
1388     const bool expensiveRenderingExpected =
1389             std::any_of(clientCompositionLayers.begin(), clientCompositionLayers.end(),
1390                         [outputDataspace =
1391                                  clientCompositionDisplay.outputDataspace](const auto& layer) {
1392                             return layer.sourceDataspace != outputDataspace;
1393                         });
1394     if (expensiveRenderingExpected) {
1395         setExpensiveRenderingExpected(true);
1396     }
1397 
1398     std::vector<renderengine::LayerSettings> clientRenderEngineLayers;
1399     clientRenderEngineLayers.reserve(clientCompositionLayers.size());
1400     std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(),
1401                    std::back_inserter(clientRenderEngineLayers),
1402                    [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings {
1403                        return settings;
1404                    });
1405 
1406     const nsecs_t renderEngineStart = systemTime();
1407     auto fenceResult = renderEngine
1408                                .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, tex,
1409                                            std::move(fd))
1410                                .get();
1411 
1412     if (mClientCompositionRequestCache && fenceStatus(fenceResult) != NO_ERROR) {
1413         // If rendering was not successful, remove the request from the cache.
1414         mClientCompositionRequestCache->remove(tex->getBuffer()->getId());
1415     }
1416     const auto fence = std::move(fenceResult).value_or(Fence::NO_FENCE);
1417     if (isPowerHintSessionEnabled()) {
1418         if (fence != Fence::NO_FENCE && fence->isValid() &&
1419             !outputCompositionState.reusedClientComposition) {
1420             setHintSessionRequiresRenderEngine(true);
1421             if (isPowerHintSessionGpuReportingEnabled()) {
1422                 // the order of the two calls here matters as we should check if the previously
1423                 // tracked fence has signaled first and archive the previous start time
1424                 setHintSessionGpuStart(TimePoint::now());
1425                 setHintSessionGpuFence(
1426                         std::make_unique<FenceTime>(sp<Fence>::make(dup(fence->get()))));
1427             }
1428         }
1429     }
1430 
1431     if (auto timeStats = getCompositionEngine().getTimeStats()) {
1432         if (fence->isValid()) {
1433             timeStats->recordRenderEngineDuration(renderEngineStart,
1434                                                   std::make_shared<FenceTime>(fence));
1435         } else {
1436             timeStats->recordRenderEngineDuration(renderEngineStart, systemTime());
1437         }
1438     }
1439 
1440     for (auto* clientComposedLayer : clientCompositionLayersFE) {
1441         clientComposedLayer->setWasClientComposed(fence);
1442     }
1443 
1444     return base::unique_fd(fence->dup());
1445 }
1446 
generateClientCompositionDisplaySettings(const std::shared_ptr<renderengine::ExternalTexture> & buffer) const1447 renderengine::DisplaySettings Output::generateClientCompositionDisplaySettings(
1448         const std::shared_ptr<renderengine::ExternalTexture>& buffer) const {
1449     const auto& outputState = getState();
1450 
1451     renderengine::DisplaySettings clientCompositionDisplay;
1452     clientCompositionDisplay.namePlusId = mNamePlusId;
1453     clientCompositionDisplay.physicalDisplay = outputState.framebufferSpace.getContent();
1454     clientCompositionDisplay.clip = outputState.layerStackSpace.getContent();
1455     clientCompositionDisplay.orientation =
1456             ui::Transform::toRotationFlags(outputState.displaySpace.getOrientation());
1457     clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
1458             ? outputState.dataspace
1459             : ui::Dataspace::UNKNOWN;
1460 
1461     // If we have a valid current display brightness use that, otherwise fall back to the
1462     // display's max desired
1463     clientCompositionDisplay.currentLuminanceNits = outputState.displayBrightnessNits > 0.f
1464             ? outputState.displayBrightnessNits
1465             : mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
1466     clientCompositionDisplay.maxLuminance =
1467             mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
1468 
1469     float hdrSdrRatioMultiplier = 1.0f / getHdrSdrRatio(buffer);
1470     clientCompositionDisplay.targetLuminanceNits = outputState.clientTargetBrightness *
1471             outputState.displayBrightnessNits * hdrSdrRatioMultiplier;
1472     clientCompositionDisplay.dimmingStage = outputState.clientTargetDimmingStage;
1473     clientCompositionDisplay.renderIntent =
1474             static_cast<aidl::android::hardware::graphics::composer3::RenderIntent>(
1475                     outputState.renderIntent);
1476 
1477     // Compute the global color transform matrix.
1478     clientCompositionDisplay.colorTransform = outputState.colorTransformMatrix;
1479     clientCompositionDisplay.deviceHandlesColorTransform =
1480             outputState.usesDeviceComposition || getSkipColorTransform();
1481     return clientCompositionDisplay;
1482 }
1483 
generateClientCompositionRequests(bool supportsProtectedContent,ui::Dataspace outputDataspace,std::vector<LayerFE * > & outLayerFEs)1484 std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests(
1485       bool supportsProtectedContent, ui::Dataspace outputDataspace, std::vector<LayerFE*>& outLayerFEs) {
1486     std::vector<LayerFE::LayerSettings> clientCompositionLayers;
1487     ALOGV("Rendering client layers");
1488 
1489     const auto& outputState = getState();
1490     const Region viewportRegion(outputState.layerStackSpace.getContent());
1491     bool firstLayer = true;
1492 
1493     bool disableBlurs = false;
1494     uint64_t previousOverrideBufferId = 0;
1495 
1496     for (auto* layer : getOutputLayersOrderedByZ()) {
1497         const auto& layerState = layer->getState();
1498         const auto* layerFEState = layer->getLayerFE().getCompositionState();
1499         auto& layerFE = layer->getLayerFE();
1500         layerFE.setWasClientComposed(nullptr);
1501 
1502         const Region clip(viewportRegion.intersect(layerState.visibleRegion));
1503         ALOGV("Layer: %s", layerFE.getDebugName());
1504         if (clip.isEmpty()) {
1505             ALOGV("  Skipping for empty clip");
1506             firstLayer = false;
1507             continue;
1508         }
1509 
1510         disableBlurs |= layerFEState->sidebandStream != nullptr;
1511 
1512         const bool clientComposition = layer->requiresClientComposition();
1513 
1514         // We clear the client target for non-client composed layers if
1515         // requested by the HWC. We skip this if the layer is not an opaque
1516         // rectangle, as by definition the layer must blend with whatever is
1517         // underneath. We also skip the first layer as the buffer target is
1518         // guaranteed to start out cleared.
1519         const bool clearClientComposition =
1520                 layerState.clearClientTarget && layerFEState->isOpaque && !firstLayer;
1521 
1522         ALOGV("  Composition type: client %d clear %d", clientComposition, clearClientComposition);
1523 
1524         // If the layer casts a shadow but the content casting the shadow is occluded, skip
1525         // composing the non-shadow content and only draw the shadows.
1526         const bool realContentIsVisible = clientComposition &&
1527                 !layerState.visibleRegion.subtract(layerState.shadowRegion).isEmpty();
1528 
1529         if (clientComposition || clearClientComposition) {
1530             if (auto overrideSettings = layer->getOverrideCompositionSettings()) {
1531                 if (overrideSettings->bufferId != previousOverrideBufferId) {
1532                     previousOverrideBufferId = overrideSettings->bufferId;
1533                     clientCompositionLayers.push_back(std::move(*overrideSettings));
1534                     ALOGV("Replacing [%s] with override in RE", layer->getLayerFE().getDebugName());
1535                 } else {
1536                     ALOGV("Skipping redundant override buffer for [%s] in RE",
1537                           layer->getLayerFE().getDebugName());
1538                 }
1539             } else {
1540                 LayerFE::ClientCompositionTargetSettings::BlurSetting blurSetting = disableBlurs
1541                         ? LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled
1542                         : (layer->getState().overrideInfo.disableBackgroundBlur
1543                                    ? LayerFE::ClientCompositionTargetSettings::BlurSetting::
1544                                              BlurRegionsOnly
1545                                    : LayerFE::ClientCompositionTargetSettings::BlurSetting::
1546                                              Enabled);
1547                 bool isProtected = supportsProtectedContent;
1548                 if (FlagManager::getInstance().display_protected()) {
1549                     isProtected = outputState.isProtected && supportsProtectedContent;
1550                 }
1551                 compositionengine::LayerFE::ClientCompositionTargetSettings
1552                         targetSettings{.clip = clip,
1553                                        .needsFiltering = layer->needsFiltering() ||
1554                                                outputState.needsFiltering,
1555                                        .isSecure = outputState.isSecure,
1556                                        .isProtected = isProtected,
1557                                        .viewport = outputState.layerStackSpace.getContent(),
1558                                        .dataspace = outputDataspace,
1559                                        .realContentIsVisible = realContentIsVisible,
1560                                        .clearContent = !clientComposition,
1561                                        .blurSetting = blurSetting,
1562                                        .whitePointNits = layerState.whitePointNits,
1563                                        .treat170mAsSrgb = outputState.treat170mAsSrgb};
1564                 if (auto clientCompositionSettings =
1565                             layerFE.prepareClientComposition(targetSettings)) {
1566                     clientCompositionLayers.push_back(std::move(*clientCompositionSettings));
1567                     if (realContentIsVisible) {
1568                         layer->editState().clientCompositionTimestamp = systemTime();
1569                     }
1570                 }
1571             }
1572 
1573             if (clientComposition) {
1574                 outLayerFEs.push_back(&layerFE);
1575             }
1576         }
1577 
1578         firstLayer = false;
1579     }
1580 
1581     return clientCompositionLayers;
1582 }
1583 
appendRegionFlashRequests(const Region & flashRegion,std::vector<LayerFE::LayerSettings> & clientCompositionLayers)1584 void Output::appendRegionFlashRequests(
1585         const Region& flashRegion, std::vector<LayerFE::LayerSettings>& clientCompositionLayers) {
1586     if (flashRegion.isEmpty()) {
1587         return;
1588     }
1589 
1590     LayerFE::LayerSettings layerSettings;
1591     layerSettings.source.buffer.buffer = nullptr;
1592     layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
1593     layerSettings.alpha = half(1.0);
1594 
1595     for (const auto& rect : flashRegion) {
1596         layerSettings.geometry.boundaries = rect.toFloatRect();
1597         clientCompositionLayers.push_back(layerSettings);
1598     }
1599 }
1600 
setExpensiveRenderingExpected(bool)1601 void Output::setExpensiveRenderingExpected(bool) {
1602     // The base class does nothing with this call.
1603 }
1604 
setHintSessionGpuStart(TimePoint)1605 void Output::setHintSessionGpuStart(TimePoint) {
1606     // The base class does nothing with this call.
1607 }
1608 
setHintSessionGpuFence(std::unique_ptr<FenceTime> &&)1609 void Output::setHintSessionGpuFence(std::unique_ptr<FenceTime>&&) {
1610     // The base class does nothing with this call.
1611 }
1612 
setHintSessionRequiresRenderEngine(bool)1613 void Output::setHintSessionRequiresRenderEngine(bool) {
1614     // The base class does nothing with this call.
1615 }
1616 
isPowerHintSessionEnabled()1617 bool Output::isPowerHintSessionEnabled() {
1618     return false;
1619 }
1620 
isPowerHintSessionGpuReportingEnabled()1621 bool Output::isPowerHintSessionGpuReportingEnabled() {
1622     return false;
1623 }
1624 
presentFrameAndReleaseLayers(bool flushEvenWhenDisabled)1625 void Output::presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) {
1626     SFTRACE_FORMAT("%s for %s", __func__, mNamePlusId.c_str());
1627     ALOGV(__FUNCTION__);
1628 
1629     if (!getState().isEnabled) {
1630         if (flushEvenWhenDisabled && FlagManager::getInstance().flush_buffer_slots_to_uncache()) {
1631             // Some commands, like clearing buffer slots, should still be executed
1632             // even if the display is not enabled.
1633             executeCommands();
1634         }
1635         return;
1636     }
1637 
1638     auto& outputState = editState();
1639     outputState.dirtyRegion.clear();
1640 
1641     auto frame = presentFrame();
1642 
1643     mRenderSurface->onPresentDisplayCompleted();
1644 
1645     for (auto* layer : getOutputLayersOrderedByZ()) {
1646         // The layer buffer from the previous frame (if any) is released
1647         // by HWC only when the release fence from this frame (if any) is
1648         // signaled.  Always get the release fence from HWC first.
1649         sp<Fence> releaseFence = Fence::NO_FENCE;
1650 
1651         if (auto hwcLayer = layer->getHwcLayer()) {
1652             if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
1653                 releaseFence = f->second;
1654             }
1655         }
1656 
1657         // If the layer was client composited in the previous frame, we
1658         // need to merge with the previous client target acquire fence.
1659         // Since we do not track that, always merge with the current
1660         // client target acquire fence when it is available, even though
1661         // this is suboptimal.
1662         // TODO(b/121291683): Track previous frame client target acquire fence.
1663         if (outputState.usesClientComposition) {
1664             releaseFence =
1665                     Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
1666         }
1667         layer->getLayerFE().setReleaseFence(releaseFence);
1668     }
1669 
1670     // We've got a list of layers needing fences, that are disjoint with
1671     // OutputLayersOrderedByZ.  The best we can do is to
1672     // supply them with the present fence.
1673     for (auto& weakLayer : mReleasedLayers) {
1674         if (const auto layer = weakLayer.promote()) {
1675             layer->setReleaseFence(frame.presentFence);
1676         }
1677     }
1678 
1679     // Clear out the released layers now that we're done with them.
1680     mReleasedLayers.clear();
1681 }
1682 
renderCachedSets(const CompositionRefreshArgs & refreshArgs)1683 void Output::renderCachedSets(const CompositionRefreshArgs& refreshArgs) {
1684     const auto& outputState = getState();
1685     if (mPlanner && outputState.isEnabled) {
1686         mPlanner->renderCachedSets(outputState, refreshArgs.scheduledFrameTime,
1687                                    outputState.usesDeviceComposition || getSkipColorTransform());
1688     }
1689 }
1690 
dirtyEntireOutput()1691 void Output::dirtyEntireOutput() {
1692     auto& outputState = editState();
1693     outputState.dirtyRegion.set(outputState.displaySpace.getBoundsAsRect());
1694 }
1695 
resetCompositionStrategy()1696 void Output::resetCompositionStrategy() {
1697     // The base output implementation can only do client composition
1698     auto& outputState = editState();
1699     outputState.usesClientComposition = true;
1700     outputState.usesDeviceComposition = false;
1701     outputState.reusedClientComposition = false;
1702 }
1703 
getSkipColorTransform() const1704 bool Output::getSkipColorTransform() const {
1705     return true;
1706 }
1707 
presentFrame()1708 compositionengine::Output::FrameFences Output::presentFrame() {
1709     compositionengine::Output::FrameFences result;
1710     if (getState().usesClientComposition) {
1711         result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
1712     }
1713     return result;
1714 }
1715 
setPredictCompositionStrategy(bool predict)1716 void Output::setPredictCompositionStrategy(bool predict) {
1717     mPredictCompositionStrategy = predict;
1718     updateHwcAsyncWorker();
1719 }
1720 
updateHwcAsyncWorker()1721 void Output::updateHwcAsyncWorker() {
1722     if (mPredictCompositionStrategy || mOffloadPresent) {
1723         if (!mHwComposerAsyncWorker) {
1724             mHwComposerAsyncWorker = std::make_unique<HwcAsyncWorker>();
1725         }
1726     } else {
1727         mHwComposerAsyncWorker.reset(nullptr);
1728     }
1729 }
1730 
setTreat170mAsSrgb(bool enable)1731 void Output::setTreat170mAsSrgb(bool enable) {
1732     editState().treat170mAsSrgb = enable;
1733 }
1734 
getOverlaySupport()1735 const aidl::android::hardware::graphics::composer3::OverlayProperties* Output::getOverlaySupport() {
1736     return nullptr;
1737 }
1738 
canPredictCompositionStrategy(const CompositionRefreshArgs & refreshArgs)1739 bool Output::canPredictCompositionStrategy(const CompositionRefreshArgs& refreshArgs) {
1740     uint64_t lastOutputLayerHash = getState().lastOutputLayerHash;
1741     uint64_t outputLayerHash = getState().outputLayerHash;
1742     editState().lastOutputLayerHash = outputLayerHash;
1743 
1744     if (!getState().isEnabled || !mPredictCompositionStrategy) {
1745         ALOGV("canPredictCompositionStrategy disabled");
1746         return false;
1747     }
1748 
1749     if (!getState().previousDeviceRequestedChanges) {
1750         ALOGV("canPredictCompositionStrategy previous changes not available");
1751         return false;
1752     }
1753 
1754     if (!mRenderSurface->supportsCompositionStrategyPrediction()) {
1755         ALOGV("canPredictCompositionStrategy surface does not support");
1756         return false;
1757     }
1758 
1759     if (refreshArgs.devOptFlashDirtyRegionsDelay) {
1760         ALOGV("canPredictCompositionStrategy devOptFlashDirtyRegionsDelay");
1761         return false;
1762     }
1763 
1764     if (lastOutputLayerHash != outputLayerHash) {
1765         ALOGV("canPredictCompositionStrategy output layers changed");
1766         return false;
1767     }
1768 
1769     // If no layer uses clientComposition, then don't predict composition strategy
1770     // because we have less work to do in parallel.
1771     if (!anyLayersRequireClientComposition()) {
1772         ALOGV("canPredictCompositionStrategy no layer uses clientComposition");
1773         return false;
1774     }
1775 
1776     return true;
1777 }
1778 
anyLayersRequireClientComposition() const1779 bool Output::anyLayersRequireClientComposition() const {
1780     const auto layers = getOutputLayersOrderedByZ();
1781     return std::any_of(layers.begin(), layers.end(),
1782                        [](const auto& layer) { return layer->requiresClientComposition(); });
1783 }
1784 
finishPrepareFrame()1785 void Output::finishPrepareFrame() {
1786     const auto& state = getState();
1787     if (mPlanner) {
1788         mPlanner->reportFinalPlan(getOutputLayersOrderedByZ());
1789     }
1790     mRenderSurface->prepareFrame(state.usesClientComposition, state.usesDeviceComposition);
1791 }
1792 
mustRecompose() const1793 bool Output::mustRecompose() const {
1794     return mMustRecompose;
1795 }
1796 
getHdrSdrRatio(const std::shared_ptr<renderengine::ExternalTexture> & buffer) const1797 float Output::getHdrSdrRatio(const std::shared_ptr<renderengine::ExternalTexture>& buffer) const {
1798     if (buffer == nullptr) {
1799         return 1.0f;
1800     }
1801 
1802     if (!FlagManager::getInstance().fp16_client_target()) {
1803         return 1.0f;
1804     }
1805 
1806     if (getState().displayBrightnessNits < 0.0f || getState().sdrWhitePointNits <= 0.0f ||
1807         buffer->getPixelFormat() != PIXEL_FORMAT_RGBA_FP16 ||
1808         (static_cast<int32_t>(getState().dataspace) &
1809          static_cast<int32_t>(ui::Dataspace::RANGE_MASK)) !=
1810                 static_cast<int32_t>(ui::Dataspace::RANGE_EXTENDED)) {
1811         return 1.0f;
1812     }
1813 
1814     return getState().displayBrightnessNits / getState().sdrWhitePointNits;
1815 }
1816 
hasPictureProcessing() const1817 bool Output::hasPictureProcessing() const {
1818     return false;
1819 }
1820 
getMaxLayerPictureProfiles() const1821 int32_t Output::getMaxLayerPictureProfiles() const {
1822     return 0;
1823 }
1824 
applyPictureProfile()1825 void Output::applyPictureProfile() {
1826     if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
1827         return;
1828     }
1829 
1830     // TODO(b/337330263): Move this into the Display class and add a Display unit test.
1831     if (!getState().pictureProfileHandle) {
1832         return;
1833     }
1834     if (!getDisplayId()) {
1835         return;
1836     }
1837     if (auto displayId = PhysicalDisplayId::tryCast(*getDisplayId())) {
1838         auto& hwc = getCompositionEngine().getHwComposer();
1839         const status_t error =
1840                 hwc.setDisplayPictureProfileHandle(*displayId, getState().pictureProfileHandle);
1841         ALOGE_IF(error, "setDisplayPictureProfileHandle failed for %s: %d, (%s)", getName().c_str(),
1842                  error, strerror(-error));
1843     }
1844 }
1845 
1846 } // namespace impl
1847 } // namespace android::compositionengine
1848