• 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 "SurfaceFlinger"
20 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
21 
22 #include <common/trace.h>
23 #include <gui/GLConsumer.h>
24 #include <math/vec3.h>
25 #include <system/window.h>
26 
27 #include "LayerFE.h"
28 #include "SurfaceFlinger.h"
29 #include "ui/FenceResult.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 
~LayerFE()81 LayerFE::~LayerFE() {
82     // Ensures that no promise is left unfulfilled before the LayerFE is destroyed.
83     // An unfulfilled promise could occur when a screenshot is attempted, but the
84     // render area is invalid and there is no memory for the capture result.
85     if (mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::INITIALIZED) {
86         setReleaseFence(Fence::NO_FENCE);
87     }
88 }
89 
getCompositionState() const90 const compositionengine::LayerFECompositionState* LayerFE::getCompositionState() const {
91     return mSnapshot.get();
92 }
93 
onPreComposition(bool)94 bool LayerFE::onPreComposition(bool) {
95     return mSnapshot->hasReadyFrame;
96 }
97 
prepareClientComposition(compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const98 std::optional<compositionengine::LayerFE::LayerSettings> LayerFE::prepareClientComposition(
99         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
100     std::optional<compositionengine::LayerFE::LayerSettings> layerSettings =
101             prepareClientCompositionInternal(targetSettings);
102     // Nothing to render.
103     if (!layerSettings) {
104         return {};
105     }
106 
107     // HWC requests to clear this layer.
108     if (targetSettings.clearContent) {
109         prepareClearClientComposition(*layerSettings, false /* blackout */);
110         return layerSettings;
111     }
112 
113     // set the shadow for the layer if needed
114     prepareShadowClientComposition(*layerSettings, targetSettings.viewport);
115 
116     layerSettings->borderSettings = mSnapshot->borderSettings;
117 
118     return layerSettings;
119 }
120 
prepareClientCompositionInternal(compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const121 std::optional<compositionengine::LayerFE::LayerSettings> LayerFE::prepareClientCompositionInternal(
122         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
123     SFTRACE_CALL();
124     compositionengine::LayerFE::LayerSettings layerSettings;
125     layerSettings.geometry.originalBounds = mSnapshot->geomLayerBounds;
126     layerSettings.geometry.boundaries =
127             reduce(mSnapshot->geomLayerBounds, mSnapshot->transparentRegionHint);
128     layerSettings.geometry.positionTransform = mSnapshot->geomLayerTransform.asMatrix4();
129 
130     // skip drawing content if the targetSettings indicate the content will be occluded
131     const bool drawContent = targetSettings.realContentIsVisible || targetSettings.clearContent;
132     layerSettings.skipContentDraw = !drawContent;
133 
134     if (!mSnapshot->colorTransformIsIdentity) {
135         layerSettings.colorTransform = mSnapshot->colorTransform;
136     }
137 
138     const auto& roundedCornerState = mSnapshot->roundedCorner;
139     layerSettings.geometry.roundedCornersRadius = roundedCornerState.radius;
140     layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect;
141 
142     layerSettings.alpha = mSnapshot->alpha;
143     layerSettings.sourceDataspace = mSnapshot->dataspace;
144 
145     // Override the dataspace transfer from 170M to sRGB if the device configuration requests this.
146     // We do this here instead of in buffer info so that dumpsys can still report layers that are
147     // using the 170M transfer.
148     if (targetSettings.treat170mAsSrgb &&
149         (layerSettings.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) ==
150                 HAL_DATASPACE_TRANSFER_SMPTE_170M) {
151         layerSettings.sourceDataspace = static_cast<ui::Dataspace>(
152                 (layerSettings.sourceDataspace & HAL_DATASPACE_STANDARD_MASK) |
153                 (layerSettings.sourceDataspace & HAL_DATASPACE_RANGE_MASK) |
154                 HAL_DATASPACE_TRANSFER_SRGB);
155     }
156 
157     layerSettings.whitePointNits = targetSettings.whitePointNits;
158     switch (targetSettings.blurSetting) {
159         case LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled:
160             layerSettings.backgroundBlurRadius = mSnapshot->backgroundBlurRadius;
161             layerSettings.blurRegions = mSnapshot->blurRegions;
162             layerSettings.blurRegionTransform = mSnapshot->localTransformInverse.asMatrix4();
163             break;
164         case LayerFE::ClientCompositionTargetSettings::BlurSetting::BackgroundBlurOnly:
165             layerSettings.backgroundBlurRadius = mSnapshot->backgroundBlurRadius;
166             break;
167         case LayerFE::ClientCompositionTargetSettings::BlurSetting::BlurRegionsOnly:
168             layerSettings.blurRegions = mSnapshot->blurRegions;
169             layerSettings.blurRegionTransform = mSnapshot->localTransformInverse.asMatrix4();
170             break;
171         case LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled:
172         default:
173             break;
174     }
175     layerSettings.stretchEffect = mSnapshot->stretchEffect;
176     layerSettings.edgeExtensionEffect = mSnapshot->edgeExtensionEffect;
177     // Record the name of the layer for debugging further down the stack.
178     layerSettings.name = mSnapshot->name;
179     layerSettings.luts = mSnapshot->luts ? mSnapshot->luts : targetSettings.luts;
180 
181     if (hasEffect() && !hasBufferOrSidebandStream()) {
182         prepareEffectsClientComposition(layerSettings, targetSettings);
183         return layerSettings;
184     }
185 
186     prepareBufferStateClientComposition(layerSettings, targetSettings);
187     return layerSettings;
188 }
189 
prepareClearClientComposition(LayerFE::LayerSettings & layerSettings,bool blackout) const190 void LayerFE::prepareClearClientComposition(LayerFE::LayerSettings& layerSettings,
191                                             bool blackout) const {
192     layerSettings.source.buffer.buffer = nullptr;
193     layerSettings.source.solidColor = half3(0.0f, 0.0f, 0.0f);
194     layerSettings.disableBlending = true;
195     layerSettings.bufferId = 0;
196     layerSettings.frameNumber = 0;
197     layerSettings.sequence = -1;
198 
199     // If layer is blacked out, force alpha to 1 so that we draw a black color layer.
200     layerSettings.alpha = blackout ? 1.0f : 0.0f;
201     layerSettings.name = mSnapshot->name;
202 }
203 
prepareEffectsClientComposition(compositionengine::LayerFE::LayerSettings & layerSettings,compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const204 void LayerFE::prepareEffectsClientComposition(
205         compositionengine::LayerFE::LayerSettings& layerSettings,
206         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
207     // If fill bounds are occluded or the fill color is invalid skip the fill settings.
208     if (targetSettings.realContentIsVisible && fillsColor()) {
209         // Set color for color fill settings.
210         layerSettings.source.solidColor = mSnapshot->color.rgb;
211     } else if (hasBlur() || drawShadows() || hasOutline()) {
212         layerSettings.skipContentDraw = true;
213     }
214 }
215 
prepareBufferStateClientComposition(compositionengine::LayerFE::LayerSettings & layerSettings,compositionengine::LayerFE::ClientCompositionTargetSettings & targetSettings) const216 void LayerFE::prepareBufferStateClientComposition(
217         compositionengine::LayerFE::LayerSettings& layerSettings,
218         compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
219     SFTRACE_CALL();
220     if (CC_UNLIKELY(!mSnapshot->externalTexture)) {
221         // If there is no buffer for the layer or we have sidebandstream where there is no
222         // activeBuffer, then we need to return LayerSettings.
223         return;
224     }
225     bool blackOutLayer;
226     if (FlagManager::getInstance().display_protected()) {
227         blackOutLayer = (mSnapshot->hasProtectedContent && !targetSettings.isProtected) ||
228                 (mSnapshot->isSecure && !targetSettings.isSecure);
229     } else {
230         blackOutLayer = (mSnapshot->hasProtectedContent && !targetSettings.isProtected) ||
231                 ((mSnapshot->isSecure || mSnapshot->hasProtectedContent) &&
232                  !targetSettings.isSecure);
233     }
234     const bool bufferCanBeUsedAsHwTexture =
235             mSnapshot->externalTexture->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
236     if (blackOutLayer || !bufferCanBeUsedAsHwTexture) {
237         ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable",
238                  mSnapshot->name.c_str());
239         prepareClearClientComposition(layerSettings, true /* blackout */);
240         return;
241     }
242 
243     layerSettings.source.buffer.buffer = mSnapshot->externalTexture;
244     layerSettings.source.buffer.isOpaque = mSnapshot->contentOpaque;
245     layerSettings.source.buffer.fence = mSnapshot->acquireFence;
246     layerSettings.source.buffer.usePremultipliedAlpha = mSnapshot->premultipliedAlpha;
247     bool hasSmpte2086 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::SMPTE2086;
248     bool hasCta861_3 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::CTA861_3;
249     float maxLuminance = 0.f;
250     if (hasSmpte2086 && hasCta861_3) {
251         maxLuminance = std::min(mSnapshot->hdrMetadata.smpte2086.maxLuminance,
252                                 mSnapshot->hdrMetadata.cta8613.maxContentLightLevel);
253     } else if (hasSmpte2086) {
254         maxLuminance = mSnapshot->hdrMetadata.smpte2086.maxLuminance;
255     } else if (hasCta861_3) {
256         maxLuminance = mSnapshot->hdrMetadata.cta8613.maxContentLightLevel;
257     } else {
258         switch (layerSettings.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) {
259             case HAL_DATASPACE_TRANSFER_ST2084:
260             case HAL_DATASPACE_TRANSFER_HLG:
261                 // Behavior-match previous releases for HDR content
262                 maxLuminance = defaultMaxLuminance;
263                 break;
264         }
265     }
266     layerSettings.source.buffer.maxLuminanceNits = maxLuminance;
267     layerSettings.frameNumber = mSnapshot->frameNumber;
268     layerSettings.bufferId = mSnapshot->externalTexture->getId();
269     layerSettings.sequence = mSnapshot->sequence;
270 
271     const bool useFiltering = targetSettings.needsFiltering ||
272                               mSnapshot->geomLayerTransform.needsBilinearFiltering();
273 
274     // Query the texture matrix given our current filtering mode.
275     float textureMatrix[16];
276     getDrawingTransformMatrix(layerSettings.source.buffer.buffer, mSnapshot->geomContentCrop,
277                               mSnapshot->geomBufferTransform, useFiltering,
278                               textureMatrix);
279 
280     if (mSnapshot->geomBufferUsesDisplayInverseTransform) {
281         /*
282          * the code below applies the primary display's inverse transform to
283          * the texture transform
284          */
285         uint32_t transform = SurfaceFlinger::getActiveDisplayRotationFlags();
286         mat4 tr = inverseOrientation(transform);
287 
288         /**
289          * TODO(b/36727915): This is basically a hack.
290          *
291          * Ensure that regardless of the parent transformation,
292          * this buffer is always transformed from native display
293          * orientation to display orientation. For example, in the case
294          * of a camera where the buffer remains in native orientation,
295          * we want the pixels to always be upright.
296          */
297         const auto parentTransform = mSnapshot->parentTransform;
298         tr = tr * inverseOrientation(parentTransform.getOrientation());
299 
300         // and finally apply it to the original texture matrix
301         const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
302         memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
303     }
304 
305     const Rect win{layerSettings.geometry.boundaries};
306     float bufferWidth = static_cast<float>(mSnapshot->bufferSize.getWidth());
307     float bufferHeight = static_cast<float>(mSnapshot->bufferSize.getHeight());
308 
309     // Layers can have a "buffer size" of [0, 0, -1, -1] when no display frame has
310     // been set and there is no parent layer bounds. In that case, the scale is meaningless so
311     // ignore them.
312     if (!mSnapshot->bufferSize.isValid()) {
313         bufferWidth = float(win.right) - float(win.left);
314         bufferHeight = float(win.bottom) - float(win.top);
315     }
316 
317     const float scaleHeight = (float(win.bottom) - float(win.top)) / bufferHeight;
318     const float scaleWidth = (float(win.right) - float(win.left)) / bufferWidth;
319     const float translateY = float(win.top) / bufferHeight;
320     const float translateX = float(win.left) / bufferWidth;
321 
322     // Flip y-coordinates because GLConsumer expects OpenGL convention.
323     mat4 tr = mat4::translate(vec4(.5f, .5f, 0.f, 1.f)) * mat4::scale(vec4(1.f, -1.f, 1.f, 1.f)) *
324             mat4::translate(vec4(-.5f, -.5f, 0.f, 1.f)) *
325             mat4::translate(vec4(translateX, translateY, 0.f, 1.f)) *
326             mat4::scale(vec4(scaleWidth, scaleHeight, 1.0f, 1.0f));
327 
328     layerSettings.source.buffer.useTextureFiltering = useFiltering;
329     layerSettings.source.buffer.textureTransform =
330             mat4(static_cast<const float*>(textureMatrix)) * tr;
331 
332     return;
333 }
334 
prepareShadowClientComposition(LayerFE::LayerSettings & caster,const Rect & layerStackRect) const335 void LayerFE::prepareShadowClientComposition(LayerFE::LayerSettings& caster,
336                                              const Rect& layerStackRect) const {
337     ShadowSettings state = mSnapshot->shadowSettings;
338     if (state.length <= 0.f || (state.ambientColor.a <= 0.f && state.spotColor.a <= 0.f)) {
339         return;
340     }
341 
342     // Shift the spot light x-position to the middle of the display and then
343     // offset it by casting layer's screen pos.
344     state.lightPos.x =
345             (static_cast<float>(layerStackRect.width()) / 2.f) - mSnapshot->transformedBounds.left;
346     state.lightPos.y -= mSnapshot->transformedBounds.top;
347     caster.shadow = state;
348 }
349 
onPictureProfileCommitted()350 void LayerFE::onPictureProfileCommitted() {
351     mCompositionResult.wasPictureProfileCommitted = true;
352     mCompositionResult.pictureProfileHandle = mSnapshot->pictureProfileHandle;
353 }
354 
stealCompositionResult()355 CompositionResult LayerFE::stealCompositionResult() {
356     CompositionResult result;
357     std::swap(mCompositionResult, result);
358     return result;
359 }
360 
getDebugName() const361 const char* LayerFE::getDebugName() const {
362     return mName.c_str();
363 }
364 
getMetadata() const365 const LayerMetadata* LayerFE::getMetadata() const {
366     return &mSnapshot->layerMetadata;
367 }
368 
getRelativeMetadata() const369 const LayerMetadata* LayerFE::getRelativeMetadata() const {
370     return &mSnapshot->relativeLayerMetadata;
371 }
372 
getSequence() const373 int32_t LayerFE::getSequence() const {
374     return static_cast<int32_t>(mSnapshot->uniqueSequence);
375 }
376 
hasRoundedCorners() const377 bool LayerFE::hasRoundedCorners() const {
378     return mSnapshot->roundedCorner.hasRoundedCorners();
379 }
380 
setWasClientComposed(const sp<Fence> & fence)381 void LayerFE::setWasClientComposed(const sp<Fence>& fence) {
382     mCompositionResult.lastClientCompositionFence = fence;
383 }
384 
hasBufferOrSidebandStream() const385 bool LayerFE::hasBufferOrSidebandStream() const {
386     return mSnapshot->externalTexture || mSnapshot->sidebandStream;
387 }
388 
fillsColor() const389 bool LayerFE::fillsColor() const {
390     return mSnapshot->color.r >= 0.0_hf && mSnapshot->color.g >= 0.0_hf &&
391             mSnapshot->color.b >= 0.0_hf;
392 }
393 
hasBlur() const394 bool LayerFE::hasBlur() const {
395     return mSnapshot->backgroundBlurRadius > 0 || mSnapshot->blurRegions.size() > 0;
396 }
397 
hasOutline() const398 bool LayerFE::hasOutline() const {
399     return mSnapshot->borderSettings.strokeWidth > 0;
400 }
401 
drawShadows() const402 bool LayerFE::drawShadows() const {
403     return mSnapshot->shadowSettings.length > 0.f &&
404             (mSnapshot->shadowSettings.ambientColor.a > 0 ||
405              mSnapshot->shadowSettings.spotColor.a > 0);
406 };
407 
getBuffer() const408 const sp<GraphicBuffer> LayerFE::getBuffer() const {
409     return mSnapshot->externalTexture ? mSnapshot->externalTexture->getBuffer() : nullptr;
410 }
411 
setReleaseFence(const FenceResult & releaseFence)412 void LayerFE::setReleaseFence(const FenceResult& releaseFence) {
413     // Promises should not be fulfilled more than once. This case can occur if virtual
414     // displays with the same layerstack ID are being created and destroyed in quick
415     // succession, such as in tests. This would result in a race condition in which
416     // multiple displays have the same layerstack ID within the same vsync interval.
417     if (mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::FULFILLED) {
418         return;
419     }
420 
421     if (releaseFence.has_value()) {
422         if (FlagManager::getInstance().monitor_buffer_fences()) {
423             if (auto strongBuffer = mReleasedBuffer.promote()) {
424                 strongBuffer->getDependencyMonitor()
425                         .addAccessCompletion(FenceTime::makeValid(releaseFence.value()), "HWC");
426             }
427         }
428     }
429     mReleaseFence.set_value(releaseFence);
430     mReleaseFencePromiseStatus = ReleaseFencePromiseStatus::FULFILLED;
431 }
432 
433 // LayerFEs are reused and a new fence needs to be created whevever a buffer is latched.
createReleaseFenceFuture()434 ftl::Future<FenceResult> LayerFE::createReleaseFenceFuture() {
435     if (mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::INITIALIZED) {
436         LOG_ALWAYS_FATAL("Attempting to create a new promise while one is still unfulfilled.");
437     }
438     mReleaseFence = std::promise<FenceResult>();
439     mReleaseFencePromiseStatus = ReleaseFencePromiseStatus::INITIALIZED;
440     return mReleaseFence.get_future();
441 }
442 
getReleaseFencePromiseStatus()443 LayerFE::ReleaseFencePromiseStatus LayerFE::getReleaseFencePromiseStatus() {
444     return mReleaseFencePromiseStatus;
445 }
446 
setReleasedBuffer(sp<GraphicBuffer> buffer)447 void LayerFE::setReleasedBuffer(sp<GraphicBuffer> buffer) {
448     mReleasedBuffer = std::move(buffer);
449 }
450 
setLastHwcState(const LayerFE::HwcLayerDebugState & state)451 void LayerFE::setLastHwcState(const LayerFE::HwcLayerDebugState &state) {
452     mLastHwcState = state;
453 }
454 
getLastHwcState() const455 const LayerFE::HwcLayerDebugState& LayerFE::getLastHwcState() const {
456     return mLastHwcState;
457 };
458 
459 } // namespace android
460