| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 2022 The Android Open Source Project | 
 | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
 | 17 | // #define LOG_NDEBUG 0 | 
 | 18 | #define ATRACE_TAG ATRACE_TAG_GRAPHICS | 
 | 19 | #undef LOG_TAG | 
 | 20 | #define LOG_TAG "LayerSnapshotBuilder" | 
 | 21 |  | 
 | 22 | #include "LayerSnapshotBuilder.h" | 
 | 23 | #include <gui/TraceUtils.h> | 
| Vishnu Nair | fed7c12 | 2023-03-18 01:54:43 +0000 | [diff] [blame] | 24 | #include <ui/FloatRect.h> | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 25 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 26 | #include <numeric> | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 27 | #include <optional> | 
 | 28 |  | 
 | 29 | #include <gui/TraceUtils.h> | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 30 | #include "DisplayHardware/HWC2.h" | 
 | 31 | #include "DisplayHardware/Hal.h" | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 32 | #include "LayerLog.h" | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 33 | #include "LayerSnapshotBuilder.h" | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 34 | #include "TimeStats/TimeStats.h" | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 35 | #include "ftl/small_map.h" | 
 | 36 |  | 
 | 37 | namespace android::surfaceflinger::frontend { | 
 | 38 |  | 
 | 39 | using namespace ftl::flag_operators; | 
 | 40 |  | 
 | 41 | namespace { | 
 | 42 | FloatRect getMaxDisplayBounds( | 
 | 43 |         const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) { | 
 | 44 |     const ui::Size maxSize = [&displays] { | 
 | 45 |         if (displays.empty()) return ui::Size{5000, 5000}; | 
 | 46 |  | 
 | 47 |         return std::accumulate(displays.begin(), displays.end(), ui::kEmptySize, | 
 | 48 |                                [](ui::Size size, const auto& pair) -> ui::Size { | 
 | 49 |                                    const auto& display = pair.second; | 
 | 50 |                                    return {std::max(size.getWidth(), display.info.logicalWidth), | 
 | 51 |                                            std::max(size.getHeight(), display.info.logicalHeight)}; | 
 | 52 |                                }); | 
 | 53 |     }(); | 
 | 54 |  | 
 | 55 |     // Ignore display bounds for now since they will be computed later. Use a large Rect bound | 
 | 56 |     // to ensure it's bigger than an actual display will be. | 
 | 57 |     const float xMax = static_cast<float>(maxSize.getWidth()) * 10.f; | 
 | 58 |     const float yMax = static_cast<float>(maxSize.getHeight()) * 10.f; | 
 | 59 |  | 
 | 60 |     return {-xMax, -yMax, xMax, yMax}; | 
 | 61 | } | 
 | 62 |  | 
 | 63 | // Applies the given transform to the region, while protecting against overflows caused by any | 
 | 64 | // offsets. If applying the offset in the transform to any of the Rects in the region would result | 
 | 65 | // in an overflow, they are not added to the output Region. | 
 | 66 | Region transformTouchableRegionSafely(const ui::Transform& t, const Region& r, | 
 | 67 |                                       const std::string& debugWindowName) { | 
 | 68 |     // Round the translation using the same rounding strategy used by ui::Transform. | 
 | 69 |     const auto tx = static_cast<int32_t>(t.tx() + 0.5); | 
 | 70 |     const auto ty = static_cast<int32_t>(t.ty() + 0.5); | 
 | 71 |  | 
 | 72 |     ui::Transform transformWithoutOffset = t; | 
 | 73 |     transformWithoutOffset.set(0.f, 0.f); | 
 | 74 |  | 
 | 75 |     const Region transformed = transformWithoutOffset.transform(r); | 
 | 76 |  | 
 | 77 |     // Apply the translation to each of the Rects in the region while discarding any that overflow. | 
 | 78 |     Region ret; | 
 | 79 |     for (const auto& rect : transformed) { | 
 | 80 |         Rect newRect; | 
 | 81 |         if (__builtin_add_overflow(rect.left, tx, &newRect.left) || | 
 | 82 |             __builtin_add_overflow(rect.top, ty, &newRect.top) || | 
 | 83 |             __builtin_add_overflow(rect.right, tx, &newRect.right) || | 
 | 84 |             __builtin_add_overflow(rect.bottom, ty, &newRect.bottom)) { | 
 | 85 |             ALOGE("Applying transform to touchable region of window '%s' resulted in an overflow.", | 
 | 86 |                   debugWindowName.c_str()); | 
 | 87 |             continue; | 
 | 88 |         } | 
 | 89 |         ret.orSelf(newRect); | 
 | 90 |     } | 
 | 91 |     return ret; | 
 | 92 | } | 
 | 93 |  | 
 | 94 | /* | 
 | 95 |  * We don't want to send the layer's transform to input, but rather the | 
 | 96 |  * parent's transform. This is because Layer's transform is | 
 | 97 |  * information about how the buffer is placed on screen. The parent's | 
 | 98 |  * transform makes more sense to send since it's information about how the | 
 | 99 |  * layer is placed on screen. This transform is used by input to determine | 
 | 100 |  * how to go from screen space back to window space. | 
 | 101 |  */ | 
 | 102 | ui::Transform getInputTransform(const LayerSnapshot& snapshot) { | 
 | 103 |     if (!snapshot.hasBufferOrSidebandStream()) { | 
 | 104 |         return snapshot.geomLayerTransform; | 
 | 105 |     } | 
 | 106 |     return snapshot.parentTransform; | 
 | 107 | } | 
 | 108 |  | 
 | 109 | /** | 
| Vishnu Nair | fed7c12 | 2023-03-18 01:54:43 +0000 | [diff] [blame] | 110 |  * Returns the bounds used to fill the input frame and the touchable region. | 
 | 111 |  * | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 112 |  * Similar to getInputTransform, we need to update the bounds to include the transform. | 
 | 113 |  * This is because bounds don't include the buffer transform, where the input assumes | 
 | 114 |  * that's already included. | 
 | 115 |  */ | 
| Vishnu Nair | fed7c12 | 2023-03-18 01:54:43 +0000 | [diff] [blame] | 116 | std::pair<FloatRect, bool> getInputBounds(const LayerSnapshot& snapshot, bool fillParentBounds) { | 
 | 117 |     FloatRect inputBounds = snapshot.croppedBufferSize.toFloatRect(); | 
 | 118 |     if (snapshot.hasBufferOrSidebandStream() && snapshot.croppedBufferSize.isValid() && | 
 | 119 |         snapshot.localTransform.getType() != ui::Transform::IDENTITY) { | 
 | 120 |         inputBounds = snapshot.localTransform.transform(inputBounds); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 121 |     } | 
 | 122 |  | 
| Vishnu Nair | fed7c12 | 2023-03-18 01:54:43 +0000 | [diff] [blame] | 123 |     bool inputBoundsValid = snapshot.croppedBufferSize.isValid(); | 
 | 124 |     if (!inputBoundsValid) { | 
 | 125 |         /** | 
 | 126 |          * Input bounds are based on the layer crop or buffer size. But if we are using | 
 | 127 |          * the layer bounds as the input bounds (replaceTouchableRegionWithCrop flag) then | 
 | 128 |          * we can use the parent bounds as the input bounds if the layer does not have buffer | 
 | 129 |          * or a crop. We want to unify this logic but because of compat reasons we cannot always | 
 | 130 |          * use the parent bounds. A layer without a buffer can get input. So when a window is | 
 | 131 |          * initially added, its touchable region can fill its parent layer bounds and that can | 
 | 132 |          * have negative consequences. | 
 | 133 |          */ | 
 | 134 |         inputBounds = fillParentBounds ? snapshot.geomLayerBounds : FloatRect{}; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 135 |     } | 
| Vishnu Nair | fed7c12 | 2023-03-18 01:54:43 +0000 | [diff] [blame] | 136 |  | 
 | 137 |     // Clamp surface inset to the input bounds. | 
 | 138 |     const float inset = static_cast<float>(snapshot.inputInfo.surfaceInset); | 
 | 139 |     const float xSurfaceInset = std::clamp(inset, 0.f, inputBounds.getWidth() / 2.f); | 
 | 140 |     const float ySurfaceInset = std::clamp(inset, 0.f, inputBounds.getHeight() / 2.f); | 
 | 141 |  | 
 | 142 |     // Apply the insets to the input bounds. | 
 | 143 |     inputBounds.left += xSurfaceInset; | 
 | 144 |     inputBounds.top += ySurfaceInset; | 
 | 145 |     inputBounds.right -= xSurfaceInset; | 
 | 146 |     inputBounds.bottom -= ySurfaceInset; | 
 | 147 |     return {inputBounds, inputBoundsValid}; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 148 | } | 
 | 149 |  | 
| Vishnu Nair | fed7c12 | 2023-03-18 01:54:43 +0000 | [diff] [blame] | 150 | Rect getInputBoundsInDisplaySpace(const LayerSnapshot& snapshot, const FloatRect& insetBounds, | 
 | 151 |                                   const ui::Transform& screenToDisplay) { | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 152 |     // InputDispatcher works in the display device's coordinate space. Here, we calculate the | 
 | 153 |     // frame and transform used for the layer, which determines the bounds and the coordinate space | 
 | 154 |     // within which the layer will receive input. | 
| Vishnu Nair | fed7c12 | 2023-03-18 01:54:43 +0000 | [diff] [blame] | 155 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 156 |     // Coordinate space definitions: | 
 | 157 |     //   - display: The display device's coordinate space. Correlates to pixels on the display. | 
 | 158 |     //   - screen: The post-rotation coordinate space for the display, a.k.a. logical display space. | 
 | 159 |     //   - layer: The coordinate space of this layer. | 
 | 160 |     //   - input: The coordinate space in which this layer will receive input events. This could be | 
 | 161 |     //            different than layer space if a surfaceInset is used, which changes the origin | 
 | 162 |     //            of the input space. | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 163 |  | 
 | 164 |     // Crop the input bounds to ensure it is within the parent's bounds. | 
| Vishnu Nair | fed7c12 | 2023-03-18 01:54:43 +0000 | [diff] [blame] | 165 |     const FloatRect croppedInsetBoundsInLayer = snapshot.geomLayerBounds.intersect(insetBounds); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 166 |  | 
 | 167 |     const ui::Transform layerToScreen = getInputTransform(snapshot); | 
 | 168 |     const ui::Transform layerToDisplay = screenToDisplay * layerToScreen; | 
 | 169 |  | 
| Vishnu Nair | fed7c12 | 2023-03-18 01:54:43 +0000 | [diff] [blame] | 170 |     return Rect{layerToDisplay.transform(croppedInsetBoundsInLayer)}; | 
 | 171 | } | 
 | 172 |  | 
 | 173 | void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& screenToDisplay, | 
 | 174 |                         const LayerSnapshot& snapshot) { | 
 | 175 |     auto [inputBounds, inputBoundsValid] = getInputBounds(snapshot, /*fillParentBounds=*/false); | 
 | 176 |     if (!inputBoundsValid) { | 
 | 177 |         info.touchableRegion.clear(); | 
 | 178 |     } | 
 | 179 |  | 
 | 180 |     const Rect roundedFrameInDisplay = | 
 | 181 |             getInputBoundsInDisplaySpace(snapshot, inputBounds, screenToDisplay); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 182 |     info.frameLeft = roundedFrameInDisplay.left; | 
 | 183 |     info.frameTop = roundedFrameInDisplay.top; | 
 | 184 |     info.frameRight = roundedFrameInDisplay.right; | 
 | 185 |     info.frameBottom = roundedFrameInDisplay.bottom; | 
 | 186 |  | 
 | 187 |     ui::Transform inputToLayer; | 
| Vishnu Nair | fed7c12 | 2023-03-18 01:54:43 +0000 | [diff] [blame] | 188 |     inputToLayer.set(inputBounds.left, inputBounds.top); | 
 | 189 |     const ui::Transform layerToScreen = getInputTransform(snapshot); | 
 | 190 |     const ui::Transform inputToDisplay = screenToDisplay * layerToScreen * inputToLayer; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 191 |  | 
 | 192 |     // InputDispatcher expects a display-to-input transform. | 
 | 193 |     info.transform = inputToDisplay.inverse(); | 
 | 194 |  | 
 | 195 |     // The touchable region is specified in the input coordinate space. Change it to display space. | 
 | 196 |     info.touchableRegion = | 
 | 197 |             transformTouchableRegionSafely(inputToDisplay, info.touchableRegion, snapshot.name); | 
 | 198 | } | 
 | 199 |  | 
 | 200 | void handleDropInputMode(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot) { | 
 | 201 |     if (snapshot.inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) { | 
 | 202 |         return; | 
 | 203 |     } | 
 | 204 |  | 
 | 205 |     // Check if we need to drop input unconditionally | 
 | 206 |     const gui::DropInputMode dropInputMode = snapshot.dropInputMode; | 
 | 207 |     if (dropInputMode == gui::DropInputMode::ALL) { | 
 | 208 |         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT; | 
 | 209 |         ALOGV("Dropping input for %s as requested by policy.", snapshot.name.c_str()); | 
 | 210 |         return; | 
 | 211 |     } | 
 | 212 |  | 
 | 213 |     // Check if we need to check if the window is obscured by parent | 
 | 214 |     if (dropInputMode != gui::DropInputMode::OBSCURED) { | 
 | 215 |         return; | 
 | 216 |     } | 
 | 217 |  | 
 | 218 |     // Check if the parent has set an alpha on the layer | 
 | 219 |     if (parentSnapshot.color.a != 1.0_hf) { | 
 | 220 |         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT; | 
 | 221 |         ALOGV("Dropping input for %s as requested by policy because alpha=%f", | 
 | 222 |               snapshot.name.c_str(), static_cast<float>(parentSnapshot.color.a)); | 
 | 223 |     } | 
 | 224 |  | 
 | 225 |     // Check if the parent has cropped the buffer | 
 | 226 |     Rect bufferSize = snapshot.croppedBufferSize; | 
 | 227 |     if (!bufferSize.isValid()) { | 
 | 228 |         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED; | 
 | 229 |         return; | 
 | 230 |     } | 
 | 231 |  | 
 | 232 |     // Screenbounds are the layer bounds cropped by parents, transformed to screenspace. | 
 | 233 |     // To check if the layer has been cropped, we take the buffer bounds, apply the local | 
 | 234 |     // layer crop and apply the same set of transforms to move to screenspace. If the bounds | 
 | 235 |     // match then the layer has not been cropped by its parents. | 
 | 236 |     Rect bufferInScreenSpace(snapshot.geomLayerTransform.transform(bufferSize)); | 
 | 237 |     bool croppedByParent = bufferInScreenSpace != Rect{snapshot.transformedBounds}; | 
 | 238 |  | 
 | 239 |     if (croppedByParent) { | 
 | 240 |         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT; | 
 | 241 |         ALOGV("Dropping input for %s as requested by policy because buffer is cropped by parent", | 
 | 242 |               snapshot.name.c_str()); | 
 | 243 |     } else { | 
 | 244 |         // If the layer is not obscured by its parents (by setting an alpha or crop), then only drop | 
 | 245 |         // input if the window is obscured. This check should be done in surfaceflinger but the | 
 | 246 |         // logic currently resides in inputflinger. So pass the if_obscured check to input to only | 
 | 247 |         // drop input events if the window is obscured. | 
 | 248 |         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED; | 
 | 249 |     } | 
 | 250 | } | 
 | 251 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 252 | auto getBlendMode(const LayerSnapshot& snapshot, const RequestedLayerState& requested) { | 
 | 253 |     auto blendMode = Hwc2::IComposerClient::BlendMode::NONE; | 
 | 254 |     if (snapshot.alpha != 1.0f || !snapshot.isContentOpaque()) { | 
 | 255 |         blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED | 
 | 256 |                                                  : Hwc2::IComposerClient::BlendMode::COVERAGE; | 
 | 257 |     } | 
 | 258 |     return blendMode; | 
 | 259 | } | 
 | 260 |  | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 261 | void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFrame, | 
 | 262 |                          bool forceFullDamage, Region& outSurfaceDamageRegion) { | 
 | 263 |     if (!hasReadyFrame) { | 
 | 264 |         outSurfaceDamageRegion.clear(); | 
 | 265 |         return; | 
 | 266 |     } | 
 | 267 |     if (forceFullDamage) { | 
 | 268 |         outSurfaceDamageRegion = Region::INVALID_REGION; | 
 | 269 |     } else { | 
 | 270 |         outSurfaceDamageRegion = requested.surfaceDamageRegion; | 
 | 271 |     } | 
 | 272 | } | 
 | 273 |  | 
