• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <compositionengine/CompositionEngine.h>
20 #include <compositionengine/CompositionRefreshArgs.h>
21 #include <compositionengine/DisplayColorProfile.h>
22 #include <compositionengine/LayerFE.h>
23 #include <compositionengine/LayerFECompositionState.h>
24 #include <compositionengine/RenderSurface.h>
25 #include <compositionengine/impl/HwcAsyncWorker.h>
26 #include <compositionengine/impl/Output.h>
27 #include <compositionengine/impl/OutputCompositionState.h>
28 #include <compositionengine/impl/OutputLayer.h>
29 #include <compositionengine/impl/OutputLayerCompositionState.h>
30 #include <compositionengine/impl/planner/Planner.h>
31 #include <ftl/future.h>
32 #include <gui/TraceUtils.h>
33 
34 #include <optional>
35 #include <thread>
36 
37 #include "renderengine/ExternalTexture.h"
38 
39 // TODO(b/129481165): remove the #pragma below and fix conversion issues
40 #pragma clang diagnostic push
41 #pragma clang diagnostic ignored "-Wconversion"
42 
43 #include <renderengine/DisplaySettings.h>
44 #include <renderengine/RenderEngine.h>
45 
46 // TODO(b/129481165): remove the #pragma below and fix conversion issues
47 #pragma clang diagnostic pop // ignored "-Wconversion"
48 
49 #include <android-base/properties.h>
50 #include <ui/DebugUtils.h>
51 #include <ui/HdrCapabilities.h>
52 #include <utils/Trace.h>
53 
54 #include "TracedOrdinal.h"
55 
56 using aidl::android::hardware::graphics::composer3::Composition;
57 
58 namespace android::compositionengine {
59 
60 Output::~Output() = default;
61 
62 namespace impl {
63 using CompositionStrategyPredictionState =
64         OutputCompositionState::CompositionStrategyPredictionState;
65 namespace {
66 
67 template <typename T>
68 class Reversed {
69 public:
Reversed(const T & container)70     explicit Reversed(const T& container) : mContainer(container) {}
begin()71     auto begin() { return mContainer.rbegin(); }
end()72     auto end() { return mContainer.rend(); }
73 
74 private:
75     const T& mContainer;
76 };
77 
78 // Helper for enumerating over a container in reverse order
79 template <typename T>
reversed(const T & c)80 Reversed<T> reversed(const T& c) {
81     return Reversed<T>(c);
82 }
83 
84 struct ScaleVector {
85     float x;
86     float y;
87 };
88 
89 // Returns a ScaleVector (x, y) such that from.scale(x, y) = to',
90 // where to' will have the same size as "to". In the case where "from" and "to"
91 // start at the origin to'=to.
getScale(const Rect & from,const Rect & to)92 ScaleVector getScale(const Rect& from, const Rect& to) {
93     return {.x = static_cast<float>(to.width()) / from.width(),
94             .y = static_cast<float>(to.height()) / from.height()};
95 }
96 
97 } // namespace
98 
createOutput(const compositionengine::CompositionEngine & compositionEngine)99 std::shared_ptr<Output> createOutput(
100         const compositionengine::CompositionEngine& compositionEngine) {
101     return createOutputTemplated<Output>(compositionEngine);
102 }
103 
104 Output::~Output() = default;
105 
isValid() const106 bool Output::isValid() const {
107     return mDisplayColorProfile && mDisplayColorProfile->isValid() && mRenderSurface &&
108             mRenderSurface->isValid();
109 }
110 
getDisplayId() const111 std::optional<DisplayId> Output::getDisplayId() const {
112     return {};
113 }
114 
getName() const115 const std::string& Output::getName() const {
116     return mName;
117 }
118 
setName(const std::string & name)119 void Output::setName(const std::string& name) {
120     mName = name;
121     auto displayIdOpt = getDisplayId();
122     mNamePlusId = displayIdOpt ? base::StringPrintf("%s (%s)", mName.c_str(),
123                                      to_string(*displayIdOpt).c_str())
124                                : mName;
125 }
126 
setCompositionEnabled(bool enabled)127 void Output::setCompositionEnabled(bool enabled) {
128     auto& outputState = editState();
129     if (outputState.isEnabled == enabled) {
130         return;
131     }
132 
133     outputState.isEnabled = enabled;
134     dirtyEntireOutput();
135 }
136 
setLayerCachingEnabled(bool enabled)137 void Output::setLayerCachingEnabled(bool enabled) {
138     if (enabled == (mPlanner != nullptr)) {
139         return;
140     }
141 
142     if (enabled) {
143         mPlanner = std::make_unique<planner::Planner>(getCompositionEngine().getRenderEngine());
144         if (mRenderSurface) {
145             mPlanner->setDisplaySize(mRenderSurface->getSize());
146         }
147     } else {
148         mPlanner.reset();
149     }
150 
151     for (auto* outputLayer : getOutputLayersOrderedByZ()) {
152         if (!outputLayer) {
153             continue;
154         }
155 
156         outputLayer->editState().overrideInfo = {};
157     }
158 }
159 
setLayerCachingTexturePoolEnabled(bool enabled)160 void Output::setLayerCachingTexturePoolEnabled(bool enabled) {
161     if (mPlanner) {
162         mPlanner->setTexturePoolEnabled(enabled);
163     }
164 }
165 
setProjection(ui::Rotation orientation,const Rect & layerStackSpaceRect,const Rect & orientedDisplaySpaceRect)166 void Output::setProjection(ui::Rotation orientation, const Rect& layerStackSpaceRect,
167                            const Rect& orientedDisplaySpaceRect) {
168     auto& outputState = editState();
169 
170     outputState.displaySpace.setOrientation(orientation);
171     LOG_FATAL_IF(outputState.displaySpace.getBoundsAsRect() == Rect::INVALID_RECT,
172                  "The display bounds are unknown.");
173 
174     // Compute orientedDisplaySpace
175     ui::Size orientedSize = outputState.displaySpace.getBounds();
176     if (orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270) {
177         std::swap(orientedSize.width, orientedSize.height);
178     }
179     outputState.orientedDisplaySpace.setBounds(orientedSize);
180     outputState.orientedDisplaySpace.setContent(orientedDisplaySpaceRect);
181 
182     // Compute displaySpace.content
183     const uint32_t transformOrientationFlags = ui::Transform::toRotationFlags(orientation);
184     ui::Transform rotation;
185     if (transformOrientationFlags != ui::Transform::ROT_INVALID) {
186         const auto displaySize = outputState.displaySpace.getBoundsAsRect();
187         rotation.set(transformOrientationFlags, displaySize.width(), displaySize.height());
188     }
189     outputState.displaySpace.setContent(rotation.transform(orientedDisplaySpaceRect));
190 
191     // Compute framebufferSpace
192     outputState.framebufferSpace.setOrientation(orientation);
193     LOG_FATAL_IF(outputState.framebufferSpace.getBoundsAsRect() == Rect::INVALID_RECT,
194                  "The framebuffer bounds are unknown.");
195     const auto scale = getScale(outputState.displaySpace.getBoundsAsRect(),
196                                 outputState.framebufferSpace.getBoundsAsRect());
197     outputState.framebufferSpace.setContent(
198             outputState.displaySpace.getContent().scale(scale.x, scale.y));
199 
200     // Compute layerStackSpace
201     outputState.layerStackSpace.setContent(layerStackSpaceRect);
202     outputState.layerStackSpace.setBounds(
203             ui::Size(layerStackSpaceRect.getWidth(), layerStackSpaceRect.getHeight()));
204 
205     outputState.transform = outputState.layerStackSpace.getTransform(outputState.displaySpace);
206     outputState.needsFiltering = outputState.transform.needsBilinearFiltering();
207     dirtyEntireOutput();
208 }
209 
setNextBrightness(float brightness)210 void Output::setNextBrightness(float brightness) {
211     editState().displayBrightness = brightness;
212 }
213 
setDisplaySize(const ui::Size & size)214 void Output::setDisplaySize(const ui::Size& size) {
215     mRenderSurface->setDisplaySize(size);
216 
217     auto& state = editState();
218 
219     // Update framebuffer space
220     const ui::Size newBounds(size);
221     state.framebufferSpace.setBounds(newBounds);
222 
223     // Update display space
224     state.displaySpace.setBounds(newBounds);
225     state.transform = state.layerStackSpace.getTransform(state.displaySpace);
226 
227     // Update oriented display space
228     const auto orientation = state.displaySpace.getOrientation();
229     ui::Size orientedSize = size;
230     if (orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270) {
231         std::swap(orientedSize.width, orientedSize.height);
232     }
233     const ui::Size newOrientedBounds(orientedSize);
234     state.orientedDisplaySpace.setBounds(newOrientedBounds);
235 
236     if (mPlanner) {
237         mPlanner->setDisplaySize(size);
238     }
239 
240     dirtyEntireOutput();
241 }
242 
getTransformHint() const243 ui::Transform::RotationFlags Output::getTransformHint() const {
244     return static_cast<ui::Transform::RotationFlags>(getState().transform.getOrientation());
245 }
246 
setLayerFilter(ui::LayerFilter filter)247 void Output::setLayerFilter(ui::LayerFilter filter) {
248     editState().layerFilter = filter;
249     dirtyEntireOutput();
250 }
251 
setColorTransform(const compositionengine::CompositionRefreshArgs & args)252 void Output::setColorTransform(const compositionengine::CompositionRefreshArgs& args) {
253     auto& colorTransformMatrix = editState().colorTransformMatrix;
254     if (!args.colorTransformMatrix || colorTransformMatrix == args.colorTransformMatrix) {
255         return;
256     }
257 
258     colorTransformMatrix = *args.colorTransformMatrix;
259 
260     dirtyEntireOutput();
261 }
262 
setColorProfile(const ColorProfile & colorProfile)263 void Output::setColorProfile(const ColorProfile& colorProfile) {
264     ui::Dataspace targetDataspace =
265             getDisplayColorProfile()->getTargetDataspace(colorProfile.mode, colorProfile.dataspace,
266                                                          colorProfile.colorSpaceAgnosticDataspace);
267 
268     auto& outputState = editState();
269     if (outputState.colorMode == colorProfile.mode &&
270         outputState.dataspace == colorProfile.dataspace &&
271         outputState.renderIntent == colorProfile.renderIntent &&
272         outputState.targetDataspace == targetDataspace) {
273         return;
274     }
275 
276     outputState.colorMode = colorProfile.mode;
277     outputState.dataspace = colorProfile.dataspace;
278     outputState.renderIntent = colorProfile.renderIntent;
279     outputState.targetDataspace = targetDataspace;
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     ATRACE_CALL();
430     ALOGV(__FUNCTION__);
431 
432     rebuildLayerStacks(refreshArgs, geomSnapshots);
433     uncacheBuffers(refreshArgs.bufferIdsToUncache);
434 }
435 
present(const compositionengine::CompositionRefreshArgs & refreshArgs)436 void Output::present(const compositionengine::CompositionRefreshArgs& refreshArgs) {
437     ATRACE_FORMAT("%s for %s", __func__, mNamePlusId.c_str());
438     ALOGV(__FUNCTION__);
439 
440     updateColorProfile(refreshArgs);
441     updateCompositionState(refreshArgs);
442     planComposition();
443     writeCompositionState(refreshArgs);
444     setColorTransform(refreshArgs);
445     beginFrame();
446 
447     GpuCompositionResult result;
448     const bool predictCompositionStrategy = canPredictCompositionStrategy(refreshArgs);
449     if (predictCompositionStrategy) {
450         result = prepareFrameAsync();
451     } else {
452         prepareFrame();
453     }
454 
455     devOptRepaintFlash(refreshArgs);
456     finishFrame(std::move(result));
457     postFramebuffer();
458     renderCachedSets(refreshArgs);
459 }
460 
uncacheBuffers(std::vector<uint64_t> const & bufferIdsToUncache)461 void Output::uncacheBuffers(std::vector<uint64_t> const& bufferIdsToUncache) {
462     if (bufferIdsToUncache.empty()) {
463         return;
464     }
465     for (auto outputLayer : getOutputLayersOrderedByZ()) {
466         outputLayer->uncacheBuffers(bufferIdsToUncache);
467     }
468 }
469 
rebuildLayerStacks(const compositionengine::CompositionRefreshArgs & refreshArgs,LayerFESet & layerFESet)470 void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& refreshArgs,
471                                 LayerFESet& layerFESet) {
472     ATRACE_CALL();
473     ALOGV(__FUNCTION__);
474 
475     auto& outputState = editState();
476 
477     // Do nothing if this output is not enabled or there is no need to perform this update
478     if (!outputState.isEnabled || CC_LIKELY(!refreshArgs.updatingOutputGeometryThisFrame)) {
479         return;
480     }
481 
482     // Process the layers to determine visibility and coverage
483     compositionengine::Output::CoverageState coverage{layerFESet};
484     coverage.aboveCoveredLayersExcludingOverlays = refreshArgs.hasTrustedPresentationListener
485             ? std::make_optional<Region>()
486             : std::nullopt;
487     collectVisibleLayers(refreshArgs, coverage);
488 
489     // Compute the resulting coverage for this output, and store it for later
490     const ui::Transform& tr = outputState.transform;
491     Region undefinedRegion{outputState.displaySpace.getBoundsAsRect()};
492     undefinedRegion.subtractSelf(tr.transform(coverage.aboveOpaqueLayers));
493 
494     outputState.undefinedRegion = undefinedRegion;
495     outputState.dirtyRegion.orSelf(coverage.dirtyRegion);
496 }
497 
collectVisibleLayers(const compositionengine::CompositionRefreshArgs & refreshArgs,compositionengine::Output::CoverageState & coverage)498 void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArgs& refreshArgs,
499                                   compositionengine::Output::CoverageState& coverage) {
500     // Evaluate the layers from front to back to determine what is visible. This
501     // also incrementally calculates the coverage information for each layer as
502     // well as the entire output.
503     for (auto layer : reversed(refreshArgs.layers)) {
504         // Incrementally process the coverage for each layer
505         ensureOutputLayerIfVisible(layer, coverage);
506 
507         // TODO(b/121291683): Stop early if the output is completely covered and
508         // no more layers could even be visible underneath the ones on top.
509     }
510 
511     setReleasedLayers(refreshArgs);
512 
513     finalizePendingOutputLayers();
514 }
515 
ensureOutputLayerIfVisible(sp<compositionengine::LayerFE> & layerFE,compositionengine::Output::CoverageState & coverage)516 void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE,
517                                         compositionengine::Output::CoverageState& coverage) {
518     // Ensure we have a snapshot of the basic geometry layer state. Limit the
519     // snapshots to once per frame for each candidate layer, as layers may
520     // appear on multiple outputs.
521     if (!coverage.latchedLayers.count(layerFE)) {
522         coverage.latchedLayers.insert(layerFE);
523     }
524 
525     // Only consider the layers on this output
526     if (!includesLayer(layerFE)) {
527         return;
528     }
529 
530     // Obtain a read-only pointer to the front-end layer state
531     const auto* layerFEState = layerFE->getCompositionState();
532     if (CC_UNLIKELY(!layerFEState)) {
533         return;
534     }
535 
536     // handle hidden surfaces by setting the visible region to empty
537     if (CC_UNLIKELY(!layerFEState->isVisible)) {
538         return;
539     }
540 
541     bool computeAboveCoveredExcludingOverlays = coverage.aboveCoveredLayersExcludingOverlays &&
542             !layerFEState->outputFilter.toInternalDisplay;
543 
544     /*
545      * opaqueRegion: area of a surface that is fully opaque.
546      */
547     Region opaqueRegion;
548 
549     /*
550      * visibleRegion: area of a surface that is visible on screen and not fully
551      * transparent. This is essentially the layer's footprint minus the opaque
552      * regions above it. Areas covered by a translucent surface are considered
553      * visible.
554      */
555     Region visibleRegion;
556 
557     /*
558      * coveredRegion: area of a surface that is covered by all visible regions
559      * above it (which includes the translucent areas).
560      */
561     Region coveredRegion;
562 
563     /*
564      * transparentRegion: area of a surface that is hinted to be completely
565      * transparent.
566      * This is used to tell when the layer has no visible non-transparent
567      * regions and can be removed from the layer list. It does not affect the
568      * visibleRegion of this layer or any layers beneath it. The hint may not
569      * be correct if apps don't respect the SurfaceView restrictions (which,
570      * sadly, some don't).
571      *
572      * In addition, it is used on DISPLAY_DECORATION layers to specify the
573      * blockingRegion, allowing the DPU to skip it to save power. Once we have
574      * hardware that supports a blockingRegion on frames with AFBC, it may be
575      * useful to use this for other layers, too, so long as we can prevent
576      * regressions on b/7179570.
577      */
578     Region transparentRegion;
579 
580     /*
581      * shadowRegion: Region cast by the layer's shadow.
582      */
583     Region shadowRegion;
584 
585     /**
586      * covered region above excluding internal display overlay layers
587      */
588     std::optional<Region> coveredRegionExcludingDisplayOverlays = std::nullopt;
589 
590     const ui::Transform& tr = layerFEState->geomLayerTransform;
591 
592     // Get the visible region
593     // TODO(b/121291683): Is it worth creating helper methods on LayerFEState
594     // for computations like this?
595     const Rect visibleRect(tr.transform(layerFEState->geomLayerBounds));
596     visibleRegion.set(visibleRect);
597 
598     if (layerFEState->shadowRadius > 0.0f) {
599         // if the layer casts a shadow, offset the layers visible region and
600         // calculate the shadow region.
601         const auto inset = static_cast<int32_t>(ceilf(layerFEState->shadowRadius) * -1.0f);
602         Rect visibleRectWithShadows(visibleRect);
603         visibleRectWithShadows.inset(inset, inset, inset, inset);
604         visibleRegion.set(visibleRectWithShadows);
605         shadowRegion = visibleRegion.subtract(visibleRect);
606     }
607 
608     if (visibleRegion.isEmpty()) {
609         return;
610     }
611 
612     // Remove the transparent area from the visible region
613     if (!layerFEState->isOpaque) {
614         if (tr.preserveRects()) {
615             // Clip the transparent region to geomLayerBounds first
616             // The transparent region may be influenced by applications, for
617             // instance, by overriding ViewGroup#gatherTransparentRegion with a
618             // custom view. Once the layer stack -> display mapping is known, we
619             // must guard against very wrong inputs to prevent underflow or
620             // overflow errors. We do this here by constraining the transparent
621             // region to be within the pre-transform layer bounds, since the
622             // layer bounds are expected to play nicely with the full
623             // transform.
624             const Region clippedTransparentRegionHint =
625                     layerFEState->transparentRegionHint.intersect(
626                             Rect(layerFEState->geomLayerBounds));
627 
628             if (clippedTransparentRegionHint.isEmpty()) {
629                 if (!layerFEState->transparentRegionHint.isEmpty()) {
630                     ALOGD("Layer: %s had an out of bounds transparent region",
631                           layerFE->getDebugName());
632                     layerFEState->transparentRegionHint.dump("transparentRegionHint");
633                 }
634                 transparentRegion.clear();
635             } else {
636                 transparentRegion = tr.transform(clippedTransparentRegionHint);
637             }
638         } else {
639             // transformation too complex, can't do the
640             // transparent region optimization.
641             transparentRegion.clear();
642         }
643     }
644 
645     // compute the opaque region
646     const auto layerOrientation = tr.getOrientation();
647     if (layerFEState->isOpaque && ((layerOrientation & ui::Transform::ROT_INVALID) == 0)) {
648         // If we one of the simple category of transforms (0/90/180/270 rotation
649         // + any flip), then the opaque region is the layer's footprint.
650         // Otherwise we don't try and compute the opaque region since there may
651         // be errors at the edges, and we treat the entire layer as
652         // translucent.
653         opaqueRegion.set(visibleRect);
654     }
655 
656     // Clip the covered region to the visible region
657     coveredRegion = coverage.aboveCoveredLayers.intersect(visibleRegion);
658 
659     // Update accumAboveCoveredLayers for next (lower) layer
660     coverage.aboveCoveredLayers.orSelf(visibleRegion);
661 
662     if (CC_UNLIKELY(computeAboveCoveredExcludingOverlays)) {
663         coveredRegionExcludingDisplayOverlays =
664                 coverage.aboveCoveredLayersExcludingOverlays->intersect(visibleRegion);
665         coverage.aboveCoveredLayersExcludingOverlays->orSelf(visibleRegion);
666     }
667 
668     // subtract the opaque region covered by the layers above us
669     visibleRegion.subtractSelf(coverage.aboveOpaqueLayers);
670 
671     if (visibleRegion.isEmpty()) {
672         return;
673     }
674 
675     // Get coverage information for the layer as previously displayed,
676     // also taking over ownership from mOutputLayersorderedByZ.
677     auto prevOutputLayerIndex = findCurrentOutputLayerForLayer(layerFE);
678     auto prevOutputLayer =
679             prevOutputLayerIndex ? getOutputLayerOrderedByZByIndex(*prevOutputLayerIndex) : nullptr;
680 
681     //  Get coverage information for the layer as previously displayed
682     // TODO(b/121291683): Define kEmptyRegion as a constant in Region.h
683     const Region kEmptyRegion;
684     const Region& oldVisibleRegion =
685             prevOutputLayer ? prevOutputLayer->getState().visibleRegion : kEmptyRegion;
686     const Region& oldCoveredRegion =
687             prevOutputLayer ? prevOutputLayer->getState().coveredRegion : kEmptyRegion;
688 
689     // compute this layer's dirty region
690     Region dirty;
691     if (layerFEState->contentDirty) {
692         // we need to invalidate the whole region
693         dirty = visibleRegion;
694         // as well, as the old visible region
695         dirty.orSelf(oldVisibleRegion);
696     } else {
697         /* compute the exposed region:
698          *   the exposed region consists of two components:
699          *   1) what's VISIBLE now and was COVERED before
700          *   2) what's EXPOSED now less what was EXPOSED before
701          *
702          * note that (1) is conservative, we start with the whole visible region
703          * but only keep what used to be covered by something -- which mean it
704          * may have been exposed.
705          *
706          * (2) handles areas that were not covered by anything but got exposed
707          * because of a resize.
708          *
709          */
710         const Region newExposed = visibleRegion - coveredRegion;
711         const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
712         dirty = (visibleRegion & oldCoveredRegion) | (newExposed - oldExposed);
713     }
714     dirty.subtractSelf(coverage.aboveOpaqueLayers);
715 
716     // accumulate to the screen dirty region
717     coverage.dirtyRegion.orSelf(dirty);
718 
719     // Update accumAboveOpaqueLayers for next (lower) layer
720     coverage.aboveOpaqueLayers.orSelf(opaqueRegion);
721 
722     // Compute the visible non-transparent region
723     Region visibleNonTransparentRegion = visibleRegion.subtract(transparentRegion);
724 
725     // Perform the final check to see if this layer is visible on this output
726     // TODO(b/121291683): Why does this not use visibleRegion? (see outputSpaceVisibleRegion below)
727     const auto& outputState = getState();
728     Region drawRegion(outputState.transform.transform(visibleNonTransparentRegion));
729     drawRegion.andSelf(outputState.displaySpace.getBoundsAsRect());
730     if (drawRegion.isEmpty()) {
731         return;
732     }
733 
734     Region visibleNonShadowRegion = visibleRegion.subtract(shadowRegion);
735 
736     // The layer is visible. Either reuse the existing outputLayer if we have
737     // one, or create a new one if we do not.
738     auto result = ensureOutputLayer(prevOutputLayerIndex, layerFE);
739 
740     // Store the layer coverage information into the layer state as some of it
741     // is useful later.
742     auto& outputLayerState = result->editState();
743     outputLayerState.visibleRegion = visibleRegion;
744     outputLayerState.visibleNonTransparentRegion = visibleNonTransparentRegion;
745     outputLayerState.coveredRegion = coveredRegion;
746     outputLayerState.outputSpaceVisibleRegion = outputState.transform.transform(
747             visibleNonShadowRegion.intersect(outputState.layerStackSpace.getContent()));
748     outputLayerState.shadowRegion = shadowRegion;
749     outputLayerState.outputSpaceBlockingRegionHint =
750             layerFEState->compositionType == Composition::DISPLAY_DECORATION
751             ? outputState.transform.transform(
752                       transparentRegion.intersect(outputState.layerStackSpace.getContent()))
753             : Region();
754     if (CC_UNLIKELY(computeAboveCoveredExcludingOverlays)) {
755         outputLayerState.coveredRegionExcludingDisplayOverlays =
756                 std::move(coveredRegionExcludingDisplayOverlays);
757     }
758 }
759 
setReleasedLayers(const compositionengine::CompositionRefreshArgs &)760 void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) {
761     // The base class does nothing with this call.
762 }
763 
updateCompositionState(const compositionengine::CompositionRefreshArgs & refreshArgs)764 void Output::updateCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) {
765     ATRACE_CALL();
766     ALOGV(__FUNCTION__);
767 
768     if (!getState().isEnabled) {
769         return;
770     }
771 
772     mLayerRequestingBackgroundBlur = findLayerRequestingBackgroundComposition();
773     bool forceClientComposition = mLayerRequestingBackgroundBlur != nullptr;
774 
775     for (auto* layer : getOutputLayersOrderedByZ()) {
776         layer->updateCompositionState(refreshArgs.updatingGeometryThisFrame,
777                                       refreshArgs.devOptForceClientComposition ||
778                                               forceClientComposition,
779                                       refreshArgs.internalDisplayRotationFlags);
780 
781         if (mLayerRequestingBackgroundBlur == layer) {
782             forceClientComposition = false;
783         }
784     }
785 
786     updateCompositionStateForBorder(refreshArgs);
787 }
788 
updateCompositionStateForBorder(const compositionengine::CompositionRefreshArgs & refreshArgs)789 void Output::updateCompositionStateForBorder(
790         const compositionengine::CompositionRefreshArgs& refreshArgs) {
791     std::unordered_map<int32_t, const Region*> layerVisibleRegionMap;
792     // Store a map of layerId to their computed visible region.
793     for (auto* layer : getOutputLayersOrderedByZ()) {
794         int layerId = (layer->getLayerFE()).getSequence();
795         layerVisibleRegionMap[layerId] = &((layer->getState()).visibleRegion);
796     }
797     OutputCompositionState& outputCompositionState = editState();
798     outputCompositionState.borderInfoList.clear();
799     bool clientComposeTopLayer = false;
800     for (const auto& borderInfo : refreshArgs.borderInfoList) {
801         renderengine::BorderRenderInfo info;
802         for (const auto& id : borderInfo.layerIds) {
803             info.combinedRegion.orSelf(*(layerVisibleRegionMap[id]));
804         }
805 
806         if (!info.combinedRegion.isEmpty()) {
807             info.width = borderInfo.width;
808             info.color = borderInfo.color;
809             outputCompositionState.borderInfoList.emplace_back(std::move(info));
810             clientComposeTopLayer = true;
811         }
812     }
813 
814     // In this situation we must client compose the top layer instead of using hwc
815     // because we want to draw the border above all else.
816     // This could potentially cause a bit of a performance regression if the top
817     // layer would have been rendered using hwc originally.
818     // TODO(b/227656283): Measure system's performance before enabling the border feature
819     if (clientComposeTopLayer) {
820         auto topLayer = getOutputLayerOrderedByZByIndex(getOutputLayerCount() - 1);
821         (topLayer->editState()).forceClientComposition = true;
822     }
823 }
824 
planComposition()825 void Output::planComposition() {
826     if (!mPlanner || !getState().isEnabled) {
827         return;
828     }
829 
830     ATRACE_CALL();
831     ALOGV(__FUNCTION__);
832 
833     mPlanner->plan(getOutputLayersOrderedByZ());
834 }
835 
writeCompositionState(const compositionengine::CompositionRefreshArgs & refreshArgs)836 void Output::writeCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) {
837     ATRACE_CALL();
838     ALOGV(__FUNCTION__);
839 
840     if (!getState().isEnabled) {
841         return;
842     }
843 
844     editState().earliestPresentTime = refreshArgs.earliestPresentTime;
845     editState().expectedPresentTime = refreshArgs.expectedPresentTime;
846     editState().powerCallback = refreshArgs.powerCallback;
847 
848     compositionengine::OutputLayer* peekThroughLayer = nullptr;
849     sp<GraphicBuffer> previousOverride = nullptr;
850     bool includeGeometry = refreshArgs.updatingGeometryThisFrame;
851     uint32_t z = 0;
852     bool overrideZ = false;
853     uint64_t outputLayerHash = 0;
854     for (auto* layer : getOutputLayersOrderedByZ()) {
855         if (layer == peekThroughLayer) {
856             // No longer needed, although it should not show up again, so
857             // resetting it is not truly needed either.
858             peekThroughLayer = nullptr;
859 
860             // peekThroughLayer was already drawn ahead of its z order.
861             continue;
862         }
863         bool skipLayer = false;
864         const auto& overrideInfo = layer->getState().overrideInfo;
865         if (overrideInfo.buffer != nullptr) {
866             if (previousOverride && overrideInfo.buffer->getBuffer() == previousOverride) {
867                 ALOGV("Skipping redundant buffer");
868                 skipLayer = true;
869             } else {
870                 // First layer with the override buffer.
871                 if (overrideInfo.peekThroughLayer) {
872                     peekThroughLayer = overrideInfo.peekThroughLayer;
873 
874                     // Draw peekThroughLayer first.
875                     overrideZ = true;
876                     includeGeometry = true;
877                     constexpr bool isPeekingThrough = true;
878                     peekThroughLayer->writeStateToHWC(includeGeometry, false, z++, overrideZ,
879                                                       isPeekingThrough);
880                     outputLayerHash ^= android::hashCombine(
881                             reinterpret_cast<uint64_t>(&peekThroughLayer->getLayerFE()),
882                             z, includeGeometry, overrideZ, isPeekingThrough,
883                             peekThroughLayer->requiresClientComposition());
884                 }
885 
886                 previousOverride = overrideInfo.buffer->getBuffer();
887             }
888         }
889 
890         constexpr bool isPeekingThrough = false;
891         layer->writeStateToHWC(includeGeometry, skipLayer, z++, overrideZ, isPeekingThrough);
892         if (!skipLayer) {
893             outputLayerHash ^= android::hashCombine(
894                     reinterpret_cast<uint64_t>(&layer->getLayerFE()),
895                     z, includeGeometry, overrideZ, isPeekingThrough,
896                     layer->requiresClientComposition());
897         }
898     }
899     editState().outputLayerHash = outputLayerHash;
900 }
901 
findLayerRequestingBackgroundComposition() const902 compositionengine::OutputLayer* Output::findLayerRequestingBackgroundComposition() const {
903     compositionengine::OutputLayer* layerRequestingBgComposition = nullptr;
904     for (auto* layer : getOutputLayersOrderedByZ()) {
905         auto* compState = layer->getLayerFE().getCompositionState();
906 
907         // If any layer has a sideband stream, we will disable blurs. In that case, we don't
908         // want to force client composition because of the blur.
909         if (compState->sidebandStream != nullptr) {
910             return nullptr;
911         }
912         if (compState->isOpaque) {
913             continue;
914         }
915         if (compState->backgroundBlurRadius > 0 || compState->blurRegions.size() > 0) {
916             layerRequestingBgComposition = layer;
917         }
918     }
919     return layerRequestingBgComposition;
920 }
921 
updateColorProfile(const compositionengine::CompositionRefreshArgs & refreshArgs)922 void Output::updateColorProfile(const compositionengine::CompositionRefreshArgs& refreshArgs) {
923     setColorProfile(pickColorProfile(refreshArgs));
924 }
925 
926 // Returns a data space that fits all visible layers.  The returned data space
927 // can only be one of
928 //  - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced)
929 //  - Dataspace::DISPLAY_P3
930 //  - Dataspace::DISPLAY_BT2020
931 // The returned HDR data space is one of
932 //  - Dataspace::UNKNOWN
933 //  - Dataspace::BT2020_HLG
934 //  - Dataspace::BT2020_PQ
getBestDataspace(ui::Dataspace * outHdrDataSpace,bool * outIsHdrClientComposition) const935 ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace,
936                                        bool* outIsHdrClientComposition) const {
937     ui::Dataspace bestDataSpace = ui::Dataspace::V0_SRGB;
938     *outHdrDataSpace = ui::Dataspace::UNKNOWN;
939 
940     // An Output's layers may be stale when it is disabled. As a consequence, the layers returned by
941     // getOutputLayersOrderedByZ may not be in a valid state and it is not safe to access their
942     // properties. Return a default dataspace value in this case.
943     if (!getState().isEnabled) {
944         return ui::Dataspace::V0_SRGB;
945     }
946 
947     for (const auto* layer : getOutputLayersOrderedByZ()) {
948         switch (layer->getLayerFE().getCompositionState()->dataspace) {
949             case ui::Dataspace::V0_SCRGB:
950             case ui::Dataspace::V0_SCRGB_LINEAR:
951             case ui::Dataspace::BT2020:
952             case ui::Dataspace::BT2020_ITU:
953             case ui::Dataspace::BT2020_LINEAR:
954             case ui::Dataspace::DISPLAY_BT2020:
955                 bestDataSpace = ui::Dataspace::DISPLAY_BT2020;
956                 break;
957             case ui::Dataspace::DISPLAY_P3:
958                 bestDataSpace = ui::Dataspace::DISPLAY_P3;
959                 break;
960             case ui::Dataspace::BT2020_PQ:
961             case ui::Dataspace::BT2020_ITU_PQ:
962                 bestDataSpace = ui::Dataspace::DISPLAY_P3;
963                 *outHdrDataSpace = ui::Dataspace::BT2020_PQ;
964                 *outIsHdrClientComposition =
965                         layer->getLayerFE().getCompositionState()->forceClientComposition;
966                 break;
967             case ui::Dataspace::BT2020_HLG:
968             case ui::Dataspace::BT2020_ITU_HLG:
969                 bestDataSpace = ui::Dataspace::DISPLAY_P3;
970                 // When there's mixed PQ content and HLG content, we set the HDR
971                 // data space to be BT2020_PQ and convert HLG to PQ.
972                 if (*outHdrDataSpace == ui::Dataspace::UNKNOWN) {
973                     *outHdrDataSpace = ui::Dataspace::BT2020_HLG;
974                 }
975                 break;
976             default:
977                 break;
978         }
979     }
980 
981     return bestDataSpace;
982 }
983 
pickColorProfile(const compositionengine::CompositionRefreshArgs & refreshArgs) const984 compositionengine::Output::ColorProfile Output::pickColorProfile(
985         const compositionengine::CompositionRefreshArgs& refreshArgs) const {
986     if (refreshArgs.outputColorSetting == OutputColorSetting::kUnmanaged) {
987         return ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
988                             ui::RenderIntent::COLORIMETRIC,
989                             refreshArgs.colorSpaceAgnosticDataspace};
990     }
991 
992     ui::Dataspace hdrDataSpace;
993     bool isHdrClientComposition = false;
994     ui::Dataspace bestDataSpace = getBestDataspace(&hdrDataSpace, &isHdrClientComposition);
995 
996     switch (refreshArgs.forceOutputColorMode) {
997         case ui::ColorMode::SRGB:
998             bestDataSpace = ui::Dataspace::V0_SRGB;
999             break;
1000         case ui::ColorMode::DISPLAY_P3:
1001             bestDataSpace = ui::Dataspace::DISPLAY_P3;
1002             break;
1003         default:
1004             break;
1005     }
1006 
1007     // respect hdrDataSpace only when there is no legacy HDR support
1008     const bool isHdr = hdrDataSpace != ui::Dataspace::UNKNOWN &&
1009             !mDisplayColorProfile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition;
1010     if (isHdr) {
1011         bestDataSpace = hdrDataSpace;
1012     }
1013 
1014     ui::RenderIntent intent;
1015     switch (refreshArgs.outputColorSetting) {
1016         case OutputColorSetting::kManaged:
1017         case OutputColorSetting::kUnmanaged:
1018             intent = isHdr ? ui::RenderIntent::TONE_MAP_COLORIMETRIC
1019                            : ui::RenderIntent::COLORIMETRIC;
1020             break;
1021         case OutputColorSetting::kEnhanced:
1022             intent = isHdr ? ui::RenderIntent::TONE_MAP_ENHANCE : ui::RenderIntent::ENHANCE;
1023             break;
1024         default: // vendor display color setting
1025             intent = static_cast<ui::RenderIntent>(refreshArgs.outputColorSetting);
1026             break;
1027     }
1028 
1029     ui::ColorMode outMode;
1030     ui::Dataspace outDataSpace;
1031     ui::RenderIntent outRenderIntent;
1032     mDisplayColorProfile->getBestColorMode(bestDataSpace, intent, &outDataSpace, &outMode,
1033                                            &outRenderIntent);
1034 
1035     return ColorProfile{outMode, outDataSpace, outRenderIntent,
1036                         refreshArgs.colorSpaceAgnosticDataspace};
1037 }
1038 
beginFrame()1039 void Output::beginFrame() {
1040     auto& outputState = editState();
1041     const bool dirty = !getDirtyRegion().isEmpty();
1042     const bool empty = getOutputLayerCount() == 0;
1043     const bool wasEmpty = !outputState.lastCompositionHadVisibleLayers;
1044 
1045     // If nothing has changed (!dirty), don't recompose.
1046     // If something changed, but we don't currently have any visible layers,
1047     //   and didn't when we last did a composition, then skip it this time.
1048     // The second rule does two things:
1049     // - When all layers are removed from a display, we'll emit one black
1050     //   frame, then nothing more until we get new layers.
1051     // - When a display is created with a private layer stack, we won't
1052     //   emit any black frames until a layer is added to the layer stack.
1053     mMustRecompose = dirty && !(empty && wasEmpty);
1054 
1055     const char flagPrefix[] = {'-', '+'};
1056     static_cast<void>(flagPrefix);
1057     ALOGV("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __func__,
1058           mMustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty],
1059           flagPrefix[empty], flagPrefix[wasEmpty]);
1060 
1061     mRenderSurface->beginFrame(mMustRecompose);
1062 
1063     if (mMustRecompose) {
1064         outputState.lastCompositionHadVisibleLayers = !empty;
1065     }
1066 }
1067 
prepareFrame()1068 void Output::prepareFrame() {
1069     ATRACE_CALL();
1070     ALOGV(__FUNCTION__);
1071 
1072     auto& outputState = editState();
1073     if (!outputState.isEnabled) {
1074         return;
1075     }
1076 
1077     std::optional<android::HWComposer::DeviceRequestedChanges> changes;
1078     bool success = chooseCompositionStrategy(&changes);
1079     resetCompositionStrategy();
1080     outputState.strategyPrediction = CompositionStrategyPredictionState::DISABLED;
1081     outputState.previousDeviceRequestedChanges = changes;
1082     outputState.previousDeviceRequestedSuccess = success;
1083     if (success) {
1084         applyCompositionStrategy(changes);
1085     }
1086     finishPrepareFrame();
1087 }
1088 
chooseCompositionStrategyAsync(std::optional<android::HWComposer::DeviceRequestedChanges> * changes)1089 std::future<bool> Output::chooseCompositionStrategyAsync(
1090         std::optional<android::HWComposer::DeviceRequestedChanges>* changes) {
1091     return mHwComposerAsyncWorker->send(
1092             [&, changes]() { return chooseCompositionStrategy(changes); });
1093 }
1094 
prepareFrameAsync()1095 GpuCompositionResult Output::prepareFrameAsync() {
1096     ATRACE_CALL();
1097     ALOGV(__FUNCTION__);
1098     auto& state = editState();
1099     const auto& previousChanges = state.previousDeviceRequestedChanges;
1100     std::optional<android::HWComposer::DeviceRequestedChanges> changes;
1101     resetCompositionStrategy();
1102     auto hwcResult = chooseCompositionStrategyAsync(&changes);
1103     if (state.previousDeviceRequestedSuccess) {
1104         applyCompositionStrategy(previousChanges);
1105     }
1106     finishPrepareFrame();
1107 
1108     base::unique_fd bufferFence;
1109     std::shared_ptr<renderengine::ExternalTexture> buffer;
1110     updateProtectedContentState();
1111     const bool dequeueSucceeded = dequeueRenderBuffer(&bufferFence, &buffer);
1112     GpuCompositionResult compositionResult;
1113     if (dequeueSucceeded) {
1114         std::optional<base::unique_fd> optFd =
1115                 composeSurfaces(Region::INVALID_REGION, buffer, bufferFence);
1116         if (optFd) {
1117             compositionResult.fence = std::move(*optFd);
1118         }
1119     }
1120 
1121     auto chooseCompositionSuccess = hwcResult.get();
1122     const bool predictionSucceeded = dequeueSucceeded && changes == previousChanges;
1123     state.strategyPrediction = predictionSucceeded ? CompositionStrategyPredictionState::SUCCESS
1124                                                    : CompositionStrategyPredictionState::FAIL;
1125     if (!predictionSucceeded) {
1126         ATRACE_NAME("CompositionStrategyPredictionMiss");
1127         resetCompositionStrategy();
1128         if (chooseCompositionSuccess) {
1129             applyCompositionStrategy(changes);
1130         }
1131         finishPrepareFrame();
1132         // Track the dequeued buffer to reuse so we don't need to dequeue another one.
1133         compositionResult.buffer = buffer;
1134     } else {
1135         ATRACE_NAME("CompositionStrategyPredictionHit");
1136     }
1137     state.previousDeviceRequestedChanges = std::move(changes);
1138     state.previousDeviceRequestedSuccess = chooseCompositionSuccess;
1139     return compositionResult;
1140 }
1141 
devOptRepaintFlash(const compositionengine::CompositionRefreshArgs & refreshArgs)1142 void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
1143     if (CC_LIKELY(!refreshArgs.devOptFlashDirtyRegionsDelay)) {
1144         return;
1145     }
1146 
1147     if (getState().isEnabled) {
1148         if (const auto dirtyRegion = getDirtyRegion(); !dirtyRegion.isEmpty()) {
1149             base::unique_fd bufferFence;
1150             std::shared_ptr<renderengine::ExternalTexture> buffer;
1151             updateProtectedContentState();
1152             dequeueRenderBuffer(&bufferFence, &buffer);
1153             static_cast<void>(composeSurfaces(dirtyRegion, buffer, bufferFence));
1154             mRenderSurface->queueBuffer(base::unique_fd());
1155         }
1156     }
1157 
1158     postFramebuffer();
1159 
1160     std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay);
1161 
1162     prepareFrame();
1163 }
1164 
finishFrame(GpuCompositionResult && result)1165 void Output::finishFrame(GpuCompositionResult&& result) {
1166     ATRACE_CALL();
1167     ALOGV(__FUNCTION__);
1168     const auto& outputState = getState();
1169     if (!outputState.isEnabled) {
1170         return;
1171     }
1172 
1173     std::optional<base::unique_fd> optReadyFence;
1174     std::shared_ptr<renderengine::ExternalTexture> buffer;
1175     base::unique_fd bufferFence;
1176     if (outputState.strategyPrediction == CompositionStrategyPredictionState::SUCCESS) {
1177         optReadyFence = std::move(result.fence);
1178     } else {
1179         if (result.bufferAvailable()) {
1180             buffer = std::move(result.buffer);
1181             bufferFence = std::move(result.fence);
1182         } else {
1183             updateProtectedContentState();
1184             if (!dequeueRenderBuffer(&bufferFence, &buffer)) {
1185                 return;
1186             }
1187         }
1188         // Repaint the framebuffer (if needed), getting the optional fence for when
1189         // the composition completes.
1190         optReadyFence = composeSurfaces(Region::INVALID_REGION, buffer, bufferFence);
1191     }
1192     if (!optReadyFence) {
1193         return;
1194     }
1195 
1196     if (isPowerHintSessionEnabled()) {
1197         // get fence end time to know when gpu is complete in display
1198         setHintSessionGpuFence(
1199                 std::make_unique<FenceTime>(sp<Fence>::make(dup(optReadyFence->get()))));
1200     }
1201     // swap buffers (presentation)
1202     mRenderSurface->queueBuffer(std::move(*optReadyFence));
1203 }
1204 
updateProtectedContentState()1205 void Output::updateProtectedContentState() {
1206     const auto& outputState = getState();
1207     auto& renderEngine = getCompositionEngine().getRenderEngine();
1208     const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
1209 
1210     // If we the display is secure, protected content support is enabled, and at
1211     // least one layer has protected content, we need to use a secure back
1212     // buffer.
1213     if (outputState.isSecure && supportsProtectedContent) {
1214         auto layers = getOutputLayersOrderedByZ();
1215         bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
1216             return layer->getLayerFE().getCompositionState()->hasProtectedContent;
1217         });
1218         if (needsProtected != mRenderSurface->isProtected()) {
1219             mRenderSurface->setProtected(needsProtected);
1220         }
1221     }
1222 }
1223 
dequeueRenderBuffer(base::unique_fd * bufferFence,std::shared_ptr<renderengine::ExternalTexture> * tex)1224 bool Output::dequeueRenderBuffer(base::unique_fd* bufferFence,
1225                                  std::shared_ptr<renderengine::ExternalTexture>* tex) {
1226     const auto& outputState = getState();
1227 
1228     // If we aren't doing client composition on this output, but do have a
1229     // flipClientTarget request for this frame on this output, we still need to
1230     // dequeue a buffer.
1231     if (outputState.usesClientComposition || outputState.flipClientTarget) {
1232         *tex = mRenderSurface->dequeueBuffer(bufferFence);
1233         if (*tex == nullptr) {
1234             ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
1235                   "client composition for this frame",
1236                   mName.c_str());
1237             return false;
1238         }
1239     }
1240     return true;
1241 }
1242 
composeSurfaces(const Region & debugRegion,std::shared_ptr<renderengine::ExternalTexture> tex,base::unique_fd & fd)1243 std::optional<base::unique_fd> Output::composeSurfaces(
1244         const Region& debugRegion, std::shared_ptr<renderengine::ExternalTexture> tex,
1245         base::unique_fd& fd) {
1246     ATRACE_CALL();
1247     ALOGV(__FUNCTION__);
1248 
1249     const auto& outputState = getState();
1250     const TracedOrdinal<bool> hasClientComposition = {
1251         base::StringPrintf("hasClientComposition %s", mNamePlusId.c_str()),
1252         outputState.usesClientComposition};
1253     if (!hasClientComposition) {
1254         setExpensiveRenderingExpected(false);
1255         return base::unique_fd();
1256     }
1257 
1258     if (tex == nullptr) {
1259         ALOGW("Buffer not valid for display [%s], bailing out of "
1260               "client composition for this frame",
1261               mName.c_str());
1262         return {};
1263     }
1264 
1265     ALOGV("hasClientComposition");
1266 
1267     renderengine::DisplaySettings clientCompositionDisplay =
1268             generateClientCompositionDisplaySettings();
1269 
1270     // Generate the client composition requests for the layers on this output.
1271     auto& renderEngine = getCompositionEngine().getRenderEngine();
1272     const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
1273     std::vector<LayerFE*> clientCompositionLayersFE;
1274     std::vector<LayerFE::LayerSettings> clientCompositionLayers =
1275             generateClientCompositionRequests(supportsProtectedContent,
1276                                               clientCompositionDisplay.outputDataspace,
1277                                               clientCompositionLayersFE);
1278     appendRegionFlashRequests(debugRegion, clientCompositionLayers);
1279 
1280     OutputCompositionState& outputCompositionState = editState();
1281     // Check if the client composition requests were rendered into the provided graphic buffer. If
1282     // so, we can reuse the buffer and avoid client composition.
1283     if (mClientCompositionRequestCache) {
1284         if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(),
1285                                                    clientCompositionDisplay,
1286                                                    clientCompositionLayers)) {
1287             ATRACE_NAME("ClientCompositionCacheHit");
1288             outputCompositionState.reusedClientComposition = true;
1289             setExpensiveRenderingExpected(false);
1290             // b/239944175 pass the fence associated with the buffer.
1291             return base::unique_fd(std::move(fd));
1292         }
1293         ATRACE_NAME("ClientCompositionCacheMiss");
1294         mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay,
1295                                             clientCompositionLayers);
1296     }
1297 
1298     // We boost GPU frequency here because there will be color spaces conversion
1299     // or complex GPU shaders and it's expensive. We boost the GPU frequency so that
1300     // GPU composition can finish in time. We must reset GPU frequency afterwards,
1301     // because high frequency consumes extra battery.
1302     const bool expensiveRenderingExpected =
1303             std::any_of(clientCompositionLayers.begin(), clientCompositionLayers.end(),
1304                         [outputDataspace =
1305                                  clientCompositionDisplay.outputDataspace](const auto& layer) {
1306                             return layer.sourceDataspace != outputDataspace;
1307                         });
1308     if (expensiveRenderingExpected) {
1309         setExpensiveRenderingExpected(true);
1310     }
1311 
1312     std::vector<renderengine::LayerSettings> clientRenderEngineLayers;
1313     clientRenderEngineLayers.reserve(clientCompositionLayers.size());
1314     std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(),
1315                    std::back_inserter(clientRenderEngineLayers),
1316                    [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings {
1317                        return settings;
1318                    });
1319 
1320     const nsecs_t renderEngineStart = systemTime();
1321     // Only use the framebuffer cache when rendering to an internal display
1322     // TODO(b/173560331): This is only to help mitigate memory leaks from virtual displays because
1323     // right now we don't have a concrete eviction policy for output buffers: GLESRenderEngine
1324     // bounds its framebuffer cache but Skia RenderEngine has no current policy. The best fix is
1325     // probably to encapsulate the output buffer into a structure that dispatches resource cleanup
1326     // over to RenderEngine, in which case this flag can be removed from the drawLayers interface.
1327     const bool useFramebufferCache = outputState.layerFilter.toInternalDisplay;
1328 
1329     auto fenceResult = renderEngine
1330                                .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, tex,
1331                                            useFramebufferCache, std::move(fd))
1332                                .get();
1333 
1334     if (mClientCompositionRequestCache && fenceStatus(fenceResult) != NO_ERROR) {
1335         // If rendering was not successful, remove the request from the cache.
1336         mClientCompositionRequestCache->remove(tex->getBuffer()->getId());
1337     }
1338 
1339     const auto fence = std::move(fenceResult).value_or(Fence::NO_FENCE);
1340 
1341     if (auto timeStats = getCompositionEngine().getTimeStats()) {
1342         if (fence->isValid()) {
1343             timeStats->recordRenderEngineDuration(renderEngineStart,
1344                                                   std::make_shared<FenceTime>(fence));
1345         } else {
1346             timeStats->recordRenderEngineDuration(renderEngineStart, systemTime());
1347         }
1348     }
1349 
1350     for (auto* clientComposedLayer : clientCompositionLayersFE) {
1351         clientComposedLayer->setWasClientComposed(fence);
1352     }
1353 
1354     return base::unique_fd(fence->dup());
1355 }
1356 
generateClientCompositionDisplaySettings() const1357 renderengine::DisplaySettings Output::generateClientCompositionDisplaySettings() const {
1358     const auto& outputState = getState();
1359 
1360     renderengine::DisplaySettings clientCompositionDisplay;
1361     clientCompositionDisplay.namePlusId = mNamePlusId;
1362     clientCompositionDisplay.physicalDisplay = outputState.framebufferSpace.getContent();
1363     clientCompositionDisplay.clip = outputState.layerStackSpace.getContent();
1364     clientCompositionDisplay.orientation =
1365             ui::Transform::toRotationFlags(outputState.displaySpace.getOrientation());
1366     clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
1367             ? outputState.dataspace
1368             : ui::Dataspace::UNKNOWN;
1369 
1370     // If we have a valid current display brightness use that, otherwise fall back to the
1371     // display's max desired
1372     clientCompositionDisplay.currentLuminanceNits = outputState.displayBrightnessNits > 0.f
1373             ? outputState.displayBrightnessNits
1374             : mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
1375     clientCompositionDisplay.maxLuminance =
1376             mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
1377     clientCompositionDisplay.targetLuminanceNits =
1378             outputState.clientTargetBrightness * outputState.displayBrightnessNits;
1379     clientCompositionDisplay.dimmingStage = outputState.clientTargetDimmingStage;
1380     clientCompositionDisplay.renderIntent =
1381             static_cast<aidl::android::hardware::graphics::composer3::RenderIntent>(
1382                     outputState.renderIntent);
1383 
1384     // Compute the global color transform matrix.
1385     clientCompositionDisplay.colorTransform = outputState.colorTransformMatrix;
1386     for (auto& info : outputState.borderInfoList) {
1387         renderengine::BorderRenderInfo borderInfo;
1388         borderInfo.width = info.width;
1389         borderInfo.color = info.color;
1390         borderInfo.combinedRegion = info.combinedRegion;
1391         clientCompositionDisplay.borderInfoList.emplace_back(std::move(borderInfo));
1392     }
1393     clientCompositionDisplay.deviceHandlesColorTransform =
1394             outputState.usesDeviceComposition || getSkipColorTransform();
1395     return clientCompositionDisplay;
1396 }
1397 
generateClientCompositionRequests(bool supportsProtectedContent,ui::Dataspace outputDataspace,std::vector<LayerFE * > & outLayerFEs)1398 std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests(
1399       bool supportsProtectedContent, ui::Dataspace outputDataspace, std::vector<LayerFE*>& outLayerFEs) {
1400     std::vector<LayerFE::LayerSettings> clientCompositionLayers;
1401     ALOGV("Rendering client layers");
1402 
1403     const auto& outputState = getState();
1404     const Region viewportRegion(outputState.layerStackSpace.getContent());
1405     bool firstLayer = true;
1406 
1407     bool disableBlurs = false;
1408     uint64_t previousOverrideBufferId = 0;
1409 
1410     for (auto* layer : getOutputLayersOrderedByZ()) {
1411         const auto& layerState = layer->getState();
1412         const auto* layerFEState = layer->getLayerFE().getCompositionState();
1413         auto& layerFE = layer->getLayerFE();
1414         layerFE.setWasClientComposed(nullptr);
1415 
1416         const Region clip(viewportRegion.intersect(layerState.visibleRegion));
1417         ALOGV("Layer: %s", layerFE.getDebugName());
1418         if (clip.isEmpty()) {
1419             ALOGV("  Skipping for empty clip");
1420             firstLayer = false;
1421             continue;
1422         }
1423 
1424         disableBlurs |= layerFEState->sidebandStream != nullptr;
1425 
1426         const bool clientComposition = layer->requiresClientComposition();
1427 
1428         // We clear the client target for non-client composed layers if
1429         // requested by the HWC. We skip this if the layer is not an opaque
1430         // rectangle, as by definition the layer must blend with whatever is
1431         // underneath. We also skip the first layer as the buffer target is
1432         // guaranteed to start out cleared.
1433         const bool clearClientComposition =
1434                 layerState.clearClientTarget && layerFEState->isOpaque && !firstLayer;
1435 
1436         ALOGV("  Composition type: client %d clear %d", clientComposition, clearClientComposition);
1437 
1438         // If the layer casts a shadow but the content casting the shadow is occluded, skip
1439         // composing the non-shadow content and only draw the shadows.
1440         const bool realContentIsVisible = clientComposition &&
1441                 !layerState.visibleRegion.subtract(layerState.shadowRegion).isEmpty();
1442 
1443         if (clientComposition || clearClientComposition) {
1444             if (auto overrideSettings = layer->getOverrideCompositionSettings()) {
1445                 if (overrideSettings->bufferId != previousOverrideBufferId) {
1446                     previousOverrideBufferId = overrideSettings->bufferId;
1447                     clientCompositionLayers.push_back(std::move(*overrideSettings));
1448                     ALOGV("Replacing [%s] with override in RE", layer->getLayerFE().getDebugName());
1449                 } else {
1450                     ALOGV("Skipping redundant override buffer for [%s] in RE",
1451                           layer->getLayerFE().getDebugName());
1452                 }
1453             } else {
1454                 LayerFE::ClientCompositionTargetSettings::BlurSetting blurSetting = disableBlurs
1455                         ? LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled
1456                         : (layer->getState().overrideInfo.disableBackgroundBlur
1457                                    ? LayerFE::ClientCompositionTargetSettings::BlurSetting::
1458                                              BlurRegionsOnly
1459                                    : LayerFE::ClientCompositionTargetSettings::BlurSetting::
1460                                              Enabled);
1461                 compositionengine::LayerFE::ClientCompositionTargetSettings
1462                         targetSettings{.clip = clip,
1463                                        .needsFiltering = layer->needsFiltering() ||
1464                                                outputState.needsFiltering,
1465                                        .isSecure = outputState.isSecure,
1466                                        .supportsProtectedContent = supportsProtectedContent,
1467                                        .viewport = outputState.layerStackSpace.getContent(),
1468                                        .dataspace = outputDataspace,
1469                                        .realContentIsVisible = realContentIsVisible,
1470                                        .clearContent = !clientComposition,
1471                                        .blurSetting = blurSetting,
1472                                        .whitePointNits = layerState.whitePointNits,
1473                                        .treat170mAsSrgb = outputState.treat170mAsSrgb};
1474                 if (auto clientCompositionSettings =
1475                             layerFE.prepareClientComposition(targetSettings)) {
1476                     clientCompositionLayers.push_back(std::move(*clientCompositionSettings));
1477                     if (realContentIsVisible) {
1478                         layer->editState().clientCompositionTimestamp = systemTime();
1479                     }
1480                 }
1481             }
1482 
1483             if (clientComposition) {
1484                 outLayerFEs.push_back(&layerFE);
1485             }
1486         }
1487 
1488         firstLayer = false;
1489     }
1490 
1491     return clientCompositionLayers;
1492 }
1493 
appendRegionFlashRequests(const Region & flashRegion,std::vector<LayerFE::LayerSettings> & clientCompositionLayers)1494 void Output::appendRegionFlashRequests(
1495         const Region& flashRegion, std::vector<LayerFE::LayerSettings>& clientCompositionLayers) {
1496     if (flashRegion.isEmpty()) {
1497         return;
1498     }
1499 
1500     LayerFE::LayerSettings layerSettings;
1501     layerSettings.source.buffer.buffer = nullptr;
1502     layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
1503     layerSettings.alpha = half(1.0);
1504 
1505     for (const auto& rect : flashRegion) {
1506         layerSettings.geometry.boundaries = rect.toFloatRect();
1507         clientCompositionLayers.push_back(layerSettings);
1508     }
1509 }
1510 
setExpensiveRenderingExpected(bool)1511 void Output::setExpensiveRenderingExpected(bool) {
1512     // The base class does nothing with this call.
1513 }
1514 
setHintSessionGpuFence(std::unique_ptr<FenceTime> &&)1515 void Output::setHintSessionGpuFence(std::unique_ptr<FenceTime>&&) {
1516     // The base class does nothing with this call.
1517 }
1518 
isPowerHintSessionEnabled()1519 bool Output::isPowerHintSessionEnabled() {
1520     return false;
1521 }
1522 
postFramebuffer()1523 void Output::postFramebuffer() {
1524     ATRACE_FORMAT("%s for %s", __func__, mNamePlusId.c_str());
1525     ALOGV(__FUNCTION__);
1526 
1527     if (!getState().isEnabled) {
1528         return;
1529     }
1530 
1531     auto& outputState = editState();
1532     outputState.dirtyRegion.clear();
1533 
1534     auto frame = presentAndGetFrameFences();
1535 
1536     mRenderSurface->onPresentDisplayCompleted();
1537 
1538     for (auto* layer : getOutputLayersOrderedByZ()) {
1539         // The layer buffer from the previous frame (if any) is released
1540         // by HWC only when the release fence from this frame (if any) is
1541         // signaled.  Always get the release fence from HWC first.
1542         sp<Fence> releaseFence = Fence::NO_FENCE;
1543 
1544         if (auto hwcLayer = layer->getHwcLayer()) {
1545             if (auto f = frame.layerFences.find(hwcLayer); f != frame.layerFences.end()) {
1546                 releaseFence = f->second;
1547             }
1548         }
1549 
1550         // If the layer was client composited in the previous frame, we
1551         // need to merge with the previous client target acquire fence.
1552         // Since we do not track that, always merge with the current
1553         // client target acquire fence when it is available, even though
1554         // this is suboptimal.
1555         // TODO(b/121291683): Track previous frame client target acquire fence.
1556         if (outputState.usesClientComposition) {
1557             releaseFence =
1558                     Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
1559         }
1560         layer->getLayerFE()
1561                 .onLayerDisplayed(ftl::yield<FenceResult>(std::move(releaseFence)).share(),
1562                                   outputState.layerFilter.layerStack);
1563     }
1564 
1565     // We've got a list of layers needing fences, that are disjoint with
1566     // OutputLayersOrderedByZ.  The best we can do is to
1567     // supply them with the present fence.
1568     for (auto& weakLayer : mReleasedLayers) {
1569         if (const auto layer = weakLayer.promote()) {
1570             layer->onLayerDisplayed(ftl::yield<FenceResult>(frame.presentFence).share(),
1571                                     outputState.layerFilter.layerStack);
1572         }
1573     }
1574 
1575     // Clear out the released layers now that we're done with them.
1576     mReleasedLayers.clear();
1577 }
1578 
renderCachedSets(const CompositionRefreshArgs & refreshArgs)1579 void Output::renderCachedSets(const CompositionRefreshArgs& refreshArgs) {
1580     const auto& outputState = getState();
1581     if (mPlanner && outputState.isEnabled) {
1582         mPlanner->renderCachedSets(outputState, refreshArgs.scheduledFrameTime,
1583                                    outputState.usesDeviceComposition || getSkipColorTransform());
1584     }
1585 }
1586 
dirtyEntireOutput()1587 void Output::dirtyEntireOutput() {
1588     auto& outputState = editState();
1589     outputState.dirtyRegion.set(outputState.displaySpace.getBoundsAsRect());
1590 }
1591 
resetCompositionStrategy()1592 void Output::resetCompositionStrategy() {
1593     // The base output implementation can only do client composition
1594     auto& outputState = editState();
1595     outputState.usesClientComposition = true;
1596     outputState.usesDeviceComposition = false;
1597     outputState.reusedClientComposition = false;
1598 }
1599 
getSkipColorTransform() const1600 bool Output::getSkipColorTransform() const {
1601     return true;
1602 }
1603 
presentAndGetFrameFences()1604 compositionengine::Output::FrameFences Output::presentAndGetFrameFences() {
1605     compositionengine::Output::FrameFences result;
1606     if (getState().usesClientComposition) {
1607         result.clientTargetAcquireFence = mRenderSurface->getClientTargetAcquireFence();
1608     }
1609     return result;
1610 }
1611 
setPredictCompositionStrategy(bool predict)1612 void Output::setPredictCompositionStrategy(bool predict) {
1613     if (predict) {
1614         mHwComposerAsyncWorker = std::make_unique<HwcAsyncWorker>();
1615     } else {
1616         mHwComposerAsyncWorker.reset(nullptr);
1617     }
1618 }
1619 
setTreat170mAsSrgb(bool enable)1620 void Output::setTreat170mAsSrgb(bool enable) {
1621     editState().treat170mAsSrgb = enable;
1622 }
1623 
canPredictCompositionStrategy(const CompositionRefreshArgs & refreshArgs)1624 bool Output::canPredictCompositionStrategy(const CompositionRefreshArgs& refreshArgs) {
1625     uint64_t lastOutputLayerHash = getState().lastOutputLayerHash;
1626     uint64_t outputLayerHash = getState().outputLayerHash;
1627     editState().lastOutputLayerHash = outputLayerHash;
1628 
1629     if (!getState().isEnabled || !mHwComposerAsyncWorker) {
1630         ALOGV("canPredictCompositionStrategy disabled");
1631         return false;
1632     }
1633 
1634     if (!getState().previousDeviceRequestedChanges) {
1635         ALOGV("canPredictCompositionStrategy previous changes not available");
1636         return false;
1637     }
1638 
1639     if (!mRenderSurface->supportsCompositionStrategyPrediction()) {
1640         ALOGV("canPredictCompositionStrategy surface does not support");
1641         return false;
1642     }
1643 
1644     if (refreshArgs.devOptFlashDirtyRegionsDelay) {
1645         ALOGV("canPredictCompositionStrategy devOptFlashDirtyRegionsDelay");
1646         return false;
1647     }
1648 
1649     if (lastOutputLayerHash != outputLayerHash) {
1650         ALOGV("canPredictCompositionStrategy output layers changed");
1651         return false;
1652     }
1653 
1654     // If no layer uses clientComposition, then don't predict composition strategy
1655     // because we have less work to do in parallel.
1656     if (!anyLayersRequireClientComposition()) {
1657         ALOGV("canPredictCompositionStrategy no layer uses clientComposition");
1658         return false;
1659     }
1660 
1661     return true;
1662 }
1663 
anyLayersRequireClientComposition() const1664 bool Output::anyLayersRequireClientComposition() const {
1665     const auto layers = getOutputLayersOrderedByZ();
1666     return std::any_of(layers.begin(), layers.end(),
1667                        [](const auto& layer) { return layer->requiresClientComposition(); });
1668 }
1669 
finishPrepareFrame()1670 void Output::finishPrepareFrame() {
1671     const auto& state = getState();
1672     if (mPlanner) {
1673         mPlanner->reportFinalPlan(getOutputLayersOrderedByZ());
1674     }
1675     mRenderSurface->prepareFrame(state.usesClientComposition, state.usesDeviceComposition);
1676 }
1677 
mustRecompose() const1678 bool Output::mustRecompose() const {
1679     return mMustRecompose;
1680 }
1681 
1682 } // namespace impl
1683 } // namespace android::compositionengine
1684