blob: 8a450933f0a95f558ca150c13945a9adf0efabd4 [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) {
Vishnu Nair93b8b792023-02-27 19:40:24 +000030 static uint32_t sUniqueSequenceId = 0;
31 // Provide a unique id for clones otherwise keeping using the sequence id.
32 // The seq id can still be useful for debugging if its available.
33 uniqueSequence = (path.isClone()) ? sUniqueSequenceId++ : state.id;
Vishnu Nair8fc721b2022-12-22 20:06:32 +000034 sequence = static_cast<int32_t>(state.id);
35 name = state.name;
36 textureName = state.textureName;
37 premultipliedAlpha = state.premultipliedAlpha;
38 inputInfo.name = state.name;
Vishnu Nair93b8b792023-02-27 19:40:24 +000039 inputInfo.id = static_cast<int32_t>(uniqueSequence);
Vishnu Nair8fc721b2022-12-22 20:06:32 +000040 inputInfo.ownerUid = static_cast<int32_t>(state.ownerUid);
41 inputInfo.ownerPid = state.ownerPid;
Vishnu Nair92990e22023-02-24 20:01:05 +000042 changes = RequestedLayerState::Changes::Created;
43 mirrorRootPath = path.variant == LayerHierarchy::Variant::Mirror
44 ? path
45 : LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair8fc721b2022-12-22 20:06:32 +000046}
47
48// As documented in libhardware header, formats in the range
49// 0x100 - 0x1FF are specific to the HAL implementation, and
50// are known to have no alpha channel
51// TODO: move definition for device-specific range into
52// hardware.h, instead of using hard-coded values here.
53#define HARDWARE_IS_DEVICE_FORMAT(f) ((f) >= 0x100 && (f) <= 0x1FF)
54
55bool LayerSnapshot::isOpaqueFormat(PixelFormat format) {
56 if (HARDWARE_IS_DEVICE_FORMAT(format)) {
57 return true;
58 }
59 switch (format) {
60 case PIXEL_FORMAT_RGBA_8888:
61 case PIXEL_FORMAT_BGRA_8888:
62 case PIXEL_FORMAT_RGBA_FP16:
63 case PIXEL_FORMAT_RGBA_1010102:
64 case PIXEL_FORMAT_R_8:
65 return false;
66 }
67 // in all other case, we have no blending (also for unknown formats)
68 return true;
69}
70
71bool LayerSnapshot::hasBufferOrSidebandStream() const {
Vishnu Naircfb2d252023-01-19 04:44:02 +000072 return ((sidebandStream != nullptr) || (externalTexture != nullptr));
Vishnu Nair8fc721b2022-12-22 20:06:32 +000073}
74
75bool LayerSnapshot::drawShadows() const {
76 return shadowSettings.length > 0.f;
77}
78
79bool LayerSnapshot::fillsColor() const {
80 return !hasBufferOrSidebandStream() && color.r >= 0.0_hf && color.g >= 0.0_hf &&
81 color.b >= 0.0_hf;
82}
83
84bool LayerSnapshot::hasBlur() const {
85 return backgroundBlurRadius > 0 || blurRegions.size() > 0;
86}
87
88bool LayerSnapshot::hasEffect() const {
89 return fillsColor() || drawShadows() || hasBlur();
90}
91
92bool LayerSnapshot::hasSomethingToDraw() const {
93 return hasEffect() || hasBufferOrSidebandStream();
94}
95
96bool LayerSnapshot::isContentOpaque() const {
97 // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
98 // layer's opaque flag.
99 if (!hasSomethingToDraw()) {
100 return false;
101 }
102
103 // if the layer has the opaque flag, then we're always opaque
104 if (layerOpaqueFlagSet) {
105 return true;
106 }
107
108 // If the buffer has no alpha channel, then we are opaque
109 if (hasBufferOrSidebandStream() &&
Vishnu Naircfb2d252023-01-19 04:44:02 +0000110 isOpaqueFormat(externalTexture ? externalTexture->getPixelFormat() : PIXEL_FORMAT_NONE)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000111 return true;
112 }
113
114 // Lastly consider the layer opaque if drawing a color with alpha == 1.0
115 return fillsColor() && color.a == 1.0_hf;
116}
117
118bool LayerSnapshot::isHiddenByPolicy() const {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000119 return invalidTransform || isHiddenByPolicyFromParent || isHiddenByPolicyFromRelativeParent;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000120}
121
122bool LayerSnapshot::getIsVisible() const {
Vishnu Naira9c43762023-01-27 19:10:25 +0000123 if (handleSkipScreenshotFlag & outputFilter.toInternalDisplay) {
124 return false;
125 }
126
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000127 if (!hasSomethingToDraw()) {
128 return false;
129 }
130
131 if (isHiddenByPolicy()) {
132 return false;
133 }
134
135 return color.a > 0.0f || hasBlur();
136}
137
138std::string LayerSnapshot::getIsVisibleReason() const {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000139 // not visible
Vishnu Naira9c43762023-01-27 19:10:25 +0000140 if (handleSkipScreenshotFlag & outputFilter.toInternalDisplay) return "eLayerSkipScreenshot";
Vishnu Naircfb2d252023-01-19 04:44:02 +0000141 if (!hasSomethingToDraw()) return "!hasSomethingToDraw";
142 if (invalidTransform) return "invalidTransform";
143 if (isHiddenByPolicyFromParent) return "hidden by parent or layer flag";
144 if (isHiddenByPolicyFromRelativeParent) return "hidden by relative parent";
145 if (color.a == 0.0f && !hasBlur()) return "alpha = 0 and no blur";
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000146
Vishnu Naircfb2d252023-01-19 04:44:02 +0000147 // visible
148 std::stringstream reason;
149 if (sidebandStream != nullptr) reason << " sidebandStream";
Vishnu Naird47bcee2023-02-24 18:08:51 +0000150 if (externalTexture != nullptr)
151 reason << " buffer:" << externalTexture->getId() << " frame:" << frameNumber;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000152 if (fillsColor() || color.a > 0.0f) reason << " color{" << color << "}";
153 if (drawShadows()) reason << " shadowSettings.length=" << shadowSettings.length;
154 if (backgroundBlurRadius > 0) reason << " backgroundBlurRadius=" << backgroundBlurRadius;
155 if (blurRegions.size() > 0) reason << " blurRegions.size()=" << blurRegions.size();
156 return reason.str();
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000157}
158
159bool LayerSnapshot::canReceiveInput() const {
160 return !isHiddenByPolicy() && (!hasBufferOrSidebandStream() || color.a > 0.0f);
161}
162
163bool LayerSnapshot::isTransformValid(const ui::Transform& t) {
164 float transformDet = t.det();
165 return transformDet != 0 && !isinf(transformDet) && !isnan(transformDet);
166}
167
Vishnu Naircfb2d252023-01-19 04:44:02 +0000168bool LayerSnapshot::hasInputInfo() const {
169 return inputInfo.token != nullptr ||
170 inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
171}
172
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000173std::string LayerSnapshot::getDebugString() const {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000174 std::stringstream debug;
175 debug << "Snapshot{" << path.toString() << name << " isVisible=" << isVisible << " {"
Vishnu Nair92990e22023-02-24 20:01:05 +0000176 << getIsVisibleReason() << "} changes=" << changes.string()
177 << " layerStack=" << outputFilter.layerStack.id << "}";
Vishnu Naircfb2d252023-01-19 04:44:02 +0000178 return debug.str();
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000179}
180
Vishnu Nair781d7252023-01-30 18:16:01 +0000181FloatRect LayerSnapshot::sourceBounds() const {
182 if (!externalTexture) {
183 return geomLayerBounds;
184 }
185 return geomBufferSize.toFloatRect();
186}
187
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000188} // namespace android::surfaceflinger::frontend