| Vishnu Nair | 80a5a70 | 2023-02-11 01:21:51 +0000 | [diff] [blame] | 274 | void updateVisibility(LayerSnapshot& snapshot, bool visible) { | 
 | 275 |     snapshot.isVisible = visible; | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 276 |  | 
 | 277 |     // TODO(b/238781169) we are ignoring this compat for now, since we will have | 
 | 278 |     // to remove any optimization based on visibility. | 
 | 279 |  | 
 | 280 |     // For compatibility reasons we let layers which can receive input | 
 | 281 |     // receive input before they have actually submitted a buffer. Because | 
 | 282 |     // of this we use canReceiveInput instead of isVisible to check the | 
 | 283 |     // policy-visibility, ignoring the buffer state. However for layers with | 
 | 284 |     // hasInputInfo()==false we can use the real visibility state. | 
 | 285 |     // We are just using these layers for occlusion detection in | 
 | 286 |     // InputDispatcher, and obviously if they aren't visible they can't occlude | 
 | 287 |     // anything. | 
| Vishnu Nair | 80a5a70 | 2023-02-11 01:21:51 +0000 | [diff] [blame] | 288 |     const bool visibleForInput = | 
| Vishnu Nair | 40d0228 | 2023-02-28 21:11:40 +0000 | [diff] [blame] | 289 |             snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible; | 
| Vishnu Nair | 80a5a70 | 2023-02-11 01:21:51 +0000 | [diff] [blame] | 290 |     snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 291 | } | 
 | 292 |  | 
 | 293 | bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) { | 
 | 294 |     if (requested.potentialCursor) { | 
 | 295 |         return false; | 
 | 296 |     } | 
 | 297 |  | 
 | 298 |     if (snapshot.inputInfo.token != nullptr) { | 
 | 299 |         return true; | 
 | 300 |     } | 
 | 301 |  | 
 | 302 |     if (snapshot.hasBufferOrSidebandStream()) { | 
 | 303 |         return true; | 
 | 304 |     } | 
 | 305 |  | 
 | 306 |     return requested.windowInfoHandle && | 
 | 307 |             requested.windowInfoHandle->getInfo()->inputConfig.test( | 
 | 308 |                     gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL); | 
 | 309 | } | 
 | 310 |  | 
