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