blob: 2fc9682849261aa91888eac7beefbbdecf28903b [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 LOG_NDEBUG 0
18#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19#undef LOG_TAG
20#define LOG_TAG "LayerSnapshotBuilder"
21
22#include "LayerSnapshotBuilder.h"
23#include <gui/TraceUtils.h>
Vishnu Nairfed7c122023-03-18 01:54:43 +000024#include <ui/FloatRect.h>
Vishnu Nair8fc721b2022-12-22 20:06:32 +000025#include <numeric>
26#include "DisplayHardware/HWC2.h"
27#include "DisplayHardware/Hal.h"
Vishnu Naircfb2d252023-01-19 04:44:02 +000028#include "LayerLog.h"
29#include "TimeStats/TimeStats.h"
Vishnu Nair8fc721b2022-12-22 20:06:32 +000030#include "ftl/small_map.h"
31
32namespace android::surfaceflinger::frontend {
33
34using namespace ftl::flag_operators;
35
36namespace {
37FloatRect getMaxDisplayBounds(
38 const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
39 const ui::Size maxSize = [&displays] {
40 if (displays.empty()) return ui::Size{5000, 5000};
41
42 return std::accumulate(displays.begin(), displays.end(), ui::kEmptySize,
43 [](ui::Size size, const auto& pair) -> ui::Size {
44 const auto& display = pair.second;
45 return {std::max(size.getWidth(), display.info.logicalWidth),
46 std::max(size.getHeight(), display.info.logicalHeight)};
47 });
48 }();
49
50 // Ignore display bounds for now since they will be computed later. Use a large Rect bound
51 // to ensure it's bigger than an actual display will be.
52 const float xMax = static_cast<float>(maxSize.getWidth()) * 10.f;
53 const float yMax = static_cast<float>(maxSize.getHeight()) * 10.f;
54
55 return {-xMax, -yMax, xMax, yMax};
56}
57
58// Applies the given transform to the region, while protecting against overflows caused by any
59// offsets. If applying the offset in the transform to any of the Rects in the region would result
60// in an overflow, they are not added to the output Region.
61Region transformTouchableRegionSafely(const ui::Transform& t, const Region& r,
62 const std::string& debugWindowName) {
63 // Round the translation using the same rounding strategy used by ui::Transform.
64 const auto tx = static_cast<int32_t>(t.tx() + 0.5);
65 const auto ty = static_cast<int32_t>(t.ty() + 0.5);
66
67 ui::Transform transformWithoutOffset = t;
68 transformWithoutOffset.set(0.f, 0.f);
69
70 const Region transformed = transformWithoutOffset.transform(r);
71
72 // Apply the translation to each of the Rects in the region while discarding any that overflow.
73 Region ret;
74 for (const auto& rect : transformed) {
75 Rect newRect;
76 if (__builtin_add_overflow(rect.left, tx, &newRect.left) ||
77 __builtin_add_overflow(rect.top, ty, &newRect.top) ||
78 __builtin_add_overflow(rect.right, tx, &newRect.right) ||
79 __builtin_add_overflow(rect.bottom, ty, &newRect.bottom)) {
80 ALOGE("Applying transform to touchable region of window '%s' resulted in an overflow.",
81 debugWindowName.c_str());
82 continue;
83 }
84 ret.orSelf(newRect);
85 }
86 return ret;
87}
88
89/*
90 * We don't want to send the layer's transform to input, but rather the
91 * parent's transform. This is because Layer's transform is
92 * information about how the buffer is placed on screen. The parent's
93 * transform makes more sense to send since it's information about how the
94 * layer is placed on screen. This transform is used by input to determine
95 * how to go from screen space back to window space.
96 */
97ui::Transform getInputTransform(const LayerSnapshot& snapshot) {
98 if (!snapshot.hasBufferOrSidebandStream()) {
99 return snapshot.geomLayerTransform;
100 }
101 return snapshot.parentTransform;
102}
103
104/**
Vishnu Nairfed7c122023-03-18 01:54:43 +0000105 * Returns the bounds used to fill the input frame and the touchable region.
106 *
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000107 * Similar to getInputTransform, we need to update the bounds to include the transform.
108 * This is because bounds don't include the buffer transform, where the input assumes
109 * that's already included.
110 */
Vishnu Nairfed7c122023-03-18 01:54:43 +0000111std::pair<FloatRect, bool> getInputBounds(const LayerSnapshot& snapshot, bool fillParentBounds) {
112 FloatRect inputBounds = snapshot.croppedBufferSize.toFloatRect();
113 if (snapshot.hasBufferOrSidebandStream() && snapshot.croppedBufferSize.isValid() &&
114 snapshot.localTransform.getType() != ui::Transform::IDENTITY) {
115 inputBounds = snapshot.localTransform.transform(inputBounds);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000116 }
117
Vishnu Nairfed7c122023-03-18 01:54:43 +0000118 bool inputBoundsValid = snapshot.croppedBufferSize.isValid();
119 if (!inputBoundsValid) {
120 /**
121 * Input bounds are based on the layer crop or buffer size. But if we are using
122 * the layer bounds as the input bounds (replaceTouchableRegionWithCrop flag) then
123 * we can use the parent bounds as the input bounds if the layer does not have buffer
124 * or a crop. We want to unify this logic but because of compat reasons we cannot always
125 * use the parent bounds. A layer without a buffer can get input. So when a window is
126 * initially added, its touchable region can fill its parent layer bounds and that can
127 * have negative consequences.
128 */
129 inputBounds = fillParentBounds ? snapshot.geomLayerBounds : FloatRect{};
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000130 }
Vishnu Nairfed7c122023-03-18 01:54:43 +0000131
132 // Clamp surface inset to the input bounds.
133 const float inset = static_cast<float>(snapshot.inputInfo.surfaceInset);
134 const float xSurfaceInset = std::clamp(inset, 0.f, inputBounds.getWidth() / 2.f);
135 const float ySurfaceInset = std::clamp(inset, 0.f, inputBounds.getHeight() / 2.f);
136
137 // Apply the insets to the input bounds.
138 inputBounds.left += xSurfaceInset;
139 inputBounds.top += ySurfaceInset;
140 inputBounds.right -= xSurfaceInset;
141 inputBounds.bottom -= ySurfaceInset;
142 return {inputBounds, inputBoundsValid};
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000143}
144
Vishnu Nairfed7c122023-03-18 01:54:43 +0000145Rect getInputBoundsInDisplaySpace(const LayerSnapshot& snapshot, const FloatRect& insetBounds,
146 const ui::Transform& screenToDisplay) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000147 // InputDispatcher works in the display device's coordinate space. Here, we calculate the
148 // frame and transform used for the layer, which determines the bounds and the coordinate space
149 // within which the layer will receive input.
Vishnu Nairfed7c122023-03-18 01:54:43 +0000150
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000151 // Coordinate space definitions:
152 // - display: The display device's coordinate space. Correlates to pixels on the display.
153 // - screen: The post-rotation coordinate space for the display, a.k.a. logical display space.
154 // - layer: The coordinate space of this layer.
155 // - input: The coordinate space in which this layer will receive input events. This could be
156 // different than layer space if a surfaceInset is used, which changes the origin
157 // of the input space.
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000158
159 // Crop the input bounds to ensure it is within the parent's bounds.
Vishnu Nairfed7c122023-03-18 01:54:43 +0000160 const FloatRect croppedInsetBoundsInLayer = snapshot.geomLayerBounds.intersect(insetBounds);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000161
162 const ui::Transform layerToScreen = getInputTransform(snapshot);
163 const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
164
Vishnu Nairfed7c122023-03-18 01:54:43 +0000165 return Rect{layerToDisplay.transform(croppedInsetBoundsInLayer)};
166}
167
168void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& screenToDisplay,
169 const LayerSnapshot& snapshot) {
170 auto [inputBounds, inputBoundsValid] = getInputBounds(snapshot, /*fillParentBounds=*/false);
171 if (!inputBoundsValid) {
172 info.touchableRegion.clear();
173 }
174
175 const Rect roundedFrameInDisplay =
176 getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000177 info.frameLeft = roundedFrameInDisplay.left;
178 info.frameTop = roundedFrameInDisplay.top;
179 info.frameRight = roundedFrameInDisplay.right;
180 info.frameBottom = roundedFrameInDisplay.bottom;
181
182 ui::Transform inputToLayer;
Vishnu Nairfed7c122023-03-18 01:54:43 +0000183 inputToLayer.set(inputBounds.left, inputBounds.top);
184 const ui::Transform layerToScreen = getInputTransform(snapshot);
185 const ui::Transform inputToDisplay = screenToDisplay * layerToScreen * inputToLayer;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000186
187 // InputDispatcher expects a display-to-input transform.
188 info.transform = inputToDisplay.inverse();
189
190 // The touchable region is specified in the input coordinate space. Change it to display space.
191 info.touchableRegion =
192 transformTouchableRegionSafely(inputToDisplay, info.touchableRegion, snapshot.name);
193}
194
195void handleDropInputMode(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot) {
196 if (snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
197 return;
198 }
199
200 // Check if we need to drop input unconditionally
201 const gui::DropInputMode dropInputMode = snapshot.dropInputMode;
202 if (dropInputMode == gui::DropInputMode::ALL) {
203 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
204 ALOGV("Dropping input for %s as requested by policy.", snapshot.name.c_str());
205 return;
206 }
207
208 // Check if we need to check if the window is obscured by parent
209 if (dropInputMode != gui::DropInputMode::OBSCURED) {
210 return;
211 }
212
213 // Check if the parent has set an alpha on the layer
214 if (parentSnapshot.color.a != 1.0_hf) {
215 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
216 ALOGV("Dropping input for %s as requested by policy because alpha=%f",
217 snapshot.name.c_str(), static_cast<float>(parentSnapshot.color.a));
218 }
219
220 // Check if the parent has cropped the buffer
221 Rect bufferSize = snapshot.croppedBufferSize;
222 if (!bufferSize.isValid()) {
223 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
224 return;
225 }
226
227 // Screenbounds are the layer bounds cropped by parents, transformed to screenspace.
228 // To check if the layer has been cropped, we take the buffer bounds, apply the local
229 // layer crop and apply the same set of transforms to move to screenspace. If the bounds
230 // match then the layer has not been cropped by its parents.
231 Rect bufferInScreenSpace(snapshot.geomLayerTransform.transform(bufferSize));
232 bool croppedByParent = bufferInScreenSpace != Rect{snapshot.transformedBounds};
233
234 if (croppedByParent) {
235 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
236 ALOGV("Dropping input for %s as requested by policy because buffer is cropped by parent",
237 snapshot.name.c_str());
238 } else {
239 // If the layer is not obscured by its parents (by setting an alpha or crop), then only drop
240 // input if the window is obscured. This check should be done in surfaceflinger but the
241 // logic currently resides in inputflinger. So pass the if_obscured check to input to only
242 // drop input events if the window is obscured.
243 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
244 }
245}
246
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000247auto getBlendMode(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
248 auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
249 if (snapshot.alpha != 1.0f || !snapshot.isContentOpaque()) {
250 blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED
251 : Hwc2::IComposerClient::BlendMode::COVERAGE;
252 }
253 return blendMode;
254}
255
Vishnu Naircfb2d252023-01-19 04:44:02 +0000256void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFrame,
257 bool forceFullDamage, Region& outSurfaceDamageRegion) {
258 if (!hasReadyFrame) {
259 outSurfaceDamageRegion.clear();
260 return;
261 }
262 if (forceFullDamage) {
263 outSurfaceDamageRegion = Region::INVALID_REGION;
264 } else {
265 outSurfaceDamageRegion = requested.surfaceDamageRegion;
266 }
267}
268
Vishnu Nair80a5a702023-02-11 01:21:51 +0000269void updateVisibility(LayerSnapshot& snapshot, bool visible) {
270 snapshot.isVisible = visible;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000271
272 // TODO(b/238781169) we are ignoring this compat for now, since we will have
273 // to remove any optimization based on visibility.
274
275 // For compatibility reasons we let layers which can receive input
276 // receive input before they have actually submitted a buffer. Because
277 // of this we use canReceiveInput instead of isVisible to check the
278 // policy-visibility, ignoring the buffer state. However for layers with
279 // hasInputInfo()==false we can use the real visibility state.
280 // We are just using these layers for occlusion detection in
281 // InputDispatcher, and obviously if they aren't visible they can't occlude
282 // anything.
Vishnu Nair80a5a702023-02-11 01:21:51 +0000283 const bool visibleForInput =
Vishnu Nair40d02282023-02-28 21:11:40 +0000284 snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000285 snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000286}
287
288bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
289 if (requested.potentialCursor) {
290 return false;
291 }
292
293 if (snapshot.inputInfo.token != nullptr) {
294 return true;
295 }
296
297 if (snapshot.hasBufferOrSidebandStream()) {
298 return true;
299 }
300
301 return requested.windowInfoHandle &&
302 requested.windowInfoHandle->getInfo()->inputConfig.test(
303 gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
304}
305
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000306void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested,
307 const LayerSnapshotBuilder::Args& args) {
308 snapshot.metadata.clear();
309 for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) {
310 auto compatIter = args.genericLayerMetadataKeyMap.find(key);
311 if (compatIter == std::end(args.genericLayerMetadataKeyMap)) {
312 continue;
313 }
314 const uint32_t id = compatIter->second;
315 auto it = requested.metadata.mMap.find(id);
316 if (it == std::end(requested.metadata.mMap)) {
317 continue;
318 }
319
320 snapshot.metadata.emplace(key,
321 compositionengine::GenericLayerMetadataEntry{mandatory,
322 it->second});
323 }
324}
325
Vishnu Naircfb2d252023-01-19 04:44:02 +0000326void clearChanges(LayerSnapshot& snapshot) {
327 snapshot.changes.clear();
328 snapshot.contentDirty = false;
329 snapshot.hasReadyFrame = false;
330 snapshot.sidebandStreamHasFrame = false;
331 snapshot.surfaceDamage.clear();
332}
333
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000334} // namespace
335
336LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
337 LayerSnapshot snapshot;
Vishnu Nair92990e22023-02-24 20:01:05 +0000338 snapshot.path = LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000339 snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
340 snapshot.isHiddenByPolicyFromParent = false;
341 snapshot.isHiddenByPolicyFromRelativeParent = false;
342 snapshot.parentTransform.reset();
343 snapshot.geomLayerTransform.reset();
344 snapshot.geomInverseLayerTransform.reset();
345 snapshot.geomLayerBounds = getMaxDisplayBounds({});
346 snapshot.roundedCorner = RoundedCornerState();
347 snapshot.stretchEffect = {};
348 snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK;
349 snapshot.outputFilter.toInternalDisplay = false;
350 snapshot.isSecure = false;
351 snapshot.color.a = 1.0_hf;
352 snapshot.colorTransformIsIdentity = true;
353 snapshot.shadowRadius = 0.f;
354 snapshot.layerMetadata.mMap.clear();
355 snapshot.relativeLayerMetadata.mMap.clear();
356 snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED;
357 snapshot.dropInputMode = gui::DropInputMode::NONE;
358 snapshot.isTrustedOverlay = false;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000359 snapshot.gameMode = gui::GameMode::Unsupported;
360 snapshot.frameRate = {};
361 snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000362 return snapshot;
363}
364
365LayerSnapshotBuilder::LayerSnapshotBuilder() : mRootSnapshot(getRootSnapshot()) {}
366
367LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000368 args.forceUpdate = ForceUpdateFlags::ALL;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000369 updateSnapshots(args);
370}
371
372bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000373 if (args.forceUpdate != ForceUpdateFlags::NONE || args.displayChanges) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000374 // force update requested, or we have display changes, so skip the fast path
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000375 return false;
376 }
377
378 if (args.layerLifecycleManager.getGlobalChanges().get() == 0) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000379 return true;
380 }
381
382 if (args.layerLifecycleManager.getGlobalChanges() != RequestedLayerState::Changes::Content) {
383 // We have changes that require us to walk the hierarchy and update child layers.
384 // No fast path for you.
385 return false;
386 }
387
388 // There are only content changes which do not require any child layer snapshots to be updated.
389 ALOGV("%s", __func__);
390 ATRACE_NAME("FastPath");
391
392 // Collect layers with changes
393 ftl::SmallMap<uint32_t, RequestedLayerState*, 10> layersWithChanges;
394 for (auto& layer : args.layerLifecycleManager.getLayers()) {
395 if (layer->changes.test(RequestedLayerState::Changes::Content)) {
396 layersWithChanges.emplace_or_replace(layer->id, layer.get());
397 }
398 }
399
400 // Walk through the snapshots, clearing previous change flags and updating the snapshots
401 // if needed.
402 for (auto& snapshot : mSnapshots) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000403 auto it = layersWithChanges.find(snapshot->path.id);
404 if (it != layersWithChanges.end()) {
405 ALOGV("%s fast path snapshot changes = %s", __func__,
406 mRootSnapshot.changes.string().c_str());
407 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair92990e22023-02-24 20:01:05 +0000408 updateSnapshot(*snapshot, args, *it->second, mRootSnapshot, root);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000409 }
410 }
411 return true;
412}
413
414void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
415 ATRACE_NAME("UpdateSnapshots");
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000416 if (args.parentCrop) {
417 mRootSnapshot.geomLayerBounds = *args.parentCrop;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000418 } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000419 mRootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
420 }
421 if (args.displayChanges) {
422 mRootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
423 RequestedLayerState::Changes::Geometry;
424 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000425 if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
426 mRootSnapshot.changes |=
427 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
428 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000429 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000430 if (args.root.getLayer()) {
431 // The hierarchy can have a root layer when used for screenshots otherwise, it will have
432 // multiple children.
433 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, args.root.getLayer()->id,
434 LayerHierarchy::Variant::Attached);
435 updateSnapshotsInHierarchy(args, args.root, root, mRootSnapshot);
436 } else {
437 for (auto& [childHierarchy, variant] : args.root.mChildren) {
438 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
439 childHierarchy->getLayer()->id,
440 variant);
441 updateSnapshotsInHierarchy(args, *childHierarchy, root, mRootSnapshot);
442 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000443 }
444
Vishnu Nairfccd6362023-02-24 23:39:53 +0000445 const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000446 clearChanges(mRootSnapshot);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000447
448 // Destroy unreachable snapshots
Vishnu Nairfccd6362023-02-24 23:39:53 +0000449 if (!hasUnreachableSnapshots) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000450 return;
451 }
452
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000453 auto it = mSnapshots.begin();
454 while (it < mSnapshots.end()) {
455 auto& traversalPath = it->get()->path;
Vishnu Nairfccd6362023-02-24 23:39:53 +0000456 if (!it->get()->unreachable) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000457 it++;
458 continue;
459 }
460
461 mIdToSnapshot.erase(traversalPath);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000462 mSnapshots.back()->globalZ = it->get()->globalZ;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000463 std::iter_swap(it, mSnapshots.end() - 1);
464 mSnapshots.erase(mSnapshots.end() - 1);
465 }
466}
467
468void LayerSnapshotBuilder::update(const Args& args) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000469 for (auto& snapshot : mSnapshots) {
470 clearChanges(*snapshot);
471 }
472
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000473 if (tryFastUpdate(args)) {
474 return;
475 }
476 updateSnapshots(args);
477}
478
Vishnu Naircfb2d252023-01-19 04:44:02 +0000479const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy(
480 const Args& args, const LayerHierarchy& hierarchy,
481 LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000482 const RequestedLayerState* layer = hierarchy.getLayer();
Vishnu Naircfb2d252023-01-19 04:44:02 +0000483 LayerSnapshot* snapshot = getSnapshot(traversalPath);
484 const bool newSnapshot = snapshot == nullptr;
485 if (newSnapshot) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000486 snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000487 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000488 scheduler::LayerInfo::FrameRate oldFrameRate = snapshot->frameRate;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000489 if (traversalPath.isRelative()) {
490 bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
491 updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
492 } else {
493 if (traversalPath.isAttached()) {
494 resetRelativeState(*snapshot);
495 }
Vishnu Nair92990e22023-02-24 20:01:05 +0000496 updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000497 }
498
499 for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
500 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(traversalPath,
501 childHierarchy->getLayer()->id,
502 variant);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000503 const LayerSnapshot& childSnapshot =
504 updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot);
505 updateChildState(*snapshot, childSnapshot, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000506 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000507
508 if (oldFrameRate == snapshot->frameRate) {
509 snapshot->changes.clear(RequestedLayerState::Changes::FrameRate);
510 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000511 return *snapshot;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000512}
513
514LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const {
515 if (layerId == UNASSIGNED_LAYER_ID) {
516 return nullptr;
517 }
518 LayerHierarchy::TraversalPath path{.id = layerId};
519 return getSnapshot(path);
520}
521
522LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
523 auto it = mIdToSnapshot.find(id);
524 return it == mIdToSnapshot.end() ? nullptr : it->second;
525}
526
Vishnu Nair92990e22023-02-24 20:01:05 +0000527LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
528 const RequestedLayerState& layer,
529 const LayerSnapshot& parentSnapshot) {
530 mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
Vishnu Naircfb2d252023-01-19 04:44:02 +0000531 LayerSnapshot* snapshot = mSnapshots.back().get();
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000532 snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
Vishnu Nair92990e22023-02-24 20:01:05 +0000533 if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) {
534 snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
535 }
536 mIdToSnapshot[path] = snapshot;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000537 return snapshot;
538}
539
Vishnu Nairfccd6362023-02-24 23:39:53 +0000540bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000541 if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000542 !args.layerLifecycleManager.getGlobalChanges().any(
543 RequestedLayerState::Changes::Hierarchy |
544 RequestedLayerState::Changes::Visibility)) {
545 // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
546 // the snapshots.
Vishnu Nairfccd6362023-02-24 23:39:53 +0000547 return false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000548 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000549 mResortSnapshots = false;
550
Vishnu Nairfccd6362023-02-24 23:39:53 +0000551 for (auto& snapshot : mSnapshots) {
552 snapshot->unreachable = true;
553 }
554
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000555 size_t globalZ = 0;
556 args.root.traverseInZOrder(
557 [this, &globalZ](const LayerHierarchy&,
558 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
559 LayerSnapshot* snapshot = getSnapshot(traversalPath);
560 if (!snapshot) {
561 return false;
562 }
563
Vishnu Nairfccd6362023-02-24 23:39:53 +0000564 snapshot->unreachable = false;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000565 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
Vishnu Nair80a5a702023-02-11 01:21:51 +0000566 updateVisibility(*snapshot, snapshot->getIsVisible());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000567 size_t oldZ = snapshot->globalZ;
568 size_t newZ = globalZ++;
569 snapshot->globalZ = newZ;
570 if (oldZ == newZ) {
571 return true;
572 }
573 mSnapshots[newZ]->globalZ = oldZ;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000574 LLOGV(snapshot->sequence, "Made visible z=%zu -> %zu %s", oldZ, newZ,
575 snapshot->getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000576 std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ),
577 mSnapshots.begin() + static_cast<ssize_t>(newZ));
578 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000579 return true;
580 });
Vishnu Naircfb2d252023-01-19 04:44:02 +0000581 mNumInterestingSnapshots = (int)globalZ;
Vishnu Nairfccd6362023-02-24 23:39:53 +0000582 bool hasUnreachableSnapshots = false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000583 while (globalZ < mSnapshots.size()) {
584 mSnapshots[globalZ]->globalZ = globalZ;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000585 /* mark unreachable snapshots as explicitly invisible */
586 updateVisibility(*mSnapshots[globalZ], false);
Vishnu Nairfccd6362023-02-24 23:39:53 +0000587 if (mSnapshots[globalZ]->unreachable) {
588 hasUnreachableSnapshots = true;
589 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000590 globalZ++;
591 }
Vishnu Nairfccd6362023-02-24 23:39:53 +0000592 return hasUnreachableSnapshots;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000593}
594
595void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
596 const LayerSnapshot& parentSnapshot,
597 bool parentIsRelative, const Args& args) {
598 if (parentIsRelative) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000599 snapshot.isHiddenByPolicyFromRelativeParent =
600 parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000601 if (args.includeMetadata) {
602 snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata;
603 }
604 } else {
605 snapshot.isHiddenByPolicyFromRelativeParent =
606 parentSnapshot.isHiddenByPolicyFromRelativeParent;
607 if (args.includeMetadata) {
608 snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
609 }
610 }
611 snapshot.isVisible = snapshot.getIsVisible();
612}
613
Vishnu Naircfb2d252023-01-19 04:44:02 +0000614void LayerSnapshotBuilder::updateChildState(LayerSnapshot& snapshot,
615 const LayerSnapshot& childSnapshot, const Args& args) {
616 if (snapshot.childState.hasValidFrameRate) {
617 return;
618 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000619 if (args.forceUpdate == ForceUpdateFlags::ALL ||
620 childSnapshot.changes.test(RequestedLayerState::Changes::FrameRate)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000621 // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes
622 // for the same reason we are allowing touch boost for those layers. See
623 // RefreshRateSelector::rankFrameRates for details.
624 using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility;
625 const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.rate.isValid() &&
626 childSnapshot.frameRate.type == FrameRateCompatibility::Default;
627 const auto layerVotedWithNoVote =
628 childSnapshot.frameRate.type == FrameRateCompatibility::NoVote;
629 const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.rate.isValid() &&
630 childSnapshot.frameRate.type == FrameRateCompatibility::Exact;
631
632 snapshot.childState.hasValidFrameRate |= layerVotedWithDefaultCompatibility ||
633 layerVotedWithNoVote || layerVotedWithExactCompatibility;
634
635 // If we don't have a valid frame rate, but the children do, we set this
636 // layer as NoVote to allow the children to control the refresh rate
637 if (!snapshot.frameRate.rate.isValid() &&
638 snapshot.frameRate.type != FrameRateCompatibility::NoVote &&
639 snapshot.childState.hasValidFrameRate) {
640 snapshot.frameRate =
641 scheduler::LayerInfo::FrameRate(Fps(), FrameRateCompatibility::NoVote);
642 snapshot.changes |= childSnapshot.changes & RequestedLayerState::Changes::FrameRate;
643 }
644 }
645}
646
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000647void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) {
648 snapshot.isHiddenByPolicyFromRelativeParent = false;
649 snapshot.relativeLayerMetadata.mMap.clear();
650}
651
652uint32_t getDisplayRotationFlags(
653 const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays,
654 const ui::LayerStack& layerStack) {
655 static frontend::DisplayInfo sDefaultDisplayInfo = {.isPrimary = false};
656 auto display = displays.get(layerStack).value_or(sDefaultDisplayInfo).get();
657 return display.isPrimary ? display.rotationFlags : 0;
658}
659
660void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
661 const RequestedLayerState& requested,
662 const LayerSnapshot& parentSnapshot,
Vishnu Nair92990e22023-02-24 20:01:05 +0000663 const LayerHierarchy::TraversalPath& path) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000664 // Always update flags and visibility
665 ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
666 (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
667 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
Vishnu Naird47bcee2023-02-24 18:08:51 +0000668 RequestedLayerState::Changes::AffectsChildren |
669 RequestedLayerState::Changes::FrameRate);
Vishnu Nair92990e22023-02-24 20:01:05 +0000670 snapshot.changes |= parentChanges | requested.changes;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000671 snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000672 parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
673 (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000674 snapshot.contentDirty = requested.what & layer_state_t::CONTENT_DIRTY;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000675 // TODO(b/238781169) scope down the changes to only buffer updates.
Vishnu Naird47bcee2023-02-24 18:08:51 +0000676 snapshot.hasReadyFrame = requested.hasReadyFrame();
677 snapshot.sidebandStreamHasFrame = requested.hasSidebandStreamFrame();
Vishnu Naircfb2d252023-01-19 04:44:02 +0000678 updateSurfaceDamage(requested, snapshot.hasReadyFrame, args.forceFullDamage,
679 snapshot.surfaceDamage);
Vishnu Nair92990e22023-02-24 20:01:05 +0000680 snapshot.outputFilter.layerStack = parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
681 ? requested.layerStack
682 : parentSnapshot.outputFilter.layerStack;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000683
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000684 uint32_t displayRotationFlags =
685 getDisplayRotationFlags(args.displays, snapshot.outputFilter.layerStack);
Vishnu Nair92990e22023-02-24 20:01:05 +0000686 const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
687 snapshot.changes.any(RequestedLayerState::Changes::Visibility |
688 RequestedLayerState::Changes::Created);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000689
Vishnu Naircfb2d252023-01-19 04:44:02 +0000690 // always update the buffer regardless of visibility
Vishnu Nair80a5a702023-02-11 01:21:51 +0000691 if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES || args.displayChanges) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000692 snapshot.acquireFence =
693 (requested.externalTexture &&
694 requested.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged))
695 ? requested.bufferData->acquireFence
696 : Fence::NO_FENCE;
697 snapshot.buffer =
698 requested.externalTexture ? requested.externalTexture->getBuffer() : nullptr;
699 snapshot.bufferSize = requested.getBufferSize(displayRotationFlags);
700 snapshot.geomBufferSize = snapshot.bufferSize;
701 snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
702 snapshot.dataspace = requested.dataspace;
703 snapshot.externalTexture = requested.externalTexture;
704 snapshot.frameNumber = (requested.bufferData) ? requested.bufferData->frameNumber : 0;
705 snapshot.geomBufferTransform = requested.bufferTransform;
706 snapshot.geomBufferUsesDisplayInverseTransform = requested.transformToDisplayInverse;
707 snapshot.geomContentCrop = requested.getBufferCrop();
708 snapshot.geomUsesSourceCrop = snapshot.hasBufferOrSidebandStream();
709 snapshot.hasProtectedContent = requested.externalTexture &&
710 requested.externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED;
711 snapshot.isHdrY410 = requested.dataspace == ui::Dataspace::BT2020_ITU_PQ &&
712 requested.api == NATIVE_WINDOW_API_MEDIA &&
713 requested.bufferData->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102;
714 snapshot.sidebandStream = requested.sidebandStream;
715 snapshot.transparentRegionHint = requested.transparentRegion;
716 snapshot.color.rgb = requested.getColor().rgb;
John Reck68796592023-01-25 13:47:12 -0500717 snapshot.currentSdrHdrRatio = requested.currentSdrHdrRatio;
718 snapshot.desiredSdrHdrRatio = requested.desiredSdrHdrRatio;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000719 }
720
Vishnu Nair92990e22023-02-24 20:01:05 +0000721 if (snapshot.isHiddenByPolicyFromParent &&
722 !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000723 if (forceUpdate ||
724 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
725 RequestedLayerState::Changes::Geometry |
726 RequestedLayerState::Changes::Input)) {
727 updateInput(snapshot, requested, parentSnapshot, path, args);
728 }
729 return;
730 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000731
732 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) {
733 // If root layer, use the layer stack otherwise get the parent's layer stack.
734 snapshot.color.a = parentSnapshot.color.a * requested.color.a;
735 snapshot.alpha = snapshot.color.a;
736 snapshot.isSecure =
737 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
738 snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000739 snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
740 (requested.flags & layer_state_t::eLayerSkipScreenshot);
741 snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
742 ? requested.stretchEffect
743 : parentSnapshot.stretchEffect;
744 if (!parentSnapshot.colorTransformIsIdentity) {
745 snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
746 snapshot.colorTransformIsIdentity = false;
747 } else {
748 snapshot.colorTransform = requested.colorTransform;
749 snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
750 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000751 snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
752 ? requested.gameMode
753 : parentSnapshot.gameMode;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000754 snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
755 ? requested.fixedTransformHint
756 : parentSnapshot.fixedTransformHint;
Vishnu Naira9c43762023-01-27 19:10:25 +0000757 // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
758 // marked as skip capture
759 snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
760 (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000761 }
762
Vishnu Naird47bcee2023-02-24 18:08:51 +0000763 if (forceUpdate ||
764 snapshot.changes.any(RequestedLayerState::Changes::FrameRate |
765 RequestedLayerState::Changes::Hierarchy)) {
766 snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() ||
767 (requested.requestedFrameRate.type ==
768 scheduler::LayerInfo::FrameRateCompatibility::NoVote))
769 ? requested.requestedFrameRate
770 : parentSnapshot.frameRate;
771 }
772
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000773 if (forceUpdate || requested.what & layer_state_t::eMetadataChanged) {
774 updateMetadata(snapshot, requested, args);
775 }
776
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000777 if (forceUpdate || requested.changes.get() != 0) {
778 snapshot.compositionType = requested.getCompositionType();
779 snapshot.dimmingEnabled = requested.dimmingEnabled;
780 snapshot.layerOpaqueFlagSet =
781 (requested.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque;
Alec Mourif4af03e2023-02-11 00:25:24 +0000782 snapshot.cachingHint = requested.cachingHint;
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000783 snapshot.frameRateSelectionPriority = requested.frameRateSelectionPriority;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000784 }
785
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000786 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content)) {
787 snapshot.color.rgb = requested.getColor().rgb;
788 snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000789 snapshot.backgroundBlurRadius = args.supportsBlur
790 ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
791 : 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000792 snapshot.blurRegions = requested.blurRegions;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000793 for (auto& region : snapshot.blurRegions) {
794 region.alpha = region.alpha * snapshot.color.a;
795 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000796 snapshot.hdrMetadata = requested.hdrMetadata;
797 }
798
799 if (forceUpdate ||
800 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
801 RequestedLayerState::Changes::Geometry)) {
802 updateLayerBounds(snapshot, requested, parentSnapshot, displayRotationFlags);
803 updateRoundedCorner(snapshot, requested, parentSnapshot);
804 }
805
806 if (forceUpdate ||
807 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
808 RequestedLayerState::Changes::Geometry |
809 RequestedLayerState::Changes::Input)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000810 updateInput(snapshot, requested, parentSnapshot, path, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000811 }
812
813 // computed snapshot properties
814 updateShadows(snapshot, requested, args.globalShadowSettings);
815 if (args.includeMetadata) {
816 snapshot.layerMetadata = parentSnapshot.layerMetadata;
817 snapshot.layerMetadata.merge(requested.metadata);
818 }
819 snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 ||
820 requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect();
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000821 snapshot.contentOpaque = snapshot.isContentOpaque();
822 snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000823 snapshot.color.a == 1.f;
824 snapshot.blendMode = getBlendMode(snapshot, requested);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000825 LLOGV(snapshot.sequence,
Vishnu Nair92990e22023-02-24 20:01:05 +0000826 "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
827 args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
828 snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
829 parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
830 std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000831}
832
833void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
834 const RequestedLayerState& requested,
835 const LayerSnapshot& parentSnapshot) {
836 snapshot.roundedCorner = RoundedCornerState();
837 RoundedCornerState parentRoundedCorner;
838 if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
839 parentRoundedCorner = parentSnapshot.roundedCorner;
840 ui::Transform t = snapshot.localTransform.inverse();
841 parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
842 parentRoundedCorner.radius.x *= t.getScaleX();
843 parentRoundedCorner.radius.y *= t.getScaleY();
844 }
845
846 FloatRect layerCropRect = snapshot.croppedBufferSize.toFloatRect();
847 const vec2 radius(requested.cornerRadius, requested.cornerRadius);
848 RoundedCornerState layerSettings(layerCropRect, radius);
849 const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
850 const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
851 if (layerSettingsValid && parentRoundedCornerValid) {
852 // If the parent and the layer have rounded corner settings, use the parent settings if
853 // the parent crop is entirely inside the layer crop. This has limitations and cause
854 // rendering artifacts. See b/200300845 for correct fix.
855 if (parentRoundedCorner.cropRect.left > layerCropRect.left &&
856 parentRoundedCorner.cropRect.top > layerCropRect.top &&
857 parentRoundedCorner.cropRect.right < layerCropRect.right &&
858 parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) {
859 snapshot.roundedCorner = parentRoundedCorner;
860 } else {
861 snapshot.roundedCorner = layerSettings;
862 }
863 } else if (layerSettingsValid) {
864 snapshot.roundedCorner = layerSettings;
865 } else if (parentRoundedCornerValid) {
866 snapshot.roundedCorner = parentRoundedCorner;
867 }
868}
869
870void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot,
871 const RequestedLayerState& requested,
872 const LayerSnapshot& parentSnapshot,
873 uint32_t displayRotationFlags) {
874 snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
875 snapshot.geomCrop = requested.crop;
876 snapshot.localTransform = requested.getTransform(displayRotationFlags);
877 snapshot.localTransformInverse = snapshot.localTransform.inverse();
878 snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000879 const bool transformWasInvalid = snapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000880 snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
881 if (snapshot.invalidTransform) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000882 auto& t = snapshot.geomLayerTransform;
883 auto& requestedT = requested.requestedTransform;
884 std::string transformDebug =
885 base::StringPrintf(" transform={%f,%f,%f,%f} requestedTransform={%f,%f,%f,%f}",
886 t.dsdx(), t.dsdy(), t.dtdx(), t.dtdy(), requestedT.dsdx(),
887 requestedT.dsdy(), requestedT.dtdx(), requestedT.dtdy());
888 std::string bufferDebug;
889 if (requested.externalTexture) {
890 auto unRotBuffer = requested.getUnrotatedBufferSize(displayRotationFlags);
891 auto& destFrame = requested.destinationFrame;
892 bufferDebug = base::StringPrintf(" buffer={%d,%d} displayRot=%d"
893 " destFrame={%d,%d,%d,%d} unRotBuffer={%d,%d}",
894 requested.externalTexture->getWidth(),
895 requested.externalTexture->getHeight(),
896 displayRotationFlags, destFrame.left, destFrame.top,
897 destFrame.right, destFrame.bottom,
898 unRotBuffer.getHeight(), unRotBuffer.getWidth());
899 }
900 ALOGW("Resetting transform for %s because it is invalid.%s%s",
901 snapshot.getDebugString().c_str(), transformDebug.c_str(), bufferDebug.c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000902 snapshot.geomLayerTransform.reset();
903 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000904 if (transformWasInvalid != snapshot.invalidTransform) {
905 // If transform is invalid, the layer will be hidden.
906 mResortSnapshots = true;
907 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000908 snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse();
909
910 FloatRect parentBounds = parentSnapshot.geomLayerBounds;
911 parentBounds = snapshot.localTransform.inverse().transform(parentBounds);
912 snapshot.geomLayerBounds =
913 (requested.externalTexture) ? snapshot.bufferSize.toFloatRect() : parentBounds;
914 if (!requested.crop.isEmpty()) {
915 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(requested.crop.toFloatRect());
916 }
917 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(parentBounds);
918 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000919 const Rect geomLayerBoundsWithoutTransparentRegion =
920 RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
921 requested.transparentRegion);
922 snapshot.transformedBoundsWithoutTransparentRegion =
923 snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000924 snapshot.parentTransform = parentSnapshot.geomLayerTransform;
925
926 // Subtract the transparent region and snap to the bounds
Vishnu Naircfb2d252023-01-19 04:44:02 +0000927 const Rect bounds =
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000928 RequestedLayerState::reduce(snapshot.croppedBufferSize, requested.transparentRegion);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000929 if (requested.potentialCursor) {
930 snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds);
931 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000932}
933
934void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot,
935 const RequestedLayerState& requested,
936 const renderengine::ShadowSettings& globalShadowSettings) {
937 snapshot.shadowRadius = requested.shadowRadius;
938 snapshot.shadowSettings.length = requested.shadowRadius;
939 if (snapshot.shadowRadius > 0.f) {
940 snapshot.shadowSettings = globalShadowSettings;
941
942 // Note: this preserves existing behavior of shadowing the entire layer and not cropping
943 // it if transparent regions are present. This may not be necessary since shadows are
944 // typically cast by layers without transparent regions.
945 snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds;
946
947 // If the casting layer is translucent, we need to fill in the shadow underneath the
948 // layer. Otherwise the generated shadow will only be shown around the casting layer.
949 snapshot.shadowSettings.casterIsTranslucent =
950 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f);
951 snapshot.shadowSettings.ambientColor *= snapshot.alpha;
952 snapshot.shadowSettings.spotColor *= snapshot.alpha;
953 }
954}
955
956void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
957 const RequestedLayerState& requested,
958 const LayerSnapshot& parentSnapshot,
Vishnu Naircfb2d252023-01-19 04:44:02 +0000959 const LayerHierarchy::TraversalPath& path,
960 const Args& args) {
961 if (requested.windowInfoHandle) {
962 snapshot.inputInfo = *requested.windowInfoHandle->getInfo();
963 } else {
964 snapshot.inputInfo = {};
Vishnu Nair40d02282023-02-28 21:11:40 +0000965 // b/271132344 revisit this and see if we can always use the layers uid/pid
966 snapshot.inputInfo.name = requested.name;
967 snapshot.inputInfo.ownerUid = static_cast<int32_t>(requested.ownerUid);
968 snapshot.inputInfo.ownerPid = requested.ownerPid;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000969 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000970
Vishnu Nair93b8b792023-02-27 19:40:24 +0000971 snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
Vishnu Naird47bcee2023-02-24 18:08:51 +0000972 snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000973 if (!needsInputInfo(snapshot, requested)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000974 return;
975 }
976
Vishnu Naircfb2d252023-01-19 04:44:02 +0000977 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
978 const std::optional<frontend::DisplayInfo> displayInfoOpt =
979 args.displays.get(snapshot.outputFilter.layerStack);
980 bool noValidDisplay = !displayInfoOpt.has_value();
981 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
982
983 if (!requested.windowInfoHandle) {
984 snapshot.inputInfo.inputConfig = gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL;
985 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000986 fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
987
988 if (noValidDisplay) {
989 // Do not let the window receive touches if it is not associated with a valid display
990 // transform. We still allow the window to receive keys and prevent ANRs.
991 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::NOT_TOUCHABLE;
992 }
993
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000994 snapshot.inputInfo.alpha = snapshot.color.a;
Vishnu Nair40d02282023-02-28 21:11:40 +0000995 snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
996 ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
997 : parentSnapshot.inputInfo.touchOcclusionMode;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000998 if (requested.dropInputMode == gui::DropInputMode::ALL ||
999 parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
1000 snapshot.dropInputMode = gui::DropInputMode::ALL;
1001 } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
1002 parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
1003 snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
1004 } else {
1005 snapshot.dropInputMode = gui::DropInputMode::NONE;
1006 }
1007
1008 handleDropInputMode(snapshot, parentSnapshot);
1009
1010 // If the window will be blacked out on a display because the display does not have the secure
1011 // flag and the layer has the secure flag set, then drop input.
1012 if (!displayInfo.isSecure && snapshot.isSecure) {
1013 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
1014 }
1015
1016 auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
1017 if (snapshot.inputInfo.replaceTouchableRegionWithCrop) {
Vishnu Nairfed7c122023-03-18 01:54:43 +00001018 Rect inputBoundsInDisplaySpace;
1019 if (!cropLayerSnapshot) {
1020 FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first;
1021 inputBoundsInDisplaySpace =
1022 getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform);
1023 } else {
1024 FloatRect inputBounds =
1025 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1026 inputBoundsInDisplaySpace =
1027 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1028 displayInfo.transform);
1029 }
1030 snapshot.inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001031 } else if (cropLayerSnapshot) {
Vishnu Nairfed7c122023-03-18 01:54:43 +00001032 FloatRect inputBounds = getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1033 Rect inputBoundsInDisplaySpace =
1034 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1035 displayInfo.transform);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001036 snapshot.inputInfo.touchableRegion = snapshot.inputInfo.touchableRegion.intersect(
Vishnu Nairfed7c122023-03-18 01:54:43 +00001037 displayInfo.transform.transform(inputBoundsInDisplaySpace));
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001038 }
1039
1040 // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
1041 // if it was set by WM for a known system overlay
1042 if (snapshot.isTrustedOverlay) {
1043 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::TRUSTED_OVERLAY;
1044 }
1045
1046 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1047 // touches from going outside the cloned area.
1048 if (path.isClone()) {
1049 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
Vishnu Nair92990e22023-02-24 20:01:05 +00001050 auto clonedRootSnapshot = getSnapshot(snapshot.mirrorRootPath);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001051 if (clonedRootSnapshot) {
1052 const Rect rect =
1053 displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
1054 snapshot.inputInfo.touchableRegion = snapshot.inputInfo.touchableRegion.intersect(rect);
1055 }
1056 }
1057}
1058
1059std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() {
1060 return mSnapshots;
1061}
1062
Vishnu Naircfb2d252023-01-19 04:44:02 +00001063void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor) const {
1064 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1065 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1066 if (!snapshot.isVisible) continue;
1067 visitor(snapshot);
1068 }
1069}
1070
Vishnu Nair3af0ec02023-02-10 04:13:48 +00001071// Visit each visible snapshot in z-order
1072void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor,
1073 const LayerHierarchy& root) const {
1074 root.traverseInZOrder(
1075 [this, visitor](const LayerHierarchy&,
1076 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
1077 LayerSnapshot* snapshot = getSnapshot(traversalPath);
1078 if (snapshot && snapshot->isVisible) {
1079 visitor(*snapshot);
1080 }
1081 return true;
1082 });
1083}
1084
Vishnu Naircfb2d252023-01-19 04:44:02 +00001085void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) {
1086 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1087 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1088 if (!snapshot->isVisible) continue;
1089 visitor(snapshot);
1090 }
1091}
1092
1093void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
1094 for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
1095 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1096 if (!snapshot.hasInputInfo()) continue;
1097 visitor(snapshot);
1098 }
1099}
1100
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001101} // namespace android::surfaceflinger::frontend