| Vishnu Nair | c765c6c | 2023-02-23 00:08:01 +0000 | [diff] [blame] | 311 | void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested, | 
 | 312 |                     const LayerSnapshotBuilder::Args& args) { | 
 | 313 |     snapshot.metadata.clear(); | 
 | 314 |     for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) { | 
 | 315 |         auto compatIter = args.genericLayerMetadataKeyMap.find(key); | 
 | 316 |         if (compatIter == std::end(args.genericLayerMetadataKeyMap)) { | 
 | 317 |             continue; | 
 | 318 |         } | 
 | 319 |         const uint32_t id = compatIter->second; | 
 | 320 |         auto it = requested.metadata.mMap.find(id); | 
 | 321 |         if (it == std::end(requested.metadata.mMap)) { | 
 | 322 |             continue; | 
 | 323 |         } | 
 | 324 |  | 
 | 325 |         snapshot.metadata.emplace(key, | 
 | 326 |                                   compositionengine::GenericLayerMetadataEntry{mandatory, | 
 | 327 |                                                                                it->second}); | 
 | 328 |     } | 
 | 329 | } | 
 | 330 |  | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 331 | void clearChanges(LayerSnapshot& snapshot) { | 
 | 332 |     snapshot.changes.clear(); | 
 | 333 |     snapshot.contentDirty = false; | 
 | 334 |     snapshot.hasReadyFrame = false; | 
 | 335 |     snapshot.sidebandStreamHasFrame = false; | 
 | 336 |     snapshot.surfaceDamage.clear(); | 
 | 337 | } | 
 | 338 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 339 | } // namespace | 
 | 340 |  | 
 | 341 | LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() { | 
 | 342 |     LayerSnapshot snapshot; | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 343 |     snapshot.path = LayerHierarchy::TraversalPath::ROOT; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 344 |     snapshot.changes = ftl::Flags<RequestedLayerState::Changes>(); | 
 | 345 |     snapshot.isHiddenByPolicyFromParent = false; | 
 | 346 |     snapshot.isHiddenByPolicyFromRelativeParent = false; | 
 | 347 |     snapshot.parentTransform.reset(); | 
 | 348 |     snapshot.geomLayerTransform.reset(); | 
 | 349 |     snapshot.geomInverseLayerTransform.reset(); | 
 | 350 |     snapshot.geomLayerBounds = getMaxDisplayBounds({}); | 
 | 351 |     snapshot.roundedCorner = RoundedCornerState(); | 
 | 352 |     snapshot.stretchEffect = {}; | 
 | 353 |     snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK; | 
 | 354 |     snapshot.outputFilter.toInternalDisplay = false; | 
 | 355 |     snapshot.isSecure = false; | 
 | 356 |     snapshot.color.a = 1.0_hf; | 
 | 357 |     snapshot.colorTransformIsIdentity = true; | 
 | 358 |     snapshot.shadowRadius = 0.f; | 
 | 359 |     snapshot.layerMetadata.mMap.clear(); | 
 | 360 |     snapshot.relativeLayerMetadata.mMap.clear(); | 
 | 361 |     snapshot.inputInfo.touchOcclusionMode = gui::TouchOcclusionMode::BLOCK_UNTRUSTED; | 
 | 362 |     snapshot.dropInputMode = gui::DropInputMode::NONE; | 
 | 363 |     snapshot.isTrustedOverlay = false; | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 364 |     snapshot.gameMode = gui::GameMode::Unsupported; | 
 | 365 |     snapshot.frameRate = {}; | 
 | 366 |     snapshot.fixedTransformHint = ui::Transform::ROT_INVALID; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 367 |     return snapshot; | 
 | 368 | } | 
 | 369 |  | 
 | 370 | LayerSnapshotBuilder::LayerSnapshotBuilder() : mRootSnapshot(getRootSnapshot()) {} | 
 | 371 |  | 
 | 372 | LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() { | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 373 |     args.forceUpdate = ForceUpdateFlags::ALL; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 374 |     updateSnapshots(args); | 
 | 375 | } | 
 | 376 |  | 
 | 377 | bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) { | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 378 |     if (args.forceUpdate != ForceUpdateFlags::NONE || args.displayChanges) { | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 379 |         // force update requested, or we have display changes, so skip the fast path | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 380 |         return false; | 
 | 381 |     } | 
 | 382 |  | 
 | 383 |     if (args.layerLifecycleManager.getGlobalChanges().get() == 0) { | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 384 |         return true; | 
 | 385 |     } | 
 | 386 |  | 
 | 387 |     if (args.layerLifecycleManager.getGlobalChanges() != RequestedLayerState::Changes::Content) { | 
 | 388 |         // We have changes that require us to walk the hierarchy and update child layers. | 
 | 389 |         // No fast path for you. | 
 | 390 |         return false; | 
 | 391 |     } | 
 | 392 |  | 
 | 393 |     // There are only content changes which do not require any child layer snapshots to be updated. | 
 | 394 |     ALOGV("%s", __func__); | 
 | 395 |     ATRACE_NAME("FastPath"); | 
 | 396 |  | 
 | 397 |     // Collect layers with changes | 
 | 398 |     ftl::SmallMap<uint32_t, RequestedLayerState*, 10> layersWithChanges; | 
 | 399 |     for (auto& layer : args.layerLifecycleManager.getLayers()) { | 
 | 400 |         if (layer->changes.test(RequestedLayerState::Changes::Content)) { | 
 | 401 |             layersWithChanges.emplace_or_replace(layer->id, layer.get()); | 
 | 402 |         } | 
 | 403 |     } | 
 | 404 |  | 
 | 405 |     // Walk through the snapshots, clearing previous change flags and updating the snapshots | 
 | 406 |     // if needed. | 
 | 407 |     for (auto& snapshot : mSnapshots) { | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 408 |         auto it = layersWithChanges.find(snapshot->path.id); | 
 | 409 |         if (it != layersWithChanges.end()) { | 
 | 410 |             ALOGV("%s fast path snapshot changes = %s", __func__, | 
 | 411 |                   mRootSnapshot.changes.string().c_str()); | 
 | 412 |             LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT; | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 413 |             updateSnapshot(*snapshot, args, *it->second, mRootSnapshot, root); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 414 |         } | 
 | 415 |     } | 
 | 416 |     return true; | 
 | 417 | } | 
 | 418 |  | 
 | 419 | void LayerSnapshotBuilder::updateSnapshots(const Args& args) { | 
 | 420 |     ATRACE_NAME("UpdateSnapshots"); | 
| Vishnu Nair | 3af0ec0 | 2023-02-10 04:13:48 +0000 | [diff] [blame] | 421 |     if (args.parentCrop) { | 
 | 422 |         mRootSnapshot.geomLayerBounds = *args.parentCrop; | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 423 |     } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) { | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 424 |         mRootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays); | 
 | 425 |     } | 
 | 426 |     if (args.displayChanges) { | 
 | 427 |         mRootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren | | 
 | 428 |                 RequestedLayerState::Changes::Geometry; | 
 | 429 |     } | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 430 |     if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) { | 
 | 431 |         mRootSnapshot.changes |= | 
 | 432 |                 RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility; | 
 | 433 |     } | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 434 |     LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT; | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 435 |     if (args.root.getLayer()) { | 
 | 436 |         // The hierarchy can have a root layer when used for screenshots otherwise, it will have | 
 | 437 |         // multiple children. | 
 | 438 |         LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, args.root.getLayer()->id, | 
 | 439 |                                                                 LayerHierarchy::Variant::Attached); | 
 | 440 |         updateSnapshotsInHierarchy(args, args.root, root, mRootSnapshot); | 
 | 441 |     } else { | 
 | 442 |         for (auto& [childHierarchy, variant] : args.root.mChildren) { | 
 | 443 |             LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, | 
 | 444 |                                                                     childHierarchy->getLayer()->id, | 
 | 445 |                                                                     variant); | 
 | 446 |             updateSnapshotsInHierarchy(args, *childHierarchy, root, mRootSnapshot); | 
 | 447 |         } | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 448 |     } | 
 | 449 |  | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 450 |     // Update touchable region crops outside the main update pass. This is because a layer could be | 
 | 451 |     // cropped by any other layer and it requires both snapshots to be updated. | 
 | 452 |     updateTouchableRegionCrop(args); | 
 | 453 |  | 
