blob: 96ff70cc349474960392d4ba858eb379f8bb0e67 [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
Vishnu Nair8fc721b2022-12-22 20:06:32 +000022#include <numeric>
Vishnu Nairb76d99a2023-03-19 18:22:31 -070023#include <optional>
24
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050025#include <ftl/small_map.h>
Vishnu Nairb76d99a2023-03-19 18:22:31 -070026#include <gui/TraceUtils.h>
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050027#include <ui/FloatRect.h>
28
Vishnu Nair8fc721b2022-12-22 20:06:32 +000029#include "DisplayHardware/HWC2.h"
30#include "DisplayHardware/Hal.h"
Vishnu Naircfb2d252023-01-19 04:44:02 +000031#include "LayerLog.h"
Vishnu Nairb76d99a2023-03-19 18:22:31 -070032#include "LayerSnapshotBuilder.h"
Vishnu Naircfb2d252023-01-19 04:44:02 +000033#include "TimeStats/TimeStats.h"
Vishnu Nair8fc721b2022-12-22 20:06:32 +000034
35namespace android::surfaceflinger::frontend {
36
37using namespace ftl::flag_operators;
38
39namespace {
Dominik Laskowski6b049ff2023-01-29 15:46:45 -050040
41FloatRect getMaxDisplayBounds(const DisplayInfos& displays) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +000042 const ui::Size maxSize = [&displays] {
43 if (displays.empty()) return ui::Size{5000, 5000};
44
45 return std::accumulate(displays.begin(), displays.end(), ui::kEmptySize,
46 [](ui::Size size, const auto& pair) -> ui::Size {
47 const auto& display = pair.second;
48 return {std::max(size.getWidth(), display.info.logicalWidth),
49 std::max(size.getHeight(), display.info.logicalHeight)};
50 });
51 }();
52
53 // Ignore display bounds for now since they will be computed later. Use a large Rect bound
54 // to ensure it's bigger than an actual display will be.
55 const float xMax = static_cast<float>(maxSize.getWidth()) * 10.f;
56 const float yMax = static_cast<float>(maxSize.getHeight()) * 10.f;
57
58 return {-xMax, -yMax, xMax, yMax};
59}
60
61// Applies the given transform to the region, while protecting against overflows caused by any
62// offsets. If applying the offset in the transform to any of the Rects in the region would result
63// in an overflow, they are not added to the output Region.
64Region transformTouchableRegionSafely(const ui::Transform& t, const Region& r,
65 const std::string& debugWindowName) {
66 // Round the translation using the same rounding strategy used by ui::Transform.
67 const auto tx = static_cast<int32_t>(t.tx() + 0.5);
68 const auto ty = static_cast<int32_t>(t.ty() + 0.5);
69
70 ui::Transform transformWithoutOffset = t;
71 transformWithoutOffset.set(0.f, 0.f);
72
73 const Region transformed = transformWithoutOffset.transform(r);
74
75 // Apply the translation to each of the Rects in the region while discarding any that overflow.
76 Region ret;
77 for (const auto& rect : transformed) {
78 Rect newRect;
79 if (__builtin_add_overflow(rect.left, tx, &newRect.left) ||
80 __builtin_add_overflow(rect.top, ty, &newRect.top) ||
81 __builtin_add_overflow(rect.right, tx, &newRect.right) ||
82 __builtin_add_overflow(rect.bottom, ty, &newRect.bottom)) {
83 ALOGE("Applying transform to touchable region of window '%s' resulted in an overflow.",
84 debugWindowName.c_str());
85 continue;
86 }
87 ret.orSelf(newRect);
88 }
89 return ret;
90}
91
92/*
93 * We don't want to send the layer's transform to input, but rather the
94 * parent's transform. This is because Layer's transform is
95 * information about how the buffer is placed on screen. The parent's
96 * transform makes more sense to send since it's information about how the
97 * layer is placed on screen. This transform is used by input to determine
98 * how to go from screen space back to window space.
99 */
100ui::Transform getInputTransform(const LayerSnapshot& snapshot) {
101 if (!snapshot.hasBufferOrSidebandStream()) {
102 return snapshot.geomLayerTransform;
103 }
104 return snapshot.parentTransform;
105}
106
107/**
Vishnu Nairfed7c122023-03-18 01:54:43 +0000108 * Returns the bounds used to fill the input frame and the touchable region.
109 *
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000110 * Similar to getInputTransform, we need to update the bounds to include the transform.
111 * This is because bounds don't include the buffer transform, where the input assumes
112 * that's already included.
113 */
Vishnu Nairfed7c122023-03-18 01:54:43 +0000114std::pair<FloatRect, bool> getInputBounds(const LayerSnapshot& snapshot, bool fillParentBounds) {
115 FloatRect inputBounds = snapshot.croppedBufferSize.toFloatRect();
116 if (snapshot.hasBufferOrSidebandStream() && snapshot.croppedBufferSize.isValid() &&
117 snapshot.localTransform.getType() != ui::Transform::IDENTITY) {
118 inputBounds = snapshot.localTransform.transform(inputBounds);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000119 }
120
Vishnu Nairfed7c122023-03-18 01:54:43 +0000121 bool inputBoundsValid = snapshot.croppedBufferSize.isValid();
122 if (!inputBoundsValid) {
123 /**
124 * Input bounds are based on the layer crop or buffer size. But if we are using
125 * the layer bounds as the input bounds (replaceTouchableRegionWithCrop flag) then
126 * we can use the parent bounds as the input bounds if the layer does not have buffer
127 * or a crop. We want to unify this logic but because of compat reasons we cannot always
128 * use the parent bounds. A layer without a buffer can get input. So when a window is
129 * initially added, its touchable region can fill its parent layer bounds and that can
130 * have negative consequences.
131 */
132 inputBounds = fillParentBounds ? snapshot.geomLayerBounds : FloatRect{};
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000133 }
Vishnu Nairfed7c122023-03-18 01:54:43 +0000134
135 // Clamp surface inset to the input bounds.
136 const float inset = static_cast<float>(snapshot.inputInfo.surfaceInset);
137 const float xSurfaceInset = std::clamp(inset, 0.f, inputBounds.getWidth() / 2.f);
138 const float ySurfaceInset = std::clamp(inset, 0.f, inputBounds.getHeight() / 2.f);
139
140 // Apply the insets to the input bounds.
141 inputBounds.left += xSurfaceInset;
142 inputBounds.top += ySurfaceInset;
143 inputBounds.right -= xSurfaceInset;
144 inputBounds.bottom -= ySurfaceInset;
145 return {inputBounds, inputBoundsValid};
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000146}
147
Vishnu Nairfed7c122023-03-18 01:54:43 +0000148Rect getInputBoundsInDisplaySpace(const LayerSnapshot& snapshot, const FloatRect& insetBounds,
149 const ui::Transform& screenToDisplay) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000150 // InputDispatcher works in the display device's coordinate space. Here, we calculate the
151 // frame and transform used for the layer, which determines the bounds and the coordinate space
152 // within which the layer will receive input.
Vishnu Nairfed7c122023-03-18 01:54:43 +0000153
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000154 // Coordinate space definitions:
155 // - display: The display device's coordinate space. Correlates to pixels on the display.
156 // - screen: The post-rotation coordinate space for the display, a.k.a. logical display space.
157 // - layer: The coordinate space of this layer.
158 // - input: The coordinate space in which this layer will receive input events. This could be
159 // different than layer space if a surfaceInset is used, which changes the origin
160 // of the input space.
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000161
162 // Crop the input bounds to ensure it is within the parent's bounds.
Vishnu Nairfed7c122023-03-18 01:54:43 +0000163 const FloatRect croppedInsetBoundsInLayer = snapshot.geomLayerBounds.intersect(insetBounds);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000164
165 const ui::Transform layerToScreen = getInputTransform(snapshot);
166 const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
167
Vishnu Nairfed7c122023-03-18 01:54:43 +0000168 return Rect{layerToDisplay.transform(croppedInsetBoundsInLayer)};
169}
170
171void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& screenToDisplay,
172 const LayerSnapshot& snapshot) {
173 auto [inputBounds, inputBoundsValid] = getInputBounds(snapshot, /*fillParentBounds=*/false);
174 if (!inputBoundsValid) {
175 info.touchableRegion.clear();
176 }
177
178 const Rect roundedFrameInDisplay =
179 getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000180 info.frameLeft = roundedFrameInDisplay.left;
181 info.frameTop = roundedFrameInDisplay.top;
182 info.frameRight = roundedFrameInDisplay.right;
183 info.frameBottom = roundedFrameInDisplay.bottom;
184
185 ui::Transform inputToLayer;
Vishnu Nairfed7c122023-03-18 01:54:43 +0000186 inputToLayer.set(inputBounds.left, inputBounds.top);
187 const ui::Transform layerToScreen = getInputTransform(snapshot);
188 const ui::Transform inputToDisplay = screenToDisplay * layerToScreen * inputToLayer;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000189
190 // InputDispatcher expects a display-to-input transform.
191 info.transform = inputToDisplay.inverse();
192
193 // The touchable region is specified in the input coordinate space. Change it to display space.
194 info.touchableRegion =
195 transformTouchableRegionSafely(inputToDisplay, info.touchableRegion, snapshot.name);
196}
197
198void handleDropInputMode(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot) {
199 if (snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
200 return;
201 }
202
203 // Check if we need to drop input unconditionally
204 const gui::DropInputMode dropInputMode = snapshot.dropInputMode;
205 if (dropInputMode == gui::DropInputMode::ALL) {
206 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
207 ALOGV("Dropping input for %s as requested by policy.", snapshot.name.c_str());
208 return;
209 }
210
211 // Check if we need to check if the window is obscured by parent
212 if (dropInputMode != gui::DropInputMode::OBSCURED) {
213 return;
214 }
215
216 // Check if the parent has set an alpha on the layer
217 if (parentSnapshot.color.a != 1.0_hf) {
218 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
219 ALOGV("Dropping input for %s as requested by policy because alpha=%f",
220 snapshot.name.c_str(), static_cast<float>(parentSnapshot.color.a));
221 }
222
223 // Check if the parent has cropped the buffer
224 Rect bufferSize = snapshot.croppedBufferSize;
225 if (!bufferSize.isValid()) {
226 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
227 return;
228 }
229
230 // Screenbounds are the layer bounds cropped by parents, transformed to screenspace.
231 // To check if the layer has been cropped, we take the buffer bounds, apply the local
232 // layer crop and apply the same set of transforms to move to screenspace. If the bounds
233 // match then the layer has not been cropped by its parents.
234 Rect bufferInScreenSpace(snapshot.geomLayerTransform.transform(bufferSize));
235 bool croppedByParent = bufferInScreenSpace != Rect{snapshot.transformedBounds};
236
237 if (croppedByParent) {
238 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
239 ALOGV("Dropping input for %s as requested by policy because buffer is cropped by parent",
240 snapshot.name.c_str());
241 } else {
242 // If the layer is not obscured by its parents (by setting an alpha or crop), then only drop
243 // input if the window is obscured. This check should be done in surfaceflinger but the
244 // logic currently resides in inputflinger. So pass the if_obscured check to input to only
245 // drop input events if the window is obscured.
246 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
247 }
248}
249
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000250auto getBlendMode(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
251 auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
252 if (snapshot.alpha != 1.0f || !snapshot.isContentOpaque()) {
253 blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED
254 : Hwc2::IComposerClient::BlendMode::COVERAGE;
255 }
256 return blendMode;
257}
258
Vishnu Naircfb2d252023-01-19 04:44:02 +0000259void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFrame,
260 bool forceFullDamage, Region& outSurfaceDamageRegion) {
261 if (!hasReadyFrame) {
262 outSurfaceDamageRegion.clear();
263 return;
264 }
265 if (forceFullDamage) {
266 outSurfaceDamageRegion = Region::INVALID_REGION;
267 } else {
268 outSurfaceDamageRegion = requested.surfaceDamageRegion;
269 }
270}
271
Vishnu Nair80a5a702023-02-11 01:21:51 +0000272void updateVisibility(LayerSnapshot& snapshot, bool visible) {
273 snapshot.isVisible = visible;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000274
275 // TODO(b/238781169) we are ignoring this compat for now, since we will have
276 // to remove any optimization based on visibility.
277
278 // For compatibility reasons we let layers which can receive input
279 // receive input before they have actually submitted a buffer. Because
280 // of this we use canReceiveInput instead of isVisible to check the
281 // policy-visibility, ignoring the buffer state. However for layers with
282 // hasInputInfo()==false we can use the real visibility state.
283 // We are just using these layers for occlusion detection in
284 // InputDispatcher, and obviously if they aren't visible they can't occlude
285 // anything.
Vishnu Nair80a5a702023-02-11 01:21:51 +0000286 const bool visibleForInput =
Vishnu Nair40d02282023-02-28 21:11:40 +0000287 snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000288 snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000289}
290
291bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
292 if (requested.potentialCursor) {
293 return false;
294 }
295
296 if (snapshot.inputInfo.token != nullptr) {
297 return true;
298 }
299
300 if (snapshot.hasBufferOrSidebandStream()) {
301 return true;
302 }
303
304 return requested.windowInfoHandle &&
305 requested.windowInfoHandle->getInfo()->inputConfig.test(
306 gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
307}
308
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000309void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested,
310 const LayerSnapshotBuilder::Args& args) {
311 snapshot.metadata.clear();
312 for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) {
313 auto compatIter = args.genericLayerMetadataKeyMap.find(key);
314 if (compatIter == std::end(args.genericLayerMetadataKeyMap)) {
315 continue;
316 }
317 const uint32_t id = compatIter->second;
318 auto it = requested.metadata.mMap.find(id);
319 if (it == std::end(requested.metadata.mMap)) {
320 continue;
321 }
322
323 snapshot.metadata.emplace(key,
324 compositionengine::GenericLayerMetadataEntry{mandatory,
325 it->second});
326 }
327}
328
Vishnu Naircfb2d252023-01-19 04:44:02 +0000329void clearChanges(LayerSnapshot& snapshot) {
330 snapshot.changes.clear();
331 snapshot.contentDirty = false;
332 snapshot.hasReadyFrame = false;
333 snapshot.sidebandStreamHasFrame = false;
334 snapshot.surfaceDamage.clear();
335}
336
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000337} // namespace
338
339LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
340 LayerSnapshot snapshot;
Vishnu Nair92990e22023-02-24 20:01:05 +0000341 snapshot.path = LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000342 snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
343 snapshot.isHiddenByPolicyFromParent = false;
344 snapshot.isHiddenByPolicyFromRelativeParent = false;
345 snapshot.parentTransform.reset();
346 snapshot.geomLayerTransform.reset();
347 snapshot.geomInverseLayerTransform.reset();
348 snapshot.geomLayerBounds = getMaxDisplayBounds({});
349 snapshot.roundedCorner = RoundedCornerState();
350 snapshot.stretchEffect = {};
351 snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK;
352 snapshot.outputFilter.toInternalDisplay = false;
353 snapshot.isSecure = false;
354 snapshot.color.a = 1.0_hf;
355 snapshot.colorTransformIsIdentity = true;
356 snapshot.shadowRadius = 0.f;
357 snapshot.layerMetadata.mMap.clear();
358 snapshot.relativeLayerMetadata.mMap.clear();
359 snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED;
360 snapshot.dropInputMode = gui::DropInputMode::NONE;
361 snapshot.isTrustedOverlay = false;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000362 snapshot.gameMode = gui::GameMode::Unsupported;
363 snapshot.frameRate = {};
364 snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000365 return snapshot;
366}
367
368LayerSnapshotBuilder::LayerSnapshotBuilder() : mRootSnapshot(getRootSnapshot()) {}
369
370LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000371 args.forceUpdate = ForceUpdateFlags::ALL;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000372 updateSnapshots(args);
373}
374
375bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000376 if (args.forceUpdate != ForceUpdateFlags::NONE || args.displayChanges) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000377 // force update requested, or we have display changes, so skip the fast path
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000378 return false;
379 }
380
381 if (args.layerLifecycleManager.getGlobalChanges().get() == 0) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000382 return true;
383 }
384
385 if (args.layerLifecycleManager.getGlobalChanges() != RequestedLayerState::Changes::Content) {
386 // We have changes that require us to walk the hierarchy and update child layers.
387 // No fast path for you.
388 return false;
389 }
390
391 // There are only content changes which do not require any child layer snapshots to be updated.
392 ALOGV("%s", __func__);
393 ATRACE_NAME("FastPath");
394
395 // Collect layers with changes
396 ftl::SmallMap<uint32_t, RequestedLayerState*, 10> layersWithChanges;
397 for (auto& layer : args.layerLifecycleManager.getLayers()) {
398 if (layer->changes.test(RequestedLayerState::Changes::Content)) {
399 layersWithChanges.emplace_or_replace(layer->id, layer.get());
400 }
401 }
402
403 // Walk through the snapshots, clearing previous change flags and updating the snapshots
404 // if needed.
405 for (auto& snapshot : mSnapshots) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000406 auto it = layersWithChanges.find(snapshot->path.id);
407 if (it != layersWithChanges.end()) {
408 ALOGV("%s fast path snapshot changes = %s", __func__,
409 mRootSnapshot.changes.string().c_str());
410 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair92990e22023-02-24 20:01:05 +0000411 updateSnapshot(*snapshot, args, *it->second, mRootSnapshot, root);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000412 }
413 }
414 return true;
415}
416
417void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
418 ATRACE_NAME("UpdateSnapshots");
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000419 if (args.parentCrop) {
420 mRootSnapshot.geomLayerBounds = *args.parentCrop;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000421 } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000422 mRootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
423 }
424 if (args.displayChanges) {
425 mRootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
426 RequestedLayerState::Changes::Geometry;
427 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000428 if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
429 mRootSnapshot.changes |=
430 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
431 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000432 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000433 if (args.root.getLayer()) {
434 // The hierarchy can have a root layer when used for screenshots otherwise, it will have
435 // multiple children.
436 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, args.root.getLayer()->id,
437 LayerHierarchy::Variant::Attached);
438 updateSnapshotsInHierarchy(args, args.root, root, mRootSnapshot);
439 } else {
440 for (auto& [childHierarchy, variant] : args.root.mChildren) {
441 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
442 childHierarchy->getLayer()->id,
443 variant);
444 updateSnapshotsInHierarchy(args, *childHierarchy, root, mRootSnapshot);
445 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000446 }
447
Vishnu Nair29354ec2023-03-28 18:51:28 -0700448 // Update touchable region crops outside the main update pass. This is because a layer could be
449 // cropped by any other layer and it requires both snapshots to be updated.
450 updateTouchableRegionCrop(args);
451
Vishnu Nairfccd6362023-02-24 23:39:53 +0000452 const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000453 clearChanges(mRootSnapshot);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000454
Vishnu Nair29354ec2023-03-28 18:51:28 -0700455 // Destroy unreachable snapshots for clone layers. And destroy snapshots for non-clone
456 // layers if the layer have been destroyed.
457 // TODO(b/238781169) consider making clone layer ids stable as well
458 if (!hasUnreachableSnapshots && args.layerLifecycleManager.getDestroyedLayers().empty()) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000459 return;
460 }
461
Vishnu Nair29354ec2023-03-28 18:51:28 -0700462 std::unordered_set<uint32_t> destroyedLayerIds;
463 for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
464 destroyedLayerIds.insert(destroyedLayer->id);
465 }
466
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000467 auto it = mSnapshots.begin();
468 while (it < mSnapshots.end()) {
469 auto& traversalPath = it->get()->path;
Vishnu Nair29354ec2023-03-28 18:51:28 -0700470 if (!it->get()->unreachable &&
471 destroyedLayerIds.find(traversalPath.id) == destroyedLayerIds.end()) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000472 it++;
473 continue;
474 }
475
476 mIdToSnapshot.erase(traversalPath);
Vishnu Nair29354ec2023-03-28 18:51:28 -0700477 mNeedsTouchableRegionCrop.erase(traversalPath);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000478 mSnapshots.back()->globalZ = it->get()->globalZ;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000479 std::iter_swap(it, mSnapshots.end() - 1);
480 mSnapshots.erase(mSnapshots.end() - 1);
481 }
482}
483
484void LayerSnapshotBuilder::update(const Args& args) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000485 for (auto& snapshot : mSnapshots) {
486 clearChanges(*snapshot);
487 }
488
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000489 if (tryFastUpdate(args)) {
490 return;
491 }
492 updateSnapshots(args);
493}
494
Vishnu Naircfb2d252023-01-19 04:44:02 +0000495const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy(
496 const Args& args, const LayerHierarchy& hierarchy,
497 LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000498 const RequestedLayerState* layer = hierarchy.getLayer();
Vishnu Naircfb2d252023-01-19 04:44:02 +0000499 LayerSnapshot* snapshot = getSnapshot(traversalPath);
500 const bool newSnapshot = snapshot == nullptr;
501 if (newSnapshot) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000502 snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000503 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000504 scheduler::LayerInfo::FrameRate oldFrameRate = snapshot->frameRate;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000505 if (traversalPath.isRelative()) {
506 bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
507 updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
508 } else {
509 if (traversalPath.isAttached()) {
510 resetRelativeState(*snapshot);
511 }
Vishnu Nair92990e22023-02-24 20:01:05 +0000512 updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000513 }
514
515 for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
516 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(traversalPath,
517 childHierarchy->getLayer()->id,
518 variant);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000519 const LayerSnapshot& childSnapshot =
520 updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot);
521 updateChildState(*snapshot, childSnapshot, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000522 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000523
524 if (oldFrameRate == snapshot->frameRate) {
525 snapshot->changes.clear(RequestedLayerState::Changes::FrameRate);
526 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000527 return *snapshot;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000528}
529
530LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const {
531 if (layerId == UNASSIGNED_LAYER_ID) {
532 return nullptr;
533 }
534 LayerHierarchy::TraversalPath path{.id = layerId};
535 return getSnapshot(path);
536}
537
538LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
539 auto it = mIdToSnapshot.find(id);
540 return it == mIdToSnapshot.end() ? nullptr : it->second;
541}
542
Vishnu Nair92990e22023-02-24 20:01:05 +0000543LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
544 const RequestedLayerState& layer,
545 const LayerSnapshot& parentSnapshot) {
546 mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
Vishnu Naircfb2d252023-01-19 04:44:02 +0000547 LayerSnapshot* snapshot = mSnapshots.back().get();
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000548 snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
Vishnu Nair92990e22023-02-24 20:01:05 +0000549 if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) {
550 snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
551 }
552 mIdToSnapshot[path] = snapshot;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000553 return snapshot;
554}
555
Vishnu Nairfccd6362023-02-24 23:39:53 +0000556bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000557 if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000558 !args.layerLifecycleManager.getGlobalChanges().any(
559 RequestedLayerState::Changes::Hierarchy |
560 RequestedLayerState::Changes::Visibility)) {
561 // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
562 // the snapshots.
Vishnu Nairfccd6362023-02-24 23:39:53 +0000563 return false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000564 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000565 mResortSnapshots = false;
566
Vishnu Nairfccd6362023-02-24 23:39:53 +0000567 for (auto& snapshot : mSnapshots) {
Vishnu Nair29354ec2023-03-28 18:51:28 -0700568 snapshot->unreachable = snapshot->path.isClone();
Vishnu Nairfccd6362023-02-24 23:39:53 +0000569 }
570
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000571 size_t globalZ = 0;
572 args.root.traverseInZOrder(
573 [this, &globalZ](const LayerHierarchy&,
574 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
575 LayerSnapshot* snapshot = getSnapshot(traversalPath);
576 if (!snapshot) {
577 return false;
578 }
579
Vishnu Nairfccd6362023-02-24 23:39:53 +0000580 snapshot->unreachable = false;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000581 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
Vishnu Nair80a5a702023-02-11 01:21:51 +0000582 updateVisibility(*snapshot, snapshot->getIsVisible());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000583 size_t oldZ = snapshot->globalZ;
584 size_t newZ = globalZ++;
585 snapshot->globalZ = newZ;
586 if (oldZ == newZ) {
587 return true;
588 }
589 mSnapshots[newZ]->globalZ = oldZ;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000590 LLOGV(snapshot->sequence, "Made visible z=%zu -> %zu %s", oldZ, newZ,
591 snapshot->getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000592 std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ),
593 mSnapshots.begin() + static_cast<ssize_t>(newZ));
594 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000595 return true;
596 });
Vishnu Naircfb2d252023-01-19 04:44:02 +0000597 mNumInterestingSnapshots = (int)globalZ;
Vishnu Nairfccd6362023-02-24 23:39:53 +0000598 bool hasUnreachableSnapshots = false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000599 while (globalZ < mSnapshots.size()) {
600 mSnapshots[globalZ]->globalZ = globalZ;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000601 /* mark unreachable snapshots as explicitly invisible */
602 updateVisibility(*mSnapshots[globalZ], false);
Vishnu Nairfccd6362023-02-24 23:39:53 +0000603 if (mSnapshots[globalZ]->unreachable) {
604 hasUnreachableSnapshots = true;
605 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000606 globalZ++;
607 }
Vishnu Nairfccd6362023-02-24 23:39:53 +0000608 return hasUnreachableSnapshots;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000609}
610
611void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
612 const LayerSnapshot& parentSnapshot,
613 bool parentIsRelative, const Args& args) {
614 if (parentIsRelative) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000615 snapshot.isHiddenByPolicyFromRelativeParent =
616 parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000617 if (args.includeMetadata) {
618 snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata;
619 }
620 } else {
621 snapshot.isHiddenByPolicyFromRelativeParent =
622 parentSnapshot.isHiddenByPolicyFromRelativeParent;
623 if (args.includeMetadata) {
624 snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
625 }
626 }
627 snapshot.isVisible = snapshot.getIsVisible();
628}
629
Vishnu Naircfb2d252023-01-19 04:44:02 +0000630void LayerSnapshotBuilder::updateChildState(LayerSnapshot& snapshot,
631 const LayerSnapshot& childSnapshot, const Args& args) {
632 if (snapshot.childState.hasValidFrameRate) {
633 return;
634 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000635 if (args.forceUpdate == ForceUpdateFlags::ALL ||
636 childSnapshot.changes.test(RequestedLayerState::Changes::FrameRate)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000637 // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes
638 // for the same reason we are allowing touch boost for those layers. See
639 // RefreshRateSelector::rankFrameRates for details.
640 using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility;
641 const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.rate.isValid() &&
642 childSnapshot.frameRate.type == FrameRateCompatibility::Default;
643 const auto layerVotedWithNoVote =
644 childSnapshot.frameRate.type == FrameRateCompatibility::NoVote;
645 const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.rate.isValid() &&
646 childSnapshot.frameRate.type == FrameRateCompatibility::Exact;
647
648 snapshot.childState.hasValidFrameRate |= layerVotedWithDefaultCompatibility ||
649 layerVotedWithNoVote || layerVotedWithExactCompatibility;
650
651 // If we don't have a valid frame rate, but the children do, we set this
652 // layer as NoVote to allow the children to control the refresh rate
653 if (!snapshot.frameRate.rate.isValid() &&
654 snapshot.frameRate.type != FrameRateCompatibility::NoVote &&
655 snapshot.childState.hasValidFrameRate) {
656 snapshot.frameRate =
657 scheduler::LayerInfo::FrameRate(Fps(), FrameRateCompatibility::NoVote);
658 snapshot.changes |= childSnapshot.changes & RequestedLayerState::Changes::FrameRate;
659 }
660 }
661}
662
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000663void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) {
664 snapshot.isHiddenByPolicyFromRelativeParent = false;
665 snapshot.relativeLayerMetadata.mMap.clear();
666}
667
Leon Scroggins III85d4b222023-05-09 13:58:18 -0400668// TODO (b/259407931): Remove.
Dominik Laskowski6b049ff2023-01-29 15:46:45 -0500669uint32_t getPrimaryDisplayRotationFlags(const DisplayInfos& displays) {
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700670 for (auto& [_, display] : displays) {
671 if (display.isPrimary) {
672 return display.rotationFlags;
673 }
674 }
675 return 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000676}
677
678void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
679 const RequestedLayerState& requested,
680 const LayerSnapshot& parentSnapshot,
Vishnu Nair92990e22023-02-24 20:01:05 +0000681 const LayerHierarchy::TraversalPath& path) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000682 // Always update flags and visibility
683 ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
684 (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
685 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
Vishnu Naird47bcee2023-02-24 18:08:51 +0000686 RequestedLayerState::Changes::AffectsChildren |
687 RequestedLayerState::Changes::FrameRate);
Vishnu Nair92990e22023-02-24 20:01:05 +0000688 snapshot.changes |= parentChanges | requested.changes;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000689 snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000690 parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
691 (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000692 snapshot.contentDirty = requested.what & layer_state_t::CONTENT_DIRTY;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000693 // TODO(b/238781169) scope down the changes to only buffer updates.
Vishnu Naird47bcee2023-02-24 18:08:51 +0000694 snapshot.hasReadyFrame = requested.hasReadyFrame();
695 snapshot.sidebandStreamHasFrame = requested.hasSidebandStreamFrame();
Vishnu Naircfb2d252023-01-19 04:44:02 +0000696 updateSurfaceDamage(requested, snapshot.hasReadyFrame, args.forceFullDamage,
697 snapshot.surfaceDamage);
Vishnu Nair92990e22023-02-24 20:01:05 +0000698 snapshot.outputFilter.layerStack = parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
699 ? requested.layerStack
700 : parentSnapshot.outputFilter.layerStack;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000701
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700702 uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
Vishnu Nair92990e22023-02-24 20:01:05 +0000703 const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
704 snapshot.changes.any(RequestedLayerState::Changes::Visibility |
705 RequestedLayerState::Changes::Created);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000706
Vishnu Naircfb2d252023-01-19 04:44:02 +0000707 // always update the buffer regardless of visibility
Vishnu Nair80a5a702023-02-11 01:21:51 +0000708 if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES || args.displayChanges) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000709 snapshot.acquireFence =
710 (requested.externalTexture &&
711 requested.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged))
712 ? requested.bufferData->acquireFence
713 : Fence::NO_FENCE;
714 snapshot.buffer =
715 requested.externalTexture ? requested.externalTexture->getBuffer() : nullptr;
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700716 snapshot.bufferSize = requested.getBufferSize(primaryDisplayRotationFlags);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000717 snapshot.geomBufferSize = snapshot.bufferSize;
718 snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
719 snapshot.dataspace = requested.dataspace;
720 snapshot.externalTexture = requested.externalTexture;
721 snapshot.frameNumber = (requested.bufferData) ? requested.bufferData->frameNumber : 0;
722 snapshot.geomBufferTransform = requested.bufferTransform;
723 snapshot.geomBufferUsesDisplayInverseTransform = requested.transformToDisplayInverse;
724 snapshot.geomContentCrop = requested.getBufferCrop();
725 snapshot.geomUsesSourceCrop = snapshot.hasBufferOrSidebandStream();
726 snapshot.hasProtectedContent = requested.externalTexture &&
727 requested.externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED;
728 snapshot.isHdrY410 = requested.dataspace == ui::Dataspace::BT2020_ITU_PQ &&
729 requested.api == NATIVE_WINDOW_API_MEDIA &&
730 requested.bufferData->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102;
731 snapshot.sidebandStream = requested.sidebandStream;
732 snapshot.transparentRegionHint = requested.transparentRegion;
733 snapshot.color.rgb = requested.getColor().rgb;
Sally Qi963049b2023-03-23 14:06:21 -0700734 snapshot.currentHdrSdrRatio = requested.currentHdrSdrRatio;
735 snapshot.desiredHdrSdrRatio = requested.desiredHdrSdrRatio;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000736 }
737
Vishnu Nair92990e22023-02-24 20:01:05 +0000738 if (snapshot.isHiddenByPolicyFromParent &&
739 !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000740 if (forceUpdate ||
741 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
742 RequestedLayerState::Changes::Geometry |
743 RequestedLayerState::Changes::Input)) {
744 updateInput(snapshot, requested, parentSnapshot, path, args);
745 }
746 return;
747 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000748
749 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) {
750 // If root layer, use the layer stack otherwise get the parent's layer stack.
751 snapshot.color.a = parentSnapshot.color.a * requested.color.a;
752 snapshot.alpha = snapshot.color.a;
Vishnu Nair29354ec2023-03-28 18:51:28 -0700753 snapshot.inputInfo.alpha = snapshot.color.a;
754
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000755 snapshot.isSecure =
756 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
757 snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000758 snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
759 (requested.flags & layer_state_t::eLayerSkipScreenshot);
760 snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
761 ? requested.stretchEffect
762 : parentSnapshot.stretchEffect;
763 if (!parentSnapshot.colorTransformIsIdentity) {
764 snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
765 snapshot.colorTransformIsIdentity = false;
766 } else {
767 snapshot.colorTransform = requested.colorTransform;
768 snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
769 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000770 snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
771 ? requested.gameMode
772 : parentSnapshot.gameMode;
Vishnu Naira9c43762023-01-27 19:10:25 +0000773 // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
774 // marked as skip capture
775 snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
776 (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000777 }
778
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700779 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren) ||
780 args.displayChanges) {
781 snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
782 ? requested.fixedTransformHint
783 : parentSnapshot.fixedTransformHint;
784
785 if (snapshot.fixedTransformHint != ui::Transform::ROT_INVALID) {
786 snapshot.transformHint = snapshot.fixedTransformHint;
787 } else {
788 const auto display = args.displays.get(snapshot.outputFilter.layerStack);
789 snapshot.transformHint = display.has_value()
790 ? std::make_optional<>(display->get().transformHint)
791 : std::nullopt;
792 }
793 }
794
Vishnu Naird47bcee2023-02-24 18:08:51 +0000795 if (forceUpdate ||
796 snapshot.changes.any(RequestedLayerState::Changes::FrameRate |
797 RequestedLayerState::Changes::Hierarchy)) {
798 snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() ||
799 (requested.requestedFrameRate.type ==
800 scheduler::LayerInfo::FrameRateCompatibility::NoVote))
801 ? requested.requestedFrameRate
802 : parentSnapshot.frameRate;
803 }
804
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000805 if (forceUpdate || requested.what & layer_state_t::eMetadataChanged) {
806 updateMetadata(snapshot, requested, args);
807 }
808
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000809 if (forceUpdate || requested.changes.get() != 0) {
810 snapshot.compositionType = requested.getCompositionType();
811 snapshot.dimmingEnabled = requested.dimmingEnabled;
812 snapshot.layerOpaqueFlagSet =
813 (requested.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque;
Alec Mourif4af03e2023-02-11 00:25:24 +0000814 snapshot.cachingHint = requested.cachingHint;
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000815 snapshot.frameRateSelectionPriority = requested.frameRateSelectionPriority;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000816 }
817
Vishnu Nair444f3952023-04-11 13:01:02 -0700818 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content) ||
819 snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000820 snapshot.color.rgb = requested.getColor().rgb;
821 snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000822 snapshot.backgroundBlurRadius = args.supportsBlur
823 ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
824 : 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000825 snapshot.blurRegions = requested.blurRegions;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000826 for (auto& region : snapshot.blurRegions) {
827 region.alpha = region.alpha * snapshot.color.a;
828 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000829 snapshot.hdrMetadata = requested.hdrMetadata;
830 }
831
832 if (forceUpdate ||
833 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
834 RequestedLayerState::Changes::Geometry)) {
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700835 updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000836 updateRoundedCorner(snapshot, requested, parentSnapshot);
837 }
838
839 if (forceUpdate ||
840 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
841 RequestedLayerState::Changes::Geometry |
842 RequestedLayerState::Changes::Input)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000843 updateInput(snapshot, requested, parentSnapshot, path, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000844 }
845
846 // computed snapshot properties
847 updateShadows(snapshot, requested, args.globalShadowSettings);
848 if (args.includeMetadata) {
849 snapshot.layerMetadata = parentSnapshot.layerMetadata;
850 snapshot.layerMetadata.merge(requested.metadata);
851 }
852 snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 ||
853 requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect();
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000854 snapshot.contentOpaque = snapshot.isContentOpaque();
855 snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000856 snapshot.color.a == 1.f;
857 snapshot.blendMode = getBlendMode(snapshot, requested);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000858 LLOGV(snapshot.sequence,
Vishnu Nair92990e22023-02-24 20:01:05 +0000859 "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
860 args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
861 snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
862 parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
863 std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000864}
865
866void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
867 const RequestedLayerState& requested,
868 const LayerSnapshot& parentSnapshot) {
869 snapshot.roundedCorner = RoundedCornerState();
870 RoundedCornerState parentRoundedCorner;
871 if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
872 parentRoundedCorner = parentSnapshot.roundedCorner;
873 ui::Transform t = snapshot.localTransform.inverse();
874 parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
875 parentRoundedCorner.radius.x *= t.getScaleX();
876 parentRoundedCorner.radius.y *= t.getScaleY();
877 }
878
879 FloatRect layerCropRect = snapshot.croppedBufferSize.toFloatRect();
880 const vec2 radius(requested.cornerRadius, requested.cornerRadius);
881 RoundedCornerState layerSettings(layerCropRect, radius);
882 const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
883 const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
884 if (layerSettingsValid && parentRoundedCornerValid) {
885 // If the parent and the layer have rounded corner settings, use the parent settings if
886 // the parent crop is entirely inside the layer crop. This has limitations and cause
887 // rendering artifacts. See b/200300845 for correct fix.
888 if (parentRoundedCorner.cropRect.left > layerCropRect.left &&
889 parentRoundedCorner.cropRect.top > layerCropRect.top &&
890 parentRoundedCorner.cropRect.right < layerCropRect.right &&
891 parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) {
892 snapshot.roundedCorner = parentRoundedCorner;
893 } else {
894 snapshot.roundedCorner = layerSettings;
895 }
896 } else if (layerSettingsValid) {
897 snapshot.roundedCorner = layerSettings;
898 } else if (parentRoundedCornerValid) {
899 snapshot.roundedCorner = parentRoundedCorner;
900 }
901}
902
903void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot,
904 const RequestedLayerState& requested,
905 const LayerSnapshot& parentSnapshot,
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700906 uint32_t primaryDisplayRotationFlags) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000907 snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
908 snapshot.geomCrop = requested.crop;
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700909 snapshot.localTransform = requested.getTransform(primaryDisplayRotationFlags);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000910 snapshot.localTransformInverse = snapshot.localTransform.inverse();
911 snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000912 const bool transformWasInvalid = snapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000913 snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
914 if (snapshot.invalidTransform) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000915 auto& t = snapshot.geomLayerTransform;
916 auto& requestedT = requested.requestedTransform;
917 std::string transformDebug =
918 base::StringPrintf(" transform={%f,%f,%f,%f} requestedTransform={%f,%f,%f,%f}",
919 t.dsdx(), t.dsdy(), t.dtdx(), t.dtdy(), requestedT.dsdx(),
920 requestedT.dsdy(), requestedT.dtdx(), requestedT.dtdy());
921 std::string bufferDebug;
922 if (requested.externalTexture) {
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700923 auto unRotBuffer = requested.getUnrotatedBufferSize(primaryDisplayRotationFlags);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000924 auto& destFrame = requested.destinationFrame;
925 bufferDebug = base::StringPrintf(" buffer={%d,%d} displayRot=%d"
926 " destFrame={%d,%d,%d,%d} unRotBuffer={%d,%d}",
927 requested.externalTexture->getWidth(),
928 requested.externalTexture->getHeight(),
Vishnu Nairb76d99a2023-03-19 18:22:31 -0700929 primaryDisplayRotationFlags, destFrame.left,
930 destFrame.top, destFrame.right, destFrame.bottom,
Vishnu Naircfb2d252023-01-19 04:44:02 +0000931 unRotBuffer.getHeight(), unRotBuffer.getWidth());
932 }
933 ALOGW("Resetting transform for %s because it is invalid.%s%s",
934 snapshot.getDebugString().c_str(), transformDebug.c_str(), bufferDebug.c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000935 snapshot.geomLayerTransform.reset();
936 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000937 if (transformWasInvalid != snapshot.invalidTransform) {
938 // If transform is invalid, the layer will be hidden.
939 mResortSnapshots = true;
940 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000941 snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse();
942
943 FloatRect parentBounds = parentSnapshot.geomLayerBounds;
944 parentBounds = snapshot.localTransform.inverse().transform(parentBounds);
945 snapshot.geomLayerBounds =
946 (requested.externalTexture) ? snapshot.bufferSize.toFloatRect() : parentBounds;
947 if (!requested.crop.isEmpty()) {
948 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(requested.crop.toFloatRect());
949 }
950 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(parentBounds);
951 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000952 const Rect geomLayerBoundsWithoutTransparentRegion =
953 RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
954 requested.transparentRegion);
955 snapshot.transformedBoundsWithoutTransparentRegion =
956 snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000957 snapshot.parentTransform = parentSnapshot.geomLayerTransform;
958
959 // Subtract the transparent region and snap to the bounds
Vishnu Naircfb2d252023-01-19 04:44:02 +0000960 const Rect bounds =
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000961 RequestedLayerState::reduce(snapshot.croppedBufferSize, requested.transparentRegion);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000962 if (requested.potentialCursor) {
963 snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds);
964 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000965}
966
967void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot,
968 const RequestedLayerState& requested,
969 const renderengine::ShadowSettings& globalShadowSettings) {
970 snapshot.shadowRadius = requested.shadowRadius;
971 snapshot.shadowSettings.length = requested.shadowRadius;
972 if (snapshot.shadowRadius > 0.f) {
973 snapshot.shadowSettings = globalShadowSettings;
974
975 // Note: this preserves existing behavior of shadowing the entire layer and not cropping
976 // it if transparent regions are present. This may not be necessary since shadows are
977 // typically cast by layers without transparent regions.
978 snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds;
979
980 // If the casting layer is translucent, we need to fill in the shadow underneath the
981 // layer. Otherwise the generated shadow will only be shown around the casting layer.
982 snapshot.shadowSettings.casterIsTranslucent =
983 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f);
984 snapshot.shadowSettings.ambientColor *= snapshot.alpha;
985 snapshot.shadowSettings.spotColor *= snapshot.alpha;
986 }
987}
988
989void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
990 const RequestedLayerState& requested,
991 const LayerSnapshot& parentSnapshot,
Vishnu Naircfb2d252023-01-19 04:44:02 +0000992 const LayerHierarchy::TraversalPath& path,
993 const Args& args) {
994 if (requested.windowInfoHandle) {
995 snapshot.inputInfo = *requested.windowInfoHandle->getInfo();
996 } else {
997 snapshot.inputInfo = {};
Vishnu Nair40d02282023-02-28 21:11:40 +0000998 // b/271132344 revisit this and see if we can always use the layers uid/pid
999 snapshot.inputInfo.name = requested.name;
1000 snapshot.inputInfo.ownerUid = static_cast<int32_t>(requested.ownerUid);
1001 snapshot.inputInfo.ownerPid = requested.ownerPid;
Vishnu Naircfb2d252023-01-19 04:44:02 +00001002 }
Vishnu Nair29354ec2023-03-28 18:51:28 -07001003 snapshot.touchCropId = requested.touchCropId;
Vishnu Naircfb2d252023-01-19 04:44:02 +00001004
Vishnu Nair93b8b792023-02-27 19:40:24 +00001005 snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
Vishnu Naird47bcee2023-02-24 18:08:51 +00001006 snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id);
Vishnu Nair29354ec2023-03-28 18:51:28 -07001007 updateVisibility(snapshot, snapshot.isVisible);
Vishnu Naircfb2d252023-01-19 04:44:02 +00001008 if (!needsInputInfo(snapshot, requested)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001009 return;
1010 }
1011
Vishnu Naircfb2d252023-01-19 04:44:02 +00001012 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1013 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1014 args.displays.get(snapshot.outputFilter.layerStack);
1015 bool noValidDisplay = !displayInfoOpt.has_value();
1016 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1017
1018 if (!requested.windowInfoHandle) {
1019 snapshot.inputInfo.inputConfig = gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL;
1020 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001021 fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
1022
1023 if (noValidDisplay) {
1024 // Do not let the window receive touches if it is not associated with a valid display
1025 // transform. We still allow the window to receive keys and prevent ANRs.
1026 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::NOT_TOUCHABLE;
1027 }
1028
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001029 snapshot.inputInfo.alpha = snapshot.color.a;
Vishnu Nair40d02282023-02-28 21:11:40 +00001030 snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
1031 ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
1032 : parentSnapshot.inputInfo.touchOcclusionMode;
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001033 if (requested.dropInputMode == gui::DropInputMode::ALL ||
1034 parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
1035 snapshot.dropInputMode = gui::DropInputMode::ALL;
1036 } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
1037 parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
1038 snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
1039 } else {
1040 snapshot.dropInputMode = gui::DropInputMode::NONE;
1041 }
1042
1043 handleDropInputMode(snapshot, parentSnapshot);
1044
1045 // If the window will be blacked out on a display because the display does not have the secure
1046 // flag and the layer has the secure flag set, then drop input.
1047 if (!displayInfo.isSecure && snapshot.isSecure) {
1048 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
1049 }
1050
1051 auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
Vishnu Nair29354ec2023-03-28 18:51:28 -07001052 if (cropLayerSnapshot) {
1053 mNeedsTouchableRegionCrop.insert(path);
1054 } else if (snapshot.inputInfo.replaceTouchableRegionWithCrop) {
1055 FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first;
Vishnu Nairfed7c122023-03-18 01:54:43 +00001056 Rect inputBoundsInDisplaySpace =
Vishnu Nair29354ec2023-03-28 18:51:28 -07001057 getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform);
1058 snapshot.inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001059 }
1060
1061 // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
1062 // if it was set by WM for a known system overlay
1063 if (snapshot.isTrustedOverlay) {
1064 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::TRUSTED_OVERLAY;
1065 }
1066
1067 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1068 // touches from going outside the cloned area.
1069 if (path.isClone()) {
1070 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
Vishnu Nair444f3952023-04-11 13:01:02 -07001071 // Cloned layers shouldn't handle watch outside since their z order is not determined by
1072 // WM or the client.
1073 snapshot.inputInfo.inputConfig.clear(gui::WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH);
1074
Vishnu Nair29354ec2023-03-28 18:51:28 -07001075 mNeedsTouchableRegionCrop.insert(path);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001076 }
1077}
1078
1079std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() {
1080 return mSnapshots;
1081}
1082
Vishnu Naircfb2d252023-01-19 04:44:02 +00001083void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor) const {
1084 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1085 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1086 if (!snapshot.isVisible) continue;
1087 visitor(snapshot);
1088 }
1089}
1090
Vishnu Nair3af0ec02023-02-10 04:13:48 +00001091// Visit each visible snapshot in z-order
1092void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor,
1093 const LayerHierarchy& root) const {
1094 root.traverseInZOrder(
1095 [this, visitor](const LayerHierarchy&,
1096 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
1097 LayerSnapshot* snapshot = getSnapshot(traversalPath);
1098 if (snapshot && snapshot->isVisible) {
1099 visitor(*snapshot);
1100 }
1101 return true;
1102 });
1103}
1104
Vishnu Naircfb2d252023-01-19 04:44:02 +00001105void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) {
1106 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1107 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1108 if (!snapshot->isVisible) continue;
1109 visitor(snapshot);
1110 }
1111}
1112
1113void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
1114 for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
1115 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1116 if (!snapshot.hasInputInfo()) continue;
1117 visitor(snapshot);
1118 }
1119}
1120
Vishnu Nair29354ec2023-03-28 18:51:28 -07001121void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) {
1122 if (mNeedsTouchableRegionCrop.empty()) {
1123 return;
1124 }
1125
1126 static constexpr ftl::Flags<RequestedLayerState::Changes> AFFECTS_INPUT =
1127 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Created |
1128 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
1129 RequestedLayerState::Changes::Input;
1130
1131 if (args.forceUpdate != ForceUpdateFlags::ALL &&
1132 !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT)) {
1133 return;
1134 }
1135
1136 for (auto& path : mNeedsTouchableRegionCrop) {
1137 frontend::LayerSnapshot* snapshot = getSnapshot(path);
1138 if (!snapshot) {
1139 continue;
1140 }
1141 const std::optional<frontend::DisplayInfo> displayInfoOpt =
1142 args.displays.get(snapshot->outputFilter.layerStack);
1143 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
1144 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
1145
1146 bool needsUpdate =
1147 args.forceUpdate == ForceUpdateFlags::ALL || snapshot->changes.any(AFFECTS_INPUT);
1148 auto cropLayerSnapshot = getSnapshot(snapshot->touchCropId);
1149 needsUpdate =
1150 needsUpdate || (cropLayerSnapshot && cropLayerSnapshot->changes.any(AFFECTS_INPUT));
1151 auto clonedRootSnapshot = path.isClone() ? getSnapshot(snapshot->mirrorRootPath) : nullptr;
1152 needsUpdate = needsUpdate ||
1153 (clonedRootSnapshot && clonedRootSnapshot->changes.any(AFFECTS_INPUT));
1154
1155 if (!needsUpdate) {
1156 continue;
1157 }
1158
1159 if (snapshot->inputInfo.replaceTouchableRegionWithCrop) {
1160 Rect inputBoundsInDisplaySpace;
1161 if (!cropLayerSnapshot) {
1162 FloatRect inputBounds = getInputBounds(*snapshot, /*fillParentBounds=*/true).first;
1163 inputBoundsInDisplaySpace =
1164 getInputBoundsInDisplaySpace(*snapshot, inputBounds, displayInfo.transform);
1165 } else {
1166 FloatRect inputBounds =
1167 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1168 inputBoundsInDisplaySpace =
1169 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1170 displayInfo.transform);
1171 }
1172 snapshot->inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace);
1173 } else if (cropLayerSnapshot) {
1174 FloatRect inputBounds =
1175 getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first;
1176 Rect inputBoundsInDisplaySpace =
1177 getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds,
1178 displayInfo.transform);
1179 snapshot->inputInfo.touchableRegion = snapshot->inputInfo.touchableRegion.intersect(
1180 displayInfo.transform.transform(inputBoundsInDisplaySpace));
1181 }
1182
1183 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1184 // touches from going outside the cloned area.
1185 if (clonedRootSnapshot) {
1186 const Rect rect =
1187 displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
1188 snapshot->inputInfo.touchableRegion =
1189 snapshot->inputInfo.touchableRegion.intersect(rect);
1190 }
1191 }
1192}
1193
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001194} // namespace android::surfaceflinger::frontend