blob: 97c4145dd14918ea0a12b3da63d4f5ba552350ce [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
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
Vishnu Naire14c6b32022-08-06 04:20:15 +000028#include "LayerFE.h"
Leon Scroggins III85d4b222023-05-09 13:58:18 -040029#include "SurfaceFlinger.h"
Vishnu Naire14c6b32022-08-06 04:20:15 +000030
31namespace android {
32
33namespace {
34constexpr float defaultMaxLuminance = 1000.0;
35
36constexpr 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
54FloatRect 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.
64void 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
79LayerFE::LayerFE(const std::string& name) : mName(name) {}
80
81const compositionengine::LayerFECompositionState* LayerFE::getCompositionState() const {
82 return mSnapshot.get();
83}
84
85bool LayerFE::onPreComposition(nsecs_t refreshStartTime, bool) {
86 mCompositionResult.refreshStartTime = refreshStartTime;
87 return mSnapshot->hasReadyFrame;
88}
89
90std::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
111std::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;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000151 layerSettings.blurRegionTransform = mSnapshot->localTransformInverse.asMatrix4();
Vishnu Naire14c6b32022-08-06 04:20:15 +0000152 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;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000158 layerSettings.blurRegionTransform = mSnapshot->localTransformInverse.asMatrix4();
Vishnu Naire14c6b32022-08-06 04:20:15 +0000159 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
177void 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
190void 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
202void 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;
Vishnu Naire14c6b32022-08-06 04:20:15 +0000226 layerSettings.source.buffer.usePremultipliedAlpha = mSnapshot->premultipliedAlpha;
Vishnu Naire14c6b32022-08-06 04:20:15 +0000227 bool hasSmpte2086 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::SMPTE2086;
228 bool hasCta861_3 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::CTA861_3;
229 float maxLuminance = 0.f;
230 if (hasSmpte2086 && hasCta861_3) {
231 maxLuminance = std::min(mSnapshot->hdrMetadata.smpte2086.maxLuminance,
232 mSnapshot->hdrMetadata.cta8613.maxContentLightLevel);
233 } else if (hasSmpte2086) {
234 maxLuminance = mSnapshot->hdrMetadata.smpte2086.maxLuminance;
235 } else if (hasCta861_3) {
236 maxLuminance = mSnapshot->hdrMetadata.cta8613.maxContentLightLevel;
237 } else {
238 switch (layerSettings.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) {
239 case HAL_DATASPACE_TRANSFER_ST2084:
240 case HAL_DATASPACE_TRANSFER_HLG:
241 // Behavior-match previous releases for HDR content
242 maxLuminance = defaultMaxLuminance;
243 break;
244 }
245 }
246 layerSettings.source.buffer.maxLuminanceNits = maxLuminance;
247 layerSettings.frameNumber = mSnapshot->frameNumber;
248 layerSettings.bufferId = mSnapshot->externalTexture->getId();
249
Vishnu Naire14c6b32022-08-06 04:20:15 +0000250 // Query the texture matrix given our current filtering mode.
251 float textureMatrix[16];
252 getDrawingTransformMatrix(layerSettings.source.buffer.buffer, mSnapshot->geomContentCrop,
Patrick Williams278a88f2023-01-27 16:52:40 -0600253 mSnapshot->geomBufferTransform, targetSettings.needsFiltering,
254 textureMatrix);
Vishnu Naire14c6b32022-08-06 04:20:15 +0000255
256 if (mSnapshot->geomBufferUsesDisplayInverseTransform) {
257 /*
258 * the code below applies the primary display's inverse transform to
259 * the texture transform
260 */
Leon Scroggins III85d4b222023-05-09 13:58:18 -0400261 uint32_t transform = SurfaceFlinger::getActiveDisplayRotationFlags();
Vishnu Naire14c6b32022-08-06 04:20:15 +0000262 mat4 tr = inverseOrientation(transform);
263
264 /**
265 * TODO(b/36727915): This is basically a hack.
266 *
267 * Ensure that regardless of the parent transformation,
268 * this buffer is always transformed from native display
269 * orientation to display orientation. For example, in the case
270 * of a camera where the buffer remains in native orientation,
271 * we want the pixels to always be upright.
272 */
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000273 const auto parentTransform = mSnapshot->parentTransform;
Vishnu Naire14c6b32022-08-06 04:20:15 +0000274 tr = tr * inverseOrientation(parentTransform.getOrientation());
275
276 // and finally apply it to the original texture matrix
277 const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
278 memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
279 }
280
281 const Rect win{layerSettings.geometry.boundaries};
282 float bufferWidth = static_cast<float>(mSnapshot->bufferSize.getWidth());
283 float bufferHeight = static_cast<float>(mSnapshot->bufferSize.getHeight());
284
285 // Layers can have a "buffer size" of [0, 0, -1, -1] when no display frame has
286 // been set and there is no parent layer bounds. In that case, the scale is meaningless so
287 // ignore them.
288 if (!mSnapshot->bufferSize.isValid()) {
289 bufferWidth = float(win.right) - float(win.left);
290 bufferHeight = float(win.bottom) - float(win.top);
291 }
292
293 const float scaleHeight = (float(win.bottom) - float(win.top)) / bufferHeight;
294 const float scaleWidth = (float(win.right) - float(win.left)) / bufferWidth;
295 const float translateY = float(win.top) / bufferHeight;
296 const float translateX = float(win.left) / bufferWidth;
297
298 // Flip y-coordinates because GLConsumer expects OpenGL convention.
299 mat4 tr = mat4::translate(vec4(.5f, .5f, 0.f, 1.f)) * mat4::scale(vec4(1.f, -1.f, 1.f, 1.f)) *
300 mat4::translate(vec4(-.5f, -.5f, 0.f, 1.f)) *
301 mat4::translate(vec4(translateX, translateY, 0.f, 1.f)) *
302 mat4::scale(vec4(scaleWidth, scaleHeight, 1.0f, 1.0f));
303
Patrick Williams278a88f2023-01-27 16:52:40 -0600304 layerSettings.source.buffer.useTextureFiltering = targetSettings.needsFiltering;
Vishnu Naire14c6b32022-08-06 04:20:15 +0000305 layerSettings.source.buffer.textureTransform =
306 mat4(static_cast<const float*>(textureMatrix)) * tr;
307
308 return;
309}
310
311void LayerFE::prepareShadowClientComposition(LayerFE::LayerSettings& caster,
312 const Rect& layerStackRect) const {
313 renderengine::ShadowSettings state = mSnapshot->shadowSettings;
314 if (state.length <= 0.f || (state.ambientColor.a <= 0.f && state.spotColor.a <= 0.f)) {
315 return;
316 }
317
318 // Shift the spot light x-position to the middle of the display and then
319 // offset it by casting layer's screen pos.
320 state.lightPos.x =
321 (static_cast<float>(layerStackRect.width()) / 2.f) - mSnapshot->transformedBounds.left;
322 state.lightPos.y -= mSnapshot->transformedBounds.top;
323 caster.shadow = state;
324}
325
Vishnu Nair7ee4f462023-04-19 09:54:09 -0700326void LayerFE::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,
327 ui::LayerStack layerStack) {
328 mCompositionResult.releaseFences.emplace_back(std::move(futureFenceResult), layerStack);
Vishnu Naire14c6b32022-08-06 04:20:15 +0000329}
330
331CompositionResult&& LayerFE::stealCompositionResult() {
332 return std::move(mCompositionResult);
333}
334
335const char* LayerFE::getDebugName() const {
336 return mName.c_str();
337}
338
339const LayerMetadata* LayerFE::getMetadata() const {
340 return &mSnapshot->layerMetadata;
341}
342
343const LayerMetadata* LayerFE::getRelativeMetadata() const {
344 return &mSnapshot->relativeLayerMetadata;
345}
346
347int32_t LayerFE::getSequence() const {
Vishnu Nair269f69d2023-09-08 11:45:26 -0700348 return static_cast<int32_t>(mSnapshot->uniqueSequence);
Vishnu Naire14c6b32022-08-06 04:20:15 +0000349}
350
351bool LayerFE::hasRoundedCorners() const {
352 return mSnapshot->roundedCorner.hasRoundedCorners();
353}
354
355void LayerFE::setWasClientComposed(const sp<Fence>& fence) {
356 mCompositionResult.lastClientCompositionFence = fence;
357}
358
359bool LayerFE::hasBufferOrSidebandStream() const {
360 return mSnapshot->externalTexture || mSnapshot->sidebandStream;
361}
362
363bool LayerFE::fillsColor() const {
364 return mSnapshot->color.r >= 0.0_hf && mSnapshot->color.g >= 0.0_hf &&
365 mSnapshot->color.b >= 0.0_hf;
366}
367
368bool LayerFE::hasBlur() const {
369 return mSnapshot->backgroundBlurRadius > 0 || mSnapshot->blurRegions.size() > 0;
370}
371
372bool LayerFE::drawShadows() const {
373 return mSnapshot->shadowSettings.length > 0.f &&
374 (mSnapshot->shadowSettings.ambientColor.a > 0 ||
375 mSnapshot->shadowSettings.spotColor.a > 0);
376};
377
378const sp<GraphicBuffer> LayerFE::getBuffer() const {
379 return mSnapshot->externalTexture ? mSnapshot->externalTexture->getBuffer() : nullptr;
380}
381
382} // namespace android