| Vishnu Nair | fccd636 | 2023-02-24 23:39:53 +0000 | [diff] [blame] | 454 |     const bool hasUnreachableSnapshots = sortSnapshotsByZ(args); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 455 |     clearChanges(mRootSnapshot); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 456 |  | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 457 |     // Destroy unreachable snapshots for clone layers. And destroy snapshots for non-clone | 
 | 458 |     // layers if the layer have been destroyed. | 
 | 459 |     // TODO(b/238781169) consider making clone layer ids stable as well | 
 | 460 |     if (!hasUnreachableSnapshots && args.layerLifecycleManager.getDestroyedLayers().empty()) { | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 461 |         return; | 
 | 462 |     } | 
 | 463 |  | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 464 |     std::unordered_set<uint32_t> destroyedLayerIds; | 
 | 465 |     for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) { | 
 | 466 |         destroyedLayerIds.insert(destroyedLayer->id); | 
 | 467 |     } | 
 | 468 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 469 |     auto it = mSnapshots.begin(); | 
 | 470 |     while (it < mSnapshots.end()) { | 
 | 471 |         auto& traversalPath = it->get()->path; | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 472 |         if (!it->get()->unreachable && | 
 | 473 |             destroyedLayerIds.find(traversalPath.id) == destroyedLayerIds.end()) { | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 474 |             it++; | 
 | 475 |             continue; | 
 | 476 |         } | 
 | 477 |  | 
 | 478 |         mIdToSnapshot.erase(traversalPath); | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 479 |         mNeedsTouchableRegionCrop.erase(traversalPath); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 480 |         mSnapshots.back()->globalZ = it->get()->globalZ; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 481 |         std::iter_swap(it, mSnapshots.end() - 1); | 
 | 482 |         mSnapshots.erase(mSnapshots.end() - 1); | 
 | 483 |     } | 
 | 484 | } | 
 | 485 |  | 
 | 486 | void LayerSnapshotBuilder::update(const Args& args) { | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 487 |     for (auto& snapshot : mSnapshots) { | 
 | 488 |         clearChanges(*snapshot); | 
 | 489 |     } | 
 | 490 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 491 |     if (tryFastUpdate(args)) { | 
 | 492 |         return; | 
 | 493 |     } | 
 | 494 |     updateSnapshots(args); | 
 | 495 | } | 
 | 496 |  | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 497 | const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy( | 
 | 498 |         const Args& args, const LayerHierarchy& hierarchy, | 
 | 499 |         LayerHierarchy::TraversalPath& traversalPath, const LayerSnapshot& parentSnapshot) { | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 500 |     const RequestedLayerState* layer = hierarchy.getLayer(); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 501 |     LayerSnapshot* snapshot = getSnapshot(traversalPath); | 
 | 502 |     const bool newSnapshot = snapshot == nullptr; | 
 | 503 |     if (newSnapshot) { | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 504 |         snapshot = createSnapshot(traversalPath, *layer, parentSnapshot); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 505 |     } | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 506 |     scheduler::LayerInfo::FrameRate oldFrameRate = snapshot->frameRate; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 507 |     if (traversalPath.isRelative()) { | 
 | 508 |         bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative; | 
 | 509 |         updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args); | 
 | 510 |     } else { | 
 | 511 |         if (traversalPath.isAttached()) { | 
 | 512 |             resetRelativeState(*snapshot); | 
 | 513 |         } | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 514 |         updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 515 |     } | 
 | 516 |  | 
 | 517 |     for (auto& [childHierarchy, variant] : hierarchy.mChildren) { | 
 | 518 |         LayerHierarchy::ScopedAddToTraversalPath addChildToPath(traversalPath, | 
 | 519 |                                                                 childHierarchy->getLayer()->id, | 
 | 520 |                                                                 variant); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 521 |         const LayerSnapshot& childSnapshot = | 
 | 522 |                 updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot); | 
 | 523 |         updateChildState(*snapshot, childSnapshot, args); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 524 |     } | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 525 |  | 
 | 526 |     if (oldFrameRate == snapshot->frameRate) { | 
 | 527 |         snapshot->changes.clear(RequestedLayerState::Changes::FrameRate); | 
 | 528 |     } | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 529 |     return *snapshot; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 530 | } | 
 | 531 |  | 
 | 532 | LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const { | 
 | 533 |     if (layerId == UNASSIGNED_LAYER_ID) { | 
 | 534 |         return nullptr; | 
 | 535 |     } | 
 | 536 |     LayerHierarchy::TraversalPath path{.id = layerId}; | 
 | 537 |     return getSnapshot(path); | 
 | 538 | } | 
 | 539 |  | 
 | 540 | LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const { | 
 | 541 |     auto it = mIdToSnapshot.find(id); | 
 | 542 |     return it == mIdToSnapshot.end() ? nullptr : it->second; | 
 | 543 | } | 
 | 544 |  | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 545 | LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path, | 
 | 546 |                                                     const RequestedLayerState& layer, | 
 | 547 |                                                     const LayerSnapshot& parentSnapshot) { | 
 | 548 |     mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path)); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 549 |     LayerSnapshot* snapshot = mSnapshots.back().get(); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 550 |     snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1; | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 551 |     if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) { | 
 | 552 |         snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath; | 
 | 553 |     } | 
 | 554 |     mIdToSnapshot[path] = snapshot; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 555 |     return snapshot; | 
 | 556 | } | 
 | 557 |  | 
| Vishnu Nair | fccd636 | 2023-02-24 23:39:53 +0000 | [diff] [blame] | 558 | bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) { | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 559 |     if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE && | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 560 |         !args.layerLifecycleManager.getGlobalChanges().any( | 
 | 561 |                 RequestedLayerState::Changes::Hierarchy | | 
 | 562 |                 RequestedLayerState::Changes::Visibility)) { | 
 | 563 |         // We are not force updating and there are no hierarchy or visibility changes. Avoid sorting | 
 | 564 |         // the snapshots. | 
| Vishnu Nair | fccd636 | 2023-02-24 23:39:53 +0000 | [diff] [blame] | 565 |         return false; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 566 |     } | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 567 |     mResortSnapshots = false; | 
 | 568 |  | 
| Vishnu Nair | fccd636 | 2023-02-24 23:39:53 +0000 | [diff] [blame] | 569 |     for (auto& snapshot : mSnapshots) { | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 570 |         snapshot->unreachable = snapshot->path.isClone(); | 
| Vishnu Nair | fccd636 | 2023-02-24 23:39:53 +0000 | [diff] [blame] | 571 |     } | 
 | 572 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 573 |     size_t globalZ = 0; | 
 | 574 |     args.root.traverseInZOrder( | 
 | 575 |             [this, &globalZ](const LayerHierarchy&, | 
 | 576 |                              const LayerHierarchy::TraversalPath& traversalPath) -> bool { | 
 | 577 |                 LayerSnapshot* snapshot = getSnapshot(traversalPath); | 
 | 578 |                 if (!snapshot) { | 
 | 579 |                     return false; | 
 | 580 |                 } | 
 | 581 |  | 
| Vishnu Nair | fccd636 | 2023-02-24 23:39:53 +0000 | [diff] [blame] | 582 |                 snapshot->unreachable = false; | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 583 |                 if (snapshot->getIsVisible() || snapshot->hasInputInfo()) { | 
| Vishnu Nair | 80a5a70 | 2023-02-11 01:21:51 +0000 | [diff] [blame] | 584 |                     updateVisibility(*snapshot, snapshot->getIsVisible()); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 585 |                     size_t oldZ = snapshot->globalZ; | 
 | 586 |                     size_t newZ = globalZ++; | 
 | 587 |                     snapshot->globalZ = newZ; | 
 | 588 |                     if (oldZ == newZ) { | 
 | 589 |                         return true; | 
 | 590 |                     } | 
 | 591 |                     mSnapshots[newZ]->globalZ = oldZ; | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 592 |                     LLOGV(snapshot->sequence, "Made visible z=%zu -> %zu %s", oldZ, newZ, | 
 | 593 |                           snapshot->getDebugString().c_str()); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 594 |                     std::iter_swap(mSnapshots.begin() + static_cast<ssize_t>(oldZ), | 
 | 595 |                                    mSnapshots.begin() + static_cast<ssize_t>(newZ)); | 
 | 596 |                 } | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 597 |                 return true; | 
 | 598 |             }); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 599 |     mNumInterestingSnapshots = (int)globalZ; | 
| Vishnu Nair | fccd636 | 2023-02-24 23:39:53 +0000 | [diff] [blame] | 600 |     bool hasUnreachableSnapshots = false; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 601 |     while (globalZ < mSnapshots.size()) { | 
 | 602 |         mSnapshots[globalZ]->globalZ = globalZ; | 
| Vishnu Nair | 80a5a70 | 2023-02-11 01:21:51 +0000 | [diff] [blame] | 603 |         /* mark unreachable snapshots as explicitly invisible */ | 
 | 604 |         updateVisibility(*mSnapshots[globalZ], false); | 
| Vishnu Nair | fccd636 | 2023-02-24 23:39:53 +0000 | [diff] [blame] | 605 |         if (mSnapshots[globalZ]->unreachable) { | 
 | 606 |             hasUnreachableSnapshots = true; | 
 | 607 |         } | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 608 |         globalZ++; | 
 | 609 |     } | 
