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 "SurfaceFlinger"
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 #include "common/FlagManager.h"
31 #include "ui/FenceResult.h"
32 #include "ui/LayerStack.h"
33 
34 namespace android {
35 
36 namespace {
37 constexpr float defaultMaxLuminance = 1000.0;
38 
inverseOrientation(uint32_t transform)39 constexpr mat4 inverseOrientation(uint32_t transform) {
40     const mat4 flipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
41     const mat4 flipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
42     const mat4 rot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
43     mat4 tr;
44 
45     if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
46         tr = tr * rot90;
47     }
48     if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
49         tr = tr * flipH;
50     }
51     if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
52         tr = tr * flipV;
53     }
54     return inverse(tr);
55 }
56 
reduce(const FloatRect & win,const Region & exclude)57 FloatRect reduce(const FloatRect& win, const Region& exclude) {
58     if (CC_LIKELY(exclude.isEmpty())) {
59         return win;
60     }
61     // Convert through Rect (by rounding) for lack of FloatRegion
62     return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect();
63 }
64 
65 // Computes the transform matrix using the setFilteringEnabled to determine whether the
66 // 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])67 void getDrawingTransformMatrix(const std::shared_ptr<renderengine::ExternalTexture>& buffer,
68                                Rect bufferCrop, uint32_t bufferTransform, bool filteringEnabled,
69                                float outMatrix[16]) {
70     if (!buffer) {
71         ALOGE("Buffer should not be null!");
72         return;
73     }
74     GLConsumer::computeTransformMatrix(outMatrix, static_cast<float>(buffer->getWidth()),
75                                        static_cast<float>(buffer->getHeight()),
76                                        buffer->getPixelFormat(), bufferCrop, bufferTransform,
77                                        filteringEnabled);
78 }
79 
80 } // namespace
81 
LayerFE(const std::string & name)82 LayerFE::LayerFE(const std::string& name) : mName(name) {}
83 
~LayerFE()84 LayerFE::~LayerFE() {
85     // Ensures that no promise is left unfulfilled before the LayerFE is destroyed.
86     // An unfulfilled promise could occur when a screenshot is attempted, but the
87     // render area is invalid and there is no memory for the capture result.
88     if (FlagManager::getInstance().ce_fence_promise() &&
89         mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::INITIALIZED) {
90         setReleaseFence(Fence::NO_FENCE);
91     }
92 }
93 
getCompositionState() const94 const compositionengine::LayerFECompositionState* LayerFE::getCompositionState() const {
95     return mSnapshot.get();
96 }
97 
onPreComposition(bool)98 bool LayerFE::onPreComposition(bool) {
99     return mSnapshot->hasReadyFrame;
100 }
101 
prepareClientComposition(compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const102 std::optional<compositionengine::LayerFE::LayerSettings> LayerFE::prepareClientComposition(
103         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
104     std::optional<compositionengine::LayerFE::LayerSettings> layerSettings =
105             prepareClientCompositionInternal(targetSettings);
106     // Nothing to render.
107     if (!layerSettings) {
108         return {};
109     }
110 
111     // HWC requests to clear this layer.
112     if (targetSettings.clearContent) {
113         prepareClearClientComposition(*layerSettings, false /* blackout */);
114         return layerSettings;
115     }
116 
117     // set the shadow for the layer if needed
118     prepareShadowClientComposition(*layerSettings, targetSettings.viewport);
119 
120     return layerSettings;
121 }
122 
prepareClientCompositionInternal(compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const123 std::optional<compositionengine::LayerFE::LayerSettings> LayerFE::prepareClientCompositionInternal(
124         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
125     ATRACE_CALL();
126     compositionengine::LayerFE::LayerSettings layerSettings;
127     layerSettings.geometry.boundaries =
128             reduce(mSnapshot->geomLayerBounds, mSnapshot->transparentRegionHint);
129     layerSettings.geometry.positionTransform = mSnapshot->geomLayerTransform.asMatrix4();
130 
131     // skip drawing content if the targetSettings indicate the content will be occluded
132     const bool drawContent = targetSettings.realContentIsVisible || targetSettings.clearContent;
133     layerSettings.skipContentDraw = !drawContent;
134 
135     if (!mSnapshot->colorTransformIsIdentity) {
136         layerSettings.colorTransform = mSnapshot->colorTransform;
137     }
138 
139     const auto& roundedCornerState = mSnapshot->roundedCorner;
140     layerSettings.geometry.roundedCornersRadius = roundedCornerState.radius;
141     layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect;
142 
143     layerSettings.alpha = mSnapshot->alpha;
144     layerSettings.sourceDataspace = mSnapshot->dataspace;
145 
146     // Override the dataspace transfer from 170M to sRGB if the device configuration requests this.
147     // We do this here instead of in buffer info so that dumpsys can still report layers that are
148     // using the 170M transfer.
149     if (targetSettings.treat170mAsSrgb &&
150         (layerSettings.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) ==
151                 HAL_DATASPACE_TRANSFER_SMPTE_170M) {
152         layerSettings.sourceDataspace = static_cast<ui::Dataspace>(
153                 (layerSettings.sourceDataspace & HAL_DATASPACE_STANDARD_MASK) |
154                 (layerSettings.sourceDataspace & HAL_DATASPACE_RANGE_MASK) |
155                 HAL_DATASPACE_TRANSFER_SRGB);
156     }
157 
158     layerSettings.whitePointNits = targetSettings.whitePointNits;
159     switch (targetSettings.blurSetting) {
160         case LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled:
161             layerSettings.backgroundBlurRadius = mSnapshot->backgroundBlurRadius;
162             layerSettings.blurRegions = mSnapshot->blurRegions;
163             layerSettings.blurRegionTransform = mSnapshot->localTransformInverse.asMatrix4();
164             break;
165         case LayerFE::ClientCompositionTargetSettings::BlurSetting::BackgroundBlurOnly:
166             layerSettings.backgroundBlurRadius = mSnapshot->backgroundBlurRadius;
167             break;
168         case LayerFE::ClientCompositionTargetSettings::BlurSetting::BlurRegionsOnly:
169             layerSettings.blurRegions = mSnapshot->blurRegions;
170             layerSettings.blurRegionTransform = mSnapshot->localTransformInverse.asMatrix4();
171             break;
172         case LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled:
173         default:
174             break;
175     }
176     layerSettings.stretchEffect = mSnapshot->stretchEffect;
177     // Record the name of the layer for debugging further down the stack.
178     layerSettings.name = mSnapshot->name;
179 
180     if (hasEffect() && !hasBufferOrSidebandStream()) {
181         prepareEffectsClientComposition(layerSettings, targetSettings);
182         return layerSettings;
183     }
184 
185     prepareBufferStateClientComposition(layerSettings, targetSettings);
186     return layerSettings;
187 }
188 
prepareClearClientComposition(LayerFE::LayerSettings & layerSettings,bool blackout) const189 void LayerFE::prepareClearClientComposition(LayerFE::LayerSettings& layerSettings,
190                                             bool blackout) const {
191     layerSettings.source.buffer.buffer = nullptr;
192     layerSettings.source.solidColor = half3(0.0f, 0.0f, 0.0f);
193     layerSettings.disableBlending = true;
194     layerSettings.bufferId = 0;
195     layerSettings.frameNumber = 0;
196 
197     // If layer is blacked out, force alpha to 1 so that we draw a black color layer.
198     layerSettings.alpha = blackout ? 1.0f : 0.0f;
199     layerSettings.name = mSnapshot->name;
200 }
201 
prepareEffectsClientComposition(compositionengine::LayerFE::LayerSettings & layerSettings,compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const202 void LayerFE::prepareEffectsClientComposition(
203         compositionengine::LayerFE::LayerSettings& layerSettings,
204         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
205     // If fill bounds are occluded or the fill color is invalid skip the fill settings.
206     if (targetSettings.realContentIsVisible && fillsColor()) {
207         // Set color for color fill settings.
208         layerSettings.source.solidColor = mSnapshot->color.rgb;
209     } else if (hasBlur() || drawShadows()) {
210         layerSettings.skipContentDraw = true;
211     }
212 }
213 
prepareBufferStateClientComposition(compositionengine::LayerFE::LayerSettings & layerSettings,compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const214 void LayerFE::prepareBufferStateClientComposition(
215         compositionengine::LayerFE::LayerSettings& layerSettings,
216         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
217     ATRACE_CALL();
218     if (CC_UNLIKELY(!mSnapshot->externalTexture)) {
219         // If there is no buffer for the layer or we have sidebandstream where there is no
220         // activeBuffer, then we need to return LayerSettings.
221         return;
222     }
223     bool blackOutLayer;
224     if (FlagManager::getInstance().display_protected()) {
225         blackOutLayer = (mSnapshot->hasProtectedContent && !targetSettings.isProtected) ||
226                 (mSnapshot->isSecure && !targetSettings.isSecure);
227     } else {
228         blackOutLayer = (mSnapshot->hasProtectedContent && !targetSettings.isProtected) ||
229                 ((mSnapshot->isSecure || mSnapshot->hasProtectedContent) &&
230                  !targetSettings.isSecure);
231     }
232     const bool bufferCanBeUsedAsHwTexture =
233             mSnapshot->externalTexture->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
234     if (blackOutLayer || !bufferCanBeUsedAsHwTexture) {
235         ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable",
236                  mSnapshot->name.c_str());
237         prepareClearClientComposition(layerSettings, true /* blackout */);
238         return;
239     }
240 
241     layerSettings.source.buffer.buffer = mSnapshot->externalTexture;
242     layerSettings.source.buffer.isOpaque = mSnapshot->contentOpaque;
243     layerSettings.source.buffer.fence = mSnapshot->acquireFence;
244     layerSettings.source.buffer.usePremultipliedAlpha = mSnapshot->premultipliedAlpha;
245     bool hasSmpte2086 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::SMPTE2086;
246     bool hasCta861_3 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::CTA861_3;
247     float maxLuminance = 0.f;
248     if (hasSmpte2086 && hasCta861_3) {
249         maxLuminance = std::min(mSnapshot->hdrMetadata.smpte2086.maxLuminance,
250                                 mSnapshot->hdrMetadata.cta8613.maxContentLightLevel);
251     } else if (hasSmpte2086) {
252         maxLuminance = mSnapshot->hdrMetadata.smpte2086.maxLuminance;
253     } else if (hasCta861_3) {
254         maxLuminance = mSnapshot->hdrMetadata.cta8613.maxContentLightLevel;
255     } else {
256         switch (layerSettings.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) {
257             case HAL_DATASPACE_TRANSFER_ST2084:
258             case HAL_DATASPACE_TRANSFER_HLG:
259                 // Behavior-match previous releases for HDR content
260                 maxLuminance = defaultMaxLuminance;
261                 break;
262         }
263     }
264     layerSettings.source.buffer.maxLuminanceNits = maxLuminance;
265     layerSettings.frameNumber = mSnapshot->frameNumber;
266     layerSettings.bufferId = mSnapshot->externalTexture->getId();
267 
268     const bool useFiltering = targetSettings.needsFiltering ||
269                               mSnapshot->geomLayerTransform.needsBilinearFiltering();
270 
271     // Query the texture matrix given our current filtering mode.
272     float textureMatrix[16];
273     getDrawingTransformMatrix(layerSettings.source.buffer.buffer, mSnapshot->geomContentCrop,
274                               mSnapshot->geomBufferTransform, useFiltering,
275                               textureMatrix);
276 
277     if (mSnapshot->geomBufferUsesDisplayInverseTransform) {
278         /*
279          * the code below applies the primary display's inverse transform to
280          * the texture transform
281          */
282         uint32_t transform = SurfaceFlinger::getActiveDisplayRotationFlags();
283         mat4 tr = inverseOrientation(transform);
284 
285         /**
286          * TODO(b/36727915): This is basically a hack.
287          *
288          * Ensure that regardless of the parent transformation,
289          * this buffer is always transformed from native display
290          * orientation to display orientation. For example, in the case
291          * of a camera where the buffer remains in native orientation,
292          * we want the pixels to always be upright.
293          */
294         const auto parentTransform = mSnapshot->parentTransform;
295         tr = tr * inverseOrientation(parentTransform.getOrientation());
296 
297         // and finally apply it to the original texture matrix
298         const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
299         memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
300     }
301 
302     const Rect win{layerSettings.geometry.boundaries};
303     float bufferWidth = static_cast<float>(mSnapshot->bufferSize.getWidth());
304     float bufferHeight = static_cast<float>(mSnapshot->bufferSize.getHeight());
305 
306     // Layers can have a "buffer size" of [0, 0, -1, -1] when no display frame has
307     // been set and there is no parent layer bounds. In that case, the scale is meaningless so
308     // ignore them.
309     if (!mSnapshot->bufferSize.isValid()) {
310         bufferWidth = float(win.right) - float(win.left);
311         bufferHeight = float(win.bottom) - float(win.top);
312     }
313 
314     const float scaleHeight = (float(win.bottom) - float(win.top)) / bufferHeight;
315     const float scaleWidth = (float(win.right) - float(win.left)) / bufferWidth;
316     const float translateY = float(win.top) / bufferHeight;
317     const float translateX = float(win.left) / bufferWidth;
318 
319     // Flip y-coordinates because GLConsumer expects OpenGL convention.
320     mat4 tr = mat4::translate(vec4(.5f, .5f, 0.f, 1.f)) * mat4::scale(vec4(1.f, -1.f, 1.f, 1.f)) *
321             mat4::translate(vec4(-.5f, -.5f, 0.f, 1.f)) *
322             mat4::translate(vec4(translateX, translateY, 0.f, 1.f)) *
323             mat4::scale(vec4(scaleWidth, scaleHeight, 1.0f, 1.0f));
324 
325     layerSettings.source.buffer.useTextureFiltering = useFiltering;
326     layerSettings.source.buffer.textureTransform =
327             mat4(static_cast<const float*>(textureMatrix)) * tr;
328 
329     return;
330 }
331 
prepareShadowClientComposition(LayerFE::LayerSettings & caster,const Rect & layerStackRect) const332 void LayerFE::prepareShadowClientComposition(LayerFE::LayerSettings& caster,
333                                              const Rect& layerStackRect) const {
334     ShadowSettings state = mSnapshot->shadowSettings;
335     if (state.length <= 0.f || (state.ambientColor.a <= 0.f && state.spotColor.a <= 0.f)) {
336         return;
337     }
338 
339     // Shift the spot light x-position to the middle of the display and then
340     // offset it by casting layer's screen pos.
341     state.lightPos.x =
342             (static_cast<float>(layerStackRect.width()) / 2.f) - mSnapshot->transformedBounds.left;
343     state.lightPos.y -= mSnapshot->transformedBounds.top;
344     caster.shadow = state;
345 }
346 
onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,ui::LayerStack layerStack)347 void LayerFE::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,
348                                ui::LayerStack layerStack) {
349     mCompositionResult.releaseFences.emplace_back(std::move(futureFenceResult), layerStack);
350 }
351 
stealCompositionResult()352 CompositionResult&& LayerFE::stealCompositionResult() {
353     return std::move(mCompositionResult);
354 }
355 
getDebugName() const356 const char* LayerFE::getDebugName() const {
357     return mName.c_str();
358 }
359 
getMetadata() const360 const LayerMetadata* LayerFE::getMetadata() const {
361     return &mSnapshot->layerMetadata;
362 }
363 
getRelativeMetadata() const364 const LayerMetadata* LayerFE::getRelativeMetadata() const {
365     return &mSnapshot->relativeLayerMetadata;
366 }
367 
getSequence() const368 int32_t LayerFE::getSequence() const {
369     return static_cast<int32_t>(mSnapshot->uniqueSequence);
370 }
371 
hasRoundedCorners() const372 bool LayerFE::hasRoundedCorners() const {
373     return mSnapshot->roundedCorner.hasRoundedCorners();
374 }
375 
setWasClientComposed(const sp<Fence> & fence)376 void LayerFE::setWasClientComposed(const sp<Fence>& fence) {
377     mCompositionResult.lastClientCompositionFence = fence;
378 }
379 
hasBufferOrSidebandStream() const380 bool LayerFE::hasBufferOrSidebandStream() const {
381     return mSnapshot->externalTexture || mSnapshot->sidebandStream;
382 }
383 
fillsColor() const384 bool LayerFE::fillsColor() const {
385     return mSnapshot->color.r >= 0.0_hf && mSnapshot->color.g >= 0.0_hf &&
386             mSnapshot->color.b >= 0.0_hf;
387 }
388 
hasBlur() const389 bool LayerFE::hasBlur() const {
390     return mSnapshot->backgroundBlurRadius > 0 || mSnapshot->blurRegions.size() > 0;
391 }
392 
drawShadows() const393 bool LayerFE::drawShadows() const {
394     return mSnapshot->shadowSettings.length > 0.f &&
395             (mSnapshot->shadowSettings.ambientColor.a > 0 ||
396              mSnapshot->shadowSettings.spotColor.a > 0);
397 };
398 
getBuffer() const399 const sp<GraphicBuffer> LayerFE::getBuffer() const {
400     return mSnapshot->externalTexture ? mSnapshot->externalTexture->getBuffer() : nullptr;
401 }
402 
setReleaseFence(const FenceResult & releaseFence)403 void LayerFE::setReleaseFence(const FenceResult& releaseFence) {
404     // Promises should not be fulfilled more than once. This case can occur if virtual
405     // displays with the same layerstack ID are being created and destroyed in quick
406     // succession, such as in tests. This would result in a race condition in which
407     // multiple displays have the same layerstack ID within the same vsync interval.
408     if (mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::FULFILLED) {
409         return;
410     }
411     mReleaseFence.set_value(releaseFence);
412     mReleaseFencePromiseStatus = ReleaseFencePromiseStatus::FULFILLED;
413 }
414 
415 // LayerFEs are reused and a new fence needs to be created whevever a buffer is latched.
createReleaseFenceFuture()416 ftl::Future<FenceResult> LayerFE::createReleaseFenceFuture() {
417     if (mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::INITIALIZED) {
418         LOG_ALWAYS_FATAL("Attempting to create a new promise while one is still unfulfilled.");
419     }
420     mReleaseFence = std::promise<FenceResult>();
421     mReleaseFencePromiseStatus = ReleaseFencePromiseStatus::INITIALIZED;
422     return mReleaseFence.get_future();
423 }
424 
getReleaseFencePromiseStatus()425 LayerFE::ReleaseFencePromiseStatus LayerFE::getReleaseFencePromiseStatus() {
426     return mReleaseFencePromiseStatus;
427 }
428 } // namespace android
429