• 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 <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     // Similar to above
241     if (layerState.forceClientComposition && layerState.borderSettings.strokeWidth > 0.0f) {
242         // Antialiasing should never add more than 2 pixels.
243         const auto outset = layerState.borderSettings.strokeWidth + 2;
244         geomLayerBounds.left -= outset;
245         geomLayerBounds.top -= outset;
246         geomLayerBounds.right += outset;
247         geomLayerBounds.bottom += outset;
248     }
249 
250     geomLayerBounds = layerTransform.transform(geomLayerBounds);
251     FloatRect frame = reduce(geomLayerBounds, activeTransparentRegion);
252     frame = frame.intersect(outputState.layerStackSpace.getContent().toFloatRect());
253 
254     // convert from layerStackSpace to displaySpace
255     const ui::Transform displayTransform{outputState.transform};
256     return Rect(displayTransform.transform(frame));
257 }
258 
calculateOutputRelativeBufferTransform(uint32_t internalDisplayRotationFlags) const259 uint32_t OutputLayer::calculateOutputRelativeBufferTransform(
260         uint32_t internalDisplayRotationFlags) const {
261     const auto& layerState = *getLayerFE().getCompositionState();
262     const auto& outputState = getOutput().getState();
263 
264     /*
265      * Transformations are applied in this order:
266      * 1) buffer orientation/flip/mirror
267      * 2) state transformation (window manager)
268      * 3) layer orientation (screen orientation)
269      * (NOTE: the matrices are multiplied in reverse order)
270      */
271     const ui::Transform& layerTransform = layerState.geomLayerTransform;
272     const ui::Transform displayTransform{outputState.transform};
273     const ui::Transform bufferTransform{layerState.geomBufferTransform};
274     ui::Transform transform(displayTransform * layerTransform * bufferTransform);
275 
276     if (layerState.geomBufferUsesDisplayInverseTransform) {
277         /*
278          * We must apply the internal display's inverse transform to the buffer
279          * transform, and not the one for the output this layer is on.
280          */
281         uint32_t invTransform = internalDisplayRotationFlags;
282 
283         // calculate the inverse transform
284         if (invTransform & HAL_TRANSFORM_ROT_90) {
285             invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
286         }
287 
288         /*
289          * Here we cancel out the orientation component of the WM transform.
290          * The scaling and translate components are already included in our bounds
291          * computation so it's enough to just omit it in the composition.
292          * See comment in BufferLayer::prepareClientLayer with ref to b/36727915 for why.
293          */
294         transform = ui::Transform(invTransform) * displayTransform * bufferTransform;
295     }
296 
297     // this gives us only the "orientation" component of the transform
298     return transform.getOrientation();
299 }
300 
updateLuts(const LayerFECompositionState & layerFEState,const std::optional<std::vector<std::optional<LutProperties>>> & properties)301 void OutputLayer::updateLuts(
302         const LayerFECompositionState& layerFEState,
303         const std::optional<std::vector<std::optional<LutProperties>>>& properties) {
304     auto& luts = layerFEState.luts;
305     if (!luts) {
306         return;
307     }
308 
309     auto& state = editState();
310 
311     if (!properties) {
312         // GPU composition if no Hwc Luts
313         state.forceClientComposition = true;
314         return;
315     }
316 
317     std::vector<LutProperties> hwcLutProperties;
318     for (auto& p : *properties) {
319         if (p) {
320             hwcLutProperties.emplace_back(*p);
321         }
322     }
323 
324     for (const auto& inputLut : luts->lutProperties) {
325         bool foundInHwcLuts = false;
326         for (const auto& hwcLut : hwcLutProperties) {
327             if (static_cast<int32_t>(hwcLut.dimension) ==
328                         static_cast<int32_t>(inputLut.dimension) &&
329                 hwcLut.size == inputLut.size &&
330                 std::find(hwcLut.samplingKeys.begin(), hwcLut.samplingKeys.end(),
331                           static_cast<LutProperties::SamplingKey>(inputLut.samplingKey)) !=
332                         hwcLut.samplingKeys.end()) {
333                 foundInHwcLuts = true;
334                 break;
335             }
336         }
337         // if any lut properties of luts can not be found in hwcLutProperties,
338         // GPU composition instead
339         if (!foundInHwcLuts) {
340             state.forceClientComposition = true;
341             return;
342         }
343     }
344 }
345 
updateCompositionState(bool includeGeometry,bool forceClientComposition,ui::Transform::RotationFlags internalDisplayRotationFlags,const std::optional<std::vector<std::optional<LutProperties>>> properties)346 void OutputLayer::updateCompositionState(
347         bool includeGeometry, bool forceClientComposition,
348         ui::Transform::RotationFlags internalDisplayRotationFlags,
349         const std::optional<std::vector<std::optional<LutProperties>>> properties) {
350     const auto* layerFEState = getLayerFE().getCompositionState();
351     if (!layerFEState) {
352         return;
353     }
354 
355     const auto& outputState = getOutput().getState();
356     const auto& profile = *getOutput().getDisplayColorProfile();
357     auto& state = editState();
358 
359     if (includeGeometry) {
360         // Clear the forceClientComposition flag before it is set for any
361         // reason. Note that since it can be set by some checks below when
362         // updating the geometry state, we only clear it when updating the
363         // geometry since those conditions for forcing client composition won't
364         // go away otherwise.
365         state.forceClientComposition = false;
366 
367         state.displayFrame = calculateOutputDisplayFrame();
368         state.sourceCrop = calculateOutputSourceCrop(internalDisplayRotationFlags);
369         state.bufferTransform = static_cast<Hwc2::Transform>(
370                 calculateOutputRelativeBufferTransform(internalDisplayRotationFlags));
371 
372         if ((layerFEState->isSecure && !outputState.isSecure) ||
373             (state.bufferTransform & ui::Transform::ROT_INVALID)) {
374             state.forceClientComposition = true;
375         }
376     }
377 
378     auto pixelFormat = layerFEState->buffer ? std::make_optional(static_cast<ui::PixelFormat>(
379                                                       layerFEState->buffer->getPixelFormat()))
380                                             : std::nullopt;
381 
382     // prefer querying this from gralloc instead to catch 2094-10 metadata
383     const bool hasHdrMetadata = layerFEState->hdrMetadata.validTypes != 0;
384 
385     auto hdrRenderType = getHdrRenderType(outputState.dataspace, pixelFormat,
386                                           layerFEState->desiredHdrSdrRatio, hasHdrMetadata);
387 
388     // Determine the output dependent dataspace for this layer. If it is
389     // colorspace agnostic, it just uses the dataspace chosen for the output to
390     // avoid the need for color conversion.
391     // For now, also respect the colorspace agnostic flag if we're drawing to HDR, to avoid drastic
392     // luminance shift. TODO(b/292162273): we should check if that's true though.
393     state.dataspace = layerFEState->isColorspaceAgnostic && hdrRenderType == HdrRenderType::SDR
394             ? outputState.dataspace
395             : layerFEState->dataspace;
396 
397     // Override the dataspace transfer from 170M to sRGB if the device configuration requests this.
398     // We do this here instead of in buffer info so that dumpsys can still report layers that are
399     // using the 170M transfer. Also we only do this if the colorspace is not agnostic for the
400     // layer, in case the color profile uses a 170M transfer function.
401     if (outputState.treat170mAsSrgb && !layerFEState->isColorspaceAgnostic &&
402         (state.dataspace & HAL_DATASPACE_TRANSFER_MASK) == HAL_DATASPACE_TRANSFER_SMPTE_170M) {
403         state.dataspace = static_cast<ui::Dataspace>(
404                 (state.dataspace & HAL_DATASPACE_STANDARD_MASK) |
405                 (state.dataspace & HAL_DATASPACE_RANGE_MASK) | HAL_DATASPACE_TRANSFER_SRGB);
406     }
407 
408     // re-get HdrRenderType after the dataspace gets changed.
409     hdrRenderType = getHdrRenderType(state.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio,
410                                      hasHdrMetadata);
411 
412     // For hdr content, treat the white point as the display brightness - HDR content should not be
413     // boosted or dimmed.
414     // If the layer explicitly requests to disable dimming, then don't dim either.
415     if (getOutput().getState().displayBrightnessNits == getOutput().getState().sdrWhitePointNits ||
416         getOutput().getState().displayBrightnessNits <= 0.f || !layerFEState->dimmingEnabled) {
417         state.dimmingRatio = 1.f;
418         state.whitePointNits = getOutput().getState().displayBrightnessNits;
419     } else if (hdrRenderType == HdrRenderType::GENERIC_HDR) {
420         float deviceHeadroom = getOutput().getState().displayBrightnessNits /
421                 getOutput().getState().sdrWhitePointNits;
422         float idealizedMaxHeadroom = deviceHeadroom;
423 
424         if (FlagManager::getInstance().begone_bright_hlg()) {
425             idealizedMaxHeadroom =
426                     std::min(idealizedMaxHeadroom, getIdealizedMaxHeadroom(state.dataspace));
427         }
428 
429         state.dimmingRatio = std::min(idealizedMaxHeadroom / deviceHeadroom, 1.0f);
430         state.whitePointNits = getOutput().getState().displayBrightnessNits * state.dimmingRatio;
431     } else {
432         const bool isLayerFp16 = pixelFormat && *pixelFormat == ui::PixelFormat::RGBA_FP16;
433         float layerBrightnessNits = getOutput().getState().sdrWhitePointNits;
434         // RANGE_EXTENDED can "self-promote" to HDR, but is still rendered for a particular
435         // range that we may need to re-adjust to the current display conditions
436         // Do NOT do this when we may render fp16 to an fp16 client target, to avoid applying
437         // and additional gain to the layer. This is because the fp16 client target should
438         // already be adapted to remap 1.0 to the SDR white point in the panel's luminance
439         // space.
440         if (hdrRenderType == HdrRenderType::DISPLAY_HDR) {
441             if (!FlagManager::getInstance().fp16_client_target() || !isLayerFp16) {
442                 layerBrightnessNits *= layerFEState->currentHdrSdrRatio;
443             }
444         }
445 
446         state.dimmingRatio =
447                 std::clamp(layerBrightnessNits / getOutput().getState().displayBrightnessNits, 0.f,
448                            1.f);
449         state.whitePointNits = layerBrightnessNits;
450     }
451 
452     updateLuts(*layerFEState, properties);
453 
454     // These are evaluated every frame as they can potentially change at any
455     // time.
456     if (layerFEState->forceClientComposition || !profile.isDataspaceSupported(state.dataspace) ||
457         forceClientComposition) {
458         state.forceClientComposition = true;
459     }
460 }
461 
commitPictureProfileToCompositionState()462 void OutputLayer::commitPictureProfileToCompositionState() {
463     if (!com_android_graphics_libgui_flags_apply_picture_profiles()) {
464         return;
465     }
466     const auto* layerState = getLayerFE().getCompositionState();
467     if (layerState) {
468         editState().pictureProfileHandle = layerState->pictureProfileHandle;
469     }
470 }
471 
writeStateToHWC(bool includeGeometry,bool skipLayer,uint32_t z,bool zIsOverridden,bool isPeekingThrough,bool hasLutsProperties)472 void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t z,
473                                   bool zIsOverridden, bool isPeekingThrough,
474                                   bool hasLutsProperties) {
475     const auto& state = getState();
476     // Skip doing this if there is no HWC interface
477     if (!state.hwc) {
478         return;
479     }
480 
481     auto& hwcLayer = (*state.hwc).hwcLayer;
482     if (!hwcLayer) {
483         ALOGE("[%s] failed to write composition state to HWC -- no hwcLayer for output %s",
484               getLayerFE().getDebugName(), getOutput().getName().c_str());
485         return;
486     }
487 
488     const auto* outputIndependentState = getLayerFE().getCompositionState();
489     if (!outputIndependentState) {
490         return;
491     }
492 
493     auto requestedCompositionType = outputIndependentState->compositionType;
494 
495     if (requestedCompositionType == Composition::SOLID_COLOR && state.overrideInfo.buffer) {
496         requestedCompositionType = Composition::DEVICE;
497     }
498 
499     // TODO(b/181172795): We now update geometry for all flattened layers. We should update it
500     // only when the geometry actually changes
501     const bool isOverridden =
502             state.overrideInfo.buffer != nullptr || isPeekingThrough || zIsOverridden;
503     const bool prevOverridden = state.hwc->stateOverridden;
504     if (isOverridden || prevOverridden || skipLayer || includeGeometry) {
505         writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType, z);
506         writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), *outputIndependentState,
507                                                  skipLayer);
508     }
509 
510     writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
511     writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState,
512                                              requestedCompositionType, skipLayer);
513 
514     writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough,
515                               skipLayer);
516     if (hasLutsProperties) {
517         writeLutToHWC(hwcLayer.get(), *outputIndependentState);
518     }
519 
520     if (requestedCompositionType == Composition::SOLID_COLOR) {
521         writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);
522     }
523 
524     editState().hwc->stateOverridden = isOverridden;
525     editState().hwc->layerSkipped = skipLayer;
526 
527 
528     // Save the final HWC state for debugging purposes, e.g. perfetto tracing, dumpsys.
529     getLayerFE().setLastHwcState({.lastCompositionType = editState().hwc->hwcCompositionType,
530                                   .wasSkipped = skipLayer,
531                                   .wasOverridden = isOverridden,
532                                   .overrideBufferId = editState().overrideInfo.buffer
533                                           ? editState().overrideInfo.buffer.get()->getId()
534                                           : 0});
535 }
536 
writeOutputDependentGeometryStateToHWC(HWC2::Layer * hwcLayer,Composition requestedCompositionType,uint32_t z)537 void OutputLayer::writeOutputDependentGeometryStateToHWC(HWC2::Layer* hwcLayer,
538                                                          Composition requestedCompositionType,
539                                                          uint32_t z) {
540     const auto& outputDependentState = getState();
541 
542     Rect displayFrame = outputDependentState.displayFrame;
543     FloatRect sourceCrop = outputDependentState.sourceCrop;
544 
545     if (outputDependentState.overrideInfo.buffer != nullptr) {
546         displayFrame = outputDependentState.overrideInfo.displayFrame;
547         sourceCrop =
548                 FloatRect(0.f, 0.f,
549                           static_cast<float>(outputDependentState.overrideInfo.buffer->getBuffer()
550                                                      ->getWidth()),
551                           static_cast<float>(outputDependentState.overrideInfo.buffer->getBuffer()
552                                                      ->getHeight()));
553     }
554 
555     ALOGV("Writing display frame [%d, %d, %d, %d]", displayFrame.left, displayFrame.top,
556           displayFrame.right, displayFrame.bottom);
557 
558     if (auto error = hwcLayer->setDisplayFrame(displayFrame); error != hal::Error::NONE) {
559         ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)",
560               getLayerFE().getDebugName(), displayFrame.left, displayFrame.top, displayFrame.right,
561               displayFrame.bottom, to_string(error).c_str(), static_cast<int32_t>(error));
562     }
563 
564     if (auto error = hwcLayer->setSourceCrop(sourceCrop); error != hal::Error::NONE) {
565         ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
566               "%s (%d)",
567               getLayerFE().getDebugName(), sourceCrop.left, sourceCrop.top, sourceCrop.right,
568               sourceCrop.bottom, to_string(error).c_str(), static_cast<int32_t>(error));
569     }
570 
571     if (auto error = hwcLayer->setZOrder(z); error != hal::Error::NONE) {
572         ALOGE("[%s] Failed to set Z %u: %s (%d)", getLayerFE().getDebugName(), z,
573               to_string(error).c_str(), static_cast<int32_t>(error));
574     }
575 
576     // Solid-color layers and overridden buffers should always use an identity transform.
577     const auto bufferTransform = (requestedCompositionType != Composition::SOLID_COLOR &&
578                                   getState().overrideInfo.buffer == nullptr)
579             ? outputDependentState.bufferTransform
580             : static_cast<hal::Transform>(0);
581     if (auto error = hwcLayer->setTransform(static_cast<hal::Transform>(bufferTransform));
582         error != hal::Error::NONE) {
583         ALOGE("[%s] Failed to set transform %s: %s (%d)", getLayerFE().getDebugName(),
584               toString(outputDependentState.bufferTransform).c_str(), to_string(error).c_str(),
585               static_cast<int32_t>(error));
586     }
587 }
588 
writeOutputIndependentGeometryStateToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState,bool skipLayer)589 void OutputLayer::writeOutputIndependentGeometryStateToHWC(
590         HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState,
591         bool skipLayer) {
592     // If there is a peekThroughLayer, then this layer has a hole in it. We need to use
593     // PREMULTIPLIED so it will peek through.
594     const auto& overrideInfo = getState().overrideInfo;
595     const auto blendMode = overrideInfo.buffer || overrideInfo.peekThroughLayer
596             ? hardware::graphics::composer::hal::BlendMode::PREMULTIPLIED
597             : outputIndependentState.blendMode;
598     if (auto error = hwcLayer->setBlendMode(blendMode); error != hal::Error::NONE) {
599         ALOGE("[%s] Failed to set blend mode %s: %s (%d)", getLayerFE().getDebugName(),
600               toString(blendMode).c_str(), to_string(error).c_str(), static_cast<int32_t>(error));
601     }
602 
603     const float alpha = skipLayer
604             ? 0.0f
605             : (getState().overrideInfo.buffer ? 1.0f : outputIndependentState.alpha);
606     ALOGV("Writing alpha %f", alpha);
607 
608     if (auto error = hwcLayer->setPlaneAlpha(alpha); error != hal::Error::NONE) {
609         ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", getLayerFE().getDebugName(), alpha,
610               to_string(error).c_str(), static_cast<int32_t>(error));
611     }
612 
613     for (const auto& [name, entry] : outputIndependentState.metadata) {
614         if (auto error = hwcLayer->setLayerGenericMetadata(name, entry.mandatory, entry.value);
615             error != hal::Error::NONE) {
616             ALOGE("[%s] Failed to set generic metadata %s %s (%d)", getLayerFE().getDebugName(),
617                   name.c_str(), to_string(error).c_str(), static_cast<int32_t>(error));
618         }
619     }
620 }
621 
writeLutToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState)622 void OutputLayer::writeLutToHWC(HWC2::Layer* hwcLayer,
623                                 const LayerFECompositionState& outputIndependentState) {
624     Luts luts;
625     // if outputIndependentState.luts is nullptr, it means we want to clear the LUTs
626     // and we pass an empty Luts object to the HWC.
627     if (outputIndependentState.luts) {
628         auto& lutFileDescriptor = outputIndependentState.luts->getLutFileDescriptor();
629         auto lutOffsets = outputIndependentState.luts->offsets;
630         auto& lutProperties = outputIndependentState.luts->lutProperties;
631 
632         std::vector<LutProperties> aidlProperties;
633         aidlProperties.reserve(lutProperties.size());
634         for (size_t i = 0; i < lutOffsets.size(); i++) {
635             aidlProperties.emplace_back(
636                     LutProperties{.dimension = static_cast<LutProperties::Dimension>(
637                                           lutProperties[i].dimension),
638                                   .size = lutProperties[i].size,
639                                   .samplingKeys = {static_cast<LutProperties::SamplingKey>(
640                                           lutProperties[i].samplingKey)}});
641         }
642 
643         luts.pfd.set(dup(lutFileDescriptor.get()));
644         luts.offsets = lutOffsets;
645         luts.lutProperties = std::move(aidlProperties);
646     }
647 
648     switch (auto error = hwcLayer->setLuts(luts)) {
649         case hal::Error::NONE:
650             break;
651         default:
652             ALOGE("[%s] Failed to set Luts: %s (%d)", getLayerFE().getDebugName(),
653                   to_string(error).c_str(), static_cast<int32_t>(error));
654     }
655 }
656 
writeOutputDependentPerFrameStateToHWC(HWC2::Layer * hwcLayer)657 void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) {
658     const auto& outputDependentState = getState();
659 
660     // TODO(lpique): b/121291683 outputSpaceVisibleRegion is output-dependent geometry
661     // state and should not change every frame.
662     Region visibleRegion = outputDependentState.overrideInfo.buffer
663             ? Region(outputDependentState.overrideInfo.visibleRegion)
664             : outputDependentState.outputSpaceVisibleRegion;
665     if (auto error = hwcLayer->setVisibleRegion(visibleRegion); error != hal::Error::NONE) {
666         ALOGE("[%s] Failed to set visible region: %s (%d)", getLayerFE().getDebugName(),
667               to_string(error).c_str(), static_cast<int32_t>(error));
668         visibleRegion.dump(LOG_TAG);
669     }
670 
671     if (auto error =
672                 hwcLayer->setBlockingRegion(outputDependentState.outputSpaceBlockingRegionHint);
673         error != hal::Error::NONE) {
674         ALOGE("[%s] Failed to set blocking region: %s (%d)", getLayerFE().getDebugName(),
675               to_string(error).c_str(), static_cast<int32_t>(error));
676         outputDependentState.outputSpaceBlockingRegionHint.dump(LOG_TAG);
677     }
678 
679     const auto dataspace = outputDependentState.overrideInfo.buffer
680             ? outputDependentState.overrideInfo.dataspace
681             : outputDependentState.dataspace;
682 
683     if (auto error = hwcLayer->setDataspace(dataspace); error != hal::Error::NONE) {
684         ALOGE("[%s] Failed to set dataspace %d: %s (%d)", getLayerFE().getDebugName(), dataspace,
685               to_string(error).c_str(), static_cast<int32_t>(error));
686     }
687 
688     // Cached layers are not dimmed, which means that composer should attempt to dim.
689     // Note that if the dimming ratio is large, then this may cause the cached layer
690     // to kick back into GPU composition :(
691     // Also note that this assumes that there are no HDR layers that are able to be cached.
692     // Otherwise, this could cause HDR layers to be dimmed twice.
693     const auto dimmingRatio = outputDependentState.overrideInfo.buffer
694             ? (getOutput().getState().displayBrightnessNits != 0.f
695                        ? std::clamp(getOutput().getState().sdrWhitePointNits /
696                                             getOutput().getState().displayBrightnessNits,
697                                     0.f, 1.f)
698                        : 1.f)
699             : outputDependentState.dimmingRatio;
700 
701     if (auto error = hwcLayer->setBrightness(dimmingRatio); error != hal::Error::NONE) {
702         ALOGE("[%s] Failed to set brightness %f: %s (%d)", getLayerFE().getDebugName(),
703               dimmingRatio, to_string(error).c_str(), static_cast<int32_t>(error));
704     }
705 
706     if (com_android_graphics_libgui_flags_apply_picture_profiles() &&
707         outputDependentState.pictureProfileHandle) {
708         if (auto error =
709                     hwcLayer->setPictureProfileHandle(outputDependentState.pictureProfileHandle);
710             error != hal::Error::NONE) {
711             ALOGE("[%s] Failed to set picture profile handle: %s (%d)", getLayerFE().getDebugName(),
712                   toString(outputDependentState.pictureProfileHandle).c_str(),
713                   static_cast<int32_t>(error));
714         }
715         // Reset the picture profile state, as it needs to be re-committed on each present cycle
716         // when Output decides that the limited picture-processing hardware should be used by this
717         // layer.
718         editState().pictureProfileHandle = PictureProfileHandle::NONE;
719     }
720 }
721 
writeOutputIndependentPerFrameStateToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState,Composition compositionType,bool skipLayer)722 void OutputLayer::writeOutputIndependentPerFrameStateToHWC(
723         HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState,
724         Composition compositionType, bool skipLayer) {
725     switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) {
726         case hal::Error::NONE:
727             break;
728         case hal::Error::UNSUPPORTED:
729             editState().forceClientComposition = true;
730             break;
731         default:
732             ALOGE("[%s] Failed to set color transform: %s (%d)", getLayerFE().getDebugName(),
733                   to_string(error).c_str(), static_cast<int32_t>(error));
734     }
735 
736     const Region& surfaceDamage = getState().overrideInfo.buffer
737             ? getState().overrideInfo.damageRegion
738             : (getState().hwc->stateOverridden ? Region::INVALID_REGION
739                                                : outputIndependentState.surfaceDamage);
740 
741     if (auto error = hwcLayer->setSurfaceDamage(surfaceDamage); error != hal::Error::NONE) {
742         ALOGE("[%s] Failed to set surface damage: %s (%d)", getLayerFE().getDebugName(),
743               to_string(error).c_str(), static_cast<int32_t>(error));
744         outputIndependentState.surfaceDamage.dump(LOG_TAG);
745     }
746 
747     // Content-specific per-frame state
748     switch (compositionType) {
749         case Composition::SOLID_COLOR:
750             // For compatibility, should be written AFTER the composition type.
751             break;
752         case Composition::SIDEBAND:
753             writeSidebandStateToHWC(hwcLayer, outputIndependentState);
754             break;
755         case Composition::CURSOR:
756         case Composition::DEVICE:
757         case Composition::DISPLAY_DECORATION:
758         case Composition::REFRESH_RATE_INDICATOR:
759             writeBufferStateToHWC(hwcLayer, outputIndependentState, skipLayer);
760             break;
761         case Composition::INVALID:
762         case Composition::CLIENT:
763             // Ignored
764             break;
765     }
766 }
767 
writeSolidColorStateToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState)768 void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer,
769                                             const LayerFECompositionState& outputIndependentState) {
770     aidl::android::hardware::graphics::composer3::Color color = {outputIndependentState.color.r,
771                                                                  outputIndependentState.color.g,
772                                                                  outputIndependentState.color.b,
773                                                                  1.0f};
774 
775     if (auto error = hwcLayer->setColor(color); error != hal::Error::NONE) {
776         ALOGE("[%s] Failed to set color: %s (%d)", getLayerFE().getDebugName(),
777               to_string(error).c_str(), static_cast<int32_t>(error));
778     }
779 }
780 
writeSidebandStateToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState)781 void OutputLayer::writeSidebandStateToHWC(HWC2::Layer* hwcLayer,
782                                           const LayerFECompositionState& outputIndependentState) {
783     if (auto error = hwcLayer->setSidebandStream(outputIndependentState.sidebandStream->handle());
784         error != hal::Error::NONE) {
785         ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", getLayerFE().getDebugName(),
786               outputIndependentState.sidebandStream->handle(), to_string(error).c_str(),
787               static_cast<int32_t>(error));
788     }
789 }
790 
uncacheBuffers(const std::vector<uint64_t> & bufferIdsToUncache)791 void OutputLayer::uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache) {
792     auto& state = editState();
793     // Skip doing this if there is no HWC interface
794     if (!state.hwc) {
795         return;
796     }
797 
798     // Uncache the active buffer last so that it's the first buffer to be purged from the cache
799     // next time a buffer is sent to this layer.
800     bool uncacheActiveBuffer = false;
801 
802     std::vector<uint32_t> slotsToClear;
803     for (uint64_t bufferId : bufferIdsToUncache) {
804         if (bufferId == state.hwc->activeBufferId) {
805             uncacheActiveBuffer = true;
806         } else {
807             uint32_t slot = state.hwc->hwcBufferCache.uncache(bufferId);
808             if (slot != UINT32_MAX) {
809                 slotsToClear.push_back(slot);
810             }
811         }
812     }
813     if (uncacheActiveBuffer) {
814         slotsToClear.push_back(state.hwc->hwcBufferCache.uncache(state.hwc->activeBufferId));
815     }
816 
817     hal::Error error =
818             state.hwc->hwcLayer->setBufferSlotsToClear(slotsToClear, state.hwc->activeBufferSlot);
819     if (error != hal::Error::NONE) {
820         ALOGE("[%s] Failed to clear buffer slots: %s (%d)", getLayerFE().getDebugName(),
821               to_string(error).c_str(), static_cast<int32_t>(error));
822     }
823 }
824 
getPictureProfilePriority() const825 int64_t OutputLayer::getPictureProfilePriority() const {
826     const auto* layerState = getLayerFE().getCompositionState();
827     return layerState ? layerState->pictureProfilePriority : 0;
828 }
829 
getPictureProfileHandle() const830 const PictureProfileHandle& OutputLayer::getPictureProfileHandle() const {
831     const auto* layerState = getLayerFE().getCompositionState();
832     return layerState ? layerState->pictureProfileHandle : PictureProfileHandle::NONE;
833 }
834 
writeBufferStateToHWC(HWC2::Layer * hwcLayer,const LayerFECompositionState & outputIndependentState,bool skipLayer)835 void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer,
836                                         const LayerFECompositionState& outputIndependentState,
837                                         bool skipLayer) {
838     if (skipLayer && outputIndependentState.buffer == nullptr) {
839         return;
840     }
841     auto supportedPerFrameMetadata =
842             getOutput().getDisplayColorProfile()->getSupportedPerFrameMetadata();
843     if (auto error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata,
844                                                    outputIndependentState.hdrMetadata);
845         error != hal::Error::NONE && error != hal::Error::UNSUPPORTED) {
846         ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", getLayerFE().getDebugName(),
847               to_string(error).c_str(), static_cast<int32_t>(error));
848     }
849 
850     HwcSlotAndBuffer hwcSlotAndBuffer;
851     sp<Fence> hwcFence;
852     {
853         // Editing the state only because we update the HWC buffer cache and active buffer.
854         auto& state = editState();
855         // Override buffers use a special cache slot so that they don't evict client buffers.
856         if (state.overrideInfo.buffer != nullptr && !skipLayer) {
857             hwcSlotAndBuffer = state.hwc->hwcBufferCache.getOverrideHwcSlotAndBuffer(
858                     state.overrideInfo.buffer->getBuffer());
859             hwcFence = state.overrideInfo.acquireFence;
860             // Keep track of the active buffer ID so when it's discarded we uncache it last so its
861             // slot will be used first, allowing the memory to be freed as soon as possible.
862             state.hwc->activeBufferId = state.overrideInfo.buffer->getBuffer()->getId();
863         } else {
864             hwcSlotAndBuffer =
865                     state.hwc->hwcBufferCache.getHwcSlotAndBuffer(outputIndependentState.buffer);
866             hwcFence = outputIndependentState.acquireFence;
867             // Keep track of the active buffer ID so when it's discarded we uncache it last so its
868             // slot will be used first, allowing the memory to be freed as soon as possible.
869             state.hwc->activeBufferId = outputIndependentState.buffer->getId();
870         }
871         // Keep track of the active buffer slot, so we can restore it after clearing other buffer
872         // slots.
873         state.hwc->activeBufferSlot = hwcSlotAndBuffer.slot;
874     }
875 
876     if (auto error = hwcLayer->setBuffer(hwcSlotAndBuffer.slot, hwcSlotAndBuffer.buffer, hwcFence);
877         error != hal::Error::NONE) {
878         ALOGE("[%s] Failed to set buffer %p: %s (%d)", getLayerFE().getDebugName(),
879               hwcSlotAndBuffer.buffer->handle, to_string(error).c_str(),
880               static_cast<int32_t>(error));
881     }
882 }
883 
writeCompositionTypeToHWC(HWC2::Layer * hwcLayer,Composition requestedCompositionType,bool isPeekingThrough,bool skipLayer)884 void OutputLayer::writeCompositionTypeToHWC(HWC2::Layer* hwcLayer,
885                                             Composition requestedCompositionType,
886                                             bool isPeekingThrough, bool skipLayer) {
887     auto& outputDependentState = editState();
888 
889     if (isClientCompositionForced(isPeekingThrough)) {
890         // If we are forcing client composition, we need to tell the HWC
891         requestedCompositionType = Composition::CLIENT;
892     }
893 
894     // Set the requested composition type with the HWC whenever it changes
895     // We also resend the composition type when this layer was previously skipped, to ensure that
896     // the composition type is up-to-date.
897     if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType ||
898         (outputDependentState.hwc->layerSkipped && !skipLayer)) {
899         outputDependentState.hwc->hwcCompositionType = requestedCompositionType;
900 
901         if (auto error = hwcLayer->setCompositionType(requestedCompositionType);
902             error != hal::Error::NONE) {
903             ALOGE("[%s] Failed to set composition type %s: %s (%d)", getLayerFE().getDebugName(),
904                   to_string(requestedCompositionType).c_str(), to_string(error).c_str(),
905                   static_cast<int32_t>(error));
906         }
907     }
908 }
909 
writeCursorPositionToHWC() const910 void OutputLayer::writeCursorPositionToHWC() const {
911     // Skip doing this if there is no HWC interface
912     auto hwcLayer = getHwcLayer();
913     if (!hwcLayer) {
914         return;
915     }
916 
917     const auto* layerState = getLayerFE().getCompositionState();
918     if (!layerState) {
919         return;
920     }
921 
922     const auto& outputState = getOutput().getState();
923 
924     Rect frame = layerState->cursorFrame;
925     frame.intersect(outputState.layerStackSpace.getContent(), &frame);
926     Rect position = outputState.transform.transform(frame);
927 
928     if (auto error = hwcLayer->setCursorPosition(position.left, position.top);
929         error != hal::Error::NONE) {
930         ALOGE("[%s] Failed to set cursor position to (%d, %d): %s (%d)",
931               getLayerFE().getDebugName(), position.left, position.top, to_string(error).c_str(),
932               static_cast<int32_t>(error));
933     }
934 }
935 
getHwcLayer() const936 HWC2::Layer* OutputLayer::getHwcLayer() const {
937     const auto& state = getState();
938     return state.hwc ? state.hwc->hwcLayer.get() : nullptr;
939 }
940 
requiresClientComposition() const941 bool OutputLayer::requiresClientComposition() const {
942     const auto& state = getState();
943     return !state.hwc || state.hwc->hwcCompositionType == Composition::CLIENT;
944 }
945 
isHardwareCursor() const946 bool OutputLayer::isHardwareCursor() const {
947     const auto& state = getState();
948     return state.hwc && state.hwc->hwcCompositionType == Composition::CURSOR;
949 }
950 
detectDisallowedCompositionTypeChange(Composition from,Composition to) const951 void OutputLayer::detectDisallowedCompositionTypeChange(Composition from, Composition to) const {
952     bool result = false;
953     switch (from) {
954         case Composition::INVALID:
955         case Composition::CLIENT:
956             result = false;
957             break;
958 
959         case Composition::DEVICE:
960         case Composition::SOLID_COLOR:
961             result = (to == Composition::CLIENT);
962             break;
963 
964         case Composition::CURSOR:
965         case Composition::SIDEBAND:
966         case Composition::DISPLAY_DECORATION:
967         case Composition::REFRESH_RATE_INDICATOR:
968             result = (to == Composition::CLIENT || to == Composition::DEVICE);
969             break;
970     }
971 
972     if (!result) {
973         ALOGE("[%s] Invalid device requested composition type change: %s (%d) --> %s (%d)",
974               getLayerFE().getDebugName(), to_string(from).c_str(), static_cast<int>(from),
975               to_string(to).c_str(), static_cast<int>(to));
976     }
977 }
978 
isClientCompositionForced(bool isPeekingThrough) const979 bool OutputLayer::isClientCompositionForced(bool isPeekingThrough) const {
980     return getState().forceClientComposition ||
981             (!isPeekingThrough && getLayerFE().hasRoundedCorners());
982 }
983 
applyDeviceCompositionTypeChange(Composition compositionType)984 void OutputLayer::applyDeviceCompositionTypeChange(Composition compositionType) {
985     auto& state = editState();
986     LOG_FATAL_IF(!state.hwc);
987     auto& hwcState = *state.hwc;
988 
989     // Only detected disallowed changes if this was not a skip layer, because the
990     // validated composition type may be arbitrary (usually DEVICE, to reflect that there were
991     // fewer GPU layers)
992     if (!hwcState.layerSkipped) {
993         detectDisallowedCompositionTypeChange(hwcState.hwcCompositionType, compositionType);
994     }
995 
996     hwcState.hwcCompositionType = compositionType;
997 
998     getLayerFE().setLastHwcState({.lastCompositionType = hwcState.hwcCompositionType,
999                                   .wasSkipped = hwcState.layerSkipped,
1000                                   .wasOverridden = hwcState.stateOverridden,
1001                                   .overrideBufferId = state.overrideInfo.buffer
1002                                           ? state.overrideInfo.buffer.get()->getId()
1003                                           : 0});
1004 }
1005 
prepareForDeviceLayerRequests()1006 void OutputLayer::prepareForDeviceLayerRequests() {
1007     auto& state = editState();
1008     state.clearClientTarget = false;
1009 }
1010 
applyDeviceLayerRequest(hal::LayerRequest request)1011 void OutputLayer::applyDeviceLayerRequest(hal::LayerRequest request) {
1012     auto& state = editState();
1013     switch (request) {
1014         case hal::LayerRequest::CLEAR_CLIENT_TARGET:
1015             state.clearClientTarget = true;
1016             break;
1017 
1018         default:
1019             ALOGE("[%s] Unknown device layer request %s (%d)", getLayerFE().getDebugName(),
1020                   toString(request).c_str(), static_cast<int>(request));
1021             break;
1022     }
1023 }
1024 
applyDeviceLayerLut(::android::base::unique_fd lutFd,std::vector<std::pair<int,LutProperties>> lutOffsetsAndProperties)1025 void OutputLayer::applyDeviceLayerLut(
1026         ::android::base::unique_fd lutFd,
1027         std::vector<std::pair<int, LutProperties>> lutOffsetsAndProperties) {
1028     auto& state = editState();
1029     LOG_FATAL_IF(!state.hwc);
1030     auto& hwcState = *state.hwc;
1031     std::vector<int32_t> offsets;
1032     std::vector<int32_t> dimensions;
1033     std::vector<int32_t> sizes;
1034     std::vector<int32_t> samplingKeys;
1035     for (const auto& [offset, properties] : lutOffsetsAndProperties) {
1036         // The Lut(s) that comes back through CommandResultPayload should be
1037         // only one sampling key.
1038         if (properties.samplingKeys.size() == 1) {
1039             offsets.emplace_back(offset);
1040             dimensions.emplace_back(static_cast<int32_t>(properties.dimension));
1041             sizes.emplace_back(static_cast<int32_t>(properties.size));
1042             samplingKeys.emplace_back(static_cast<int32_t>(properties.samplingKeys[0]));
1043         }
1044     }
1045     hwcState.luts = std::make_shared<gui::DisplayLuts>(std::move(lutFd), std::move(offsets),
1046                                                        std::move(dimensions), std::move(sizes),
1047                                                        std::move(samplingKeys));
1048 }
1049 
needsFiltering() const1050 bool OutputLayer::needsFiltering() const {
1051     const auto& state = getState();
1052     const auto& sourceCrop = state.sourceCrop;
1053     auto displayFrameWidth = static_cast<float>(state.displayFrame.getWidth());
1054     auto displayFrameHeight = static_cast<float>(state.displayFrame.getHeight());
1055 
1056     if (state.bufferTransform & HAL_TRANSFORM_ROT_90) {
1057         std::swap(displayFrameWidth, displayFrameHeight);
1058     }
1059 
1060     return sourceCrop.getHeight() != displayFrameHeight ||
1061             sourceCrop.getWidth() != displayFrameWidth;
1062 }
1063 
getOverrideCompositionSettings() const1064 std::optional<LayerFE::LayerSettings> OutputLayer::getOverrideCompositionSettings() const {
1065     if (getState().overrideInfo.buffer == nullptr) {
1066         return {};
1067     }
1068 
1069     // Compute the geometry boundaries in layer stack space: we need to transform from the
1070     // framebuffer space of the override buffer to layer space.
1071     const ProjectionSpace& layerSpace = getOutput().getState().layerStackSpace;
1072     const ui::Transform transform = getState().overrideInfo.displaySpace.getTransform(layerSpace);
1073     const Rect boundaries = transform.transform(getState().overrideInfo.displayFrame);
1074 
1075     LayerFE::LayerSettings settings;
1076     settings.geometry = renderengine::Geometry{
1077             .boundaries = boundaries.toFloatRect(),
1078     };
1079     settings.bufferId = getState().overrideInfo.buffer->getBuffer()->getId();
1080     settings.source = renderengine::PixelSource{
1081             .buffer = renderengine::Buffer{
1082                     .buffer = getState().overrideInfo.buffer,
1083                     .fence = getState().overrideInfo.acquireFence,
1084                     // If the transform from layer space to display space contains a rotation, we
1085                     // need to undo the rotation in the texture transform
1086                     .textureTransform =
1087                             ui::Transform(transform.inverse().getOrientation(), 1, 1).asMatrix4(),
1088             }};
1089     settings.sourceDataspace = getState().overrideInfo.dataspace;
1090     settings.alpha = 1.0f;
1091     settings.whitePointNits = getOutput().getState().sdrWhitePointNits;
1092 
1093     return settings;
1094 }
1095 
dump(std::string & out) const1096 void OutputLayer::dump(std::string& out) const {
1097     using android::base::StringAppendF;
1098 
1099     StringAppendF(&out, "  - Output Layer %p(%s)\n", this, getLayerFE().getDebugName());
1100     dumpState(out);
1101 }
1102 
1103 } // namespace impl
1104 } // namespace android::compositionengine
1105