| Vishnu Nair | fccd636 | 2023-02-24 23:39:53 +0000 | [diff] [blame] | 610 |     return hasUnreachableSnapshots; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 611 | } | 
 | 612 |  | 
 | 613 | void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot, | 
 | 614 |                                                const LayerSnapshot& parentSnapshot, | 
 | 615 |                                                bool parentIsRelative, const Args& args) { | 
 | 616 |     if (parentIsRelative) { | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 617 |         snapshot.isHiddenByPolicyFromRelativeParent = | 
 | 618 |                 parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 619 |         if (args.includeMetadata) { | 
 | 620 |             snapshot.relativeLayerMetadata = parentSnapshot.layerMetadata; | 
 | 621 |         } | 
 | 622 |     } else { | 
 | 623 |         snapshot.isHiddenByPolicyFromRelativeParent = | 
 | 624 |                 parentSnapshot.isHiddenByPolicyFromRelativeParent; | 
 | 625 |         if (args.includeMetadata) { | 
 | 626 |             snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata; | 
 | 627 |         } | 
 | 628 |     } | 
 | 629 |     snapshot.isVisible = snapshot.getIsVisible(); | 
 | 630 | } | 
 | 631 |  | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 632 | void LayerSnapshotBuilder::updateChildState(LayerSnapshot& snapshot, | 
 | 633 |                                             const LayerSnapshot& childSnapshot, const Args& args) { | 
 | 634 |     if (snapshot.childState.hasValidFrameRate) { | 
 | 635 |         return; | 
 | 636 |     } | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 637 |     if (args.forceUpdate == ForceUpdateFlags::ALL || | 
 | 638 |         childSnapshot.changes.test(RequestedLayerState::Changes::FrameRate)) { | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 639 |         // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes | 
 | 640 |         // for the same reason we are allowing touch boost for those layers. See | 
 | 641 |         // RefreshRateSelector::rankFrameRates for details. | 
 | 642 |         using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility; | 
 | 643 |         const auto layerVotedWithDefaultCompatibility = childSnapshot.frameRate.rate.isValid() && | 
 | 644 |                 childSnapshot.frameRate.type == FrameRateCompatibility::Default; | 
 | 645 |         const auto layerVotedWithNoVote = | 
 | 646 |                 childSnapshot.frameRate.type == FrameRateCompatibility::NoVote; | 
 | 647 |         const auto layerVotedWithExactCompatibility = childSnapshot.frameRate.rate.isValid() && | 
 | 648 |                 childSnapshot.frameRate.type == FrameRateCompatibility::Exact; | 
 | 649 |  | 
 | 650 |         snapshot.childState.hasValidFrameRate |= layerVotedWithDefaultCompatibility || | 
 | 651 |                 layerVotedWithNoVote || layerVotedWithExactCompatibility; | 
 | 652 |  | 
 | 653 |         // If we don't have a valid frame rate, but the children do, we set this | 
 | 654 |         // layer as NoVote to allow the children to control the refresh rate | 
 | 655 |         if (!snapshot.frameRate.rate.isValid() && | 
 | 656 |             snapshot.frameRate.type != FrameRateCompatibility::NoVote && | 
 | 657 |             snapshot.childState.hasValidFrameRate) { | 
 | 658 |             snapshot.frameRate = | 
 | 659 |                     scheduler::LayerInfo::FrameRate(Fps(), FrameRateCompatibility::NoVote); | 
 | 660 |             snapshot.changes |= childSnapshot.changes & RequestedLayerState::Changes::FrameRate; | 
 | 661 |         } | 
 | 662 |     } | 
 | 663 | } | 
 | 664 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 665 | void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) { | 
 | 666 |     snapshot.isHiddenByPolicyFromRelativeParent = false; | 
 | 667 |     snapshot.relativeLayerMetadata.mMap.clear(); | 
 | 668 | } | 
 | 669 |  | 
| Leon Scroggins III | 9550c09 | 2023-05-09 13:58:18 -0400 | [diff] [blame] | 670 | // TODO (b/259407931): Remove. | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 671 | uint32_t getPrimaryDisplayRotationFlags( | 
 | 672 |         const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) { | 
 | 673 |     for (auto& [_, display] : displays) { | 
 | 674 |         if (display.isPrimary) { | 
 | 675 |             return display.rotationFlags; | 
 | 676 |         } | 
 | 677 |     } | 
 | 678 |     return 0; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 679 | } | 
 | 680 |  | 
 | 681 | void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args, | 
 | 682 |                                           const RequestedLayerState& requested, | 
 | 683 |                                           const LayerSnapshot& parentSnapshot, | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 684 |                                           const LayerHierarchy::TraversalPath& path) { | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 685 |     // Always update flags and visibility | 
 | 686 |     ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes & | 
 | 687 |             (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry | | 
 | 688 |              RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata | | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 689 |              RequestedLayerState::Changes::AffectsChildren | | 
 | 690 |              RequestedLayerState::Changes::FrameRate); | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 691 |     snapshot.changes |= parentChanges | requested.changes; | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 692 |     snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent || | 
| Vishnu Nair | 3af0ec0 | 2023-02-10 04:13:48 +0000 | [diff] [blame] | 693 |             parentSnapshot.invalidTransform || requested.isHiddenByPolicy() || | 
 | 694 |             (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end()); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 695 |     snapshot.contentDirty = requested.what & layer_state_t::CONTENT_DIRTY; | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 696 |     // TODO(b/238781169) scope down the changes to only buffer updates. | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 697 |     snapshot.hasReadyFrame = requested.hasReadyFrame(); | 
 | 698 |     snapshot.sidebandStreamHasFrame = requested.hasSidebandStreamFrame(); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 699 |     updateSurfaceDamage(requested, snapshot.hasReadyFrame, args.forceFullDamage, | 
 | 700 |                         snapshot.surfaceDamage); | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 701 |     snapshot.outputFilter.layerStack = parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT | 
 | 702 |             ? requested.layerStack | 
 | 703 |             : parentSnapshot.outputFilter.layerStack; | 
| Vishnu Nair | 80a5a70 | 2023-02-11 01:21:51 +0000 | [diff] [blame] | 704 |  | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 705 |     uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays); | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 706 |     const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL || | 
 | 707 |             snapshot.changes.any(RequestedLayerState::Changes::Visibility | | 
 | 708 |                                  RequestedLayerState::Changes::Created); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 709 |  | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 710 |     // always update the buffer regardless of visibility | 
| Vishnu Nair | 80a5a70 | 2023-02-11 01:21:51 +0000 | [diff] [blame] | 711 |     if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES || args.displayChanges) { | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 712 |         snapshot.acquireFence = | 
 | 713 |                 (requested.externalTexture && | 
 | 714 |                  requested.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged)) | 
 | 715 |                 ? requested.bufferData->acquireFence | 
 | 716 |                 : Fence::NO_FENCE; | 
 | 717 |         snapshot.buffer = | 
 | 718 |                 requested.externalTexture ? requested.externalTexture->getBuffer() : nullptr; | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 719 |         snapshot.bufferSize = requested.getBufferSize(primaryDisplayRotationFlags); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 720 |         snapshot.geomBufferSize = snapshot.bufferSize; | 
 | 721 |         snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize); | 
 | 722 |         snapshot.dataspace = requested.dataspace; | 
 | 723 |         snapshot.externalTexture = requested.externalTexture; | 
 | 724 |         snapshot.frameNumber = (requested.bufferData) ? requested.bufferData->frameNumber : 0; | 
 | 725 |         snapshot.geomBufferTransform = requested.bufferTransform; | 
 | 726 |         snapshot.geomBufferUsesDisplayInverseTransform = requested.transformToDisplayInverse; | 
 | 727 |         snapshot.geomContentCrop = requested.getBufferCrop(); | 
 | 728 |         snapshot.geomUsesSourceCrop = snapshot.hasBufferOrSidebandStream(); | 
 | 729 |         snapshot.hasProtectedContent = requested.externalTexture && | 
 | 730 |                 requested.externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED; | 
 | 731 |         snapshot.isHdrY410 = requested.dataspace == ui::Dataspace::BT2020_ITU_PQ && | 
 | 732 |                 requested.api == NATIVE_WINDOW_API_MEDIA && | 
 | 733 |                 requested.bufferData->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102; | 
 | 734 |         snapshot.sidebandStream = requested.sidebandStream; | 
 | 735 |         snapshot.transparentRegionHint = requested.transparentRegion; | 
 | 736 |         snapshot.color.rgb = requested.getColor().rgb; | 
| Sally Qi | 963049b | 2023-03-23 14:06:21 -0700 | [diff] [blame] | 737 |         snapshot.currentHdrSdrRatio = requested.currentHdrSdrRatio; | 
 | 738 |         snapshot.desiredHdrSdrRatio = requested.desiredHdrSdrRatio; | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 739 |     } | 
 | 740 |  | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 741 |     if (snapshot.isHiddenByPolicyFromParent && | 
 | 742 |         !snapshot.changes.test(RequestedLayerState::Changes::Created)) { | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 743 |         if (forceUpdate || | 
 | 744 |             snapshot.changes.any(RequestedLayerState::Changes::Hierarchy | | 
 | 745 |                                  RequestedLayerState::Changes::Geometry | | 
 | 746 |                                  RequestedLayerState::Changes::Input)) { | 
 | 747 |             updateInput(snapshot, requested, parentSnapshot, path, args); | 
 | 748 |         } | 
 | 749 |         return; | 
 | 750 |     } | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 751 |  | 
 | 752 |     if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) { | 
 | 753 |         // If root layer, use the layer stack otherwise get the parent's layer stack. | 
 | 754 |         snapshot.color.a = parentSnapshot.color.a * requested.color.a; | 
 | 755 |         snapshot.alpha = snapshot.color.a; | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 756 |         snapshot.inputInfo.alpha = snapshot.color.a; | 
 | 757 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 758 |         snapshot.isSecure = | 
 | 759 |                 parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure); | 
 | 760 |         snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 761 |         snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay || | 
 | 762 |                 (requested.flags & layer_state_t::eLayerSkipScreenshot); | 
 | 763 |         snapshot.stretchEffect = (requested.stretchEffect.hasEffect()) | 
 | 764 |                 ? requested.stretchEffect | 
 | 765 |                 : parentSnapshot.stretchEffect; | 
 | 766 |         if (!parentSnapshot.colorTransformIsIdentity) { | 
 | 767 |             snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform; | 
 | 768 |             snapshot.colorTransformIsIdentity = false; | 
 | 769 |         } else { | 
 | 770 |             snapshot.colorTransform = requested.colorTransform; | 
 | 771 |             snapshot.colorTransformIsIdentity = !requested.hasColorTransform; | 
 | 772 |         } | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 773 |         snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE) | 
 | 774 |                 ? requested.gameMode | 
 | 775 |                 : parentSnapshot.gameMode; | 
