xref: /aosp_15_r20/frameworks/native/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <DisplayHardware/Hal.h>
18 #include <android-base/stringprintf.h>
19 #include <compositionengine/DisplayColorProfile.h>
20 #include <compositionengine/LayerFECompositionState.h>
21 #include <compositionengine/Output.h>
22 #include <compositionengine/impl/HwcBufferCache.h>
23 #include <compositionengine/impl/OutputCompositionState.h>
24 #include <compositionengine/impl/OutputLayer.h>
25 #include <compositionengine/impl/OutputLayerCompositionState.h>
26 #include <ui/FloatRect.h>
27 #include <ui/HdrRenderTypeUtils.h>
28 #include <cstdint>
29 #include <limits>
30 #include "system/graphics-base-v1.0.h"
31 
32 #include <com_android_graphics_libgui_flags.h>
33 
34 // TODO(b/129481165): remove the #pragma below and fix conversion issues
35 #pragma clang diagnostic push
36 #pragma clang diagnostic ignored "-Wconversion"
37 
38 #include "DisplayHardware/HWComposer.h"
39 
40 // TODO(b/129481165): remove the #pragma below and fix conversion issues
41 #pragma clang diagnostic pop // ignored "-Wconversion"
42 
43 using aidl::android::hardware::graphics::composer3::Composition;
44 using aidl::android::hardware::graphics::composer3::Luts;
45 
46 namespace android::compositionengine {
47 
48 OutputLayer::~OutputLayer() = default;
49 
50 namespace impl {
51 
52 namespace {
53 
reduce(const FloatRect & win,const Region & exclude)54 FloatRect reduce(const FloatRect& win, const Region& exclude) {
55     if (CC_LIKELY(exclude.isEmpty())) {
56         return win;
57     }
58     // Convert through Rect (by rounding) for lack of FloatRegion
59     return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect();
60 }
61 
62 } // namespace
63 
createOutputLayer(const compositionengine::Output & output,const sp<compositionengine::LayerFE> & layerFE)64 std::unique_ptr<OutputLayer> createOutputLayer(const compositionengine::Output& output,
65                                                const sp<compositionengine::LayerFE>& layerFE) {
66     return createOutputLayerTemplated<OutputLayer>(output, layerFE);
67 }
68 
69 OutputLayer::~OutputLayer() = default;
70 
setHwcLayer(std::shared_ptr<HWC2::Layer> hwcLayer)71 void OutputLayer::setHwcLayer(std::shared_ptr<HWC2::Layer> hwcLayer) {
72     auto& state = editState();
73     if (hwcLayer) {
74         state.hwc.emplace(std::move(hwcLayer));
75     } else {
76         state.hwc.reset();
77     }
78 }
79 
calculateInitialCrop() const80 Rect OutputLayer::calculateInitialCrop() const {
81     const auto& layerState = *getLayerFE().getCompositionState();
82 
83     // apply the projection's clipping to the window crop in
84     // layerstack space, and convert-back to layer space.
85     // if there are no window scaling involved, this operation will map to full
86     // pixels in the buffer.
87 
88     FloatRect activeCropFloat =
89             reduce(layerState.geomLayerBounds, layerState.transparentRegionHint);
90 
91     const Rect& viewport = getOutput().getState().layerStackSpace.getContent();
92     const ui::Transform& layerTransform = layerState.geomLayerTransform;
93     const ui::Transform& inverseLayerTransform = layerState.geomInverseLayerTransform;
94     // Transform to screen space.
95     activeCropFloat = layerTransform.transform(activeCropFloat);
96     activeCropFloat = activeCropFloat.intersect(viewport.toFloatRect());
97     // Back to layer space to work with the content crop.
98     activeCropFloat = inverseLayerTransform.transform(activeCropFloat);
99 
100     // This needs to be here as transform.transform(Rect) computes the
101     // transformed rect and then takes the bounding box of the result before
102     // returning. This means
103     // transform.inverse().transform(transform.transform(Rect)) != Rect
104     // in which case we need to make sure the final rect is clipped to the
105     // display bounds.
106     Rect activeCrop{activeCropFloat};
107     if (!activeCrop.intersect(layerState.geomBufferSize, &activeCrop)) {
108         activeCrop.clear();
109     }
110     return activeCrop;
111 }
112 
calculateOutputSourceCrop(uint32_t internalDisplayRotationFlags) const113 FloatRect OutputLayer::calculateOutputSourceCrop(uint32_t internalDisplayRotationFlags) const {
114     const auto& layerState = *getLayerFE().getCompositionState();
115 
116     if (!layerState.geomUsesSourceCrop) {
117         return {};
118     }
119 
120     // the content crop is the area of the content that gets scaled to the
121     // layer's size. This is in buffer space.
122     FloatRect crop = layerState.geomContentCrop.toFloatRect();
123 
124     // In addition there is a WM-specified crop we pull from our drawing state.
125     Rect activeCrop = calculateInitialCrop();
126     const Rect& bufferSize = layerState.geomBufferSize;
127 
128     int winWidth = bufferSize.getWidth();
129     int winHeight = bufferSize.getHeight();
130 
131     // The bufferSize for buffer state layers can be unbounded ([0, 0, -1, -1])
132     // if display frame hasn't been set and the parent is an unbounded layer.
133     if (winWidth < 0 && winHeight < 0) {
134         return crop;
135     }
136 
137     // Transform the window crop to match the buffer coordinate system,
138     // which means using the inverse of the current transform set on the
139     // SurfaceFlingerConsumer.
140     uint32_t invTransform = layerState.geomBufferTransform;
141     if (layerState.geomBufferUsesDisplayInverseTransform) {
142         /*
143          * the code below applies the primary display's inverse transform to the
144          * buffer
145          */
146         uint32_t invTransformOrient = internalDisplayRotationFlags;
147         // calculate the inverse transform
148         if (invTransformOrient & HAL_TRANSFORM_ROT_90) {
149             invTransformOrient ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
150         }
151         // and apply to the current transform
152         invTransform =
153                 (ui::Transform(invTransformOrient) * ui::Transform(invTransform)).getOrientation();
154     }
155 
156     if (invTransform & HAL_TRANSFORM_ROT_90) {
157         // If the activeCrop has been rotate the ends are rotated but not
158         // the space itself so when transforming ends back we can't rely on
159         // a modification of the axes of rotation. To account for this we
160         // need to reorient the inverse rotation in terms of the current
161         // axes of rotation.
162         bool isHFlipped = (invTransform & HAL_TRANSFORM_FLIP_H) != 0;
163         bool isVFlipped = (invTransform & HAL_TRANSFORM_FLIP_V) != 0;
164         if (isHFlipped == isVFlipped) {
165             invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
166         }
167         std::swap(winWidth, winHeight);
168     }
169     const Rect winCrop =
170             activeCrop.transform(invTransform, bufferSize.getWidth(), bufferSize.getHeight());
171 
172     // below, crop is intersected with winCrop expressed in crop's coordinate space
173     const float xScale = crop.getWidth() / float(winWidth);
174     const float yScale = crop.getHeight() / float(winHeight);
175 
176     const float insetLeft = winCrop.left * xScale;
177     const float insetTop = winCrop.top * yScale;
178     const float insetRight = (winWidth - winCrop.right) * xScale;
179     const float insetBottom = (winHeight - winCrop.bottom) * yScale;
180 
181     crop.left += insetLeft;
182     crop.top += insetTop;
183     crop.right -= insetRight;
184     crop.bottom -= insetBottom;
185 
186     return crop;
187 }
188 
calculateOutputDisplayFrame() const189 Rect OutputLayer::calculateOutputDisplayFrame() const {
190     const auto& layerState = *getLayerFE().getCompositionState();
191     const auto& outputState = getOutput().getState();
192 
193     // Convert from layer space to layerStackSpace
194     // apply the layer's transform, followed by the display's global transform
195     // here we're guaranteed that the layer's transform preserves rects
196     const ui::Transform& layerTransform = layerState.geomLayerTransform;
197     Region activeTransparentRegion = layerTransform.transform(layerState.transparentRegionHint);
198     if (!layerState.geomCrop.isEmpty() && layerState.geomBufferSize.isValid()) {
199         FloatRect activeCrop = layerTransform.transform(layerState.geomCrop);
200         activeCrop = activeCrop.intersect(outputState.layerStackSpace.getContent().toFloatRect());
201         const FloatRect& bufferSize =
202                 layerTransform.transform(layerState.geomBufferSize.toFloatRect());
203         activeCrop = activeCrop.intersect(bufferSize);
204 
205         // mark regions outside the crop as transparent
206         Rect topRegion = Rect(layerTransform.transform(
207                 FloatRect(0, 0, layerState.geomBufferSize.getWidth(), layerState.geomCrop.top)));
208         Rect bottomRegion = Rect(layerTransform.transform(
209                 FloatRect(0, layerState.geomCrop.bottom, layerState.geomBufferSize.getWidth(),
210                           layerState.geomBufferSize.getHeight())));
211         Rect leftRegion = Rect(layerTransform.transform(FloatRect(0, layerState.geomCrop.top,
212                                                                  layerState.geomCrop.left,
213                                                                  layerState.geomCrop.bottom)));
214         Rect rightRegion = Rect(layerTransform.transform(
215                 FloatRect(layerState.geomCrop.right, layerState.geomCrop.top,
216                           layerState.geomBufferSize.getWidth(), layerState.geomCrop.bottom)));
217 
218         activeTransparentRegion.orSelf(topRegion);
219         activeTransparentRegion.orSelf(bottomRegion);
220         activeTransparentRegion.orSelf(leftRegion);
221         activeTransparentRegion.orSelf(rightRegion);
222     }
223 
224     // reduce uses a FloatRect to provide more accuracy during the
225     // transformation. We then round upon constructing 'frame'.
226     FloatRect geomLayerBounds = layerState.geomLayerBounds;
227 
228     // Some HWCs may clip client composited input to its displayFrame. Make sure
229     // that this does not cut off the shadow.
230     if (layerState.forceClientComposition && layerState.shadowSettings.length > 0.0f) {
231         // RenderEngine currently blurs shadows to smooth out edges, so outset by
232         // 2x the length instead of 1x to compensate
233         const auto outset = layerState.shadowSettings.length * 2;
234         geomLayerBounds.left -= outset;
235         geomLayerBounds.top -= outset;
236         geomLayerBounds.right += outset;
237         geomLayerBounds.bottom += outset;
238     }
239 
240     geomLayerBounds = layerTransform.transform(geomLayerBounds);
241     FloatRect frame = reduce(geomLayerBounds, activeTransparentRegion);
242     frame = frame.intersect(outputState.layerStackSpace.getContent().toFloatRect());
243 
244     // convert from layerStackSpace to displaySpace
245     const ui::Transform displayTransform{outputState.transform};
246     return Rect(displayTransform.transform(frame));
247 }
248 
calculateOutputRelativeBufferTransform(uint32_t internalDisplayRotationFlags) const249 uint32_t OutputLayer::calculateOutputRelativeBufferTransform(
250         uint32_t internalDisplayRotationFlags) const {
251     const auto& layerState = *getLayerFE().getCompositionState();
252     const auto& outputState = getOutput().getState();
253 
254     /*
255      * Transformations are applied in this order:
256      * 1) buffer orientation/flip/mirror
257      * 2) state transformation (window manager)
258      * 3) layer orientation (screen orientation)
259      * (NOTE: the matrices are multiplied in reverse order)
260      */
261     const ui::Transform& layerTransform = layerState.geomLayerTransform;
262     const ui::Transform displayTransform{outputState.transform};
263     const ui::Transform bufferTransform{layerState.geomBufferTransform};
264     ui::Transform transform(displayTransform * layerTransform * bufferTransform);
265 
266     if (layerState.geomBufferUsesDisplayInverseTransform) {
267         /*
268          * We must apply the internal display's inverse transform to the buffer
269          * transform, and not the one for the output this layer is on.
270          */
271         uint32_t invTransform = internalDisplayRotationFlags;
272 
273         // calculate the inverse transform
274         if (invTransform & HAL_TRANSFORM_ROT_90) {
275             invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
276         }
277 
278         /*
279          * Here we cancel out the orientation component of the WM transform.
280          * The scaling and translate components are already included in our bounds
281          * computation so it's enough to just omit it in the composition.
282          * See comment in BufferLayer::prepareClientLayer with ref to b/36727915 for why.
283          */
284         transform = ui::Transform(invTransform) * displayTransform * bufferTransform;
285     }
286 
287     // this gives us only the "orientation" component of the transform
288     return transform.getOrientation();
289 }
290 
updateLuts(const LayerFECompositionState & layerFEState,const std::optional<std::vector<std::optional<LutProperties>>> & properties)291 void OutputLayer::updateLuts(
292         const LayerFECompositionState& layerFEState,
293         const std::optional<std::vector<std::optional<LutProperties>>>& properties) {
294     auto& luts = layerFEState.luts;
295     if (!luts) {
296         return;
297     }
298 
299     auto& state = editState();
300 
301     if (!properties) {
302         // GPU composition if no Hwc Luts
303         state.forceClientComposition = true;
304         return;
305     }
306 
307     std::vector<LutProperties> hwcLutProperties;
308     for (auto& p : *properties) {
309         if (p) {
310             hwcLutProperties.emplace_back(*p);
311         }
312     }
313 
314     for (const auto& inputLut : luts->lutProperties) {
315         bool foundInHwcLuts = false;
316         for (const auto& hwcLut : hwcLutProperties) {
317             if (static_cast<int32_t>(hwcLut.dimension) ==
318                         static_cast<int32_t>(inputLut.dimension) &&
319                 hwcLut.size == inputLut.size &&
320                 std::find(hwcLut.samplingKeys.begin(), hwcLut.samplingKeys.end(),
321                           static_cast<LutProperties::SamplingKey>(inputLut.samplingKey)) !=
322                         hwcLut.samplingKeys.end()) {
323                 foundInHwcLuts = true;
324                 break;
325             }
326         }
327         // if any lut properties of luts can not be found in hwcLutProperties,
328         // GPU composition instead
329         if (!foundInHwcLuts) {
330             state.forceClientComposition = true;
331             return;
332         }
333     }
334 }
335 
updateCompositionState(bool includeGeometry,bool forceClientComposition,ui::Transform::RotationFlags internalDisplayRotationFlags,const std::optional<std::vector<std::optional<LutProperties>>> properties)336 void OutputLayer::updateCompositionState(
337         bool includeGeometry, bool forceClientComposition,
338         ui::Transform::RotationFlags internalDisplayRotationFlags,
339         const std::optional<std::vector<std::optional<LutProperties>>> properties) {
340     const auto* layerFEState = getLayerFE().getCompositionState();
341     if (!layerFEState) {
342         return;
343     }
344 
345     const auto& outputState = getOutput().getState();
346     const auto& profile = *getOutput().getDisplayColorProfile();
347     auto& state = editState();
348 
349     if (includeGeometry) {
350         // Clear the forceClientComposition flag before it is set for any
351         // reason. Note that since it can be set by some checks below when
352         // updating the geometry state, we only clear it when updating the
353         // geometry since those conditions for forcing client composition won't
354         // go away otherwise.
355         state.forceClientComposition = false;
356 
357         state.displayFrame = calculateOutputDisplayFrame();
358         state.sourceCrop = calculateOutputSourceCrop(internalDisplayRotationFlags);
359         state.bufferTransform = static_cast<Hwc2::Transform>(
360                 calculateOutputRelativeBufferTransform(internalDisplayRotationFlags));
361 
362         if ((layerFEState->isSecure && !outputState.isSecure) ||
363             (state.bufferTransform & ui::Transform::ROT_INVALID)) {
364             state.forceClientComposition = true;
365         }
366     }
367 
368     auto pixelFormat = layerFEState->buffer ? std::make_optional(static_cast<ui::PixelFormat>(
369                                                       layerFEState->buffer->getPixelFormat()))
370                                             : std::nullopt;
371 
372     auto hdrRenderType =
373             getHdrRenderType(outputState.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio);
374 
375     // Determine the output dependent dataspace for this layer. If it is
376     // colorspace agnostic, it just uses the dataspace chosen for the output to
377     // avoid the need for color conversion.
378     // For now, also respect the colorspace agnostic flag if we're drawing to HDR, to avoid drastic
379     // luminance shift. TODO(b/292162273): we should check if that's true though.
380     state.dataspace = layerFEState->isColorspaceAgnostic && hdrRenderType == HdrRenderType::SDR
381             ? outputState.dataspace
382             : layerFEState->dataspace;
383 
384     // Override the dataspace transfer from 170M to sRGB if the device configuration requests this.
385     // We do this here instead of in buffer info so that dumpsys can still report layers that are
386     // using the 170M transfer. Also we only do this if the colorspace is not agnostic for the
387     // layer, in case the color profile uses a 170M transfer function.
388     if (outputState.treat170mAsSrgb && !layerFEState->isColorspaceAgnostic &&
389         (state.dataspace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_SMPTE_170M) {
390         state.dataspace = static_cast<ui::Dataspace>(
391                 (state.dataspace & HAL_DATASPACE_STANDARD_MASK) |
392                 (state.dataspace & HAL_DATASPACE_RANGE_MASK) | HAL_DATASPACE_TRANSFER_SRGB);
393     }
394 
395     // re-get HdrRenderType after the dataspace gets changed.
396     hdrRenderType =
397             getHdrRenderType(state.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio);
398 
399     // For hdr content, treat the white point as the display brightness - HDR content should not be
400     // boosted or dimmed.
401     // If the layer explicitly requests to disable dimming, then don't dim either.
402     if (getOutput().getState().displayBrightnessNits == getOutput().getState().sdrWhitePointNits ||
403         getOutput().getState().displayBrightnessNits <= 0.f || !layerFEState->dimmingEnabled) {
404         state.dimmingRatio = 1.f;
405         state.whitePointNits = getOutput().getState().displayBrightnessNits;
406     } else if (hdrRenderType == HdrRenderType::GENERIC_HDR) {
407         float deviceHeadroom = getOutput().getState().displayBrightnessNits /
408                 getOutput().getState().sdrWhitePointNits;
409         float idealizedMaxHeadroom = deviceHeadroom;
410 
411         if (FlagManager::getInstance().begone_bright_hlg()) {
412             idealizedMaxHeadroom =
413                     std::min(idealizedMaxHeadroom, getIdealizedMaxHeadroom(state.dataspace));
414         }
415 
416         state.dimmingRatio = std::min(idealizedMaxHeadroom / deviceHeadroom, 1.0f);
417         state.whitePointNits = getOutput().getState().displayBrightnessNits * state.dimmingRatio;
418     } else {
419         float layerBrightnessNits = getOutput().getState().sdrWhitePointNits;
420         // RANGE_EXTENDED can "self-promote" to HDR, but is still rendered for a particular
421         // range that we may need to re-adjust to the current display conditions
422         if (hdrRenderType == HdrRenderType::DISPLAY_HDR) {
423             layerBrightnessNits *= layerFEState->currentHdrSdrRatio;
424         }
425         state.dimmingRatio =
426                 std::clamp(layerBrightnessNits / getOutput().getState().displayBrightnessNits, 0.f,
427                            1.f);
428         state.whitePointNits = layerBrightnessNits;
429     }
430 
431     updateLuts(*layerFEState, properties);
432 
433     // These are evaluated every frame as they can potentially change at any
434     // time.
435     if (layerFEState->forceClientComposition || !profile.isDataspaceSupported(state.dataspace) ||
436         forceClientComposition) {
437         state.forceClientComposition = true;
438     }
439 }
440 
commitPictureProfileToCompositionState()441 void OutputLayer::commitPictureProfileToCompositionState() {
442     if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
443         return;
444     }
445     const auto* layerState = getLayerFE().getCompositionState();
446     if (layerState) {
447         editState().pictureProfileHandle = layerState->pictureProfileHandle;
448     }
449 }
450 
writeStateToHWC(bool includeGeometry,bool skipLayer,uint32_t z,bool zIsOverridden,bool isPeekingThrough)451 void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t z,
452                                   bool zIsOverridden, bool isPeekingThrough) {
453     const auto& state = getState();
454     // Skip doing this if there is no HWC interface
455     if (!state.hwc) {
456         return;
457     }
458 
459     auto& hwcLayer = (*state.hwc).hwcLayer;
460     if (!hwcLayer) {
461         ALOGE("[%s] failed to write composition state to HWC -- no hwcLayer for output %s",
462               getLayerFE().getDebugName(), getOutput().getName().c_str());
463         return;
464     }
465 
466     const auto* outputIndependentState = getLayerFE().getCompositionState();
467     if (!outputIndependentState) {
468         return;
469     }
470 
471     auto requestedCompositionType = outputIndependentState->compositionType;
472 
473     if (requestedCompositionType == Composition::SOLID_COLOR && state.overrideInfo.buffer) {
474         requestedCompositionType = Composition::DEVICE;
475     }
476 
477     // TODO(b/181172795): We now update geometry for all flattened layers. We should update it
478     // only when the geometry actually changes
479     const bool isOverridden =
480             state.overrideInfo.buffer != nullptr || isPeekingThrough || zIsOverridden;
481     const bool prevOverridden = state.hwc->stateOverridden;
482     if (isOverridden || prevOverridden || skipLayer || includeGeometry) {
483         writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType, z);
484         writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), *outputIndependentState,
485                                                  skipLayer);
486     }
487 
488     writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
489     writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState,
490                                              requestedCompositionType, skipLayer);
491 
492     writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough,
493                               skipLayer);
494 
495     writeLutToHWC(hwcLayer.get(), *outputIndependentState);
496 
497     if (requestedCompositionType == Composition::SOLID_COLOR) {
498         writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);
499     }
500 
501     editState().hwc->stateOverridden = isOverridden;
502     editState().hwc->layerSkipped = skipLayer;
503 }
504 
writeOutputDependentGeometryStateToHWC(HWC2::Layer * hwcLayer,Composition requestedCompositionType,uint32_t z)505 void OutputLayer::writeOutputDependentGeometryStateToHWC(HWC2::Layer* hwcLayer,
506                                                          Composition requestedCompositionType,
507                                                          uint32_t z) {
508     const auto& outputDependentState = getState();
509 
510     Rect displayFrame = outputDependentState.displayFrame;
511     FloatRect sourceCrop = outputDependentState.sourceCrop;
512 
513     if (outputDependentState.overrideInfo.buffer != nullptr) {
514         displayFrame = outputDependentState.overrideInfo.displayFrame;
515         sourceCrop =
516                 FloatRect(0.f, 0.f,
517                           static_cast<float>(outputDependentState.overrideInfo.buffer->getBuffer()
518                                                      ->getWidth()),
519                           static_cast<float>(outputDependentState.overrideInfo.buffer->getBuffer()
520                                                      ->getHeight()));
521     }
522 
523     ALOGV("Writing display frame [%d, %d, %d, %d]", displayFrame.left, displayFrame.top,
524           displayFrame.right, displayFrame.bottom);
525 
526     if (auto error = hwcLayer->setDisplayFrame(displayFrame); error != hal::Error::NONE) {
527         ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
528               getLayerFE().getDebugName(), displayFrame.left, displayFrame.top, displayFrame.right,
529               displayFrame.bottom, to_string(error).c_str(), static_cast<int32_t>(error));
530     }
531 
532     if (auto error = hwcLayer->setSourceCrop(sourceCrop); error != hal::Error::NONE) {
533         ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
534               "%s (%d)",
535               getLayerFE().getDebugName(), sourceCrop.left, sourceCrop.top, sourceCrop.right,
536               sourceCrop.bottom, to_string(error).c_str(), static_cast<int32_t>(error));
537     }
538 
539     if (auto error = hwcLayer->setZOrder(z); error != hal::Error::NONE) {
540         ALOGE("[%s] Failed to set Z %u: %s (%d)", getLayerFE().getDebugName(), z,
541               to_string(error).c_str(), static_cast<int32_t>(error));
542     }
543 
544     // Solid-color layers and overridden buffers should always use an identity transform.
545     const auto bufferTransform = (requestedCompositionType != Composition::SOLID_COLOR &&
546                                   getState().overrideInfo.buffer == nullptr)
547             ? outputDependentState.bufferTransform
548             : static_cast<hal::Transform>(0);
549     if (auto error = hwcLayer->setTransform(static_cast<hal::Transform>(bufferTransform));
550         error != hal::Error::NONE) {
551         ALOGE("[%s] Failed to set transform %s: %s (%d)", getLayerFE().getDebugName(),
552               toString(outputDependentState.bufferTransform).c_str(), to_string(error).c_str(),
553               static_cast<int32_t>(error));
554     }
555 }
556 
writeOutputIndependentGeometryStateToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState,bool skipLayer)557 void OutputLayer::writeOutputIndependentGeometryStateToHWC(
558         HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState,
559         bool skipLayer) {
560     // If there is a peekThroughLayer, then this layer has a hole in it. We need to use
561     // PREMULTIPLIED so it will peek through.
562     const auto& overrideInfo = getState().overrideInfo;
563     const auto blendMode = overrideInfo.buffer || overrideInfo.peekThroughLayer
564             ? hardware::graphics::composer::hal::BlendMode::PREMULTIPLIED
565             : outputIndependentState.blendMode;
566     if (auto error = hwcLayer->setBlendMode(blendMode); error != hal::Error::NONE) {
567         ALOGE("[%s] Failed to set blend mode %s: %s (%d)", getLayerFE().getDebugName(),
568               toString(blendMode).c_str(), to_string(error).c_str(), static_cast<int32_t>(error));
569     }
570 
571     const float alpha = skipLayer
572             ? 0.0f
573             : (getState().overrideInfo.buffer ? 1.0f : outputIndependentState.alpha);
574     ALOGV("Writing alpha %f", alpha);
575 
576     if (auto error = hwcLayer->setPlaneAlpha(alpha); error != hal::Error::NONE) {
577         ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", getLayerFE().getDebugName(), alpha,
578               to_string(error).c_str(), static_cast<int32_t>(error));
579     }
580 
581     for (const auto& [name, entry] : outputIndependentState.metadata) {
582         if (auto error = hwcLayer->setLayerGenericMetadata(name, entry.mandatory, entry.value);
583             error != hal::Error::NONE) {
584             ALOGE("[%s] Failed to set generic metadata %s %s (%d)", getLayerFE().getDebugName(),
585                   name.c_str(), to_string(error).c_str(), static_cast<int32_t>(error));
586         }
587     }
588 }
589 
writeLutToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState)590 void OutputLayer::writeLutToHWC(HWC2::Layer* hwcLayer,
591                                 const LayerFECompositionState& outputIndependentState) {
592     if (!outputIndependentState.luts) {
593         return;
594     }
595     auto& lutFileDescriptor = outputIndependentState.luts->getLutFileDescriptor();
596     auto lutOffsets = outputIndependentState.luts->offsets;
597     auto& lutProperties = outputIndependentState.luts->lutProperties;
598 
599     std::vector<LutProperties> aidlProperties;
600     aidlProperties.reserve(lutProperties.size());
601     for (size_t i = 0; i < lutOffsets.size(); i++) {
602         LutProperties properties;
603         properties.dimension = static_cast<LutProperties::Dimension>(lutProperties[i].dimension);
604         properties.size = lutProperties[i].size;
605         properties.samplingKeys = {
606                 static_cast<LutProperties::SamplingKey>(lutProperties[i].samplingKey)};
607         aidlProperties.emplace_back(properties);
608     }
609 
610     Luts luts;
611     luts.pfd = ndk::ScopedFileDescriptor(dup(lutFileDescriptor.get()));
612     luts.offsets = lutOffsets;
613     luts.lutProperties = std::move(aidlProperties);
614 
615     switch (auto error = hwcLayer->setLuts(luts)) {
616         case hal::Error::NONE:
617             break;
618         default:
619             ALOGE("[%s] Failed to set Luts: %s (%d)", getLayerFE().getDebugName(),
620                   to_string(error).c_str(), static_cast<int32_t>(error));
621     }
622 }
623 
writeOutputDependentPerFrameStateToHWC(HWC2::Layer * hwcLayer)624 void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) {
625     const auto& outputDependentState = getState();
626 
627     // TODO(lpique): b/121291683 outputSpaceVisibleRegion is output-dependent geometry
628     // state and should not change every frame.
629     Region visibleRegion = outputDependentState.overrideInfo.buffer
630             ? Region(outputDependentState.overrideInfo.visibleRegion)
631             : outputDependentState.outputSpaceVisibleRegion;
632     if (auto error = hwcLayer->setVisibleRegion(visibleRegion); error != hal::Error::NONE) {
633         ALOGE("[%s] Failed to set visible region: %s (%d)", getLayerFE().getDebugName(),
634               to_string(error).c_str(), static_cast<int32_t>(error));
635         visibleRegion.dump(LOG_TAG);
636     }
637 
638     if (auto error =
639                 hwcLayer->setBlockingRegion(outputDependentState.outputSpaceBlockingRegionHint);
640         error != hal::Error::NONE) {
641         ALOGE("[%s] Failed to set blocking region: %s (%d)", getLayerFE().getDebugName(),
642               to_string(error).c_str(), static_cast<int32_t>(error));
643         outputDependentState.outputSpaceBlockingRegionHint.dump(LOG_TAG);
644     }
645 
646     const auto dataspace = outputDependentState.overrideInfo.buffer
647             ? outputDependentState.overrideInfo.dataspace
648             : outputDependentState.dataspace;
649 
650     if (auto error = hwcLayer->setDataspace(dataspace); error != hal::Error::NONE) {
651         ALOGE("[%s] Failed to set dataspace %d: %s (%d)", getLayerFE().getDebugName(), dataspace,
652               to_string(error).c_str(), static_cast<int32_t>(error));
653     }
654 
655     // Cached layers are not dimmed, which means that composer should attempt to dim.
656     // Note that if the dimming ratio is large, then this may cause the cached layer
657     // to kick back into GPU composition :(
658     // Also note that this assumes that there are no HDR layers that are able to be cached.
659     // Otherwise, this could cause HDR layers to be dimmed twice.
660     const auto dimmingRatio = outputDependentState.overrideInfo.buffer
661             ? (getOutput().getState().displayBrightnessNits != 0.f
662                        ? std::clamp(getOutput().getState().sdrWhitePointNits /
663                                             getOutput().getState().displayBrightnessNits,
664                                     0.f, 1.f)
665                        : 1.f)
666             : outputDependentState.dimmingRatio;
667 
668     if (auto error = hwcLayer->setBrightness(dimmingRatio); error != hal::Error::NONE) {
669         ALOGE("[%s] Failed to set brightness %f: %s (%d)", getLayerFE().getDebugName(),
670               dimmingRatio, to_string(error).c_str(), static_cast<int32_t>(error));
671     }
672 
673     if (com_android_graphics_libgui_flags_apply_picture_profiles() &&
674         outputDependentState.pictureProfileHandle) {
675         if (auto error =
676                     hwcLayer->setPictureProfileHandle(outputDependentState.pictureProfileHandle);
677             error != hal::Error::NONE) {
678             ALOGE("[%s] Failed to set picture profile handle: %s (%d)", getLayerFE().getDebugName(),
679                   toString(outputDependentState.pictureProfileHandle).c_str(),
680                   static_cast<int32_t>(error));
681         }
682         // Reset the picture profile state, as it needs to be re-committed on each present cycle
683         // when Output decides that the limited picture-processing hardware should be used by this
684         // layer.
685         editState().pictureProfileHandle = PictureProfileHandle::NONE;
686     }
687 }
688 
writeOutputIndependentPerFrameStateToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState,Composition compositionType,bool skipLayer)689 void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
690         HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState,
691         Composition compositionType, bool skipLayer) {
692     switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
693         case hal::Error::NONE:
694             break;
695         case hal::Error::UNSUPPORTED:
696             editState().forceClientComposition = true;
697             break;
698         default:
699             ALOGE("[%s] Failed to set color transform: %s (%d)", getLayerFE().getDebugName(),
700                   to_string(error).c_str(), static_cast<int32_t>(error));
701     }
702 
703     const Region& surfaceDamage = getState().overrideInfo.buffer
704             ? getState().overrideInfo.damageRegion
705             : (getState().hwc->stateOverridden ? Region::INVALID_REGION
706                                                : outputIndependentState.surfaceDamage);
707 
708     if (auto error = hwcLayer->setSurfaceDamage(surfaceDamage); error != hal::Error::NONE) {
709         ALOGE("[%s] Failed to set surface damage: %s (%d)", getLayerFE().getDebugName(),
710               to_string(error).c_str(), static_cast<int32_t>(error));
711         outputIndependentState.surfaceDamage.dump(LOG_TAG);
712     }
713 
714     // Content-specific per-frame state
715     switch (compositionType) {
716         case Composition::SOLID_COLOR:
717             // For compatibility, should be written AFTER the composition type.
718             break;
719         case Composition::SIDEBAND:
720             writeSidebandStateToHWC(hwcLayer, outputIndependentState);
721             break;
722         case Composition::CURSOR:
723         case Composition::DEVICE:
724         case Composition::DISPLAY_DECORATION:
725         case Composition::REFRESH_RATE_INDICATOR:
726             writeBufferStateToHWC(hwcLayer, outputIndependentState, skipLayer);
727             break;
728         case Composition::INVALID:
729         case Composition::CLIENT:
730             // Ignored
731             break;
732     }
733 }
734 
writeSolidColorStateToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState)735 void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer,
736                                             const LayerFECompositionState& outputIndependentState) {
737     aidl::android::hardware::graphics::composer3::Color color = {outputIndependentState.color.r,
738                                                                  outputIndependentState.color.g,
739                                                                  outputIndependentState.color.b,
740                                                                  1.0f};
741 
742     if (auto error = hwcLayer->setColor(color); error != hal::Error::NONE) {
743         ALOGE("[%s] Failed to set color: %s (%d)", getLayerFE().getDebugName(),
744               to_string(error).c_str(), static_cast<int32_t>(error));
745     }
746 }
747 
writeSidebandStateToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState)748 void OutputLayer::writeSidebandStateToHWC(HWC2::Layer* hwcLayer,
749                                           const LayerFECompositionState& outputIndependentState) {
750     if (auto error = hwcLayer->setSidebandStream(outputIndependentState.sidebandStream->handle());
751         error != hal::Error::NONE) {
752         ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", getLayerFE().getDebugName(),
753               outputIndependentState.sidebandStream->handle(), to_string(error).c_str(),
754               static_cast<int32_t>(error));
755     }
756 }
757 
uncacheBuffers(const std::vector<uint64_t> & bufferIdsToUncache)758 void OutputLayer::uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache) {
759     auto& state = editState();
760     // Skip doing this if there is no HWC interface
761     if (!state.hwc) {
762         return;
763     }
764 
765     // Uncache the active buffer last so that it's the first buffer to be purged from the cache
766     // next time a buffer is sent to this layer.
767     bool uncacheActiveBuffer = false;
768 
769     std::vector<uint32_t> slotsToClear;
770     for (uint64_t bufferId : bufferIdsToUncache) {
771         if (bufferId == state.hwc->activeBufferId) {
772             uncacheActiveBuffer = true;
773         } else {
774             uint32_t slot = state.hwc->hwcBufferCache.uncache(bufferId);
775             if (slot != UINT32_MAX) {
776                 slotsToClear.push_back(slot);
777             }
778         }
779     }
780     if (uncacheActiveBuffer) {
781         slotsToClear.push_back(state.hwc->hwcBufferCache.uncache(state.hwc->activeBufferId));
782     }
783 
784     hal::Error error =
785             state.hwc->hwcLayer->setBufferSlotsToClear(slotsToClear, state.hwc->activeBufferSlot);
786     if (error != hal::Error::NONE) {
787         ALOGE("[%s] Failed to clear buffer slots: %s (%d)", getLayerFE().getDebugName(),
788               to_string(error).c_str(), static_cast<int32_t>(error));
789     }
790 }
791 
getPictureProfilePriority() const792 int64_t OutputLayer::getPictureProfilePriority() const {
793     const auto* layerState = getLayerFE().getCompositionState();
794     return layerState ? layerState->pictureProfilePriority : 0;
795 }
796 
getPictureProfileHandle() const797 const PictureProfileHandle& OutputLayer::getPictureProfileHandle() const {
798     const auto* layerState = getLayerFE().getCompositionState();
799     return layerState ? layerState->pictureProfileHandle : PictureProfileHandle::NONE;
800 }
801 
writeBufferStateToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState,bool skipLayer)802 void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer,
803                                         const LayerFECompositionState& outputIndependentState,
804                                         bool skipLayer) {
805     if (skipLayer && outputIndependentState.buffer == nullptr) {
806         return;
807     }
808     auto supportedPerFrameMetadata =
809             getOutput().getDisplayColorProfile()->getSupportedPerFrameMetadata();
810     if (auto error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata,
811                                                    outputIndependentState.hdrMetadata);
812         error != hal::Error::NONE && error != hal::Error::UNSUPPORTED) {
813         ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", getLayerFE().getDebugName(),
814               to_string(error).c_str(), static_cast<int32_t>(error));
815     }
816 
817     HwcSlotAndBuffer hwcSlotAndBuffer;
818     sp<Fence> hwcFence;
819     {
820         // Editing the state only because we update the HWC buffer cache and active buffer.
821         auto& state = editState();
822         // Override buffers use a special cache slot so that they don't evict client buffers.
823         if (state.overrideInfo.buffer != nullptr && !skipLayer) {
824             hwcSlotAndBuffer = state.hwc->hwcBufferCache.getOverrideHwcSlotAndBuffer(
825                     state.overrideInfo.buffer->getBuffer());
826             hwcFence = state.overrideInfo.acquireFence;
827             // Keep track of the active buffer ID so when it's discarded we uncache it last so its
828             // slot will be used first, allowing the memory to be freed as soon as possible.
829             state.hwc->activeBufferId = state.overrideInfo.buffer->getBuffer()->getId();
830         } else {
831             hwcSlotAndBuffer =
832                     state.hwc->hwcBufferCache.getHwcSlotAndBuffer(outputIndependentState.buffer);
833             hwcFence = outputIndependentState.acquireFence;
834             // Keep track of the active buffer ID so when it's discarded we uncache it last so its
835             // slot will be used first, allowing the memory to be freed as soon as possible.
836             state.hwc->activeBufferId = outputIndependentState.buffer->getId();
837         }
838         // Keep track of the active buffer slot, so we can restore it after clearing other buffer
839         // slots.
840         state.hwc->activeBufferSlot = hwcSlotAndBuffer.slot;
841     }
842 
843     if (auto error = hwcLayer->setBuffer(hwcSlotAndBuffer.slot, hwcSlotAndBuffer.buffer, hwcFence);
844         error != hal::Error::NONE) {
845         ALOGE("[%s] Failed to set buffer %p: %s (%d)", getLayerFE().getDebugName(),
846               hwcSlotAndBuffer.buffer->handle, to_string(error).c_str(),
847               static_cast<int32_t>(error));
848     }
849 }
850 
writeCompositionTypeToHWC(HWC2::Layer * hwcLayer,Composition requestedCompositionType,bool isPeekingThrough,bool skipLayer)851 void OutputLayer::writeCompositionTypeToHWC(HWC2::Layer* hwcLayer,
852                                             Composition requestedCompositionType,
853                                             bool isPeekingThrough, bool skipLayer) {
854     auto& outputDependentState = editState();
855 
856     if (isClientCompositionForced(isPeekingThrough)) {
857         // If we are forcing client composition, we need to tell the HWC
858         requestedCompositionType = Composition::CLIENT;
859     }
860 
861     // Set the requested composition type with the HWC whenever it changes
862     // We also resend the composition type when this layer was previously skipped, to ensure that
863     // the composition type is up-to-date.
864     if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType ||
865         (outputDependentState.hwc->layerSkipped && !skipLayer)) {
866         outputDependentState.hwc->hwcCompositionType = requestedCompositionType;
867 
868         if (auto error = hwcLayer->setCompositionType(requestedCompositionType);
869             error != hal::Error::NONE) {
870             ALOGE("[%s] Failed to set composition type %s: %s (%d)", getLayerFE().getDebugName(),
871                   to_string(requestedCompositionType).c_str(), to_string(error).c_str(),
872                   static_cast<int32_t>(error));
873         }
874     }
875 }
876 
writeCursorPositionToHWC() const877 void OutputLayer::writeCursorPositionToHWC() const {
878     // Skip doing this if there is no HWC interface
879     auto hwcLayer = getHwcLayer();
880     if (!hwcLayer) {
881         return;
882     }
883 
884     const auto* layerState = getLayerFE().getCompositionState();
885     if (!layerState) {
886         return;
887     }
888 
889     const auto& outputState = getOutput().getState();
890 
891     Rect frame = layerState->cursorFrame;
892     frame.intersect(outputState.layerStackSpace.getContent(), &frame);
893     Rect position = outputState.transform.transform(frame);
894 
895     if (auto error = hwcLayer->setCursorPosition(position.left, position.top);
896         error != hal::Error::NONE) {
897         ALOGE("[%s] Failed to set cursor position to (%d, %d): %s (%d)",
898               getLayerFE().getDebugName(), position.left, position.top, to_string(error).c_str(),
899               static_cast<int32_t>(error));
900     }
901 }
902 
getHwcLayer() const903 HWC2::Layer* OutputLayer::getHwcLayer() const {
904     const auto& state = getState();
905     return state.hwc ? state.hwc->hwcLayer.get() : nullptr;
906 }
907 
requiresClientComposition() const908 bool OutputLayer::requiresClientComposition() const {
909     const auto& state = getState();
910     return !state.hwc || state.hwc->hwcCompositionType == Composition::CLIENT;
911 }
912 
isHardwareCursor() const913 bool OutputLayer::isHardwareCursor() const {
914     const auto& state = getState();
915     return state.hwc && state.hwc->hwcCompositionType == Composition::CURSOR;
916 }
917 
detectDisallowedCompositionTypeChange(Composition from,Composition to) const918 void OutputLayer::detectDisallowedCompositionTypeChange(Composition from, Composition to) const {
919     bool result = false;
920     switch (from) {
921         case Composition::INVALID:
922         case Composition::CLIENT:
923             result = false;
924             break;
925 
926         case Composition::DEVICE:
927         case Composition::SOLID_COLOR:
928             result = (to == Composition::CLIENT);
929             break;
930 
931         case Composition::CURSOR:
932         case Composition::SIDEBAND:
933         case Composition::DISPLAY_DECORATION:
934         case Composition::REFRESH_RATE_INDICATOR:
935             result = (to == Composition::CLIENT || to == Composition::DEVICE);
936             break;
937     }
938 
939     if (!result) {
940         ALOGE("[%s] Invalid device requested composition type change: %s (%d) --> %s (%d)",
941               getLayerFE().getDebugName(), to_string(from).c_str(), static_cast<int>(from),
942               to_string(to).c_str(), static_cast<int>(to));
943     }
944 }
945 
isClientCompositionForced(bool isPeekingThrough) const946 bool OutputLayer::isClientCompositionForced(bool isPeekingThrough) const {
947     return getState().forceClientComposition ||
948             (!isPeekingThrough && getLayerFE().hasRoundedCorners());
949 }
950 
applyDeviceCompositionTypeChange(Composition compositionType)951 void OutputLayer::applyDeviceCompositionTypeChange(Composition compositionType) {
952     auto& state = editState();
953     LOG_FATAL_IF(!state.hwc);
954     auto& hwcState = *state.hwc;
955 
956     // Only detected disallowed changes if this was not a skip layer, because the
957     // validated composition type may be arbitrary (usually DEVICE, to reflect that there were
958     // fewer GPU layers)
959     if (!hwcState.layerSkipped) {
960         detectDisallowedCompositionTypeChange(hwcState.hwcCompositionType, compositionType);
961     }
962 
963     hwcState.hwcCompositionType = compositionType;
964 }
965 
prepareForDeviceLayerRequests()966 void OutputLayer::prepareForDeviceLayerRequests() {
967     auto& state = editState();
968     state.clearClientTarget = false;
969 }
970 
applyDeviceLayerRequest(hal::LayerRequest request)971 void OutputLayer::applyDeviceLayerRequest(hal::LayerRequest request) {
972     auto& state = editState();
973     switch (request) {
974         case hal::LayerRequest::CLEAR_CLIENT_TARGET:
975             state.clearClientTarget = true;
976             break;
977 
978         default:
979             ALOGE("[%s] Unknown device layer request %s (%d)", getLayerFE().getDebugName(),
980                   toString(request).c_str(), static_cast<int>(request));
981             break;
982     }
983 }
984 
applyDeviceLayerLut(ndk::ScopedFileDescriptor lutFileDescriptor,std::vector<std::pair<int,LutProperties>> lutOffsetsAndProperties)985 void OutputLayer::applyDeviceLayerLut(
986         ndk::ScopedFileDescriptor lutFileDescriptor,
987         std::vector<std::pair<int, LutProperties>> lutOffsetsAndProperties) {
988     auto& state = editState();
989     LOG_FATAL_IF(!state.hwc);
990     auto& hwcState = *state.hwc;
991     std::vector<int32_t> offsets;
992     std::vector<int32_t> dimensions;
993     std::vector<int32_t> sizes;
994     std::vector<int32_t> samplingKeys;
995     for (const auto& [offset, properties] : lutOffsetsAndProperties) {
996         // The Lut(s) that comes back through CommandResultPayload should be
997         // only one sampling key.
998         if (properties.samplingKeys.size() == 1) {
999             offsets.emplace_back(offset);
1000             dimensions.emplace_back(static_cast<int32_t>(properties.dimension));
1001             sizes.emplace_back(static_cast<int32_t>(properties.size));
1002             samplingKeys.emplace_back(static_cast<int32_t>(properties.samplingKeys[0]));
1003         }
1004     }
1005     hwcState.luts = std::make_shared<gui::DisplayLuts>(base::unique_fd(lutFileDescriptor.release()),
1006                                                        std::move(offsets), std::move(dimensions),
1007                                                        std::move(sizes), std::move(samplingKeys));
1008 }
1009 
needsFiltering() const1010 bool OutputLayer::needsFiltering() const {
1011     const auto& state = getState();
1012     const auto& sourceCrop = state.sourceCrop;
1013     auto displayFrameWidth = static_cast<float>(state.displayFrame.getWidth());
1014     auto displayFrameHeight = static_cast<float>(state.displayFrame.getHeight());
1015 
1016     if (state.bufferTransform & HAL_TRANSFORM_ROT_90) {
1017         std::swap(displayFrameWidth, displayFrameHeight);
1018     }
1019 
1020     return sourceCrop.getHeight() != displayFrameHeight ||
1021             sourceCrop.getWidth() != displayFrameWidth;
1022 }
1023 
getOverrideCompositionSettings() const1024 std::optional<LayerFE::LayerSettings> OutputLayer::getOverrideCompositionSettings() const {
1025     if (getState().overrideInfo.buffer == nullptr) {
1026         return {};
1027     }
1028 
1029     // Compute the geometry boundaries in layer stack space: we need to transform from the
1030     // framebuffer space of the override buffer to layer space.
1031     const ProjectionSpace& layerSpace = getOutput().getState().layerStackSpace;
1032     const ui::Transform transform = getState().overrideInfo.displaySpace.getTransform(layerSpace);
1033     const Rect boundaries = transform.transform(getState().overrideInfo.displayFrame);
1034 
1035     LayerFE::LayerSettings settings;
1036     settings.geometry = renderengine::Geometry{
1037             .boundaries = boundaries.toFloatRect(),
1038     };
1039     settings.bufferId = getState().overrideInfo.buffer->getBuffer()->getId();
1040     settings.source = renderengine::PixelSource{
1041             .buffer = renderengine::Buffer{
1042                     .buffer = getState().overrideInfo.buffer,
1043                     .fence = getState().overrideInfo.acquireFence,
1044                     // If the transform from layer space to display space contains a rotation, we
1045                     // need to undo the rotation in the texture transform
1046                     .textureTransform =
1047                             ui::Transform(transform.inverse().getOrientation(), 1, 1).asMatrix4(),
1048             }};
1049     settings.sourceDataspace = getState().overrideInfo.dataspace;
1050     settings.alpha = 1.0f;
1051     settings.whitePointNits = getOutput().getState().sdrWhitePointNits;
1052 
1053     return settings;
1054 }
1055 
dump(std::string & out) const1056 void OutputLayer::dump(std::string& out) const {
1057     using android::base::StringAppendF;
1058 
1059     StringAppendF(&out, "  - Output Layer %p(%s)\n", this, getLayerFE().getDebugName());
1060     dumpState(out);
1061 }
1062 
1063 } // namespace impl
1064 } // namespace android::compositionengine
1065