blob: a16de1bcfb0612f8324a498c835b508891529f56 [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>
24#include <numeric>
25#include "DisplayHardware/HWC2.h"
26#include "DisplayHardware/Hal.h"
Vishnu Naircfb2d252023-01-19 04:44:02 +000027#include "LayerLog.h"
28#include "TimeStats/TimeStats.h"
Vishnu Nair8fc721b2022-12-22 20:06:32 +000029#include "ftl/small_map.h"
30
31namespace android::surfaceflinger::frontend {
32
33using namespace ftl::flag_operators;
34
35namespace {
36FloatRect getMaxDisplayBounds(
37 const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
38 const ui::Size maxSize = [&displays] {
39 if (displays.empty()) return ui::Size{5000, 5000};
40
41 return std::accumulate(displays.begin(), displays.end(), ui::kEmptySize,
42 [](ui::Size size, const auto& pair) -> ui::Size {
43 const auto& display = pair.second;
44 return {std::max(size.getWidth(), display.info.logicalWidth),
45 std::max(size.getHeight(), display.info.logicalHeight)};
46 });
47 }();
48
49 // Ignore display bounds for now since they will be computed later. Use a large Rect bound
50 // to ensure it's bigger than an actual display will be.
51 const float xMax = static_cast<float>(maxSize.getWidth()) * 10.f;
52 const float yMax = static_cast<float>(maxSize.getHeight()) * 10.f;
53
54 return {-xMax, -yMax, xMax, yMax};
55}
56
57// Applies the given transform to the region, while protecting against overflows caused by any
58// offsets. If applying the offset in the transform to any of the Rects in the region would result
59// in an overflow, they are not added to the output Region.
60Region transformTouchableRegionSafely(const ui::Transform& t, const Region& r,
61 const std::string& debugWindowName) {
62 // Round the translation using the same rounding strategy used by ui::Transform.
63 const auto tx = static_cast<int32_t>(t.tx() + 0.5);
64 const auto ty = static_cast<int32_t>(t.ty() + 0.5);
65
66 ui::Transform transformWithoutOffset = t;
67 transformWithoutOffset.set(0.f, 0.f);
68
69 const Region transformed = transformWithoutOffset.transform(r);
70
71 // Apply the translation to each of the Rects in the region while discarding any that overflow.
72 Region ret;
73 for (const auto& rect : transformed) {
74 Rect newRect;
75 if (__builtin_add_overflow(rect.left, tx, &newRect.left) ||
76 __builtin_add_overflow(rect.top, ty, &newRect.top) ||
77 __builtin_add_overflow(rect.right, tx, &newRect.right) ||
78 __builtin_add_overflow(rect.bottom, ty, &newRect.bottom)) {
79 ALOGE("Applying transform to touchable region of window '%s' resulted in an overflow.",
80 debugWindowName.c_str());
81 continue;
82 }
83 ret.orSelf(newRect);
84 }
85 return ret;
86}
87
88/*
89 * We don't want to send the layer's transform to input, but rather the
90 * parent's transform. This is because Layer's transform is
91 * information about how the buffer is placed on screen. The parent's
92 * transform makes more sense to send since it's information about how the
93 * layer is placed on screen. This transform is used by input to determine
94 * how to go from screen space back to window space.
95 */
96ui::Transform getInputTransform(const LayerSnapshot& snapshot) {
97 if (!snapshot.hasBufferOrSidebandStream()) {
98 return snapshot.geomLayerTransform;
99 }
100 return snapshot.parentTransform;
101}
102
103/**
104 * Similar to getInputTransform, we need to update the bounds to include the transform.
105 * This is because bounds don't include the buffer transform, where the input assumes
106 * that's already included.
107 */
108Rect getInputBounds(const LayerSnapshot& snapshot) {
109 if (!snapshot.hasBufferOrSidebandStream()) {
110 return snapshot.croppedBufferSize;
111 }
112
113 if (snapshot.localTransform.getType() == ui::Transform::IDENTITY ||
114 !snapshot.croppedBufferSize.isValid()) {
115 return snapshot.croppedBufferSize;
116 }
117 return snapshot.localTransform.transform(snapshot.croppedBufferSize);
118}
119
120void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& screenToDisplay,
121 const LayerSnapshot& snapshot) {
122 Rect tmpBounds = getInputBounds(snapshot);
123 if (!tmpBounds.isValid()) {
124 info.touchableRegion.clear();
125 // A layer could have invalid input bounds and still expect to receive touch input if it has
126 // replaceTouchableRegionWithCrop. For that case, the input transform needs to be calculated
127 // correctly to determine the coordinate space for input events. Use an empty rect so that
128 // the layer will receive input in its own layer space.
129 tmpBounds = Rect::EMPTY_RECT;
130 }
131
132 // InputDispatcher works in the display device's coordinate space. Here, we calculate the
133 // frame and transform used for the layer, which determines the bounds and the coordinate space
134 // within which the layer will receive input.
135 //
136 // The coordinate space within which each of the bounds are specified is explicitly documented
137 // in the variable name. For example "inputBoundsInLayer" is specified in layer space. A
138 // Transform converts one coordinate space to another, which is apparent in its naming. For
139 // example, "layerToDisplay" transforms layer space to display space.
140 //
141 // Coordinate space definitions:
142 // - display: The display device's coordinate space. Correlates to pixels on the display.
143 // - screen: The post-rotation coordinate space for the display, a.k.a. logical display space.
144 // - layer: The coordinate space of this layer.
145 // - input: The coordinate space in which this layer will receive input events. This could be
146 // different than layer space if a surfaceInset is used, which changes the origin
147 // of the input space.
148 const FloatRect inputBoundsInLayer = tmpBounds.toFloatRect();
149
150 // Clamp surface inset to the input bounds.
151 const auto surfaceInset = static_cast<float>(info.surfaceInset);
152 const float xSurfaceInset =
153 std::max(0.f, std::min(surfaceInset, inputBoundsInLayer.getWidth() / 2.f));
154 const float ySurfaceInset =
155 std::max(0.f, std::min(surfaceInset, inputBoundsInLayer.getHeight() / 2.f));
156
157 // Apply the insets to the input bounds.
158 const FloatRect insetBoundsInLayer(inputBoundsInLayer.left + xSurfaceInset,
159 inputBoundsInLayer.top + ySurfaceInset,
160 inputBoundsInLayer.right - xSurfaceInset,
161 inputBoundsInLayer.bottom - ySurfaceInset);
162
163 // Crop the input bounds to ensure it is within the parent's bounds.
164 const FloatRect croppedInsetBoundsInLayer =
165 snapshot.geomLayerBounds.intersect(insetBoundsInLayer);
166
167 const ui::Transform layerToScreen = getInputTransform(snapshot);
168 const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
169
170 const Rect roundedFrameInDisplay{layerToDisplay.transform(croppedInsetBoundsInLayer)};
171 info.frameLeft = roundedFrameInDisplay.left;
172 info.frameTop = roundedFrameInDisplay.top;
173 info.frameRight = roundedFrameInDisplay.right;
174 info.frameBottom = roundedFrameInDisplay.bottom;
175
176 ui::Transform inputToLayer;
177 inputToLayer.set(insetBoundsInLayer.left, insetBoundsInLayer.top);
178 const ui::Transform inputToDisplay = layerToDisplay * inputToLayer;
179
180 // InputDispatcher expects a display-to-input transform.
181 info.transform = inputToDisplay.inverse();
182
183 // The touchable region is specified in the input coordinate space. Change it to display space.
184 info.touchableRegion =
185 transformTouchableRegionSafely(inputToDisplay, info.touchableRegion, snapshot.name);
186}
187
188void handleDropInputMode(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot) {
189 if (snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
190 return;
191 }
192
193 // Check if we need to drop input unconditionally
194 const gui::DropInputMode dropInputMode = snapshot.dropInputMode;
195 if (dropInputMode == gui::DropInputMode::ALL) {
196 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
197 ALOGV("Dropping input for %s as requested by policy.", snapshot.name.c_str());
198 return;
199 }
200
201 // Check if we need to check if the window is obscured by parent
202 if (dropInputMode != gui::DropInputMode::OBSCURED) {
203 return;
204 }
205
206 // Check if the parent has set an alpha on the layer
207 if (parentSnapshot.color.a != 1.0_hf) {
208 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
209 ALOGV("Dropping input for %s as requested by policy because alpha=%f",
210 snapshot.name.c_str(), static_cast<float>(parentSnapshot.color.a));
211 }
212
213 // Check if the parent has cropped the buffer
214 Rect bufferSize = snapshot.croppedBufferSize;
215 if (!bufferSize.isValid()) {
216 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
217 return;
218 }
219
220 // Screenbounds are the layer bounds cropped by parents, transformed to screenspace.
221 // To check if the layer has been cropped, we take the buffer bounds, apply the local
222 // layer crop and apply the same set of transforms to move to screenspace. If the bounds
223 // match then the layer has not been cropped by its parents.
224 Rect bufferInScreenSpace(snapshot.geomLayerTransform.transform(bufferSize));
225 bool croppedByParent = bufferInScreenSpace != Rect{snapshot.transformedBounds};
226
227 if (croppedByParent) {
228 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
229 ALOGV("Dropping input for %s as requested by policy because buffer is cropped by parent",
230 snapshot.name.c_str());
231 } else {
232 // If the layer is not obscured by its parents (by setting an alpha or crop), then only drop
233 // input if the window is obscured. This check should be done in surfaceflinger but the
234 // logic currently resides in inputflinger. So pass the if_obscured check to input to only
235 // drop input events if the window is obscured.
236 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
237 }
238}
239
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000240auto getBlendMode(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
241 auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
242 if (snapshot.alpha != 1.0f || !snapshot.isContentOpaque()) {
243 blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED
244 : Hwc2::IComposerClient::BlendMode::COVERAGE;
245 }
246 return blendMode;
247}
248
Vishnu Naircfb2d252023-01-19 04:44:02 +0000249void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFrame,
250 bool forceFullDamage, Region& outSurfaceDamageRegion) {
251 if (!hasReadyFrame) {
252 outSurfaceDamageRegion.clear();
253 return;
254 }
255 if (forceFullDamage) {
256 outSurfaceDamageRegion = Region::INVALID_REGION;
257 } else {
258 outSurfaceDamageRegion = requested.surfaceDamageRegion;
259 }
260}
261
Vishnu Nair80a5a702023-02-11 01:21:51 +0000262void updateVisibility(LayerSnapshot& snapshot, bool visible) {
263 snapshot.isVisible = visible;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000264
265 // TODO(b/238781169) we are ignoring this compat for now, since we will have
266 // to remove any optimization based on visibility.
267
268 // For compatibility reasons we let layers which can receive input
269 // receive input before they have actually submitted a buffer. Because
270 // of this we use canReceiveInput instead of isVisible to check the
271 // policy-visibility, ignoring the buffer state. However for layers with
272 // hasInputInfo()==false we can use the real visibility state.
273 // We are just using these layers for occlusion detection in
274 // InputDispatcher, and obviously if they aren't visible they can't occlude
275 // anything.
Vishnu Nair80a5a702023-02-11 01:21:51 +0000276 const bool visibleForInput =
Vishnu Nair40d02282023-02-28 21:11:40 +0000277 snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000278 snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000279}
280
281bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
282 if (requested.potentialCursor) {
283 return false;
284 }
285
286 if (snapshot.inputInfo.token != nullptr) {
287 return true;
288 }
289
290 if (snapshot.hasBufferOrSidebandStream()) {
291 return true;
292 }
293
294 return requested.windowInfoHandle &&
295 requested.windowInfoHandle->getInfo()->inputConfig.test(
296 gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
297}
298
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000299void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested,
300 const LayerSnapshotBuilder::Args& args) {
301 snapshot.metadata.clear();
302 for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) {
303 auto compatIter = args.genericLayerMetadataKeyMap.find(key);
304 if (compatIter == std::end(args.genericLayerMetadataKeyMap)) {
305 continue;
306 }
307 const uint32_t id = compatIter->second;
308 auto it = requested.metadata.mMap.find(id);
309 if (it == std::end(requested.metadata.mMap)) {
310 continue;
311 }
312
313 snapshot.metadata.emplace(key,
314 compositionengine::GenericLayerMetadataEntry{mandatory,
315 it->second});
316 }
317}
318
Vishnu Naircfb2d252023-01-19 04:44:02 +0000319void clearChanges(LayerSnapshot& snapshot) {
320 snapshot.changes.clear();
321 snapshot.contentDirty = false;
322 snapshot.hasReadyFrame = false;
323 snapshot.sidebandStreamHasFrame = false;
324 snapshot.surfaceDamage.clear();
325}
326
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000327} // namespace
328
329LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
330 LayerSnapshot snapshot;
Vishnu Nair92990e22023-02-24 20:01:05 +0000331 snapshot.path = LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000332 snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
333 snapshot.isHiddenByPolicyFromParent = false;
334 snapshot.isHiddenByPolicyFromRelativeParent = false;
335 snapshot.parentTransform.reset();
336 snapshot.geomLayerTransform.reset();
337 snapshot.geomInverseLayerTransform.reset();
338 snapshot.geomLayerBounds = getMaxDisplayBounds({});
339 snapshot.roundedCorner = RoundedCornerState();
340 snapshot.stretchEffect = {};
341 snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK;
342 snapshot.outputFilter.toInternalDisplay = false;
343 snapshot.isSecure = false;
344 snapshot.color.a = 1.0_hf;
345 snapshot.colorTransformIsIdentity = true;
346 snapshot.shadowRadius = 0.f;
347 snapshot.layerMetadata.mMap.clear();
348 snapshot.relativeLayerMetadata.mMap.clear();
349 snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED;
350 snapshot.dropInputMode = gui::DropInputMode::NONE;
351 snapshot.isTrustedOverlay = false;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000352 snapshot.gameMode = gui::GameMode::Unsupported;
353 snapshot.frameRate = {};
354 snapshot.fixedTransformHint = ui::Transform::ROT_INVALID;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000355 return snapshot;
356}
357
358LayerSnapshotBuilder::LayerSnapshotBuilder() : mRootSnapshot(getRootSnapshot()) {}
359
360LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000361 args.forceUpdate = ForceUpdateFlags::ALL;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000362 updateSnapshots(args);
363}
364
365bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000366 if (args.forceUpdate != ForceUpdateFlags::NONE || args.displayChanges) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000367 // force update requested, or we have display changes, so skip the fast path
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000368 return false;
369 }
370
371 if (args.layerLifecycleManager.getGlobalChanges().get() == 0) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000372 return true;
373 }
374
375 if (args.layerLifecycleManager.getGlobalChanges() != RequestedLayerState::Changes::Content) {
376 // We have changes that require us to walk the hierarchy and update child layers.
377 // No fast path for you.
378 return false;
379 }
380
381 // There are only content changes which do not require any child layer snapshots to be updated.
382 ALOGV("%s", __func__);
383 ATRACE_NAME("FastPath");
384
385 // Collect layers with changes
386 ftl::SmallMap<uint32_t, RequestedLayerState*, 10> layersWithChanges;
387 for (auto& layer : args.layerLifecycleManager.getLayers()) {
388 if (layer->changes.test(RequestedLayerState::Changes::Content)) {
389 layersWithChanges.emplace_or_replace(layer->id, layer.get());
390 }
391 }
392
393 // Walk through the snapshots, clearing previous change flags and updating the snapshots
394 // if needed.
395 for (auto& snapshot : mSnapshots) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000396 auto it = layersWithChanges.find(snapshot->path.id);
397 if (it != layersWithChanges.end()) {
398 ALOGV("%s fast path snapshot changes = %s", __func__,
399 mRootSnapshot.changes.string().c_str());
400 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
Vishnu Nair92990e22023-02-24 20:01:05 +0000401 updateSnapshot(*snapshot, args, *it->second, mRootSnapshot, root);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000402 }
403 }
404 return true;
405}
406
407void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
408 ATRACE_NAME("UpdateSnapshots");
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000409 if (args.parentCrop) {
410 mRootSnapshot.geomLayerBounds = *args.parentCrop;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000411 } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000412 mRootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
413 }
414 if (args.displayChanges) {
415 mRootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
416 RequestedLayerState::Changes::Geometry;
417 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000418 if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
419 mRootSnapshot.changes |=
420 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
421 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000422 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
Vishnu Naird47bcee2023-02-24 18:08:51 +0000423 if (args.root.getLayer()) {
424 // The hierarchy can have a root layer when used for screenshots otherwise, it will have
425 // multiple children.
426 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, args.root.getLayer()->id,
427 LayerHierarchy::Variant::Attached);
428 updateSnapshotsInHierarchy(args, args.root, root, mRootSnapshot);
429 } else {
430 for (auto& [childHierarchy, variant] : args.root.mChildren) {
431 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
432 childHierarchy->getLayer()->id,
433 variant);
434 updateSnapshotsInHierarchy(args, *childHierarchy, root, mRootSnapshot);
435 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000436 }
437
Vishnu Nairfccd6362023-02-24 23:39:53 +0000438 const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000439 clearChanges(mRootSnapshot);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000440
441 // Destroy unreachable snapshots
Vishnu Nairfccd6362023-02-24 23:39:53 +0000442 if (!hasUnreachableSnapshots) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000443 return;
444 }
445
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000446 auto it = mSnapshots.begin();
447 while (it < mSnapshots.end()) {
448 auto& traversalPath = it->get()->path;
Vishnu Nairfccd6362023-02-24 23:39:53 +0000449 if (!it->get()->unreachable) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000450 it++;
451 continue;
452 }
453
454 mIdToSnapshot.erase(traversalPath);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000455 mSnapshots.back()->globalZ = it->get()->globalZ;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000456 std::iter_swap(it, mSnapshots.end() - 1);
457 mSnapshots.erase(mSnapshots.end() - 1);
458 }
459}
460
461void LayerSnapshotBuilder::update(const Args& args) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000462 for (auto& snapshot : mSnapshots) {
463 clearChanges(*snapshot);
464 }
465
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000466 if (tryFastUpdate(args)) {
467 return;
468 }
469 updateSnapshots(args);
470}
471
Vishnu Naircfb2d252023-01-19 04:44:02 +0000472const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy(
473 const Args& args, const LayerHierarchy& hierarchy,
474 LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000475 const RequestedLayerState* layer = hierarchy.getLayer();
Vishnu Naircfb2d252023-01-19 04:44:02 +0000476 LayerSnapshot* snapshot = getSnapshot(traversalPath);
477 const bool newSnapshot = snapshot == nullptr;
478 if (newSnapshot) {
Vishnu Nair92990e22023-02-24 20:01:05 +0000479 snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000480 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000481 scheduler::LayerInfo::FrameRate oldFrameRate = snapshot->frameRate;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000482 if (traversalPath.isRelative()) {
483 bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
484 updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
485 } else {
486 if (traversalPath.isAttached()) {
487 resetRelativeState(*snapshot);
488 }
Vishnu Nair92990e22023-02-24 20:01:05 +0000489 updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000490 }
491
492 for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
493 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(traversalPath,
494 childHierarchy->getLayer()->id,
495 variant);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000496 const LayerSnapshot& childSnapshot =
497 updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot);
498 updateChildState(*snapshot, childSnapshot, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000499 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000500
501 if (oldFrameRate == snapshot->frameRate) {
502 snapshot->changes.clear(RequestedLayerState::Changes::FrameRate);
503 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000504 return *snapshot;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000505}
506
507LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const {
508 if (layerId == UNASSIGNED_LAYER_ID) {
509 return nullptr;
510 }
511 LayerHierarchy::TraversalPath path{.id = layerId};
512 return getSnapshot(path);
513}
514
515LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
516 auto it = mIdToSnapshot.find(id);
517 return it == mIdToSnapshot.end() ? nullptr : it->second;
518}
519
Vishnu Nair92990e22023-02-24 20:01:05 +0000520LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
521 const RequestedLayerState& layer,
522 const LayerSnapshot& parentSnapshot) {
523 mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
Vishnu Naircfb2d252023-01-19 04:44:02 +0000524 LayerSnapshot* snapshot = mSnapshots.back().get();
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000525 snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
Vishnu Nair92990e22023-02-24 20:01:05 +0000526 if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) {
527 snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
528 }
529 mIdToSnapshot[path] = snapshot;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000530 return snapshot;
531}
532
Vishnu Nairfccd6362023-02-24 23:39:53 +0000533bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
Vishnu Naird47bcee2023-02-24 18:08:51 +0000534 if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000535 !args.layerLifecycleManager.getGlobalChanges().any(
536 RequestedLayerState::Changes::Hierarchy |
537 RequestedLayerState::Changes::Visibility)) {
538 // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
539 // the snapshots.
Vishnu Nairfccd6362023-02-24 23:39:53 +0000540 return false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000541 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000542 mResortSnapshots = false;
543
Vishnu Nairfccd6362023-02-24 23:39:53 +0000544 for (auto& snapshot : mSnapshots) {
545 snapshot->unreachable = true;
546 }
547
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000548 size_t globalZ = 0;
549 args.root.traverseInZOrder(
550 [this, &globalZ](const LayerHierarchy&,
551 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
552 LayerSnapshot* snapshot = getSnapshot(traversalPath);
553 if (!snapshot) {
554 return false;
555 }
556
Vishnu Nairfccd6362023-02-24 23:39:53 +0000557 snapshot->unreachable = false;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000558 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
Vishnu Nair80a5a702023-02-11 01:21:51 +0000559 updateVisibility(*snapshot, snapshot->getIsVisible());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000560 size_t oldZ = snapshot->globalZ;
561 size_t newZ = globalZ++;
562 snapshot->globalZ = newZ;
563 if (oldZ == newZ) {
564 return true;
565 }
566 mSnapshots[newZ]->globalZ = oldZ;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000567 LLOGV(snapshot->sequence, "Made visible z=%zu -> %zu %s", oldZ, newZ,
568 snapshot->getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000569 std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ),
570 mSnapshots.begin() + static_cast<ssize_t>(newZ));
571 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000572 return true;
573 });
Vishnu Naircfb2d252023-01-19 04:44:02 +0000574 mNumInterestingSnapshots = (int)globalZ;
Vishnu Nairfccd6362023-02-24 23:39:53 +0000575 bool hasUnreachableSnapshots = false;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000576 while (globalZ < mSnapshots.size()) {
577 mSnapshots[globalZ]->globalZ = globalZ;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000578 /* mark unreachable snapshots as explicitly invisible */
579 updateVisibility(*mSnapshots[globalZ], false);
Vishnu Nairfccd6362023-02-24 23:39:53 +0000580 if (mSnapshots[globalZ]->unreachable) {
581 hasUnreachableSnapshots = true;
582 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000583 globalZ++;
584 }
Vishnu Nairfccd6362023-02-24 23:39:53 +0000585 return hasUnreachableSnapshots;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000586}
587
588void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
589 const LayerSnapshot& parentSnapshot,
590 bool parentIsRelative, const Args& args) {
591 if (parentIsRelative) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000592 snapshot.isHiddenByPolicyFromRelativeParent =
593 parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000594 if (args.includeMetadata) {
595 snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata;
596 }
597 } else {
598 snapshot.isHiddenByPolicyFromRelativeParent =
599 parentSnapshot.isHiddenByPolicyFromRelativeParent;
600 if (args.includeMetadata) {
601 snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
602 }
603 }
604 snapshot.isVisible = snapshot.getIsVisible();
605}
606
Vishnu Naircfb2d252023-01-19 04:44:02 +0000607void LayerSnapshotBuilder::updateChildState(LayerSnapshot& snapshot,
608 const LayerSnapshot& childSnapshot, const Args& args) {
609 if (snapshot.childState.hasValidFrameRate) {
610 return;
611 }
Vishnu Naird47bcee2023-02-24 18:08:51 +0000612 if (args.forceUpdate == ForceUpdateFlags::ALL ||
613 childSnapshot.changes.test(RequestedLayerState::Changes::FrameRate)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000614 // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes
615 // for the same reason we are allowing touch boost for those layers. See
616 // RefreshRateSelector::rankFrameRates for details.
617 using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility;
618 const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.rate.isValid() &&
619 childSnapshot.frameRate.type == FrameRateCompatibility::Default;
620 const auto layerVotedWithNoVote =
621 childSnapshot.frameRate.type == FrameRateCompatibility::NoVote;
622 const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.rate.isValid() &&
623 childSnapshot.frameRate.type == FrameRateCompatibility::Exact;
624
625 snapshot.childState.hasValidFrameRate |= layerVotedWithDefaultCompatibility ||
626 layerVotedWithNoVote || layerVotedWithExactCompatibility;
627
628 // If we don't have a valid frame rate, but the children do, we set this
629 // layer as NoVote to allow the children to control the refresh rate
630 if (!snapshot.frameRate.rate.isValid() &&
631 snapshot.frameRate.type != FrameRateCompatibility::NoVote &&
632 snapshot.childState.hasValidFrameRate) {
633 snapshot.frameRate =
634 scheduler::LayerInfo::FrameRate(Fps(), FrameRateCompatibility::NoVote);
635 snapshot.changes |= childSnapshot.changes & RequestedLayerState::Changes::FrameRate;
636 }
637 }
638}
639
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000640void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) {
641 snapshot.isHiddenByPolicyFromRelativeParent = false;
642 snapshot.relativeLayerMetadata.mMap.clear();
643}
644
645uint32_t getDisplayRotationFlags(
646 const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays,
647 const ui::LayerStack& layerStack) {
648 static frontend::DisplayInfo sDefaultDisplayInfo = {.isPrimary = false};
649 auto display = displays.get(layerStack).value_or(sDefaultDisplayInfo).get();
650 return display.isPrimary ? display.rotationFlags : 0;
651}
652
653void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
654 const RequestedLayerState& requested,
655 const LayerSnapshot& parentSnapshot,
Vishnu Nair92990e22023-02-24 20:01:05 +0000656 const LayerHierarchy::TraversalPath& path) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000657 // Always update flags and visibility
658 ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
659 (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
660 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
Vishnu Naird47bcee2023-02-24 18:08:51 +0000661 RequestedLayerState::Changes::AffectsChildren |
662 RequestedLayerState::Changes::FrameRate);
Vishnu Nair92990e22023-02-24 20:01:05 +0000663 snapshot.changes |= parentChanges | requested.changes;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000664 snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
Vishnu Nair3af0ec02023-02-10 04:13:48 +0000665 parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
666 (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000667 snapshot.contentDirty = requested.what & layer_state_t::CONTENT_DIRTY;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000668 // TODO(b/238781169) scope down the changes to only buffer updates.
Vishnu Naird47bcee2023-02-24 18:08:51 +0000669 snapshot.hasReadyFrame = requested.hasReadyFrame();
670 snapshot.sidebandStreamHasFrame = requested.hasSidebandStreamFrame();
Vishnu Naircfb2d252023-01-19 04:44:02 +0000671 updateSurfaceDamage(requested, snapshot.hasReadyFrame, args.forceFullDamage,
672 snapshot.surfaceDamage);
Vishnu Nair92990e22023-02-24 20:01:05 +0000673 snapshot.outputFilter.layerStack = parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
674 ? requested.layerStack
675 : parentSnapshot.outputFilter.layerStack;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000676
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000677 uint32_t displayRotationFlags =
678 getDisplayRotationFlags(args.displays, snapshot.outputFilter.layerStack);
Vishnu Nair92990e22023-02-24 20:01:05 +0000679 const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
680 snapshot.changes.any(RequestedLayerState::Changes::Visibility |
681 RequestedLayerState::Changes::Created);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000682
Vishnu Naircfb2d252023-01-19 04:44:02 +0000683 // always update the buffer regardless of visibility
Vishnu Nair80a5a702023-02-11 01:21:51 +0000684 if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES || args.displayChanges) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000685 snapshot.acquireFence =
686 (requested.externalTexture &&
687 requested.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged))
688 ? requested.bufferData->acquireFence
689 : Fence::NO_FENCE;
690 snapshot.buffer =
691 requested.externalTexture ? requested.externalTexture->getBuffer() : nullptr;
692 snapshot.bufferSize = requested.getBufferSize(displayRotationFlags);
693 snapshot.geomBufferSize = snapshot.bufferSize;
694 snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
695 snapshot.dataspace = requested.dataspace;
696 snapshot.externalTexture = requested.externalTexture;
697 snapshot.frameNumber = (requested.bufferData) ? requested.bufferData->frameNumber : 0;
698 snapshot.geomBufferTransform = requested.bufferTransform;
699 snapshot.geomBufferUsesDisplayInverseTransform = requested.transformToDisplayInverse;
700 snapshot.geomContentCrop = requested.getBufferCrop();
701 snapshot.geomUsesSourceCrop = snapshot.hasBufferOrSidebandStream();
702 snapshot.hasProtectedContent = requested.externalTexture &&
703 requested.externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED;
704 snapshot.isHdrY410 = requested.dataspace == ui::Dataspace::BT2020_ITU_PQ &&
705 requested.api == NATIVE_WINDOW_API_MEDIA &&
706 requested.bufferData->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102;
707 snapshot.sidebandStream = requested.sidebandStream;
708 snapshot.transparentRegionHint = requested.transparentRegion;
709 snapshot.color.rgb = requested.getColor().rgb;
John Reck68796592023-01-25 13:47:12 -0500710 snapshot.currentSdrHdrRatio = requested.currentSdrHdrRatio;
711 snapshot.desiredSdrHdrRatio = requested.desiredSdrHdrRatio;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000712 }
713
Vishnu Nair92990e22023-02-24 20:01:05 +0000714 if (snapshot.isHiddenByPolicyFromParent &&
715 !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000716 if (forceUpdate ||
717 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
718 RequestedLayerState::Changes::Geometry |
719 RequestedLayerState::Changes::Input)) {
720 updateInput(snapshot, requested, parentSnapshot, path, args);
721 }
722 return;
723 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000724
725 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) {
726 // If root layer, use the layer stack otherwise get the parent's layer stack.
727 snapshot.color.a = parentSnapshot.color.a * requested.color.a;
728 snapshot.alpha = snapshot.color.a;
729 snapshot.isSecure =
730 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
731 snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000732 snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
733 (requested.flags & layer_state_t::eLayerSkipScreenshot);
734 snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
735 ? requested.stretchEffect
736 : parentSnapshot.stretchEffect;
737 if (!parentSnapshot.colorTransformIsIdentity) {
738 snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
739 snapshot.colorTransformIsIdentity = false;
740 } else {
741 snapshot.colorTransform = requested.colorTransform;
742 snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
743 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000744 snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
745 ? requested.gameMode
746 : parentSnapshot.gameMode;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000747 snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
748 ? requested.fixedTransformHint
749 : parentSnapshot.fixedTransformHint;
Vishnu Naira9c43762023-01-27 19:10:25 +0000750 // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
751 // marked as skip capture
752 snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
753 (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000754 }
755
Vishnu Naird47bcee2023-02-24 18:08:51 +0000756 if (forceUpdate ||
757 snapshot.changes.any(RequestedLayerState::Changes::FrameRate |
758 RequestedLayerState::Changes::Hierarchy)) {
759 snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() ||
760 (requested.requestedFrameRate.type ==
761 scheduler::LayerInfo::FrameRateCompatibility::NoVote))
762 ? requested.requestedFrameRate
763 : parentSnapshot.frameRate;
764 }
765
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000766 if (forceUpdate || requested.what & layer_state_t::eMetadataChanged) {
767 updateMetadata(snapshot, requested, args);
768 }
769
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000770 if (forceUpdate || requested.changes.get() != 0) {
771 snapshot.compositionType = requested.getCompositionType();
772 snapshot.dimmingEnabled = requested.dimmingEnabled;
773 snapshot.layerOpaqueFlagSet =
774 (requested.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque;
Alec Mourif4af03e2023-02-11 00:25:24 +0000775 snapshot.cachingHint = requested.cachingHint;
Vishnu Nairef68d6d2023-02-28 06:18:27 +0000776 snapshot.frameRateSelectionPriority = requested.frameRateSelectionPriority;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000777 }
778
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000779 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content)) {
780 snapshot.color.rgb = requested.getColor().rgb;
781 snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000782 snapshot.backgroundBlurRadius = args.supportsBlur
783 ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
784 : 0;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000785 snapshot.blurRegions = requested.blurRegions;
Vishnu Nair80a5a702023-02-11 01:21:51 +0000786 for (auto& region : snapshot.blurRegions) {
787 region.alpha = region.alpha * snapshot.color.a;
788 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000789 snapshot.hdrMetadata = requested.hdrMetadata;
790 }
791
792 if (forceUpdate ||
793 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
794 RequestedLayerState::Changes::Geometry)) {
795 updateLayerBounds(snapshot, requested, parentSnapshot, displayRotationFlags);
796 updateRoundedCorner(snapshot, requested, parentSnapshot);
797 }
798
799 if (forceUpdate ||
800 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
801 RequestedLayerState::Changes::Geometry |
802 RequestedLayerState::Changes::Input)) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000803 updateInput(snapshot, requested, parentSnapshot, path, args);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000804 }
805
806 // computed snapshot properties
807 updateShadows(snapshot, requested, args.globalShadowSettings);
808 if (args.includeMetadata) {
809 snapshot.layerMetadata = parentSnapshot.layerMetadata;
810 snapshot.layerMetadata.merge(requested.metadata);
811 }
812 snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 ||
813 requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect();
Vishnu Nairc765c6c2023-02-23 00:08:01 +0000814 snapshot.contentOpaque = snapshot.isContentOpaque();
815 snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() &&
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000816 snapshot.color.a == 1.f;
817 snapshot.blendMode = getBlendMode(snapshot, requested);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000818 LLOGV(snapshot.sequence,
Vishnu Nair92990e22023-02-24 20:01:05 +0000819 "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
820 args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
821 snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
822 parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
823 std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000824}
825
826void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
827 const RequestedLayerState& requested,
828 const LayerSnapshot& parentSnapshot) {
829 snapshot.roundedCorner = RoundedCornerState();
830 RoundedCornerState parentRoundedCorner;
831 if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
832 parentRoundedCorner = parentSnapshot.roundedCorner;
833 ui::Transform t = snapshot.localTransform.inverse();
834 parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
835 parentRoundedCorner.radius.x *= t.getScaleX();
836 parentRoundedCorner.radius.y *= t.getScaleY();
837 }
838
839 FloatRect layerCropRect = snapshot.croppedBufferSize.toFloatRect();
840 const vec2 radius(requested.cornerRadius, requested.cornerRadius);
841 RoundedCornerState layerSettings(layerCropRect, radius);
842 const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
843 const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
844 if (layerSettingsValid && parentRoundedCornerValid) {
845 // If the parent and the layer have rounded corner settings, use the parent settings if
846 // the parent crop is entirely inside the layer crop. This has limitations and cause
847 // rendering artifacts. See b/200300845 for correct fix.
848 if (parentRoundedCorner.cropRect.left > layerCropRect.left &&
849 parentRoundedCorner.cropRect.top > layerCropRect.top &&
850 parentRoundedCorner.cropRect.right < layerCropRect.right &&
851 parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) {
852 snapshot.roundedCorner = parentRoundedCorner;
853 } else {
854 snapshot.roundedCorner = layerSettings;
855 }
856 } else if (layerSettingsValid) {
857 snapshot.roundedCorner = layerSettings;
858 } else if (parentRoundedCornerValid) {
859 snapshot.roundedCorner = parentRoundedCorner;
860 }
861}
862
863void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot,
864 const RequestedLayerState& requested,
865 const LayerSnapshot& parentSnapshot,
866 uint32_t displayRotationFlags) {
867 snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
868 snapshot.geomCrop = requested.crop;
869 snapshot.localTransform = requested.getTransform(displayRotationFlags);
870 snapshot.localTransformInverse = snapshot.localTransform.inverse();
871 snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000872 const bool transformWasInvalid = snapshot.invalidTransform;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000873 snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
874 if (snapshot.invalidTransform) {
Vishnu Naircfb2d252023-01-19 04:44:02 +0000875 auto& t = snapshot.geomLayerTransform;
876 auto& requestedT = requested.requestedTransform;
877 std::string transformDebug =
878 base::StringPrintf(" transform={%f,%f,%f,%f} requestedTransform={%f,%f,%f,%f}",
879 t.dsdx(), t.dsdy(), t.dtdx(), t.dtdy(), requestedT.dsdx(),
880 requestedT.dsdy(), requestedT.dtdx(), requestedT.dtdy());
881 std::string bufferDebug;
882 if (requested.externalTexture) {
883 auto unRotBuffer = requested.getUnrotatedBufferSize(displayRotationFlags);
884 auto& destFrame = requested.destinationFrame;
885 bufferDebug = base::StringPrintf(" buffer={%d,%d} displayRot=%d"
886 " destFrame={%d,%d,%d,%d} unRotBuffer={%d,%d}",
887 requested.externalTexture->getWidth(),
888 requested.externalTexture->getHeight(),
889 displayRotationFlags, destFrame.left, destFrame.top,
890 destFrame.right, destFrame.bottom,
891 unRotBuffer.getHeight(), unRotBuffer.getWidth());
892 }
893 ALOGW("Resetting transform for %s because it is invalid.%s%s",
894 snapshot.getDebugString().c_str(), transformDebug.c_str(), bufferDebug.c_str());
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000895 snapshot.geomLayerTransform.reset();
896 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000897 if (transformWasInvalid != snapshot.invalidTransform) {
898 // If transform is invalid, the layer will be hidden.
899 mResortSnapshots = true;
900 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000901 snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse();
902
903 FloatRect parentBounds = parentSnapshot.geomLayerBounds;
904 parentBounds = snapshot.localTransform.inverse().transform(parentBounds);
905 snapshot.geomLayerBounds =
906 (requested.externalTexture) ? snapshot.bufferSize.toFloatRect() : parentBounds;
907 if (!requested.crop.isEmpty()) {
908 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(requested.crop.toFloatRect());
909 }
910 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(parentBounds);
911 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000912 const Rect geomLayerBoundsWithoutTransparentRegion =
913 RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
914 requested.transparentRegion);
915 snapshot.transformedBoundsWithoutTransparentRegion =
916 snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion);
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000917 snapshot.parentTransform = parentSnapshot.geomLayerTransform;
918
919 // Subtract the transparent region and snap to the bounds
Vishnu Naircfb2d252023-01-19 04:44:02 +0000920 const Rect bounds =
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000921 RequestedLayerState::reduce(snapshot.croppedBufferSize, requested.transparentRegion);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000922 if (requested.potentialCursor) {
923 snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds);
924 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000925}
926
927void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot,
928 const RequestedLayerState& requested,
929 const renderengine::ShadowSettings& globalShadowSettings) {
930 snapshot.shadowRadius = requested.shadowRadius;
931 snapshot.shadowSettings.length = requested.shadowRadius;
932 if (snapshot.shadowRadius > 0.f) {
933 snapshot.shadowSettings = globalShadowSettings;
934
935 // Note: this preserves existing behavior of shadowing the entire layer and not cropping
936 // it if transparent regions are present. This may not be necessary since shadows are
937 // typically cast by layers without transparent regions.
938 snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds;
939
940 // If the casting layer is translucent, we need to fill in the shadow underneath the
941 // layer. Otherwise the generated shadow will only be shown around the casting layer.
942 snapshot.shadowSettings.casterIsTranslucent =
943 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f);
944 snapshot.shadowSettings.ambientColor *= snapshot.alpha;
945 snapshot.shadowSettings.spotColor *= snapshot.alpha;
946 }
947}
948
949void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
950 const RequestedLayerState& requested,
951 const LayerSnapshot& parentSnapshot,
Vishnu Naircfb2d252023-01-19 04:44:02 +0000952 const LayerHierarchy::TraversalPath& path,
953 const Args& args) {
954 if (requested.windowInfoHandle) {
955 snapshot.inputInfo = *requested.windowInfoHandle->getInfo();
956 } else {
957 snapshot.inputInfo = {};
Vishnu Nair40d02282023-02-28 21:11:40 +0000958 // b/271132344 revisit this and see if we can always use the layers uid/pid
959 snapshot.inputInfo.name = requested.name;
960 snapshot.inputInfo.ownerUid = static_cast<int32_t>(requested.ownerUid);
961 snapshot.inputInfo.ownerPid = requested.ownerPid;
Vishnu Naircfb2d252023-01-19 04:44:02 +0000962 }
Vishnu Naircfb2d252023-01-19 04:44:02 +0000963
Vishnu Nair93b8b792023-02-27 19:40:24 +0000964 snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
Vishnu Naird47bcee2023-02-24 18:08:51 +0000965 snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id);
Vishnu Naircfb2d252023-01-19 04:44:02 +0000966 if (!needsInputInfo(snapshot, requested)) {
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000967 return;
968 }
969
Vishnu Naircfb2d252023-01-19 04:44:02 +0000970 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
971 const std::optional<frontend::DisplayInfo> displayInfoOpt =
972 args.displays.get(snapshot.outputFilter.layerStack);
973 bool noValidDisplay = !displayInfoOpt.has_value();
974 auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
975
976 if (!requested.windowInfoHandle) {
977 snapshot.inputInfo.inputConfig = gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL;
978 }
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000979 fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
980
981 if (noValidDisplay) {
982 // Do not let the window receive touches if it is not associated with a valid display
983 // transform. We still allow the window to receive keys and prevent ANRs.
984 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::NOT_TOUCHABLE;
985 }
986
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000987 snapshot.inputInfo.alpha = snapshot.color.a;
Vishnu Nair40d02282023-02-28 21:11:40 +0000988 snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
989 ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
990 : parentSnapshot.inputInfo.touchOcclusionMode;
Vishnu Nair8fc721b2022-12-22 20:06:32 +0000991 if (requested.dropInputMode == gui::DropInputMode::ALL ||
992 parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
993 snapshot.dropInputMode = gui::DropInputMode::ALL;
994 } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
995 parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
996 snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
997 } else {
998 snapshot.dropInputMode = gui::DropInputMode::NONE;
999 }
1000
1001 handleDropInputMode(snapshot, parentSnapshot);
1002
1003 // If the window will be blacked out on a display because the display does not have the secure
1004 // flag and the layer has the secure flag set, then drop input.
1005 if (!displayInfo.isSecure && snapshot.isSecure) {
1006 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
1007 }
1008
1009 auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
1010 if (snapshot.inputInfo.replaceTouchableRegionWithCrop) {
1011 const Rect bounds(cropLayerSnapshot ? cropLayerSnapshot->transformedBounds
1012 : snapshot.transformedBounds);
1013 snapshot.inputInfo.touchableRegion = Region(displayInfo.transform.transform(bounds));
1014 } else if (cropLayerSnapshot) {
1015 snapshot.inputInfo.touchableRegion = snapshot.inputInfo.touchableRegion.intersect(
1016 displayInfo.transform.transform(Rect{cropLayerSnapshot->transformedBounds}));
1017 }
1018
1019 // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
1020 // if it was set by WM for a known system overlay
1021 if (snapshot.isTrustedOverlay) {
1022 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::TRUSTED_OVERLAY;
1023 }
1024
1025 // If the layer is a clone, we need to crop the input region to cloned root to prevent
1026 // touches from going outside the cloned area.
1027 if (path.isClone()) {
1028 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
Vishnu Nair92990e22023-02-24 20:01:05 +00001029 auto clonedRootSnapshot = getSnapshot(snapshot.mirrorRootPath);
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001030 if (clonedRootSnapshot) {
1031 const Rect rect =
1032 displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
1033 snapshot.inputInfo.touchableRegion = snapshot.inputInfo.touchableRegion.intersect(rect);
1034 }
1035 }
1036}
1037
1038std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() {
1039 return mSnapshots;
1040}
1041
Vishnu Naircfb2d252023-01-19 04:44:02 +00001042void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor) const {
1043 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1044 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1045 if (!snapshot.isVisible) continue;
1046 visitor(snapshot);
1047 }
1048}
1049
Vishnu Nair3af0ec02023-02-10 04:13:48 +00001050// Visit each visible snapshot in z-order
1051void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor,
1052 const LayerHierarchy& root) const {
1053 root.traverseInZOrder(
1054 [this, visitor](const LayerHierarchy&,
1055 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
1056 LayerSnapshot* snapshot = getSnapshot(traversalPath);
1057 if (snapshot && snapshot->isVisible) {
1058 visitor(*snapshot);
1059 }
1060 return true;
1061 });
1062}
1063
Vishnu Naircfb2d252023-01-19 04:44:02 +00001064void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) {
1065 for (int i = 0; i < mNumInterestingSnapshots; i++) {
1066 std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i);
1067 if (!snapshot->isVisible) continue;
1068 visitor(snapshot);
1069 }
1070}
1071
1072void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
1073 for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
1074 LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
1075 if (!snapshot.hasInputInfo()) continue;
1076 visitor(snapshot);
1077 }
1078}
1079
Vishnu Nair8fc721b2022-12-22 20:06:32 +00001080} // namespace android::surfaceflinger::frontend