| Vishnu Nair | a9c4376 | 2023-01-27 19:10:25 +0000 | [diff] [blame] | 776 |         // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers | 
 | 777 |         // marked as skip capture | 
 | 778 |         snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag || | 
 | 779 |                 (requested.layerStackToMirror != ui::INVALID_LAYER_STACK); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 780 |     } | 
 | 781 |  | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 782 |     if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren) || | 
 | 783 |         args.displayChanges) { | 
 | 784 |         snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID | 
 | 785 |                 ? requested.fixedTransformHint | 
 | 786 |                 : parentSnapshot.fixedTransformHint; | 
 | 787 |  | 
 | 788 |         if (snapshot.fixedTransformHint != ui::Transform::ROT_INVALID) { | 
 | 789 |             snapshot.transformHint = snapshot.fixedTransformHint; | 
 | 790 |         } else { | 
 | 791 |             const auto display = args.displays.get(snapshot.outputFilter.layerStack); | 
 | 792 |             snapshot.transformHint = display.has_value() | 
 | 793 |                     ? std::make_optional<>(display->get().transformHint) | 
 | 794 |                     : std::nullopt; | 
 | 795 |         } | 
 | 796 |     } | 
 | 797 |  | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 798 |     if (forceUpdate || | 
 | 799 |         snapshot.changes.any(RequestedLayerState::Changes::FrameRate | | 
 | 800 |                              RequestedLayerState::Changes::Hierarchy)) { | 
 | 801 |         snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() || | 
 | 802 |                               (requested.requestedFrameRate.type == | 
 | 803 |                                scheduler::LayerInfo::FrameRateCompatibility::NoVote)) | 
 | 804 |                 ? requested.requestedFrameRate | 
 | 805 |                 : parentSnapshot.frameRate; | 
 | 806 |     } | 
 | 807 |  | 
| Vishnu Nair | c765c6c | 2023-02-23 00:08:01 +0000 | [diff] [blame] | 808 |     if (forceUpdate || requested.what & layer_state_t::eMetadataChanged) { | 
 | 809 |         updateMetadata(snapshot, requested, args); | 
 | 810 |     } | 
 | 811 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 812 |     if (forceUpdate || requested.changes.get() != 0) { | 
 | 813 |         snapshot.compositionType = requested.getCompositionType(); | 
 | 814 |         snapshot.dimmingEnabled = requested.dimmingEnabled; | 
 | 815 |         snapshot.layerOpaqueFlagSet = | 
 | 816 |                 (requested.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque; | 
| Alec Mouri | f4af03e | 2023-02-11 00:25:24 +0000 | [diff] [blame] | 817 |         snapshot.cachingHint = requested.cachingHint; | 
| Vishnu Nair | ef68d6d | 2023-02-28 06:18:27 +0000 | [diff] [blame] | 818 |         snapshot.frameRateSelectionPriority = requested.frameRateSelectionPriority; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 819 |     } | 
 | 820 |  | 
| Vishnu Nair | 444f395 | 2023-04-11 13:01:02 -0700 | [diff] [blame] | 821 |     if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content) || | 
 | 822 |         snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) { | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 823 |         snapshot.color.rgb = requested.getColor().rgb; | 
 | 824 |         snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic; | 
| Vishnu Nair | 80a5a70 | 2023-02-11 01:21:51 +0000 | [diff] [blame] | 825 |         snapshot.backgroundBlurRadius = args.supportsBlur | 
 | 826 |                 ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius) | 
 | 827 |                 : 0; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 828 |         snapshot.blurRegions = requested.blurRegions; | 
| Vishnu Nair | 80a5a70 | 2023-02-11 01:21:51 +0000 | [diff] [blame] | 829 |         for (auto& region : snapshot.blurRegions) { | 
 | 830 |             region.alpha = region.alpha * snapshot.color.a; | 
 | 831 |         } | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 832 |         snapshot.hdrMetadata = requested.hdrMetadata; | 
 | 833 |     } | 
 | 834 |  | 
 | 835 |     if (forceUpdate || | 
 | 836 |         snapshot.changes.any(RequestedLayerState::Changes::Hierarchy | | 
 | 837 |                              RequestedLayerState::Changes::Geometry)) { | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 838 |         updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 839 |         updateRoundedCorner(snapshot, requested, parentSnapshot); | 
 | 840 |     } | 
 | 841 |  | 
 | 842 |     if (forceUpdate || | 
 | 843 |         snapshot.changes.any(RequestedLayerState::Changes::Hierarchy | | 
 | 844 |                              RequestedLayerState::Changes::Geometry | | 
 | 845 |                              RequestedLayerState::Changes::Input)) { | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 846 |         updateInput(snapshot, requested, parentSnapshot, path, args); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 847 |     } | 
 | 848 |  | 
 | 849 |     // computed snapshot properties | 
 | 850 |     updateShadows(snapshot, requested, args.globalShadowSettings); | 
 | 851 |     if (args.includeMetadata) { | 
 | 852 |         snapshot.layerMetadata = parentSnapshot.layerMetadata; | 
 | 853 |         snapshot.layerMetadata.merge(requested.metadata); | 
 | 854 |     } | 
 | 855 |     snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 || | 
 | 856 |             requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect(); | 
