blob: 85b00d77b4580586592fcf2ce03157585fafc9a8 [file] [log] [blame]
Vishnu Nair8fc721b2022-12-22 20:06:32 +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 ATRACE_TAG ATRACE_TAG_GRAPHICS
18#undef LOG_TAG
19#define LOG_TAG "LayerSnapshot"
20
21#include "LayerSnapshot.h"
22
23namespace android::surfaceflinger::frontend {
24
25using namespace ftl::flag_operators;
26
27LayerSnapshot::LayerSnapshot(const RequestedLayerState& state,
28 const LayerHierarchy::TraversalPath& path)
29 : path(path) {
30 sequence = static_cast<int32_t>(state.id);
31 name = state.name;
32 textureName = state.textureName;
33 premultipliedAlpha = state.premultipliedAlpha;
34 inputInfo.name = state.name;
35 inputInfo.id = static_cast<int32_t>(state.id);
36 inputInfo.ownerUid = static_cast<int32_t>(state.ownerUid);
37 inputInfo.ownerPid = state.ownerPid;
Vishnu Nair92990e22023-02-24 20:01:05 +000038 changes = RequestedLayerState::Changes::Created;
39 mirrorRootPath = path.variant == LayerHierarchy::Variant::Mirror
40 ? path
41 : LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair8fc721b2022-12-22 20:06:32 +000042}
43
44// As documented in libhardware header, formats in the range
45// 0x100 - 0x1FF are specific to the HAL implementation, and
46// are known to have no alpha channel
47// TODO: move definition for device-specific range into
48// hardware.h, instead of using hard-coded values here.
49#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
50
51bool LayerSnapshot::isOpaqueFormat(PixelFormat format) {
52 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
53 return true;
54 }
55 switch (format) {
56 case PIXEL_FORMAT_RGBA_8888:
57 case PIXEL_FORMAT_BGRA_8888:
58 case PIXEL_FORMAT_RGBA_FP16:
59 case PIXEL_FORMAT_RGBA_1010102:
60 case PIXEL_FORMAT_R_8:
61 return false;
62 }
63 // in all other case, we have no blending (also for unknown formats)
64 return true;
65}
66
67bool LayerSnapshot::hasBufferOrSidebandStream() const {
Vishnu Naircfb2d252023-01-19 04:44:02 +000068 return ((sidebandStream != nullptr) || (externalTexture != nullptr));
Vishnu Nair8fc721b2022-12-22 20:06:32 +000069}
70
71bool LayerSnapshot::drawShadows() const {
72 return shadowSettings.length > 0.f;
73}
74
75bool LayerSnapshot::fillsColor() const {
76 return !hasBufferOrSidebandStream() && color.r >= 0.0_hf && color.g >= 0.0_hf &&
77 color.b >= 0.0_hf;
78}
79
80bool LayerSnapshot::hasBlur() const {
81 return backgroundBlurRadius > 0 || blurRegions.size() > 0;
82}
83
84bool LayerSnapshot::hasEffect() const {
85 return fillsColor() || drawShadows() || hasBlur();
86}
87
88bool LayerSnapshot::hasSomethingToDraw() const {
89 return hasEffect() || hasBufferOrSidebandStream();
90}
91
92bool LayerSnapshot::isContentOpaque() const {
93 // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
94 // layer's opaque flag.
95 if (!hasSomethingToDraw()) {
96 return false;
97 }
98
99 // if the layer has the opaque flag, then we're always opaque
100 if (layerOpaqueFlagSet) {
101 return true;
102 }
103
104 // If the buffer has no alpha channel, then we are opaque
105 if (hasBufferOrSidebandStream() &&
Vishnu Naircfb2d252023-01-19 04:44:02 +0000106 isOpaqueFormat(externalTexture ? externalTexture->getPixelFormat() : PIXEL_FORMAT_NONE)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000107 return true;
108 }
109
110 // Lastly consider the layer opaque if drawing a color with alpha == 1.0
111 return fillsColor() && color.a == 1.0_hf;
112}
113
114bool LayerSnapshot::isHiddenByPolicy() const {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000115 return invalidTransform || isHiddenByPolicyFromParent || isHiddenByPolicyFromRelativeParent;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000116}
117
118bool LayerSnapshot::getIsVisible() const {
Vishnu Naira9c43762023-01-27 19:10:25 +0000119 if (handleSkipScreenshotFlag & outputFilter.toInternalDisplay) {
120 return false;
121 }
122
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000123 if (!hasSomethingToDraw()) {
124 return false;
125 }
126
127 if (isHiddenByPolicy()) {
128 return false;
129 }
130
131 return color.a > 0.0f || hasBlur();
132}
133
134std::string LayerSnapshot::getIsVisibleReason() const {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000135 // not visible
Vishnu Naira9c43762023-01-27 19:10:25 +0000136 if (handleSkipScreenshotFlag & outputFilter.toInternalDisplay) return "eLayerSkipScreenshot";
Vishnu Naircfb2d252023-01-19 04:44:02 +0000137 if (!hasSomethingToDraw()) return "!hasSomethingToDraw";
138 if (invalidTransform) return "invalidTransform";
139 if (isHiddenByPolicyFromParent) return "hidden by parent or layer flag";
140 if (isHiddenByPolicyFromRelativeParent) return "hidden by relative parent";
141 if (color.a == 0.0f && !hasBlur()) return "alpha = 0 and no blur";
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000142
Vishnu Naircfb2d252023-01-19 04:44:02 +0000143 // visible
144 std::stringstream reason;
145 if (sidebandStream != nullptr) reason << " sidebandStream";
Vishnu Naird47bcee2023-02-24 18:08:51 +0000146 if (externalTexture != nullptr)
147 reason << " buffer:" << externalTexture->getId() << " frame:" << frameNumber;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000148 if (fillsColor() || color.a > 0.0f) reason << " color{" << color << "}";
149 if (drawShadows()) reason << " shadowSettings.length=" << shadowSettings.length;
150 if (backgroundBlurRadius > 0) reason << " backgroundBlurRadius=" << backgroundBlurRadius;
151 if (blurRegions.size() > 0) reason << " blurRegions.size()=" << blurRegions.size();
152 return reason.str();
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000153}
154
155bool LayerSnapshot::canReceiveInput() const {
156 return !isHiddenByPolicy() && (!hasBufferOrSidebandStream() || color.a > 0.0f);
157}
158
159bool LayerSnapshot::isTransformValid(const ui::Transform& t) {
160 float transformDet = t.det();
161 return transformDet != 0 && !isinf(transformDet) && !isnan(transformDet);
162}
163
Vishnu Naircfb2d252023-01-19 04:44:02 +0000164bool LayerSnapshot::hasInputInfo() const {
165 return inputInfo.token != nullptr ||
166 inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
167}
168
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000169std::string LayerSnapshot::getDebugString() const {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000170 std::stringstream debug;
171 debug << "Snapshot{" << path.toString() << name << " isVisible=" << isVisible << " {"
Vishnu Nair92990e22023-02-24 20:01:05 +0000172 << getIsVisibleReason() << "} changes=" << changes.string()
173 << " layerStack=" << outputFilter.layerStack.id << "}";
Vishnu Naircfb2d252023-01-19 04:44:02 +0000174 return debug.str();
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000175}
176
Vishnu Nair781d7252023-01-30 18:16:01 +0000177FloatRect LayerSnapshot::sourceBounds() const {
178 if (!externalTexture) {
179 return geomLayerBounds;
180 }
181 return geomBufferSize.toFloatRect();
182}
183
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000184} // namespace android::surfaceflinger::frontend