blob: bff12d7b5a80b7f6ecb09704c95e6d7d3bf4a8e2 [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"
27#include "ftl/small_map.h"
28
29namespace android::surfaceflinger::frontend {
30
31using namespace ftl::flag_operators;
32
33namespace {
34FloatRect getMaxDisplayBounds(
35 const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
36 const ui::Size maxSize = [&displays] {
37 if (displays.empty()) return ui::Size{5000, 5000};
38
39 return std::accumulate(displays.begin(), displays.end(), ui::kEmptySize,
40 [](ui::Size size, const auto& pair) -> ui::Size {
41 const auto& display = pair.second;
42 return {std::max(size.getWidth(), display.info.logicalWidth),
43 std::max(size.getHeight(), display.info.logicalHeight)};
44 });
45 }();
46
47 // Ignore display bounds for now since they will be computed later. Use a large Rect bound
48 // to ensure it's bigger than an actual display will be.
49 const float xMax = static_cast<float>(maxSize.getWidth()) * 10.f;
50 const float yMax = static_cast<float>(maxSize.getHeight()) * 10.f;
51
52 return {-xMax, -yMax, xMax, yMax};
53}
54
55// Applies the given transform to the region, while protecting against overflows caused by any
56// offsets. If applying the offset in the transform to any of the Rects in the region would result
57// in an overflow, they are not added to the output Region.
58Region transformTouchableRegionSafely(const ui::Transform& t, const Region& r,
59 const std::string& debugWindowName) {
60 // Round the translation using the same rounding strategy used by ui::Transform.
61 const auto tx = static_cast<int32_t>(t.tx() + 0.5);
62 const auto ty = static_cast<int32_t>(t.ty() + 0.5);
63
64 ui::Transform transformWithoutOffset = t;
65 transformWithoutOffset.set(0.f, 0.f);
66
67 const Region transformed = transformWithoutOffset.transform(r);
68
69 // Apply the translation to each of the Rects in the region while discarding any that overflow.
70 Region ret;
71 for (const auto& rect : transformed) {
72 Rect newRect;
73 if (__builtin_add_overflow(rect.left, tx, &newRect.left) ||
74 __builtin_add_overflow(rect.top, ty, &newRect.top) ||
75 __builtin_add_overflow(rect.right, tx, &newRect.right) ||
76 __builtin_add_overflow(rect.bottom, ty, &newRect.bottom)) {
77 ALOGE("Applying transform to touchable region of window '%s' resulted in an overflow.",
78 debugWindowName.c_str());
79 continue;
80 }
81 ret.orSelf(newRect);
82 }
83 return ret;
84}
85
86/*
87 * We don't want to send the layer's transform to input, but rather the
88 * parent's transform. This is because Layer's transform is
89 * information about how the buffer is placed on screen. The parent's
90 * transform makes more sense to send since it's information about how the
91 * layer is placed on screen. This transform is used by input to determine
92 * how to go from screen space back to window space.
93 */
94ui::Transform getInputTransform(const LayerSnapshot& snapshot) {
95 if (!snapshot.hasBufferOrSidebandStream()) {
96 return snapshot.geomLayerTransform;
97 }
98 return snapshot.parentTransform;
99}
100
101/**
102 * Similar to getInputTransform, we need to update the bounds to include the transform.
103 * This is because bounds don't include the buffer transform, where the input assumes
104 * that's already included.
105 */
106Rect getInputBounds(const LayerSnapshot& snapshot) {
107 if (!snapshot.hasBufferOrSidebandStream()) {
108 return snapshot.croppedBufferSize;
109 }
110
111 if (snapshot.localTransform.getType() == ui::Transform::IDENTITY ||
112 !snapshot.croppedBufferSize.isValid()) {
113 return snapshot.croppedBufferSize;
114 }
115 return snapshot.localTransform.transform(snapshot.croppedBufferSize);
116}
117
118void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& screenToDisplay,
119 const LayerSnapshot& snapshot) {
120 Rect tmpBounds = getInputBounds(snapshot);
121 if (!tmpBounds.isValid()) {
122 info.touchableRegion.clear();
123 // A layer could have invalid input bounds and still expect to receive touch input if it has
124 // replaceTouchableRegionWithCrop. For that case, the input transform needs to be calculated
125 // correctly to determine the coordinate space for input events. Use an empty rect so that
126 // the layer will receive input in its own layer space.
127 tmpBounds = Rect::EMPTY_RECT;
128 }
129
130 // InputDispatcher works in the display device's coordinate space. Here, we calculate the
131 // frame and transform used for the layer, which determines the bounds and the coordinate space
132 // within which the layer will receive input.
133 //
134 // The coordinate space within which each of the bounds are specified is explicitly documented
135 // in the variable name. For example "inputBoundsInLayer" is specified in layer space. A
136 // Transform converts one coordinate space to another, which is apparent in its naming. For
137 // example, "layerToDisplay" transforms layer space to display space.
138 //
139 // Coordinate space definitions:
140 // - display: The display device's coordinate space. Correlates to pixels on the display.
141 // - screen: The post-rotation coordinate space for the display, a.k.a. logical display space.
142 // - layer: The coordinate space of this layer.
143 // - input: The coordinate space in which this layer will receive input events. This could be
144 // different than layer space if a surfaceInset is used, which changes the origin
145 // of the input space.
146 const FloatRect inputBoundsInLayer = tmpBounds.toFloatRect();
147
148 // Clamp surface inset to the input bounds.
149 const auto surfaceInset = static_cast<float>(info.surfaceInset);
150 const float xSurfaceInset =
151 std::max(0.f, std::min(surfaceInset, inputBoundsInLayer.getWidth() / 2.f));
152 const float ySurfaceInset =
153 std::max(0.f, std::min(surfaceInset, inputBoundsInLayer.getHeight() / 2.f));
154
155 // Apply the insets to the input bounds.
156 const FloatRect insetBoundsInLayer(inputBoundsInLayer.left + xSurfaceInset,
157 inputBoundsInLayer.top + ySurfaceInset,
158 inputBoundsInLayer.right - xSurfaceInset,
159 inputBoundsInLayer.bottom - ySurfaceInset);
160
161 // Crop the input bounds to ensure it is within the parent's bounds.
162 const FloatRect croppedInsetBoundsInLayer =
163 snapshot.geomLayerBounds.intersect(insetBoundsInLayer);
164
165 const ui::Transform layerToScreen = getInputTransform(snapshot);
166 const ui::Transform layerToDisplay = screenToDisplay * layerToScreen;
167
168 const Rect roundedFrameInDisplay{layerToDisplay.transform(croppedInsetBoundsInLayer)};
169 info.frameLeft = roundedFrameInDisplay.left;
170 info.frameTop = roundedFrameInDisplay.top;
171 info.frameRight = roundedFrameInDisplay.right;
172 info.frameBottom = roundedFrameInDisplay.bottom;
173
174 ui::Transform inputToLayer;
175 inputToLayer.set(insetBoundsInLayer.left, insetBoundsInLayer.top);
176 const ui::Transform inputToDisplay = layerToDisplay * inputToLayer;
177
178 // InputDispatcher expects a display-to-input transform.
179 info.transform = inputToDisplay.inverse();
180
181 // The touchable region is specified in the input coordinate space. Change it to display space.
182 info.touchableRegion =
183 transformTouchableRegionSafely(inputToDisplay, info.touchableRegion, snapshot.name);
184}
185
186void handleDropInputMode(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot) {
187 if (snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) {
188 return;
189 }
190
191 // Check if we need to drop input unconditionally
192 const gui::DropInputMode dropInputMode = snapshot.dropInputMode;
193 if (dropInputMode == gui::DropInputMode::ALL) {
194 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
195 ALOGV("Dropping input for %s as requested by policy.", snapshot.name.c_str());
196 return;
197 }
198
199 // Check if we need to check if the window is obscured by parent
200 if (dropInputMode != gui::DropInputMode::OBSCURED) {
201 return;
202 }
203
204 // Check if the parent has set an alpha on the layer
205 if (parentSnapshot.color.a != 1.0_hf) {
206 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
207 ALOGV("Dropping input for %s as requested by policy because alpha=%f",
208 snapshot.name.c_str(), static_cast<float>(parentSnapshot.color.a));
209 }
210
211 // Check if the parent has cropped the buffer
212 Rect bufferSize = snapshot.croppedBufferSize;
213 if (!bufferSize.isValid()) {
214 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
215 return;
216 }
217
218 // Screenbounds are the layer bounds cropped by parents, transformed to screenspace.
219 // To check if the layer has been cropped, we take the buffer bounds, apply the local
220 // layer crop and apply the same set of transforms to move to screenspace. If the bounds
221 // match then the layer has not been cropped by its parents.
222 Rect bufferInScreenSpace(snapshot.geomLayerTransform.transform(bufferSize));
223 bool croppedByParent = bufferInScreenSpace != Rect{snapshot.transformedBounds};
224
225 if (croppedByParent) {
226 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
227 ALOGV("Dropping input for %s as requested by policy because buffer is cropped by parent",
228 snapshot.name.c_str());
229 } else {
230 // If the layer is not obscured by its parents (by setting an alpha or crop), then only drop
231 // input if the window is obscured. This check should be done in surfaceflinger but the
232 // logic currently resides in inputflinger. So pass the if_obscured check to input to only
233 // drop input events if the window is obscured.
234 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED;
235 }
236}
237
238bool getBufferNeedsFiltering(const LayerSnapshot& snapshot, const ui::Size& unrotatedBufferSize) {
239 const int32_t layerWidth = static_cast<int32_t>(snapshot.geomLayerBounds.getWidth());
240 const int32_t layerHeight = static_cast<int32_t>(snapshot.geomLayerBounds.getHeight());
241 return layerWidth != unrotatedBufferSize.width || layerHeight != unrotatedBufferSize.height;
242}
243
244auto getBlendMode(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
245 auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
246 if (snapshot.alpha != 1.0f || !snapshot.isContentOpaque()) {
247 blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED
248 : Hwc2::IComposerClient::BlendMode::COVERAGE;
249 }
250 return blendMode;
251}
252
253} // namespace
254
255LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
256 LayerSnapshot snapshot;
257 snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
258 snapshot.isHiddenByPolicyFromParent = false;
259 snapshot.isHiddenByPolicyFromRelativeParent = false;
260 snapshot.parentTransform.reset();
261 snapshot.geomLayerTransform.reset();
262 snapshot.geomInverseLayerTransform.reset();
263 snapshot.geomLayerBounds = getMaxDisplayBounds({});
264 snapshot.roundedCorner = RoundedCornerState();
265 snapshot.stretchEffect = {};
266 snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK;
267 snapshot.outputFilter.toInternalDisplay = false;
268 snapshot.isSecure = false;
269 snapshot.color.a = 1.0_hf;
270 snapshot.colorTransformIsIdentity = true;
271 snapshot.shadowRadius = 0.f;
272 snapshot.layerMetadata.mMap.clear();
273 snapshot.relativeLayerMetadata.mMap.clear();
274 snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED;
275 snapshot.dropInputMode = gui::DropInputMode::NONE;
276 snapshot.isTrustedOverlay = false;
277 return snapshot;
278}
279
280LayerSnapshotBuilder::LayerSnapshotBuilder() : mRootSnapshot(getRootSnapshot()) {}
281
282LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() {
283 args.forceUpdate = true;
284 updateSnapshots(args);
285}
286
287bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
288 if (args.forceUpdate) {
289 // force update requested, so skip the fast path
290 return false;
291 }
292
293 if (args.layerLifecycleManager.getGlobalChanges().get() == 0) {
294 // there are no changes, so just clear the change flags from before.
295 for (auto& snapshot : mSnapshots) {
296 snapshot->changes.clear();
297 snapshot->contentDirty = false;
298 }
299 return true;
300 }
301
302 if (args.layerLifecycleManager.getGlobalChanges() != RequestedLayerState::Changes::Content) {
303 // We have changes that require us to walk the hierarchy and update child layers.
304 // No fast path for you.
305 return false;
306 }
307
308 // There are only content changes which do not require any child layer snapshots to be updated.
309 ALOGV("%s", __func__);
310 ATRACE_NAME("FastPath");
311
312 // Collect layers with changes
313 ftl::SmallMap<uint32_t, RequestedLayerState*, 10> layersWithChanges;
314 for (auto& layer : args.layerLifecycleManager.getLayers()) {
315 if (layer->changes.test(RequestedLayerState::Changes::Content)) {
316 layersWithChanges.emplace_or_replace(layer->id, layer.get());
317 }
318 }
319
320 // Walk through the snapshots, clearing previous change flags and updating the snapshots
321 // if needed.
322 for (auto& snapshot : mSnapshots) {
323 snapshot->changes.clear();
324 snapshot->contentDirty = false;
325 auto it = layersWithChanges.find(snapshot->path.id);
326 if (it != layersWithChanges.end()) {
327 ALOGV("%s fast path snapshot changes = %s", __func__,
328 mRootSnapshot.changes.string().c_str());
329 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
330 updateSnapshot(*snapshot, args, *it->second, mRootSnapshot, root);
331 }
332 }
333 return true;
334}
335
336void LayerSnapshotBuilder::updateSnapshots(const Args& args) {
337 ATRACE_NAME("UpdateSnapshots");
338 ALOGV("%s updateSnapshots force = %s", __func__, std::to_string(args.forceUpdate).c_str());
339 if (args.forceUpdate || args.displayChanges) {
340 mRootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
341 }
342 if (args.displayChanges) {
343 mRootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
344 RequestedLayerState::Changes::Geometry;
345 }
346 LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
347 for (auto& [childHierarchy, variant] : args.root.mChildren) {
348 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
349 childHierarchy->getLayer()->id,
350 variant);
351 updateSnapshotsInHierarchy(args, *childHierarchy, root, mRootSnapshot);
352 }
353
354 sortSnapshotsByZ(args);
355 mRootSnapshot.changes.clear();
356
357 // Destroy unreachable snapshots
358 if (args.layerLifecycleManager.getDestroyedLayers().empty()) {
359 return;
360 }
361
362 std::unordered_set<uint32_t> destroyedLayerIds;
363 for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
364 destroyedLayerIds.emplace(destroyedLayer->id);
365 }
366 auto it = mSnapshots.begin();
367 while (it < mSnapshots.end()) {
368 auto& traversalPath = it->get()->path;
369 if (destroyedLayerIds.find(traversalPath.id) == destroyedLayerIds.end()) {
370 it++;
371 continue;
372 }
373
374 mIdToSnapshot.erase(traversalPath);
375 std::iter_swap(it, mSnapshots.end() - 1);
376 mSnapshots.erase(mSnapshots.end() - 1);
377 }
378}
379
380void LayerSnapshotBuilder::update(const Args& args) {
381 if (tryFastUpdate(args)) {
382 return;
383 }
384 updateSnapshots(args);
385}
386
387void LayerSnapshotBuilder::updateSnapshotsInHierarchy(const Args& args,
388 const LayerHierarchy& hierarchy,
389 LayerHierarchy::TraversalPath& traversalPath,
390 const LayerSnapshot& parentSnapshot) {
391 const RequestedLayerState* layer = hierarchy.getLayer();
392 LayerSnapshot* snapshot = getOrCreateSnapshot(traversalPath, *layer);
393 if (traversalPath.isRelative()) {
394 bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
395 updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
396 } else {
397 if (traversalPath.isAttached()) {
398 resetRelativeState(*snapshot);
399 }
400 updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
401 }
402
403 // If layer is hidden by policy we can avoid update its children. If the visibility
404 // changed this update, then we still need to set the visibility on all the children.
405 if (snapshot->isHiddenByPolicy() &&
406 (!snapshot->changes.any(RequestedLayerState::Changes::Visibility |
407 RequestedLayerState::Changes::Hierarchy))) {
408 return;
409 }
410
411 for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
412 LayerHierarchy::ScopedAddToTraversalPath addChildToPath(traversalPath,
413 childHierarchy->getLayer()->id,
414 variant);
415 updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot);
416 }
417}
418
419LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const {
420 if (layerId == UNASSIGNED_LAYER_ID) {
421 return nullptr;
422 }
423 LayerHierarchy::TraversalPath path{.id = layerId};
424 return getSnapshot(path);
425}
426
427LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
428 auto it = mIdToSnapshot.find(id);
429 return it == mIdToSnapshot.end() ? nullptr : it->second;
430}
431
432LayerSnapshot* LayerSnapshotBuilder::getOrCreateSnapshot(const LayerHierarchy::TraversalPath& id,
433 const RequestedLayerState& layer) {
434 auto snapshot = getSnapshot(id);
435 if (snapshot) {
436 return snapshot;
437 }
438
439 mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, id));
440 snapshot = mSnapshots.back().get();
441 snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
442 mIdToSnapshot[id] = snapshot;
443 return snapshot;
444}
445
446void LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
447 if (!args.forceUpdate &&
448 !args.layerLifecycleManager.getGlobalChanges().any(
449 RequestedLayerState::Changes::Hierarchy |
450 RequestedLayerState::Changes::Visibility)) {
451 // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
452 // the snapshots.
453 return;
454 }
455
456 size_t globalZ = 0;
457 args.root.traverseInZOrder(
458 [this, &globalZ](const LayerHierarchy&,
459 const LayerHierarchy::TraversalPath& traversalPath) -> bool {
460 LayerSnapshot* snapshot = getSnapshot(traversalPath);
461 if (!snapshot) {
462 return false;
463 }
464
465 if (snapshot->isHiddenByPolicy() &&
466 !snapshot->changes.test(RequestedLayerState::Changes::Visibility)) {
467 return false;
468 }
469
470 if (snapshot->isVisible) {
471 size_t oldZ = snapshot->globalZ;
472 size_t newZ = globalZ++;
473 snapshot->globalZ = newZ;
474 if (oldZ == newZ) {
475 return true;
476 }
477 mSnapshots[newZ]->globalZ = oldZ;
478 std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ),
479 mSnapshots.begin() + static_cast<ssize_t>(newZ));
480 }
481
482 return true;
483 });
484
485 while (globalZ < mSnapshots.size()) {
486 mSnapshots[globalZ]->globalZ = globalZ;
487 mSnapshots[globalZ]->isVisible = false;
488 globalZ++;
489 }
490}
491
492void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
493 const LayerSnapshot& parentSnapshot,
494 bool parentIsRelative, const Args& args) {
495 if (parentIsRelative) {
496 snapshot.isHiddenByPolicyFromRelativeParent = parentSnapshot.isHiddenByPolicyFromParent;
497 if (args.includeMetadata) {
498 snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata;
499 }
500 } else {
501 snapshot.isHiddenByPolicyFromRelativeParent =
502 parentSnapshot.isHiddenByPolicyFromRelativeParent;
503 if (args.includeMetadata) {
504 snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
505 }
506 }
507 snapshot.isVisible = snapshot.getIsVisible();
508}
509
510void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) {
511 snapshot.isHiddenByPolicyFromRelativeParent = false;
512 snapshot.relativeLayerMetadata.mMap.clear();
513}
514
515uint32_t getDisplayRotationFlags(
516 const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays,
517 const ui::LayerStack& layerStack) {
518 static frontend::DisplayInfo sDefaultDisplayInfo = {.isPrimary = false};
519 auto display = displays.get(layerStack).value_or(sDefaultDisplayInfo).get();
520 return display.isPrimary ? display.rotationFlags : 0;
521}
522
523void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
524 const RequestedLayerState& requested,
525 const LayerSnapshot& parentSnapshot,
526 const LayerHierarchy::TraversalPath& path) {
527 // Always update flags and visibility
528 ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
529 (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
530 RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
531 RequestedLayerState::Changes::AffectsChildren);
532 snapshot.changes = parentChanges | requested.changes;
533 snapshot.isHiddenByPolicyFromParent =
534 parentSnapshot.isHiddenByPolicyFromParent || requested.isHiddenByPolicy();
535 snapshot.contentDirty = requested.what & layer_state_t::CONTENT_DIRTY;
536 if (snapshot.isHiddenByPolicyFromParent) {
537 snapshot.isVisible = false;
538 return;
539 }
540
541 uint32_t displayRotationFlags =
542 getDisplayRotationFlags(args.displays, snapshot.outputFilter.layerStack);
543
544 const bool forceUpdate = args.forceUpdate ||
545 snapshot.changes.any(RequestedLayerState::Changes::Visibility |
546 RequestedLayerState::Changes::Created);
547
548 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) {
549 // If root layer, use the layer stack otherwise get the parent's layer stack.
550 snapshot.color.a = parentSnapshot.color.a * requested.color.a;
551 snapshot.alpha = snapshot.color.a;
552 snapshot.isSecure =
553 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
554 snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
555 snapshot.outputFilter.layerStack = requested.parentId != UNASSIGNED_LAYER_ID
556 ? parentSnapshot.outputFilter.layerStack
557 : requested.layerStack;
558 snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
559 (requested.flags & layer_state_t::eLayerSkipScreenshot);
560 snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
561 ? requested.stretchEffect
562 : parentSnapshot.stretchEffect;
563 if (!parentSnapshot.colorTransformIsIdentity) {
564 snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
565 snapshot.colorTransformIsIdentity = false;
566 } else {
567 snapshot.colorTransform = requested.colorTransform;
568 snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
569 }
570 }
571
572 if (forceUpdate || requested.changes.get() != 0) {
573 snapshot.compositionType = requested.getCompositionType();
574 snapshot.dimmingEnabled = requested.dimmingEnabled;
575 snapshot.layerOpaqueFlagSet =
576 (requested.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque;
577 }
578
579 if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES) {
580 snapshot.acquireFence =
581 (requested.bufferData) ? requested.bufferData->acquireFence : Fence::NO_FENCE;
582 snapshot.buffer =
583 requested.externalTexture ? requested.externalTexture->getBuffer() : nullptr;
584 snapshot.bufferSize = requested.getBufferSize(displayRotationFlags);
585 snapshot.geomBufferSize = snapshot.bufferSize;
586 snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
587 snapshot.dataspace = requested.dataspace;
588 snapshot.externalTexture = requested.externalTexture;
589 snapshot.frameNumber = (requested.bufferData) ? requested.bufferData->frameNumber : 0;
590 snapshot.geomBufferTransform = requested.bufferTransform;
591 snapshot.geomBufferUsesDisplayInverseTransform = requested.transformToDisplayInverse;
592 snapshot.geomContentCrop = requested.getBufferCrop();
593 snapshot.geomUsesSourceCrop = snapshot.hasBufferOrSidebandStream();
594 snapshot.hasProtectedContent = requested.externalTexture &&
595 requested.externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED;
596 snapshot.isHdrY410 = requested.dataspace == ui::Dataspace::BT2020_ITU_PQ &&
597 requested.api == NATIVE_WINDOW_API_MEDIA &&
598 requested.bufferData->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102;
599 snapshot.sidebandStream = requested.sidebandStream;
600 snapshot.surfaceDamage = requested.surfaceDamageRegion;
601 snapshot.transparentRegionHint = requested.transparentRegion;
602 }
603
604 if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content)) {
605 snapshot.color.rgb = requested.getColor().rgb;
606 snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic;
607 snapshot.backgroundBlurRadius = static_cast<int>(requested.backgroundBlurRadius);
608 snapshot.blurRegions = requested.blurRegions;
609 snapshot.hdrMetadata = requested.hdrMetadata;
610 }
611
612 if (forceUpdate ||
613 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
614 RequestedLayerState::Changes::Geometry)) {
615 updateLayerBounds(snapshot, requested, parentSnapshot, displayRotationFlags);
616 updateRoundedCorner(snapshot, requested, parentSnapshot);
617 }
618
619 if (forceUpdate ||
620 snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
621 RequestedLayerState::Changes::Geometry |
622 RequestedLayerState::Changes::Input)) {
623 static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
624 const std::optional<frontend::DisplayInfo> displayInfo =
625 args.displays.get(snapshot.outputFilter.layerStack);
626 bool noValidDisplay = !displayInfo.has_value();
627 updateInput(snapshot, requested, parentSnapshot, displayInfo.value_or(sDefaultInfo),
628 noValidDisplay, path);
629 }
630
631 // computed snapshot properties
632 updateShadows(snapshot, requested, args.globalShadowSettings);
633 if (args.includeMetadata) {
634 snapshot.layerMetadata = parentSnapshot.layerMetadata;
635 snapshot.layerMetadata.merge(requested.metadata);
636 }
637 snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 ||
638 requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect();
639 snapshot.isVisible = snapshot.getIsVisible();
640 snapshot.isOpaque = snapshot.isContentOpaque() && !snapshot.roundedCorner.hasRoundedCorners() &&
641 snapshot.color.a == 1.f;
642 snapshot.blendMode = getBlendMode(snapshot, requested);
643
644 ALOGV("%supdated [%d]%s changes parent:%s global:%s local:%s requested:%s %s from parent %s",
645 args.forceUpdate ? "Force " : "", requested.id, requested.name.c_str(),
646 parentSnapshot.changes.string().c_str(), snapshot.changes.string().c_str(),
647 requested.changes.string().c_str(), std::to_string(requested.what).c_str(),
648 snapshot.getDebugString().c_str(), parentSnapshot.getDebugString().c_str());
649}
650
651void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
652 const RequestedLayerState& requested,
653 const LayerSnapshot& parentSnapshot) {
654 snapshot.roundedCorner = RoundedCornerState();
655 RoundedCornerState parentRoundedCorner;
656 if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
657 parentRoundedCorner = parentSnapshot.roundedCorner;
658 ui::Transform t = snapshot.localTransform.inverse();
659 parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
660 parentRoundedCorner.radius.x *= t.getScaleX();
661 parentRoundedCorner.radius.y *= t.getScaleY();
662 }
663
664 FloatRect layerCropRect = snapshot.croppedBufferSize.toFloatRect();
665 const vec2 radius(requested.cornerRadius, requested.cornerRadius);
666 RoundedCornerState layerSettings(layerCropRect, radius);
667 const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
668 const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
669 if (layerSettingsValid && parentRoundedCornerValid) {
670 // If the parent and the layer have rounded corner settings, use the parent settings if
671 // the parent crop is entirely inside the layer crop. This has limitations and cause
672 // rendering artifacts. See b/200300845 for correct fix.
673 if (parentRoundedCorner.cropRect.left > layerCropRect.left &&
674 parentRoundedCorner.cropRect.top > layerCropRect.top &&
675 parentRoundedCorner.cropRect.right < layerCropRect.right &&
676 parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) {
677 snapshot.roundedCorner = parentRoundedCorner;
678 } else {
679 snapshot.roundedCorner = layerSettings;
680 }
681 } else if (layerSettingsValid) {
682 snapshot.roundedCorner = layerSettings;
683 } else if (parentRoundedCornerValid) {
684 snapshot.roundedCorner = parentRoundedCorner;
685 }
686}
687
688void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot,
689 const RequestedLayerState& requested,
690 const LayerSnapshot& parentSnapshot,
691 uint32_t displayRotationFlags) {
692 snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
693 snapshot.geomCrop = requested.crop;
694 snapshot.localTransform = requested.getTransform(displayRotationFlags);
695 snapshot.localTransformInverse = snapshot.localTransform.inverse();
696 snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
697 snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
698 if (snapshot.invalidTransform) {
699 ALOGW("Resetting transform for %s because it has an invalid transformation.",
700 requested.getDebugStringShort().c_str());
701 snapshot.geomLayerTransform.reset();
702 }
703 snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse();
704
705 FloatRect parentBounds = parentSnapshot.geomLayerBounds;
706 parentBounds = snapshot.localTransform.inverse().transform(parentBounds);
707 snapshot.geomLayerBounds =
708 (requested.externalTexture) ? snapshot.bufferSize.toFloatRect() : parentBounds;
709 if (!requested.crop.isEmpty()) {
710 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(requested.crop.toFloatRect());
711 }
712 snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(parentBounds);
713 snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds);
714 snapshot.parentTransform = parentSnapshot.geomLayerTransform;
715
716 // Subtract the transparent region and snap to the bounds
717 Rect bounds =
718 RequestedLayerState::reduce(snapshot.croppedBufferSize, requested.transparentRegion);
719 snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds);
720
721 // TODO(b/238781169) use dest vs src
722 snapshot.bufferNeedsFiltering = snapshot.externalTexture &&
723 getBufferNeedsFiltering(snapshot,
724 requested.getUnrotatedBufferSize(displayRotationFlags));
725}
726
727void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot,
728 const RequestedLayerState& requested,
729 const renderengine::ShadowSettings& globalShadowSettings) {
730 snapshot.shadowRadius = requested.shadowRadius;
731 snapshot.shadowSettings.length = requested.shadowRadius;
732 if (snapshot.shadowRadius > 0.f) {
733 snapshot.shadowSettings = globalShadowSettings;
734
735 // Note: this preserves existing behavior of shadowing the entire layer and not cropping
736 // it if transparent regions are present. This may not be necessary since shadows are
737 // typically cast by layers without transparent regions.
738 snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds;
739
740 // If the casting layer is translucent, we need to fill in the shadow underneath the
741 // layer. Otherwise the generated shadow will only be shown around the casting layer.
742 snapshot.shadowSettings.casterIsTranslucent =
743 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f);
744 snapshot.shadowSettings.ambientColor *= snapshot.alpha;
745 snapshot.shadowSettings.spotColor *= snapshot.alpha;
746 }
747}
748
749void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot,
750 const RequestedLayerState& requested,
751 const LayerSnapshot& parentSnapshot,
752 const frontend::DisplayInfo& displayInfo,
753 bool noValidDisplay,
754 const LayerHierarchy::TraversalPath& path) {
755 snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id);
756 if (!requested.hasInputInfo()) {
757 snapshot.inputInfo.inputConfig = gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL;
758 return;
759 }
760
761 fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
762
763 if (noValidDisplay) {
764 // Do not let the window receive touches if it is not associated with a valid display
765 // transform. We still allow the window to receive keys and prevent ANRs.
766 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::NOT_TOUCHABLE;
767 }
768
769 // For compatibility reasons we let layers which can receive input
770 // receive input before they have actually submitted a buffer. Because
771 // of this we use canReceiveInput instead of isVisible to check the
772 // policy-visibility, ignoring the buffer state. However for layers with
773 // hasInputInfo()==false we can use the real visibility state.
774 // We are just using these layers for occlusion detection in
775 // InputDispatcher, and obviously if they aren't visible they can't occlude
776 // anything.
777 const bool visible = requested.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
778 snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visible);
779
780 snapshot.inputInfo.alpha = snapshot.color.a;
781 snapshot.inputInfo.touchOcclusionMode = parentSnapshot.inputInfo.touchOcclusionMode;
782 if (requested.dropInputMode == gui::DropInputMode::ALL ||
783 parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
784 snapshot.dropInputMode = gui::DropInputMode::ALL;
785 } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
786 parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
787 snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
788 } else {
789 snapshot.dropInputMode = gui::DropInputMode::NONE;
790 }
791
792 handleDropInputMode(snapshot, parentSnapshot);
793
794 // If the window will be blacked out on a display because the display does not have the secure
795 // flag and the layer has the secure flag set, then drop input.
796 if (!displayInfo.isSecure && snapshot.isSecure) {
797 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
798 }
799
800 auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
801 if (snapshot.inputInfo.replaceTouchableRegionWithCrop) {
802 const Rect bounds(cropLayerSnapshot ? cropLayerSnapshot->transformedBounds
803 : snapshot.transformedBounds);
804 snapshot.inputInfo.touchableRegion = Region(displayInfo.transform.transform(bounds));
805 } else if (cropLayerSnapshot) {
806 snapshot.inputInfo.touchableRegion = snapshot.inputInfo.touchableRegion.intersect(
807 displayInfo.transform.transform(Rect{cropLayerSnapshot->transformedBounds}));
808 }
809
810 // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
811 // if it was set by WM for a known system overlay
812 if (snapshot.isTrustedOverlay) {
813 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::TRUSTED_OVERLAY;
814 }
815
816 // If the layer is a clone, we need to crop the input region to cloned root to prevent
817 // touches from going outside the cloned area.
818 if (path.isClone()) {
819 snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
820 auto clonedRootSnapshot = getSnapshot(path.mirrorRootIds.back());
821 if (clonedRootSnapshot) {
822 const Rect rect =
823 displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
824 snapshot.inputInfo.touchableRegion = snapshot.inputInfo.touchableRegion.intersect(rect);
825 }
826 }
827}
828
829std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() {
830 return mSnapshots;
831}
832
833} // namespace android::surfaceflinger::frontend