| Vishnu Nair | c765c6c | 2023-02-23 00:08:01 +0000 | [diff] [blame] | 857 |     snapshot.contentOpaque = snapshot.isContentOpaque(); | 
 | 858 |     snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() && | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 859 |             snapshot.color.a == 1.f; | 
 | 860 |     snapshot.blendMode = getBlendMode(snapshot, requested); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 861 |     LLOGV(snapshot.sequence, | 
| Vishnu Nair | 92990e2 | 2023-02-24 20:01:05 +0000 | [diff] [blame] | 862 |           "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s", | 
 | 863 |           args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "", | 
 | 864 |           snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(), | 
 | 865 |           parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(), | 
 | 866 |           std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str()); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 867 | } | 
 | 868 |  | 
 | 869 | void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot, | 
 | 870 |                                                const RequestedLayerState& requested, | 
 | 871 |                                                const LayerSnapshot& parentSnapshot) { | 
 | 872 |     snapshot.roundedCorner = RoundedCornerState(); | 
 | 873 |     RoundedCornerState parentRoundedCorner; | 
 | 874 |     if (parentSnapshot.roundedCorner.hasRoundedCorners()) { | 
 | 875 |         parentRoundedCorner = parentSnapshot.roundedCorner; | 
 | 876 |         ui::Transform t = snapshot.localTransform.inverse(); | 
 | 877 |         parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect); | 
 | 878 |         parentRoundedCorner.radius.x *= t.getScaleX(); | 
 | 879 |         parentRoundedCorner.radius.y *= t.getScaleY(); | 
 | 880 |     } | 
 | 881 |  | 
 | 882 |     FloatRect layerCropRect = snapshot.croppedBufferSize.toFloatRect(); | 
 | 883 |     const vec2 radius(requested.cornerRadius, requested.cornerRadius); | 
 | 884 |     RoundedCornerState layerSettings(layerCropRect, radius); | 
 | 885 |     const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty(); | 
 | 886 |     const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners(); | 
 | 887 |     if (layerSettingsValid && parentRoundedCornerValid) { | 
 | 888 |         // If the parent and the layer have rounded corner settings, use the parent settings if | 
 | 889 |         // the parent crop is entirely inside the layer crop. This has limitations and cause | 
 | 890 |         // rendering artifacts. See b/200300845 for correct fix. | 
 | 891 |         if (parentRoundedCorner.cropRect.left > layerCropRect.left && | 
 | 892 |             parentRoundedCorner.cropRect.top > layerCropRect.top && | 
 | 893 |             parentRoundedCorner.cropRect.right < layerCropRect.right && | 
 | 894 |             parentRoundedCorner.cropRect.bottom < layerCropRect.bottom) { | 
 | 895 |             snapshot.roundedCorner = parentRoundedCorner; | 
 | 896 |         } else { | 
 | 897 |             snapshot.roundedCorner = layerSettings; | 
 | 898 |         } | 
 | 899 |     } else if (layerSettingsValid) { | 
 | 900 |         snapshot.roundedCorner = layerSettings; | 
 | 901 |     } else if (parentRoundedCornerValid) { | 
 | 902 |         snapshot.roundedCorner = parentRoundedCorner; | 
 | 903 |     } | 
 | 904 | } | 
 | 905 |  | 
 | 906 | void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot, | 
 | 907 |                                              const RequestedLayerState& requested, | 
 | 908 |                                              const LayerSnapshot& parentSnapshot, | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 909 |                                              uint32_t primaryDisplayRotationFlags) { | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 910 |     snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize); | 
 | 911 |     snapshot.geomCrop = requested.crop; | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 912 |     snapshot.localTransform = requested.getTransform(primaryDisplayRotationFlags); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 913 |     snapshot.localTransformInverse = snapshot.localTransform.inverse(); | 
 | 914 |     snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform; | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 915 |     const bool transformWasInvalid = snapshot.invalidTransform; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 916 |     snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform); | 
 | 917 |     if (snapshot.invalidTransform) { | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 918 |         auto& t = snapshot.geomLayerTransform; | 
 | 919 |         auto& requestedT = requested.requestedTransform; | 
 | 920 |         std::string transformDebug = | 
 | 921 |                 base::StringPrintf(" transform={%f,%f,%f,%f}  requestedTransform={%f,%f,%f,%f}", | 
 | 922 |                                    t.dsdx(), t.dsdy(), t.dtdx(), t.dtdy(), requestedT.dsdx(), | 
 | 923 |                                    requestedT.dsdy(), requestedT.dtdx(), requestedT.dtdy()); | 
 | 924 |         std::string bufferDebug; | 
 | 925 |         if (requested.externalTexture) { | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 926 |             auto unRotBuffer = requested.getUnrotatedBufferSize(primaryDisplayRotationFlags); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 927 |             auto& destFrame = requested.destinationFrame; | 
 | 928 |             bufferDebug = base::StringPrintf(" buffer={%d,%d}  displayRot=%d" | 
 | 929 |                                              " destFrame={%d,%d,%d,%d} unRotBuffer={%d,%d}", | 
 | 930 |                                              requested.externalTexture->getWidth(), | 
 | 931 |                                              requested.externalTexture->getHeight(), | 
| Vishnu Nair | b76d99a | 2023-03-19 18:22:31 -0700 | [diff] [blame] | 932 |                                              primaryDisplayRotationFlags, destFrame.left, | 
 | 933 |                                              destFrame.top, destFrame.right, destFrame.bottom, | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 934 |                                              unRotBuffer.getHeight(), unRotBuffer.getWidth()); | 
 | 935 |         } | 
 | 936 |         ALOGW("Resetting transform for %s because it is invalid.%s%s", | 
 | 937 |               snapshot.getDebugString().c_str(), transformDebug.c_str(), bufferDebug.c_str()); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 938 |         snapshot.geomLayerTransform.reset(); | 
 | 939 |     } | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 940 |     if (transformWasInvalid != snapshot.invalidTransform) { | 
 | 941 |         // If transform is invalid, the layer will be hidden. | 
 | 942 |         mResortSnapshots = true; | 
 | 943 |     } | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 944 |     snapshot.geomInverseLayerTransform = snapshot.geomLayerTransform.inverse(); | 
 | 945 |  | 
 | 946 |     FloatRect parentBounds = parentSnapshot.geomLayerBounds; | 
 | 947 |     parentBounds = snapshot.localTransform.inverse().transform(parentBounds); | 
 | 948 |     snapshot.geomLayerBounds = | 
 | 949 |             (requested.externalTexture) ? snapshot.bufferSize.toFloatRect() : parentBounds; | 
 | 950 |     if (!requested.crop.isEmpty()) { | 
 | 951 |         snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(requested.crop.toFloatRect()); | 
 | 952 |     } | 
 | 953 |     snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(parentBounds); | 
 | 954 |     snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 955 |     const Rect geomLayerBoundsWithoutTransparentRegion = | 
 | 956 |             RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds), | 
 | 957 |                                         requested.transparentRegion); | 
 | 958 |     snapshot.transformedBoundsWithoutTransparentRegion = | 
 | 959 |             snapshot.geomLayerTransform.transform(geomLayerBoundsWithoutTransparentRegion); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 960 |     snapshot.parentTransform = parentSnapshot.geomLayerTransform; | 
 | 961 |  | 
 | 962 |     // Subtract the transparent region and snap to the bounds | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 963 |     const Rect bounds = | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 964 |             RequestedLayerState::reduce(snapshot.croppedBufferSize, requested.transparentRegion); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 965 |     if (requested.potentialCursor) { | 
 | 966 |         snapshot.cursorFrame = snapshot.geomLayerTransform.transform(bounds); | 
 | 967 |     } | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 968 | } | 
 | 969 |  | 
 | 970 | void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, | 
 | 971 |                                          const RequestedLayerState& requested, | 
 | 972 |                                          const renderengine::ShadowSettings& globalShadowSettings) { | 
 | 973 |     snapshot.shadowRadius = requested.shadowRadius; | 
 | 974 |     snapshot.shadowSettings.length = requested.shadowRadius; | 
 | 975 |     if (snapshot.shadowRadius > 0.f) { | 
 | 976 |         snapshot.shadowSettings = globalShadowSettings; | 
 | 977 |  | 
 | 978 |         // Note: this preserves existing behavior of shadowing the entire layer and not cropping | 
 | 979 |         // it if transparent regions are present. This may not be necessary since shadows are | 
 | 980 |         // typically cast by layers without transparent regions. | 
 | 981 |         snapshot.shadowSettings.boundaries = snapshot.geomLayerBounds; | 
 | 982 |  | 
 | 983 |         // If the casting layer is translucent, we need to fill in the shadow underneath the | 
 | 984 |         // layer. Otherwise the generated shadow will only be shown around the casting layer. | 
 | 985 |         snapshot.shadowSettings.casterIsTranslucent = | 
 | 986 |                 !snapshot.isContentOpaque() || (snapshot.alpha < 1.0f); | 
 | 987 |         snapshot.shadowSettings.ambientColor *= snapshot.alpha; | 
 | 988 |         snapshot.shadowSettings.spotColor *= snapshot.alpha; | 
 | 989 |     } | 
 | 990 | } | 
 | 991 |  | 
 | 992 | void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot, | 
 | 993 |                                        const RequestedLayerState& requested, | 
 | 994 |                                        const LayerSnapshot& parentSnapshot, | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 995 |                                        const LayerHierarchy::TraversalPath& path, | 
 | 996 |                                        const Args& args) { | 
 | 997 |     if (requested.windowInfoHandle) { | 
 | 998 |         snapshot.inputInfo = *requested.windowInfoHandle->getInfo(); | 
 | 999 |     } else { | 
 | 1000 |         snapshot.inputInfo = {}; | 
| Vishnu Nair | 40d0228 | 2023-02-28 21:11:40 +0000 | [diff] [blame] | 1001 |         // b/271132344 revisit this and see if we can always use the layers uid/pid | 
 | 1002 |         snapshot.inputInfo.name = requested.name; | 
 | 1003 |         snapshot.inputInfo.ownerUid = static_cast<int32_t>(requested.ownerUid); | 
 | 1004 |         snapshot.inputInfo.ownerPid = requested.ownerPid; | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 1005 |     } | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 1006 |     snapshot.touchCropId = requested.touchCropId; | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 1007 |  | 
| Vishnu Nair | 93b8b79 | 2023-02-27 19:40:24 +0000 | [diff] [blame] | 1008 |     snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence); | 
| Vishnu Nair | d47bcee | 2023-02-24 18:08:51 +0000 | [diff] [blame] | 1009 |     snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id); | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 1010 |     updateVisibility(snapshot, snapshot.isVisible); | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 1011 |     if (!needsInputInfo(snapshot, requested)) { | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 1012 |         return; | 
 | 1013 |     } | 
 | 1014 |  | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 1015 |     static frontend::DisplayInfo sDefaultInfo = {.isSecure = false}; | 
 | 1016 |     const std::optional<frontend::DisplayInfo> displayInfoOpt = | 
 | 1017 |             args.displays.get(snapshot.outputFilter.layerStack); | 
 | 1018 |     bool noValidDisplay = !displayInfoOpt.has_value(); | 
 | 1019 |     auto displayInfo = displayInfoOpt.value_or(sDefaultInfo); | 
 | 1020 |  | 
 | 1021 |     if (!requested.windowInfoHandle) { | 
 | 1022 |         snapshot.inputInfo.inputConfig = gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL; | 
 | 1023 |     } | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 1024 |     fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot); | 
 | 1025 |  | 
 | 1026 |     if (noValidDisplay) { | 
 | 1027 |         // Do not let the window receive touches if it is not associated with a valid display | 
 | 1028 |         // transform. We still allow the window to receive keys and prevent ANRs. | 
 | 1029 |         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::NOT_TOUCHABLE; | 
 | 1030 |     } | 
 | 1031 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 1032 |     snapshot.inputInfo.alpha = snapshot.color.a; | 
