• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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 // #define LOG_NDEBUG 0
18 #undef LOG_TAG
19 #define LOG_TAG "LayerFE"
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21 
22 #include <gui/GLConsumer.h>
23 #include <gui/TraceUtils.h>
24 #include <math/vec3.h>
25 #include <system/window.h>
26 #include <utils/Log.h>
27 
28 #include "LayerFE.h"
29 #include "SurfaceFlinger.h"
30 
31 namespace android {
32 
33 namespace {
34 constexpr float defaultMaxLuminance = 1000.0;
35 
inverseOrientation(uint32_t transform)36 constexpr mat4 inverseOrientation(uint32_t transform) {
37     const mat4 flipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
38     const mat4 flipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
39     const mat4 rot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
40     mat4 tr;
41 
42     if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
43         tr = tr * rot90;
44     }
45     if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
46         tr = tr * flipH;
47     }
48     if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
49         tr = tr * flipV;
50     }
51     return inverse(tr);
52 }
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 // Computes the transform matrix using the setFilteringEnabled to determine whether the
63 // transform matrix should be computed for use with bilinear filtering.
getDrawingTransformMatrix(const std::shared_ptr<renderengine::ExternalTexture> & buffer,Rect bufferCrop,uint32_t bufferTransform,bool filteringEnabled,float outMatrix[16])64 void getDrawingTransformMatrix(const std::shared_ptr<renderengine::ExternalTexture>& buffer,
65                                Rect bufferCrop, uint32_t bufferTransform, bool filteringEnabled,
66                                float outMatrix[16]) {
67     if (!buffer) {
68         ALOGE("Buffer should not be null!");
69         return;
70     }
71     GLConsumer::computeTransformMatrix(outMatrix, static_cast<float>(buffer->getWidth()),
72                                        static_cast<float>(buffer->getHeight()),
73                                        buffer->getPixelFormat(), bufferCrop, bufferTransform,
74                                        filteringEnabled);
75 }
76 
77 } // namespace
78 
LayerFE(const std::string & name)79 LayerFE::LayerFE(const std::string& name) : mName(name) {}
80 
getCompositionState() const81 const compositionengine::LayerFECompositionState* LayerFE::getCompositionState() const {
82     return mSnapshot.get();
83 }
84 
onPreComposition(nsecs_t refreshStartTime,bool)85 bool LayerFE::onPreComposition(nsecs_t refreshStartTime, bool) {
86     mCompositionResult.refreshStartTime = refreshStartTime;
87     return mSnapshot->hasReadyFrame;
88 }
89 
prepareClientComposition(compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const90 std::optional<compositionengine::LayerFE::LayerSettings> LayerFE::prepareClientComposition(
91         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
92     std::optional<compositionengine::LayerFE::LayerSettings> layerSettings =
93             prepareClientCompositionInternal(targetSettings);
94     // Nothing to render.
95     if (!layerSettings) {
96         return {};
97     }
98 
99     // HWC requests to clear this layer.
100     if (targetSettings.clearContent) {
101         prepareClearClientComposition(*layerSettings, false /* blackout */);
102         return layerSettings;
103     }
104 
105     // set the shadow for the layer if needed
106     prepareShadowClientComposition(*layerSettings, targetSettings.viewport);
107 
108     return layerSettings;
109 }
110 
prepareClientCompositionInternal(compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const111 std::optional<compositionengine::LayerFE::LayerSettings> LayerFE::prepareClientCompositionInternal(
112         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
113     ATRACE_CALL();
114     compositionengine::LayerFE::LayerSettings layerSettings;
115     layerSettings.geometry.boundaries =
116             reduce(mSnapshot->geomLayerBounds, mSnapshot->transparentRegionHint);
117     layerSettings.geometry.positionTransform = mSnapshot->geomLayerTransform.asMatrix4();
118 
119     // skip drawing content if the targetSettings indicate the content will be occluded
120     const bool drawContent = targetSettings.realContentIsVisible || targetSettings.clearContent;
121     layerSettings.skipContentDraw = !drawContent;
122 
123     if (!mSnapshot->colorTransformIsIdentity) {
124         layerSettings.colorTransform = mSnapshot->colorTransform;
125     }
126 
127     const auto& roundedCornerState = mSnapshot->roundedCorner;
128     layerSettings.geometry.roundedCornersRadius = roundedCornerState.radius;
129     layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect;
130 
131     layerSettings.alpha = mSnapshot->alpha;
132     layerSettings.sourceDataspace = mSnapshot->dataspace;
133 
134     // Override the dataspace transfer from 170M to sRGB if the device configuration requests this.
135     // We do this here instead of in buffer info so that dumpsys can still report layers that are
136     // using the 170M transfer.
137     if (targetSettings.treat170mAsSrgb &&
138         (layerSettings.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) ==
139                 HAL_DATASPACE_TRANSFER_SMPTE_170M) {
140         layerSettings.sourceDataspace = static_cast<ui::Dataspace>(
141                 (layerSettings.sourceDataspace & HAL_DATASPACE_STANDARD_MASK) |
142                 (layerSettings.sourceDataspace & HAL_DATASPACE_RANGE_MASK) |
143                 HAL_DATASPACE_TRANSFER_SRGB);
144     }
145 
146     layerSettings.whitePointNits = targetSettings.whitePointNits;
147     switch (targetSettings.blurSetting) {
148         case LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled:
149             layerSettings.backgroundBlurRadius = mSnapshot->backgroundBlurRadius;
150             layerSettings.blurRegions = mSnapshot->blurRegions;
151             layerSettings.blurRegionTransform = mSnapshot->localTransformInverse.asMatrix4();
152             break;
153         case LayerFE::ClientCompositionTargetSettings::BlurSetting::BackgroundBlurOnly:
154             layerSettings.backgroundBlurRadius = mSnapshot->backgroundBlurRadius;
155             break;
156         case LayerFE::ClientCompositionTargetSettings::BlurSetting::BlurRegionsOnly:
157             layerSettings.blurRegions = mSnapshot->blurRegions;
158             layerSettings.blurRegionTransform = mSnapshot->localTransformInverse.asMatrix4();
159             break;
160         case LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled:
161         default:
162             break;
163     }
164     layerSettings.stretchEffect = mSnapshot->stretchEffect;
165     // Record the name of the layer for debugging further down the stack.
166     layerSettings.name = mSnapshot->name;
167 
168     if (hasEffect() && !hasBufferOrSidebandStream()) {
169         prepareEffectsClientComposition(layerSettings, targetSettings);
170         return layerSettings;
171     }
172 
173     prepareBufferStateClientComposition(layerSettings, targetSettings);
174     return layerSettings;
175 }
176 
prepareClearClientComposition(LayerFE::LayerSettings & layerSettings,bool blackout) const177 void LayerFE::prepareClearClientComposition(LayerFE::LayerSettings& layerSettings,
178                                             bool blackout) const {
179     layerSettings.source.buffer.buffer = nullptr;
180     layerSettings.source.solidColor = half3(0.0f, 0.0f, 0.0f);
181     layerSettings.disableBlending = true;
182     layerSettings.bufferId = 0;
183     layerSettings.frameNumber = 0;
184 
185     // If layer is blacked out, force alpha to 1 so that we draw a black color layer.
186     layerSettings.alpha = blackout ? 1.0f : 0.0f;
187     layerSettings.name = mSnapshot->name;
188 }
189 
prepareEffectsClientComposition(compositionengine::LayerFE::LayerSettings & layerSettings,compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const190 void LayerFE::prepareEffectsClientComposition(
191         compositionengine::LayerFE::LayerSettings& layerSettings,
192         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
193     // If fill bounds are occluded or the fill color is invalid skip the fill settings.
194     if (targetSettings.realContentIsVisible && fillsColor()) {
195         // Set color for color fill settings.
196         layerSettings.source.solidColor = mSnapshot->color.rgb;
197     } else if (hasBlur() || drawShadows()) {
198         layerSettings.skipContentDraw = true;
199     }
200 }
201 
prepareBufferStateClientComposition(compositionengine::LayerFE::LayerSettings & layerSettings,compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const202 void LayerFE::prepareBufferStateClientComposition(
203         compositionengine::LayerFE::LayerSettings& layerSettings,
204         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
205     ATRACE_CALL();
206     if (CC_UNLIKELY(!mSnapshot->externalTexture)) {
207         // If there is no buffer for the layer or we have sidebandstream where there is no
208         // activeBuffer, then we need to return LayerSettings.
209         return;
210     }
211     const bool blackOutLayer =
212             (mSnapshot->hasProtectedContent && !targetSettings.supportsProtectedContent) ||
213             ((mSnapshot->isSecure || mSnapshot->hasProtectedContent) && !targetSettings.isSecure);
214     const bool bufferCanBeUsedAsHwTexture =
215             mSnapshot->externalTexture->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
216     if (blackOutLayer || !bufferCanBeUsedAsHwTexture) {
217         ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable",
218                  mSnapshot->name.c_str());
219         prepareClearClientComposition(layerSettings, true /* blackout */);
220         return;
221     }
222 
223     layerSettings.source.buffer.buffer = mSnapshot->externalTexture;
224     layerSettings.source.buffer.isOpaque = mSnapshot->contentOpaque;
225     layerSettings.source.buffer.fence = mSnapshot->acquireFence;
226     layerSettings.source.buffer.textureName = mSnapshot->textureName;
227     layerSettings.source.buffer.usePremultipliedAlpha = mSnapshot->premultipliedAlpha;
228     layerSettings.source.buffer.isY410BT2020 = mSnapshot->isHdrY410;
229     bool hasSmpte2086 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::SMPTE2086;
230     bool hasCta861_3 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::CTA861_3;
231     float maxLuminance = 0.f;
232     if (hasSmpte2086 && hasCta861_3) {
233         maxLuminance = std::min(mSnapshot->hdrMetadata.smpte2086.maxLuminance,
234                                 mSnapshot->hdrMetadata.cta8613.maxContentLightLevel);
235     } else if (hasSmpte2086) {
236         maxLuminance = mSnapshot->hdrMetadata.smpte2086.maxLuminance;
237     } else if (hasCta861_3) {
238         maxLuminance = mSnapshot->hdrMetadata.cta8613.maxContentLightLevel;
239     } else {
240         switch (layerSettings.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) {
241             case HAL_DATASPACE_TRANSFER_ST2084:
242             case HAL_DATASPACE_TRANSFER_HLG:
243                 // Behavior-match previous releases for HDR content
244                 maxLuminance = defaultMaxLuminance;
245                 break;
246         }
247     }
248     layerSettings.source.buffer.maxLuminanceNits = maxLuminance;
249     layerSettings.frameNumber = mSnapshot->frameNumber;
250     layerSettings.bufferId = mSnapshot->externalTexture->getId();
251 
252     // Query the texture matrix given our current filtering mode.
253     float textureMatrix[16];
254     getDrawingTransformMatrix(layerSettings.source.buffer.buffer, mSnapshot->geomContentCrop,
255                               mSnapshot->geomBufferTransform, targetSettings.needsFiltering,
256                               textureMatrix);
257 
258     if (mSnapshot->geomBufferUsesDisplayInverseTransform) {
259         /*
260          * the code below applies the primary display's inverse transform to
261          * the texture transform
262          */
263         uint32_t transform = SurfaceFlinger::getActiveDisplayRotationFlags();
264         mat4 tr = inverseOrientation(transform);
265 
266         /**
267          * TODO(b/36727915): This is basically a hack.
268          *
269          * Ensure that regardless of the parent transformation,
270          * this buffer is always transformed from native display
271          * orientation to display orientation. For example, in the case
272          * of a camera where the buffer remains in native orientation,
273          * we want the pixels to always be upright.
274          */
275         const auto parentTransform = mSnapshot->parentTransform;
276         tr = tr * inverseOrientation(parentTransform.getOrientation());
277 
278         // and finally apply it to the original texture matrix
279         const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
280         memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
281     }
282 
283     const Rect win{layerSettings.geometry.boundaries};
284     float bufferWidth = static_cast<float>(mSnapshot->bufferSize.getWidth());
285     float bufferHeight = static_cast<float>(mSnapshot->bufferSize.getHeight());
286 
287     // Layers can have a "buffer size" of [0, 0, -1, -1] when no display frame has
288     // been set and there is no parent layer bounds. In that case, the scale is meaningless so
289     // ignore them.
290     if (!mSnapshot->bufferSize.isValid()) {
291         bufferWidth = float(win.right) - float(win.left);
292         bufferHeight = float(win.bottom) - float(win.top);
293     }
294 
295     const float scaleHeight = (float(win.bottom) - float(win.top)) / bufferHeight;
296     const float scaleWidth = (float(win.right) - float(win.left)) / bufferWidth;
297     const float translateY = float(win.top) / bufferHeight;
298     const float translateX = float(win.left) / bufferWidth;
299 
300     // Flip y-coordinates because GLConsumer expects OpenGL convention.
301     mat4 tr = mat4::translate(vec4(.5f, .5f, 0.f, 1.f)) * mat4::scale(vec4(1.f, -1.f, 1.f, 1.f)) *
302             mat4::translate(vec4(-.5f, -.5f, 0.f, 1.f)) *
303             mat4::translate(vec4(translateX, translateY, 0.f, 1.f)) *
304             mat4::scale(vec4(scaleWidth, scaleHeight, 1.0f, 1.0f));
305 
306     layerSettings.source.buffer.useTextureFiltering = targetSettings.needsFiltering;
307     layerSettings.source.buffer.textureTransform =
308             mat4(static_cast<const float*>(textureMatrix)) * tr;
309 
310     return;
311 }
312 
prepareShadowClientComposition(LayerFE::LayerSettings & caster,const Rect & layerStackRect) const313 void LayerFE::prepareShadowClientComposition(LayerFE::LayerSettings& caster,
314                                              const Rect& layerStackRect) const {
315     renderengine::ShadowSettings state = mSnapshot->shadowSettings;
316     if (state.length <= 0.f || (state.ambientColor.a <= 0.f && state.spotColor.a <= 0.f)) {
317         return;
318     }
319 
320     // Shift the spot light x-position to the middle of the display and then
321     // offset it by casting layer's screen pos.
322     state.lightPos.x =
323             (static_cast<float>(layerStackRect.width()) / 2.f) - mSnapshot->transformedBounds.left;
324     state.lightPos.y -= mSnapshot->transformedBounds.top;
325     caster.shadow = state;
326 }
327 
onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,ui::LayerStack layerStack)328 void LayerFE::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,
329                                ui::LayerStack layerStack) {
330     mCompositionResult.releaseFences.emplace_back(std::move(futureFenceResult), layerStack);
331 }
332 
stealCompositionResult()333 CompositionResult&& LayerFE::stealCompositionResult() {
334     return std::move(mCompositionResult);
335 }
336 
getDebugName() const337 const char* LayerFE::getDebugName() const {
338     return mName.c_str();
339 }
340 
getMetadata() const341 const LayerMetadata* LayerFE::getMetadata() const {
342     return &mSnapshot->layerMetadata;
343 }
344 
getRelativeMetadata() const345 const LayerMetadata* LayerFE::getRelativeMetadata() const {
346     return &mSnapshot->relativeLayerMetadata;
347 }
348 
getSequence() const349 int32_t LayerFE::getSequence() const {
350     return mSnapshot->sequence;
351 }
352 
hasRoundedCorners() const353 bool LayerFE::hasRoundedCorners() const {
354     return mSnapshot->roundedCorner.hasRoundedCorners();
355 }
356 
setWasClientComposed(const sp<Fence> & fence)357 void LayerFE::setWasClientComposed(const sp<Fence>& fence) {
358     mCompositionResult.lastClientCompositionFence = fence;
359 }
360 
hasBufferOrSidebandStream() const361 bool LayerFE::hasBufferOrSidebandStream() const {
362     return mSnapshot->externalTexture || mSnapshot->sidebandStream;
363 }
364 
fillsColor() const365 bool LayerFE::fillsColor() const {
366     return mSnapshot->color.r >= 0.0_hf && mSnapshot->color.g >= 0.0_hf &&
367             mSnapshot->color.b >= 0.0_hf;
368 }
369 
hasBlur() const370 bool LayerFE::hasBlur() const {
371     return mSnapshot->backgroundBlurRadius > 0 || mSnapshot->blurRegions.size() > 0;
372 }
373 
drawShadows() const374 bool LayerFE::drawShadows() const {
375     return mSnapshot->shadowSettings.length > 0.f &&
376             (mSnapshot->shadowSettings.ambientColor.a > 0 ||
377              mSnapshot->shadowSettings.spotColor.a > 0);
378 };
379 
getBuffer() const380 const sp<GraphicBuffer> LayerFE::getBuffer() const {
381     return mSnapshot->externalTexture ? mSnapshot->externalTexture->getBuffer() : nullptr;
382 }
383 
384 } // namespace android
385