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