| Vishnu Nair | 40d0228 | 2023-02-28 21:11:40 +0000 | [diff] [blame] | 1033 |     snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo() | 
 | 1034 |             ? requested.windowInfoHandle->getInfo()->touchOcclusionMode | 
 | 1035 |             : parentSnapshot.inputInfo.touchOcclusionMode; | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 1036 |     if (requested.dropInputMode == gui::DropInputMode::ALL || | 
 | 1037 |         parentSnapshot.dropInputMode == gui::DropInputMode::ALL) { | 
 | 1038 |         snapshot.dropInputMode = gui::DropInputMode::ALL; | 
 | 1039 |     } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED || | 
 | 1040 |                parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) { | 
 | 1041 |         snapshot.dropInputMode = gui::DropInputMode::OBSCURED; | 
 | 1042 |     } else { | 
 | 1043 |         snapshot.dropInputMode = gui::DropInputMode::NONE; | 
 | 1044 |     } | 
 | 1045 |  | 
 | 1046 |     handleDropInputMode(snapshot, parentSnapshot); | 
 | 1047 |  | 
 | 1048 |     // If the window will be blacked out on a display because the display does not have the secure | 
 | 1049 |     // flag and the layer has the secure flag set, then drop input. | 
 | 1050 |     if (!displayInfo.isSecure && snapshot.isSecure) { | 
 | 1051 |         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT; | 
 | 1052 |     } | 
 | 1053 |  | 
 | 1054 |     auto cropLayerSnapshot = getSnapshot(requested.touchCropId); | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 1055 |     if (cropLayerSnapshot) { | 
 | 1056 |         mNeedsTouchableRegionCrop.insert(path); | 
 | 1057 |     } else if (snapshot.inputInfo.replaceTouchableRegionWithCrop) { | 
 | 1058 |         FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first; | 
| Vishnu Nair | fed7c12 | 2023-03-18 01:54:43 +0000 | [diff] [blame] | 1059 |         Rect inputBoundsInDisplaySpace = | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 1060 |                 getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform); | 
 | 1061 |         snapshot.inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 1062 |     } | 
 | 1063 |  | 
 | 1064 |     // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state | 
 | 1065 |     // if it was set by WM for a known system overlay | 
 | 1066 |     if (snapshot.isTrustedOverlay) { | 
 | 1067 |         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::TRUSTED_OVERLAY; | 
 | 1068 |     } | 
 | 1069 |  | 
 | 1070 |     // If the layer is a clone, we need to crop the input region to cloned root to prevent | 
 | 1071 |     // touches from going outside the cloned area. | 
 | 1072 |     if (path.isClone()) { | 
 | 1073 |         snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE; | 
| Vishnu Nair | 444f395 | 2023-04-11 13:01:02 -0700 | [diff] [blame] | 1074 |         // Cloned layers shouldn't handle watch outside since their z order is not determined by | 
 | 1075 |         // WM or the client. | 
 | 1076 |         snapshot.inputInfo.inputConfig.clear(gui::WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH); | 
 | 1077 |  | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 1078 |         mNeedsTouchableRegionCrop.insert(path); | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 1079 |     } | 
 | 1080 | } | 
 | 1081 |  | 
 | 1082 | std::vector<std::unique_ptr<LayerSnapshot>>& LayerSnapshotBuilder::getSnapshots() { | 
 | 1083 |     return mSnapshots; | 
 | 1084 | } | 
 | 1085 |  | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 1086 | void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor) const { | 
 | 1087 |     for (int i = 0; i < mNumInterestingSnapshots; i++) { | 
 | 1088 |         LayerSnapshot& snapshot = *mSnapshots[(size_t)i]; | 
 | 1089 |         if (!snapshot.isVisible) continue; | 
 | 1090 |         visitor(snapshot); | 
 | 1091 |     } | 
 | 1092 | } | 
 | 1093 |  | 
| Vishnu Nair | 3af0ec0 | 2023-02-10 04:13:48 +0000 | [diff] [blame] | 1094 | // Visit each visible snapshot in z-order | 
 | 1095 | void LayerSnapshotBuilder::forEachVisibleSnapshot(const ConstVisitor& visitor, | 
 | 1096 |                                                   const LayerHierarchy& root) const { | 
 | 1097 |     root.traverseInZOrder( | 
 | 1098 |             [this, visitor](const LayerHierarchy&, | 
 | 1099 |                             const LayerHierarchy::TraversalPath& traversalPath) -> bool { | 
 | 1100 |                 LayerSnapshot* snapshot = getSnapshot(traversalPath); | 
 | 1101 |                 if (snapshot && snapshot->isVisible) { | 
 | 1102 |                     visitor(*snapshot); | 
 | 1103 |                 } | 
 | 1104 |                 return true; | 
 | 1105 |             }); | 
 | 1106 | } | 
 | 1107 |  | 
| Vishnu Nair | cfb2d25 | 2023-01-19 04:44:02 +0000 | [diff] [blame] | 1108 | void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) { | 
 | 1109 |     for (int i = 0; i < mNumInterestingSnapshots; i++) { | 
 | 1110 |         std::unique_ptr<LayerSnapshot>& snapshot = mSnapshots.at((size_t)i); | 
 | 1111 |         if (!snapshot->isVisible) continue; | 
 | 1112 |         visitor(snapshot); | 
 | 1113 |     } | 
 | 1114 | } | 
 | 1115 |  | 
 | 1116 | void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const { | 
 | 1117 |     for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) { | 
 | 1118 |         LayerSnapshot& snapshot = *mSnapshots[(size_t)i]; | 
 | 1119 |         if (!snapshot.hasInputInfo()) continue; | 
 | 1120 |         visitor(snapshot); | 
 | 1121 |     } | 
 | 1122 | } | 
 | 1123 |  | 
| Vishnu Nair | 29354ec | 2023-03-28 18:51:28 -0700 | [diff] [blame] | 1124 | void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) { | 
 | 1125 |     if (mNeedsTouchableRegionCrop.empty()) { | 
 | 1126 |         return; | 
 | 1127 |     } | 
 | 1128 |  | 
 | 1129 |     static constexpr ftl::Flags<RequestedLayerState::Changes> AFFECTS_INPUT = | 
 | 1130 |             RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Created | | 
 | 1131 |             RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry | | 
 | 1132 |             RequestedLayerState::Changes::Input; | 
 | 1133 |  | 
 | 1134 |     if (args.forceUpdate != ForceUpdateFlags::ALL && | 
 | 1135 |         !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT)) { | 
 | 1136 |         return; | 
 | 1137 |     } | 
 | 1138 |  | 
 | 1139 |     for (auto& path : mNeedsTouchableRegionCrop) { | 
 | 1140 |         frontend::LayerSnapshot* snapshot = getSnapshot(path); | 
 | 1141 |         if (!snapshot) { | 
 | 1142 |             continue; | 
 | 1143 |         } | 
 | 1144 |         const std::optional<frontend::DisplayInfo> displayInfoOpt = | 
 | 1145 |                 args.displays.get(snapshot->outputFilter.layerStack); | 
 | 1146 |         static frontend::DisplayInfo sDefaultInfo = {.isSecure = false}; | 
 | 1147 |         auto displayInfo = displayInfoOpt.value_or(sDefaultInfo); | 
 | 1148 |  | 
 | 1149 |         bool needsUpdate = | 
 | 1150 |                 args.forceUpdate == ForceUpdateFlags::ALL || snapshot->changes.any(AFFECTS_INPUT); | 
 | 1151 |         auto cropLayerSnapshot = getSnapshot(snapshot->touchCropId); | 
 | 1152 |         needsUpdate = | 
 | 1153 |                 needsUpdate || (cropLayerSnapshot && cropLayerSnapshot->changes.any(AFFECTS_INPUT)); | 
 | 1154 |         auto clonedRootSnapshot = path.isClone() ? getSnapshot(snapshot->mirrorRootPath) : nullptr; | 
 | 1155 |         needsUpdate = needsUpdate || | 
 | 1156 |                 (clonedRootSnapshot && clonedRootSnapshot->changes.any(AFFECTS_INPUT)); | 
 | 1157 |  | 
 | 1158 |         if (!needsUpdate) { | 
 | 1159 |             continue; | 
 | 1160 |         } | 
 | 1161 |  | 
 | 1162 |         if (snapshot->inputInfo.replaceTouchableRegionWithCrop) { | 
 | 1163 |             Rect inputBoundsInDisplaySpace; | 
 | 1164 |             if (!cropLayerSnapshot) { | 
 | 1165 |                 FloatRect inputBounds = getInputBounds(*snapshot, /*fillParentBounds=*/true).first; | 
 | 1166 |                 inputBoundsInDisplaySpace = | 
 | 1167 |                         getInputBoundsInDisplaySpace(*snapshot, inputBounds, displayInfo.transform); | 
 | 1168 |             } else { | 
 | 1169 |                 FloatRect inputBounds = | 
 | 1170 |                         getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first; | 
 | 1171 |                 inputBoundsInDisplaySpace = | 
 | 1172 |                         getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds, | 
 | 1173 |                                                      displayInfo.transform); | 
 | 1174 |             } | 
 | 1175 |             snapshot->inputInfo.touchableRegion = Region(inputBoundsInDisplaySpace); | 
 | 1176 |         } else if (cropLayerSnapshot) { | 
 | 1177 |             FloatRect inputBounds = | 
 | 1178 |                     getInputBounds(*cropLayerSnapshot, /*fillParentBounds=*/true).first; | 
 | 1179 |             Rect inputBoundsInDisplaySpace = | 
 | 1180 |                     getInputBoundsInDisplaySpace(*cropLayerSnapshot, inputBounds, | 
 | 1181 |                                                  displayInfo.transform); | 
 | 1182 |             snapshot->inputInfo.touchableRegion = snapshot->inputInfo.touchableRegion.intersect( | 
 | 1183 |                     displayInfo.transform.transform(inputBoundsInDisplaySpace)); | 
 | 1184 |         } | 
 | 1185 |  | 
 | 1186 |         // If the layer is a clone, we need to crop the input region to cloned root to prevent | 
 | 1187 |         // touches from going outside the cloned area. | 
 | 1188 |         if (clonedRootSnapshot) { | 
 | 1189 |             const Rect rect = | 
 | 1190 |                     displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds}); | 
 | 1191 |             snapshot->inputInfo.touchableRegion = | 
 | 1192 |                     snapshot->inputInfo.touchableRegion.intersect(rect); | 
 | 1193 |         } | 
 | 1194 |     } | 
 | 1195 | } | 
 | 1196 |  | 
| Vishnu Nair | 8fc721b | 2022-12-22 20:06:32 +0000 | [diff] [blame] | 1197 | } // namespace android::surfaceflinger::frontend |