diff options
| author | 2023-06-03 13:44:46 -0700 | |
|---|---|---|
| committer | 2023-06-23 20:16:33 +0000 | |
| commit | a02943f3b11e5915e1eca651c01e60ebd7afd8a6 (patch) | |
| tree | 47ff5733f1b4575d53ab512e7d038da77461341c | |
| parent | e371d683a1f39c34c3339d323937e4810d24d2d4 (diff) | |
[sf] optimize snapshot updates
Modify the snapshot update logic so its easier to maintain. Instead of
walking the tree and updating all the snapshots, this cl introduces a
preliminary step of walking though all the requested changes and
updating the affected snapshots by merging the changes to the snapshot.
This is followed by walking down the tree and updating properties that
are dependent on the parent snapshots.
If the changes are confined to buffer updates, then the fast path avoids
walking down the tree.
Bug: 238781169
Test: presubmit
Change-Id: Ic9aa66c376bf7ea80e38b321dd08b8d0f69559a9
15 files changed, 471 insertions, 198 deletions
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index a6f503ef55..62e5f89d21 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -270,9 +270,9 @@ struct layer_state_t { layer_state_t::eFrameRateChanged | layer_state_t::eFixedTransformHintChanged; // Changes affecting data sent to input. - static constexpr uint64_t INPUT_CHANGES = layer_state_t::GEOMETRY_CHANGES | - layer_state_t::HIERARCHY_CHANGES | layer_state_t::eInputInfoChanged | - layer_state_t::eDropInputModeChanged | layer_state_t::eTrustedOverlayChanged; + static constexpr uint64_t INPUT_CHANGES = layer_state_t::eInputInfoChanged | + layer_state_t::eDropInputModeChanged | layer_state_t::eTrustedOverlayChanged | + layer_state_t::eLayerStackChanged; // Changes that affect the visible region on a display. static constexpr uint64_t VISIBLE_REGION_CHANGES = diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp index 5913d4b589..163d34575c 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp @@ -16,7 +16,7 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #undef LOG_TAG -#define LOG_TAG "LayerHierarchy" +#define LOG_TAG "SurfaceFlinger" #include "LayerHierarchy.h" #include "LayerLog.h" diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h index b25b731356..5389adab6a 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h @@ -42,10 +42,10 @@ class LayerHierarchyBuilder; class LayerHierarchy { public: enum Variant : uint32_t { - Attached, - Detached, - Relative, - Mirror, + Attached, // child of the parent + Detached, // child of the parent but currently relative parented to another layer + Relative, // relative child of the parent + Mirror, // mirrored from another layer ftl_first = Attached, ftl_last = Mirror, }; diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp index c9eb9c475c..1712137a7e 100644 --- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp +++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp @@ -17,7 +17,7 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #undef LOG_TAG -#define LOG_TAG "LayerLifecycleManager" +#define LOG_TAG "SurfaceFlinger" #include "LayerLifecycleManager.h" #include "Client.h" // temporarily needed for LayerCreationArgs @@ -51,6 +51,7 @@ void LayerLifecycleManager::addLayers(std::vector<std::unique_ptr<RequestedLayer it->second.owner.getDebugString().c_str()); } mAddedLayers.push_back(newLayer.get()); + mChangedLayers.push_back(newLayer.get()); layer.parentId = linkLayer(layer.parentId, layer.id); layer.relativeParentId = linkLayer(layer.relativeParentId, layer.id); if (layer.layerStackToMirror != ui::INVALID_LAYER_STACK) { @@ -202,6 +203,10 @@ void LayerLifecycleManager::applyTransactions(const std::vector<TransactionState continue; } + if (layer->changes.get() == 0) { + mChangedLayers.push_back(layer); + } + if (transaction.flags & ISurfaceComposer::eAnimation) { layer->changes |= RequestedLayerState::Changes::Animation; } @@ -244,6 +249,7 @@ void LayerLifecycleManager::applyTransactions(const std::vector<TransactionState bgColorLayer->what |= layer_state_t::eColorChanged | layer_state_t::eDataspaceChanged | layer_state_t::eAlphaChanged; bgColorLayer->changes |= RequestedLayerState::Changes::Content; + mChangedLayers.push_back(bgColorLayer); mGlobalChanges |= RequestedLayerState::Changes::Content; } } @@ -290,6 +296,7 @@ void LayerLifecycleManager::commitChanges() { } } mDestroyedLayers.clear(); + mChangedLayers.clear(); mGlobalChanges.clear(); } @@ -310,10 +317,25 @@ const std::vector<std::unique_ptr<RequestedLayerState>>& LayerLifecycleManager:: return mDestroyedLayers; } +const std::vector<RequestedLayerState*>& LayerLifecycleManager::getChangedLayers() const { + return mChangedLayers; +} + const ftl::Flags<RequestedLayerState::Changes> LayerLifecycleManager::getGlobalChanges() const { return mGlobalChanges; } +const RequestedLayerState* LayerLifecycleManager::getLayerFromId(uint32_t id) const { + if (id == UNASSIGNED_LAYER_ID) { + return nullptr; + } + auto it = mIdToLayer.find(id); + if (it == mIdToLayer.end()) { + return nullptr; + } + return &it->second.owner; +} + RequestedLayerState* LayerLifecycleManager::getLayerFromId(uint32_t id) { if (id == UNASSIGNED_LAYER_ID) { return nullptr; diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h index f0d2c22e5a..48571bf923 100644 --- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h +++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h @@ -76,7 +76,9 @@ public: void removeLifecycleListener(std::shared_ptr<ILifecycleListener>); const std::vector<std::unique_ptr<RequestedLayerState>>& getLayers() const; const std::vector<std::unique_ptr<RequestedLayerState>>& getDestroyedLayers() const; + const std::vector<RequestedLayerState*>& getChangedLayers() const; const ftl::Flags<RequestedLayerState::Changes> getGlobalChanges() const; + const RequestedLayerState* getLayerFromId(uint32_t) const; private: friend class LayerLifecycleManagerTest; @@ -111,6 +113,8 @@ private: // Keeps track of all the layers that were added in order. Changes will be cleared once // committed. std::vector<RequestedLayerState*> mAddedLayers; + // Keeps track of new and layers with states changes since last commit. + std::vector<RequestedLayerState*> mChangedLayers; }; } // namespace android::surfaceflinger::frontend diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index 3caeebec2a..f0826c6db3 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -16,7 +16,7 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #undef LOG_TAG -#define LOG_TAG "LayerSnapshot" +#define LOG_TAG "SurfaceFlinger" #include "LayerSnapshot.h" @@ -24,6 +24,23 @@ namespace android::surfaceflinger::frontend { using namespace ftl::flag_operators; +namespace { + +void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFrame, + bool forceFullDamage, Region& outSurfaceDamageRegion) { + if (!hasReadyFrame) { + outSurfaceDamageRegion.clear(); + return; + } + if (forceFullDamage) { + outSurfaceDamageRegion = Region::INVALID_REGION; + } else { + outSurfaceDamageRegion = requested.surfaceDamageRegion; + } +} + +} // namespace + LayerSnapshot::LayerSnapshot(const RequestedLayerState& state, const LayerHierarchy::TraversalPath& path) : path(path) { @@ -51,9 +68,11 @@ LayerSnapshot::LayerSnapshot(const RequestedLayerState& state, uid = state.ownerUid; pid = state.ownerPid; changes = RequestedLayerState::Changes::Created; + clientChanges = 0; mirrorRootPath = path.variant == LayerHierarchy::Variant::Mirror ? path : LayerHierarchy::TraversalPath::ROOT; + reachablilty = LayerSnapshot::Reachablilty::Unreachable; } // As documented in libhardware header, formats in the range @@ -131,6 +150,10 @@ bool LayerSnapshot::isHiddenByPolicy() const { } bool LayerSnapshot::getIsVisible() const { + if (reachablilty != LayerSnapshot::Reachablilty::Reachable) { + return false; + } + if (handleSkipScreenshotFlag & outputFilter.toInternalDisplay) { return false; } @@ -148,12 +171,16 @@ bool LayerSnapshot::getIsVisible() const { std::string LayerSnapshot::getIsVisibleReason() const { // not visible - if (handleSkipScreenshotFlag & outputFilter.toInternalDisplay) return "eLayerSkipScreenshot"; - if (!hasSomethingToDraw()) return "!hasSomethingToDraw"; - if (invalidTransform) return "invalidTransform"; + if (reachablilty == LayerSnapshot::Reachablilty::Unreachable) + return "layer not reachable from root"; + if (reachablilty == LayerSnapshot::Reachablilty::ReachableByRelativeParent) + return "layer only reachable via relative parent"; if (isHiddenByPolicyFromParent) return "hidden by parent or layer flag"; if (isHiddenByPolicyFromRelativeParent) return "hidden by relative parent"; + if (handleSkipScreenshotFlag & outputFilter.toInternalDisplay) return "eLayerSkipScreenshot"; + if (invalidTransform) return "invalidTransform"; if (color.a == 0.0f && !hasBlur()) return "alpha = 0 and no blur"; + if (!hasSomethingToDraw()) return "!hasSomethingToDraw"; // visible std::stringstream reason; @@ -177,8 +204,9 @@ bool LayerSnapshot::isTransformValid(const ui::Transform& t) { } bool LayerSnapshot::hasInputInfo() const { - return inputInfo.token != nullptr || - inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL); + return (inputInfo.token != nullptr || + inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) && + reachablilty == Reachablilty::Reachable; } std::string LayerSnapshot::getDebugString() const { @@ -191,8 +219,16 @@ std::string LayerSnapshot::getDebugString() const { << " geomLayerTransform={tx=" << geomLayerTransform.tx() << ",ty=" << geomLayerTransform.ty() << "}" << "}"; - debug << " input{ touchCropId=" << touchCropId - << " replaceTouchableRegionWithCrop=" << inputInfo.replaceTouchableRegionWithCrop << "}"; + if (hasInputInfo()) { + debug << " input{" + << "(" << inputInfo.inputConfig.string() << ")"; + if (touchCropId != UNASSIGNED_LAYER_ID) debug << " touchCropId=" << touchCropId; + if (inputInfo.replaceTouchableRegionWithCrop) debug << " replaceTouchableRegionWithCrop"; + auto touchableRegion = inputInfo.touchableRegion.getBounds(); + debug << " touchableRegion={" << touchableRegion.left << "," << touchableRegion.top << "," + << touchableRegion.bottom << "," << touchableRegion.right << "}" + << "}"; + } return debug.str(); } @@ -203,4 +239,172 @@ FloatRect LayerSnapshot::sourceBounds() const { return geomBufferSize.toFloatRect(); } +Hwc2::IComposerClient::BlendMode LayerSnapshot::getBlendMode( + const RequestedLayerState& requested) const { + auto blendMode = Hwc2::IComposerClient::BlendMode::NONE; + if (alpha != 1.0f || !contentOpaque) { + blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED + : Hwc2::IComposerClient::BlendMode::COVERAGE; + } + return blendMode; +} + +void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate, + bool displayChanges, bool forceFullDamage, + uint32_t displayRotationFlags) { + clientChanges = requested.what; + changes = requested.changes; + contentDirty = requested.what & layer_state_t::CONTENT_DIRTY; + // TODO(b/238781169) scope down the changes to only buffer updates. + hasReadyFrame = requested.hasReadyFrame(); + sidebandStreamHasFrame = requested.hasSidebandStreamFrame(); + updateSurfaceDamage(requested, hasReadyFrame, forceFullDamage, surfaceDamage); + + if (forceUpdate || requested.what & layer_state_t::eTransparentRegionChanged) { + transparentRegionHint = requested.transparentRegion; + } + if (forceUpdate || requested.what & layer_state_t::eFlagsChanged) { + layerOpaqueFlagSet = + (requested.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque; + } + if (forceUpdate || requested.what & layer_state_t::eBufferTransformChanged) { + geomBufferTransform = requested.bufferTransform; + } + if (forceUpdate || requested.what & layer_state_t::eTransformToDisplayInverseChanged) { + geomBufferUsesDisplayInverseTransform = requested.transformToDisplayInverse; + } + if (forceUpdate || requested.what & layer_state_t::eDataspaceChanged) { + dataspace = requested.dataspace; + } + if (forceUpdate || requested.what & layer_state_t::eExtendedRangeBrightnessChanged) { + currentHdrSdrRatio = requested.currentHdrSdrRatio; + desiredHdrSdrRatio = requested.desiredHdrSdrRatio; + } + if (forceUpdate || requested.what & layer_state_t::eCachingHintChanged) { + cachingHint = requested.cachingHint; + } + if (forceUpdate || requested.what & layer_state_t::eHdrMetadataChanged) { + hdrMetadata = requested.hdrMetadata; + } + if (forceUpdate || requested.what & layer_state_t::eSidebandStreamChanged) { + sidebandStream = requested.sidebandStream; + } + if (forceUpdate || requested.what & layer_state_t::eShadowRadiusChanged) { + shadowRadius = requested.shadowRadius; + shadowSettings.length = requested.shadowRadius; + } + if (forceUpdate || requested.what & layer_state_t::eFrameRateSelectionPriority) { + frameRateSelectionPriority = requested.frameRateSelectionPriority; + } + if (forceUpdate || requested.what & layer_state_t::eColorSpaceAgnosticChanged) { + isColorspaceAgnostic = requested.colorSpaceAgnostic; + } + if (forceUpdate || requested.what & layer_state_t::eDimmingEnabledChanged) { + dimmingEnabled = requested.dimmingEnabled; + } + if (forceUpdate || requested.what & layer_state_t::eCropChanged) { + geomCrop = requested.crop; + } + + if (forceUpdate || + requested.what & + (layer_state_t::eFlagsChanged | layer_state_t::eBufferChanged | + layer_state_t::eSidebandStreamChanged)) { + compositionType = requested.getCompositionType(); + } + + if (forceUpdate || requested.what & layer_state_t::eInputInfoChanged) { + if (requested.windowInfoHandle) { + inputInfo = *requested.windowInfoHandle->getInfo(); + } else { + inputInfo = {}; + // b/271132344 revisit this and see if we can always use the layers uid/pid + inputInfo.name = requested.name; + inputInfo.ownerUid = requested.ownerUid; + inputInfo.ownerPid = requested.ownerPid; + } + inputInfo.id = static_cast<int32_t>(uniqueSequence); + touchCropId = requested.touchCropId; + } + + if (forceUpdate || + requested.what & + (layer_state_t::eColorChanged | layer_state_t::eBufferChanged | + layer_state_t::eSidebandStreamChanged)) { + color.rgb = requested.getColor().rgb; + } + + if (forceUpdate || requested.what & layer_state_t::eBufferChanged) { + acquireFence = + (requested.externalTexture && + requested.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged)) + ? requested.bufferData->acquireFence + : Fence::NO_FENCE; + buffer = requested.externalTexture ? requested.externalTexture->getBuffer() : nullptr; + externalTexture = requested.externalTexture; + frameNumber = (requested.bufferData) ? requested.bufferData->frameNumber : 0; + hasProtectedContent = requested.externalTexture && + requested.externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED; + geomUsesSourceCrop = hasBufferOrSidebandStream(); + } + + if (forceUpdate || + requested.what & + (layer_state_t::eCropChanged | layer_state_t::eBufferCropChanged | + layer_state_t::eBufferTransformChanged | + layer_state_t::eTransformToDisplayInverseChanged) || + requested.changes.test(RequestedLayerState::Changes::BufferSize) || displayChanges) { + bufferSize = requested.getBufferSize(displayRotationFlags); + geomBufferSize = bufferSize; + croppedBufferSize = requested.getCroppedBufferSize(bufferSize); + geomContentCrop = requested.getBufferCrop(); + } + + if (forceUpdate || + requested.what & + (layer_state_t::eFlagsChanged | layer_state_t::eDestinationFrameChanged | + layer_state_t::ePositionChanged | layer_state_t::eMatrixChanged | + layer_state_t::eBufferTransformChanged | + layer_state_t::eTransformToDisplayInverseChanged) || + requested.changes.test(RequestedLayerState::Changes::BufferSize) || displayChanges) { + localTransform = requested.getTransform(displayRotationFlags); + localTransformInverse = localTransform.inverse(); + } + + if (forceUpdate || requested.what & (layer_state_t::eColorChanged) || + requested.changes.test(RequestedLayerState::Changes::BufferSize)) { + color.rgb = requested.getColor().rgb; + } + + if (forceUpdate || + requested.what & + (layer_state_t::eBufferChanged | layer_state_t::eDataspaceChanged | + layer_state_t::eApiChanged)) { + isHdrY410 = requested.dataspace == ui::Dataspace::BT2020_ITU_PQ && + requested.api == NATIVE_WINDOW_API_MEDIA && + requested.bufferData->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102; + } + + if (forceUpdate || + requested.what & + (layer_state_t::eBufferChanged | layer_state_t::eDataspaceChanged | + layer_state_t::eApiChanged | layer_state_t::eShadowRadiusChanged | + layer_state_t::eBlurRegionsChanged | layer_state_t::eStretchChanged)) { + forceClientComposition = isHdrY410 || shadowSettings.length > 0 || + requested.blurRegions.size() > 0 || stretchEffect.hasEffect(); + } + + if (forceUpdate || + requested.what & + (layer_state_t::eColorChanged | layer_state_t::eShadowRadiusChanged | + layer_state_t::eBlurRegionsChanged | layer_state_t::eBackgroundBlurRadiusChanged | + layer_state_t::eCornerRadiusChanged | layer_state_t::eAlphaChanged | + layer_state_t::eFlagsChanged | layer_state_t::eBufferChanged | + layer_state_t::eSidebandStreamChanged)) { + contentOpaque = isContentOpaque(); + isOpaque = contentOpaque && !roundedCorner.hasRoundedCorners() && color.a == 1.f; + blendMode = getBlendMode(requested); + } +} + } // namespace android::surfaceflinger::frontend diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h index b167d3ea1b..2f45d52162 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h @@ -18,6 +18,7 @@ #include <compositionengine/LayerFECompositionState.h> #include <renderengine/LayerSettings.h> +#include "DisplayHardware/ComposerHal.h" #include "LayerHierarchy.h" #include "RequestedLayerState.h" #include "Scheduler/LayerInfo.h" @@ -57,6 +58,7 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { bool isHiddenByPolicyFromParent = false; bool isHiddenByPolicyFromRelativeParent = false; ftl::Flags<RequestedLayerState::Changes> changes; + uint64_t clientChanges = 0; // Some consumers of this snapshot (input, layer traces) rely on each snapshot to be unique. // For mirrored layers, snapshots will have the same sequence so this unique id provides // an alternative identifier when needed. @@ -93,11 +95,37 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { bool handleSkipScreenshotFlag = false; int32_t frameRateSelectionPriority; LayerHierarchy::TraversalPath mirrorRootPath; - bool unreachable = true; uint32_t touchCropId; - uid_t uid; - pid_t pid; + gui::Uid uid = gui::Uid::INVALID; + gui::Pid pid = gui::Pid::INVALID; ChildState childState; + enum class Reachablilty : uint32_t { + // Can traverse the hierarchy from a root node and reach this snapshot + Reachable, + // Cannot traverse the hierarchy from a root node and reach this snapshot + Unreachable, + // Can only reach this node from a relative parent. This means the nodes parents are + // not reachable. + // See example scenario: + // ROOT + // ├── 1 + // │ ├── 11 + // │ │ └── 111 + // │ ├── 12 + // │ │ └ - 111 (relative) + // │ ├── 13 + // │ └── 14 + // │ └ * 12 (mirroring) + // └── 2 + // 111 will create two snapshots, first when visited from 1 -> 12 or 1 -> 11 and the + // second when visited from 1 -> 14 -> 12. Because its parent 11 doesn't exist in the + // mirrored hierarchy, the second snapshot will be marked as ReachableByRelativeParent. + // This snapshot doesn't have any valid properties because it cannot inherit from its + // parent. Therefore, snapshots that are not reachable will be ignored for composition + // and input. + ReachableByRelativeParent + }; + Reachablilty reachablilty; static bool isOpaqueFormat(PixelFormat format); static bool isTransformValid(const ui::Transform& t); @@ -116,6 +144,10 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState { std::string getIsVisibleReason() const; bool hasInputInfo() const; FloatRect sourceBounds() const; + Hwc2::IComposerClient::BlendMode getBlendMode(const RequestedLayerState& requested) const; + + void merge(const RequestedLayerState& requested, bool forceUpdate, bool displayChanges, + bool forceFullDamage, uint32_t displayRotationFlags); }; } // namespace android::surfaceflinger::frontend diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index a266493c38..21f0a672b7 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -17,13 +17,14 @@ // #define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS #undef LOG_TAG -#define LOG_TAG "LayerSnapshotBuilder" +#define LOG_TAG "SurfaceFlinger" #include <numeric> #include <optional> #include <ftl/small_map.h> #include <gui/TraceUtils.h> +#include <ui/DisplayMap.h> #include <ui/FloatRect.h> #include "DisplayHardware/HWC2.h" @@ -257,19 +258,6 @@ auto getBlendMode(const LayerSnapshot& snapshot, const RequestedLayerState& requ return blendMode; } -void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFrame, - bool forceFullDamage, Region& outSurfaceDamageRegion) { - if (!hasReadyFrame) { - outSurfaceDamageRegion.clear(); - return; - } - if (forceFullDamage) { - outSurfaceDamageRegion = Region::INVALID_REGION; - } else { - outSurfaceDamageRegion = requested.surfaceDamageRegion; - } -} - void updateVisibility(LayerSnapshot& snapshot, bool visible) { snapshot.isVisible = visible; @@ -287,6 +275,8 @@ void updateVisibility(LayerSnapshot& snapshot, bool visible) { const bool visibleForInput = snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible; snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput); + LLOGV(snapshot.sequence, "updating visibility %s %s", visible ? "true" : "false", + snapshot.getDebugString().c_str()); } bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) { @@ -329,18 +319,31 @@ void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requeste void clearChanges(LayerSnapshot& snapshot) { snapshot.changes.clear(); + snapshot.clientChanges = 0; snapshot.contentDirty = false; snapshot.hasReadyFrame = false; snapshot.sidebandStreamHasFrame = false; snapshot.surfaceDamage.clear(); } +// TODO (b/259407931): Remove. +uint32_t getPrimaryDisplayRotationFlags( + const ui::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) { + for (auto& [_, display] : displays) { + if (display.isPrimary) { + return display.rotationFlags; + } + } + return 0; +} + } // namespace LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() { LayerSnapshot snapshot; snapshot.path = LayerHierarchy::TraversalPath::ROOT; snapshot.changes = ftl::Flags<RequestedLayerState::Changes>(); + snapshot.clientChanges = 0; snapshot.isHiddenByPolicyFromParent = false; snapshot.isHiddenByPolicyFromRelativeParent = false; snapshot.parentTransform.reset(); @@ -374,44 +377,45 @@ LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() { } bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) { - if (args.forceUpdate != ForceUpdateFlags::NONE || args.displayChanges) { - // force update requested, or we have display changes, so skip the fast path - return false; - } + const bool forceUpdate = args.forceUpdate != ForceUpdateFlags::NONE; - if (args.layerLifecycleManager.getGlobalChanges().get() == 0) { + if (args.layerLifecycleManager.getGlobalChanges().get() == 0 && !forceUpdate && + !args.displayChanges) { return true; } - if (args.layerLifecycleManager.getGlobalChanges() != RequestedLayerState::Changes::Content) { - // We have changes that require us to walk the hierarchy and update child layers. - // No fast path for you. - return false; - } - // There are only content changes which do not require any child layer snapshots to be updated. ALOGV("%s", __func__); ATRACE_NAME("FastPath"); - // Collect layers with changes - ftl::SmallMap<uint32_t, RequestedLayerState*, 10> layersWithChanges; - for (auto& layer : args.layerLifecycleManager.getLayers()) { - if (layer->changes.test(RequestedLayerState::Changes::Content)) { - layersWithChanges.emplace_or_replace(layer->id, layer.get()); + uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays); + if (forceUpdate || args.displayChanges) { + for (auto& snapshot : mSnapshots) { + const RequestedLayerState* requested = + args.layerLifecycleManager.getLayerFromId(snapshot->path.id); + if (!requested) continue; + snapshot->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage, + primaryDisplayRotationFlags); } + return false; } - // Walk through the snapshots, clearing previous change flags and updating the snapshots - // if needed. - for (auto& snapshot : mSnapshots) { - auto it = layersWithChanges.find(snapshot->path.id); - if (it != layersWithChanges.end()) { - ALOGV("%s fast path snapshot changes = %s", __func__, - mRootSnapshot.changes.string().c_str()); - LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT; - updateSnapshot(*snapshot, args, *it->second, mRootSnapshot, root); + // Walk through all the updated requested layer states and update the corresponding snapshots. + for (const RequestedLayerState* requested : args.layerLifecycleManager.getChangedLayers()) { + auto range = mIdToSnapshots.equal_range(requested->id); + for (auto it = range.first; it != range.second; it++) { + it->second->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage, + primaryDisplayRotationFlags); } } + + if ((args.layerLifecycleManager.getGlobalChanges().get() & + ~(RequestedLayerState::Changes::Content | RequestedLayerState::Changes::Buffer).get()) != + 0) { + // We have changes that require us to walk the hierarchy and update child layers. + // No fast path for you. + return false; + } return true; } @@ -429,7 +433,15 @@ void LayerSnapshotBuilder::updateSnapshots(const Args& args) { if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) { mRootSnapshot.changes |= RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility; + mRootSnapshot.clientChanges |= layer_state_t::eReparent; } + + for (auto& snapshot : mSnapshots) { + if (snapshot->reachablilty == LayerSnapshot::Reachablilty::Reachable) { + snapshot->reachablilty = LayerSnapshot::Reachablilty::Unreachable; + } + } + LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT; if (args.root.getLayer()) { // The hierarchy can have a root layer when used for screenshots otherwise, it will have @@ -468,13 +480,26 @@ void LayerSnapshotBuilder::updateSnapshots(const Args& args) { auto it = mSnapshots.begin(); while (it < mSnapshots.end()) { auto& traversalPath = it->get()->path; - if (!it->get()->unreachable && - destroyedLayerIds.find(traversalPath.id) == destroyedLayerIds.end()) { + const bool unreachable = + it->get()->reachablilty == LayerSnapshot::Reachablilty::Unreachable; + const bool isClone = traversalPath.isClone(); + const bool layerIsDestroyed = + destroyedLayerIds.find(traversalPath.id) != destroyedLayerIds.end(); + const bool destroySnapshot = (unreachable && isClone) || layerIsDestroyed; + + if (!destroySnapshot) { it++; continue; } - mIdToSnapshot.erase(traversalPath); + mPathToSnapshot.erase(traversalPath); + + auto range = mIdToSnapshots.equal_range(traversalPath.id); + auto matchingSnapshot = + std::find_if(range.first, range.second, [&traversalPath](auto& snapshotWithId) { + return snapshotWithId.second->path == traversalPath; + }); + mIdToSnapshots.erase(matchingSnapshot); mNeedsTouchableRegionCrop.erase(traversalPath); mSnapshots.back()->globalZ = it->get()->globalZ; std::iter_swap(it, mSnapshots.end() - 1); @@ -507,8 +532,12 @@ const LayerSnapshot& LayerSnapshotBuilder::updateSnapshotsInHierarchy( const RequestedLayerState* layer = hierarchy.getLayer(); LayerSnapshot* snapshot = getSnapshot(traversalPath); const bool newSnapshot = snapshot == nullptr; + uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays); if (newSnapshot) { snapshot = createSnapshot(traversalPath, *layer, parentSnapshot); + snapshot->merge(*layer, /*forceUpdate=*/true, /*displayChanges=*/true, args.forceFullDamage, + primaryDisplayRotationFlags); + snapshot->changes |= RequestedLayerState::Changes::Created; } scheduler::LayerInfo::FrameRate oldFrameRate = snapshot->frameRate; if (traversalPath.isRelative()) { @@ -546,8 +575,8 @@ LayerSnapshot* LayerSnapshotBuilder::getSnapshot(uint32_t layerId) const { } LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const { - auto it = mIdToSnapshot.find(id); - return it == mIdToSnapshot.end() ? nullptr : it->second; + auto it = mPathToSnapshot.find(id); + return it == mPathToSnapshot.end() ? nullptr : it->second; } LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path, @@ -559,7 +588,9 @@ LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::Traver if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) { snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath; } - mIdToSnapshot[path] = snapshot; + mPathToSnapshot[path] = snapshot; + + mIdToSnapshots.emplace(path.id, snapshot); return snapshot; } @@ -574,20 +605,15 @@ bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) { } mResortSnapshots = false; - for (auto& snapshot : mSnapshots) { - snapshot->unreachable = snapshot->path.isClone(); - } - size_t globalZ = 0; args.root.traverseInZOrder( [this, &globalZ](const LayerHierarchy&, const LayerHierarchy::TraversalPath& traversalPath) -> bool { LayerSnapshot* snapshot = getSnapshot(traversalPath); if (!snapshot) { - return false; + return true; } - snapshot->unreachable = false; if (snapshot->getIsVisible() || snapshot->hasInputInfo()) { updateVisibility(*snapshot, snapshot->getIsVisible()); size_t oldZ = snapshot->globalZ; @@ -610,7 +636,7 @@ bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) { mSnapshots[globalZ]->globalZ = globalZ; /* mark unreachable snapshots as explicitly invisible */ updateVisibility(*mSnapshots[globalZ], false); - if (mSnapshots[globalZ]->unreachable) { + if (mSnapshots[globalZ]->reachablilty == LayerSnapshot::Reachablilty::Unreachable) { hasUnreachableSnapshots = true; } globalZ++; @@ -634,7 +660,9 @@ void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot, snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata; } } - snapshot.isVisible = snapshot.getIsVisible(); + if (snapshot.reachablilty == LayerSnapshot::Reachablilty::Unreachable) { + snapshot.reachablilty = LayerSnapshot::Reachablilty::ReachableByRelativeParent; + } } void LayerSnapshotBuilder::updateChildState(LayerSnapshot& snapshot, @@ -675,16 +703,6 @@ void LayerSnapshotBuilder::resetRelativeState(LayerSnapshot& snapshot) { snapshot.relativeLayerMetadata.mMap.clear(); } -// TODO (b/259407931): Remove. -uint32_t getPrimaryDisplayRotationFlags(const DisplayInfos& displays) { - for (auto& [_, display] : displays) { - if (display.isPrimary) { - return display.rotationFlags; - } - } - return 0; -} - void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args, const RequestedLayerState& requested, const LayerSnapshot& parentSnapshot, @@ -694,82 +712,69 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a (RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry | RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata | RequestedLayerState::Changes::AffectsChildren | - RequestedLayerState::Changes::FrameRate); - snapshot.changes |= parentChanges | requested.changes; + RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::GameMode); + snapshot.changes |= parentChanges; + if (args.displayChanges) snapshot.changes |= RequestedLayerState::Changes::Geometry; + snapshot.reachablilty = LayerSnapshot::Reachablilty::Reachable; + snapshot.clientChanges |= (parentSnapshot.clientChanges & layer_state_t::AFFECTS_CHILDREN); snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent || parentSnapshot.invalidTransform || requested.isHiddenByPolicy() || (args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end()); - snapshot.contentDirty = requested.what & layer_state_t::CONTENT_DIRTY; - // TODO(b/238781169) scope down the changes to only buffer updates. - snapshot.hasReadyFrame = requested.hasReadyFrame(); - snapshot.sidebandStreamHasFrame = requested.hasSidebandStreamFrame(); - updateSurfaceDamage(requested, snapshot.hasReadyFrame, args.forceFullDamage, - snapshot.surfaceDamage); - snapshot.outputFilter.layerStack = parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT - ? requested.layerStack - : parentSnapshot.outputFilter.layerStack; - uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays); const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL || + snapshot.clientChanges & layer_state_t::eReparent || snapshot.changes.any(RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Created); - // always update the buffer regardless of visibility - if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES || args.displayChanges) { - snapshot.acquireFence = - (requested.externalTexture && - requested.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged)) - ? requested.bufferData->acquireFence - : Fence::NO_FENCE; - snapshot.buffer = - requested.externalTexture ? requested.externalTexture->getBuffer() : nullptr; - snapshot.bufferSize = requested.getBufferSize(primaryDisplayRotationFlags); - snapshot.geomBufferSize = snapshot.bufferSize; - snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize); - snapshot.dataspace = requested.dataspace; - snapshot.externalTexture = requested.externalTexture; - snapshot.frameNumber = (requested.bufferData) ? requested.bufferData->frameNumber : 0; - snapshot.geomBufferTransform = requested.bufferTransform; - snapshot.geomBufferUsesDisplayInverseTransform = requested.transformToDisplayInverse; - snapshot.geomContentCrop = requested.getBufferCrop(); - snapshot.geomUsesSourceCrop = snapshot.hasBufferOrSidebandStream(); - snapshot.hasProtectedContent = requested.externalTexture && - requested.externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED; - snapshot.isHdrY410 = requested.dataspace == ui::Dataspace::BT2020_ITU_PQ && - requested.api == NATIVE_WINDOW_API_MEDIA && - requested.bufferData->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102; - snapshot.sidebandStream = requested.sidebandStream; - snapshot.transparentRegionHint = requested.transparentRegion; - snapshot.color.rgb = requested.getColor().rgb; - snapshot.currentHdrSdrRatio = requested.currentHdrSdrRatio; - snapshot.desiredHdrSdrRatio = requested.desiredHdrSdrRatio; + if (forceUpdate || snapshot.clientChanges & layer_state_t::eLayerStackChanged) { + // If root layer, use the layer stack otherwise get the parent's layer stack. + snapshot.outputFilter.layerStack = + parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT + ? requested.layerStack + : parentSnapshot.outputFilter.layerStack; } if (snapshot.isHiddenByPolicyFromParent && !snapshot.changes.test(RequestedLayerState::Changes::Created)) { if (forceUpdate || - snapshot.changes.any(RequestedLayerState::Changes::Hierarchy | - RequestedLayerState::Changes::Geometry | + snapshot.changes.any(RequestedLayerState::Changes::Geometry | RequestedLayerState::Changes::Input)) { updateInput(snapshot, requested, parentSnapshot, path, args); } return; } - if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) { - // If root layer, use the layer stack otherwise get the parent's layer stack. + if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Mirror)) { + // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers + // marked as skip capture + snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag || + (requested.layerStackToMirror != ui::INVALID_LAYER_STACK); + } + + if (forceUpdate || snapshot.clientChanges & layer_state_t::eAlphaChanged) { snapshot.color.a = parentSnapshot.color.a * requested.color.a; snapshot.alpha = snapshot.color.a; snapshot.inputInfo.alpha = snapshot.color.a; + } + if (forceUpdate || snapshot.clientChanges & layer_state_t::eFlagsChanged) { snapshot.isSecure = parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure); - snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay; snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay || (requested.flags & layer_state_t::eLayerSkipScreenshot); + } + + if (forceUpdate || snapshot.clientChanges & layer_state_t::eTrustedOverlayChanged) { + snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay; + } + + if (forceUpdate || snapshot.clientChanges & layer_state_t::eStretchChanged) { snapshot.stretchEffect = (requested.stretchEffect.hasEffect()) ? requested.stretchEffect : parentSnapshot.stretchEffect; + } + + if (forceUpdate || snapshot.clientChanges & layer_state_t::eColorTransformChanged) { if (!parentSnapshot.colorTransformIsIdentity) { snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform; snapshot.colorTransformIsIdentity = false; @@ -777,16 +782,20 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a snapshot.colorTransform = requested.colorTransform; snapshot.colorTransformIsIdentity = !requested.hasColorTransform; } + } + + if (forceUpdate || snapshot.changes.test(RequestedLayerState::Changes::GameMode)) { snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE) ? requested.gameMode : parentSnapshot.gameMode; - // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers - // marked as skip capture - snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag || - (requested.layerStackToMirror != ui::INVALID_LAYER_STACK); + updateMetadata(snapshot, requested, args); + if (args.includeMetadata) { + snapshot.layerMetadata = parentSnapshot.layerMetadata; + snapshot.layerMetadata.merge(requested.metadata); + } } - if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren) || + if (forceUpdate || snapshot.clientChanges & layer_state_t::eFixedTransformHintChanged || args.displayChanges) { snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID ? requested.fixedTransformHint @@ -802,9 +811,7 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a } } - if (forceUpdate || - snapshot.changes.any(RequestedLayerState::Changes::FrameRate | - RequestedLayerState::Changes::Hierarchy)) { + if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::FrameRate)) { snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() || (requested.requestedFrameRate.type == scheduler::LayerInfo::FrameRateCompatibility::NoVote)) @@ -812,23 +819,10 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a : parentSnapshot.frameRate; } - if (forceUpdate || requested.what & layer_state_t::eMetadataChanged) { - updateMetadata(snapshot, requested, args); - } - - if (forceUpdate || requested.changes.get() != 0) { - snapshot.compositionType = requested.getCompositionType(); - snapshot.dimmingEnabled = requested.dimmingEnabled; - snapshot.layerOpaqueFlagSet = - (requested.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque; - snapshot.cachingHint = requested.cachingHint; - snapshot.frameRateSelectionPriority = requested.frameRateSelectionPriority; - } - - if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content) || - snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) { - snapshot.color.rgb = requested.getColor().rgb; - snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic; + if (forceUpdate || + snapshot.clientChanges & + (layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBlurRegionsChanged | + layer_state_t::eAlphaChanged)) { snapshot.backgroundBlurRadius = args.supportsBlur ? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius) : 0; @@ -836,29 +830,30 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a for (auto& region : snapshot.blurRegions) { region.alpha = region.alpha * snapshot.color.a; } - snapshot.hdrMetadata = requested.hdrMetadata; } - if (forceUpdate || - snapshot.changes.any(RequestedLayerState::Changes::Hierarchy | - RequestedLayerState::Changes::Geometry)) { + if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Geometry)) { + uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays); updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags); + } + + if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged || + snapshot.changes.any(RequestedLayerState::Changes::Geometry)) { updateRoundedCorner(snapshot, requested, parentSnapshot); } + if (forceUpdate || snapshot.clientChanges & layer_state_t::eShadowRadiusChanged || + snapshot.changes.any(RequestedLayerState::Changes::Geometry)) { + updateShadows(snapshot, requested, args.globalShadowSettings); + } + if (forceUpdate || - snapshot.changes.any(RequestedLayerState::Changes::Hierarchy | - RequestedLayerState::Changes::Geometry | + snapshot.changes.any(RequestedLayerState::Changes::Geometry | RequestedLayerState::Changes::Input)) { updateInput(snapshot, requested, parentSnapshot, path, args); } // computed snapshot properties - updateShadows(snapshot, requested, args.globalShadowSettings); - if (args.includeMetadata) { - snapshot.layerMetadata = parentSnapshot.layerMetadata; - snapshot.layerMetadata.merge(requested.metadata); - } snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 || requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect(); snapshot.contentOpaque = snapshot.isContentOpaque(); @@ -914,10 +909,6 @@ void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot, const RequestedLayerState& requested, const LayerSnapshot& parentSnapshot, uint32_t primaryDisplayRotationFlags) { - snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize); - snapshot.geomCrop = requested.crop; - snapshot.localTransform = requested.getTransform(primaryDisplayRotationFlags); - snapshot.localTransformInverse = snapshot.localTransform.inverse(); snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform; const bool transformWasInvalid = snapshot.invalidTransform; snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform); @@ -974,11 +965,8 @@ void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot, } } -void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, - const RequestedLayerState& requested, +void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, const RequestedLayerState&, const renderengine::ShadowSettings& globalShadowSettings) { - snapshot.shadowRadius = requested.shadowRadius; - snapshot.shadowSettings.length = requested.shadowRadius; if (snapshot.shadowRadius > 0.f) { snapshot.shadowSettings = globalShadowSettings; @@ -1058,10 +1046,11 @@ void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot, snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT; } - auto cropLayerSnapshot = getSnapshot(requested.touchCropId); - if (cropLayerSnapshot) { + if (requested.touchCropId != UNASSIGNED_LAYER_ID || path.isClone()) { mNeedsTouchableRegionCrop.insert(path); - } else if (snapshot.inputInfo.replaceTouchableRegionWithCrop) { + } + auto cropLayerSnapshot = getSnapshot(requested.touchCropId); + if (!cropLayerSnapshot && snapshot.inputInfo.replaceTouchableRegionWithCrop) { FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first; Rect inputBoundsInDisplaySpace = getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform); @@ -1081,8 +1070,6 @@ void LayerSnapshotBuilder::updateInput(LayerSnapshot& snapshot, // Cloned layers shouldn't handle watch outside since their z order is not determined by // WM or the client. snapshot.inputInfo.inputConfig.clear(gui::WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH); - - mNeedsTouchableRegionCrop.insert(path); } } @@ -1139,7 +1126,7 @@ void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) { RequestedLayerState::Changes::Input; if (args.forceUpdate != ForceUpdateFlags::ALL && - !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT)) { + !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT) && !args.displayChanges) { return; } @@ -1148,6 +1135,8 @@ void LayerSnapshotBuilder::updateTouchableRegionCrop(const Args& args) { if (!snapshot) { continue; } + LLOGV(snapshot->sequence, "updateTouchableRegionCrop=%s", + snapshot->getDebugString().c_str()); const std::optional<frontend::DisplayInfo> displayInfoOpt = args.displays.get(snapshot->outputFilter.layerStack); static frontend::DisplayInfo sDefaultInfo = {.isSecure = false}; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h index 2e46dc661c..c81a5d2b9e 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h @@ -122,7 +122,9 @@ private: std::unordered_map<LayerHierarchy::TraversalPath, LayerSnapshot*, LayerHierarchy::TraversalPathHash> - mIdToSnapshot; + mPathToSnapshot; + std::multimap<uint32_t, LayerSnapshot*> mIdToSnapshots; + // Track snapshots that needs touchable region crop from other snapshots std::unordered_set<LayerHierarchy::TraversalPath, LayerHierarchy::TraversalPathHash> mNeedsTouchableRegionCrop; diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index bde2d0561a..5738262bf0 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +// #define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS #undef LOG_TAG -#define LOG_TAG "RequestedLayerState" +#define LOG_TAG "SurfaceFlinger" #include <log/log.h> #include <private/android_filesystem_config.h> @@ -132,12 +133,16 @@ void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerSta const half oldAlpha = color.a; const bool hadBuffer = externalTexture != nullptr; uint64_t oldFramenumber = hadBuffer ? bufferData->frameNumber : 0; + const ui::Size oldBufferSize = hadBuffer + ? ui::Size(externalTexture->getWidth(), externalTexture->getHeight()) + : ui::Size(); const bool hadSideStream = sidebandStream != nullptr; const layer_state_t& clientState = resolvedComposerState.state; const bool hadBlur = hasBlur(); uint64_t clientChanges = what | layer_state_t::diff(clientState); layer_state_t::merge(clientState); what = clientChanges; + LLOGV(layerId, "requested=%" PRIu64 "flags=%" PRIu64, clientState.what, clientChanges); if (clientState.what & layer_state_t::eFlagsChanged) { if ((oldFlags ^ flags) & layer_state_t::eLayerHidden) { @@ -154,6 +159,13 @@ void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerSta const bool hasBuffer = externalTexture != nullptr; if (hasBuffer || hasBuffer != hadBuffer) { changes |= RequestedLayerState::Changes::Buffer; + const ui::Size newBufferSize = hasBuffer + ? ui::Size(externalTexture->getWidth(), externalTexture->getHeight()) + : ui::Size(); + if (oldBufferSize != newBufferSize) { + changes |= RequestedLayerState::Changes::BufferSize; + changes |= RequestedLayerState::Changes::Geometry; + } } if (hasBuffer != hadBuffer) { @@ -281,7 +293,7 @@ void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerSta // child layers. if (static_cast<int32_t>(gameMode) != requestedGameMode) { gameMode = static_cast<gui::GameMode>(requestedGameMode); - changes |= RequestedLayerState::Changes::AffectsChildren; + changes |= RequestedLayerState::Changes::GameMode; } } } @@ -372,7 +384,7 @@ bool RequestedLayerState::isHiddenByPolicy() const { return (flags & layer_state_t::eLayerHidden) == layer_state_t::eLayerHidden; }; half4 RequestedLayerState::getColor() const { - if ((sidebandStream != nullptr) || (externalTexture != nullptr)) { + if (sidebandStream || externalTexture) { return {0._hf, 0._hf, 0._hf, color.a}; } return color; diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h index 0ef50bc60a..02e3bac18b 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h @@ -54,6 +54,8 @@ struct RequestedLayerState : layer_state_t { Buffer = 1u << 15, SidebandStream = 1u << 16, Animation = 1u << 17, + BufferSize = 1u << 18, + GameMode = 1u << 19, }; static Rect reduce(const Rect& win, const Region& exclude); RequestedLayerState(const LayerCreationArgs&); @@ -91,10 +93,10 @@ struct RequestedLayerState : layer_state_t { const uint32_t textureName; // The owner of the layer. If created from a non system process, it will be the calling uid. // If created from a system process, the value can be passed in. - const uid_t ownerUid; + const gui::Uid ownerUid; // The owner pid of the layer. If created from a non system process, it will be the calling pid. // If created from a system process, the value can be passed in. - const pid_t ownerPid; + const gui::Pid ownerPid; bool dataspaceRequested; bool hasColorTransform; bool premultipliedAlpha{true}; diff --git a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp index 9cbe0bb224..fa8eb3cf13 100644 --- a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp +++ b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp @@ -16,7 +16,7 @@ // #define LOG_NDEBUG 0 #undef LOG_TAG -#define LOG_TAG "TransactionHandler" +#define LOG_TAG "SurfaceFlinger" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <cutils/trace.h> diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 427a85ced1..1c7581b093 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -428,7 +428,7 @@ void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo, layerInfo->set_is_relative_of(requestedState.isRelativeOf); - layerInfo->set_owner_uid(requestedState.ownerUid); + layerInfo->set_owner_uid(requestedState.ownerUid.val()); if ((traceFlags & LayerTracing::TRACE_INPUT) && snapshot.hasInputInfo()) { LayerProtoHelper::writeToProto(snapshot.inputInfo, {}, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b494529b9f..c364ccb3a4 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2173,6 +2173,7 @@ void SurfaceFlinger::configure() FTL_FAKE_GUARD(kMainThreadContext) { bool SurfaceFlinger::updateLayerSnapshotsLegacy(VsyncId vsyncId, frontend::Update& update, bool transactionsFlushed, bool& outTransactionsAreEmpty) { + ATRACE_CALL(); bool needsTraversal = false; if (transactionsFlushed) { needsTraversal |= commitMirrorDisplays(vsyncId); @@ -2225,7 +2226,7 @@ void SurfaceFlinger::updateLayerHistory(const frontend::LayerSnapshot& snapshot) bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, frontend::Update& update, bool transactionsFlushed, bool& outTransactionsAreEmpty) { using Changes = frontend::RequestedLayerState::Changes; - ATRACE_NAME("updateLayerSnapshots"); + ATRACE_CALL(); { mLayerLifecycleManager.addLayers(std::move(update.newLayers)); mLayerLifecycleManager.applyTransactions(update.transactions); @@ -8165,7 +8166,7 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots( if (layerStack && snapshot->outputFilter.layerStack != *layerStack) { return; } - if (uid != CaptureArgs::UNSET_UID && snapshot->uid != uid) { + if (uid != CaptureArgs::UNSET_UID && snapshot->uid != gui::Uid(uid)) { return; } if (!snapshot->hasSomethingToDraw()) { diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 12cf0709ea..5da893ee62 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -228,6 +228,7 @@ TEST_F(LayerSnapshotTest, AlphaInheritedByChildren) { setAlpha(1, 0.5); setAlpha(122, 0.5); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); + EXPECT_EQ(getSnapshot(1)->alpha, 0.5f); EXPECT_EQ(getSnapshot(12)->alpha, 0.5f); EXPECT_EQ(getSnapshot(1221)->alpha, 0.25f); } @@ -236,28 +237,30 @@ TEST_F(LayerSnapshotTest, AlphaInheritedByChildren) { TEST_F(LayerSnapshotTest, UpdateClearsPreviousChangeStates) { setCrop(1, Rect(1, 2, 3, 4)); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); - EXPECT_TRUE(getSnapshot(1)->changes.get() != 0); - EXPECT_TRUE(getSnapshot(11)->changes.get() != 0); + EXPECT_TRUE(getSnapshot(1)->changes.test(RequestedLayerState::Changes::Geometry)); + EXPECT_TRUE(getSnapshot(11)->changes.test(RequestedLayerState::Changes::Geometry)); setCrop(2, Rect(1, 2, 3, 4)); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); - EXPECT_TRUE(getSnapshot(2)->changes.get() != 0); - EXPECT_TRUE(getSnapshot(1)->changes.get() == 0); - EXPECT_TRUE(getSnapshot(11)->changes.get() == 0); + EXPECT_TRUE(getSnapshot(2)->changes.test(RequestedLayerState::Changes::Geometry)); + EXPECT_FALSE(getSnapshot(1)->changes.test(RequestedLayerState::Changes::Geometry)); + EXPECT_FALSE(getSnapshot(11)->changes.test(RequestedLayerState::Changes::Geometry)); } TEST_F(LayerSnapshotTest, FastPathClearsPreviousChangeStates) { setColor(11, {1._hf, 0._hf, 0._hf}); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); - EXPECT_TRUE(getSnapshot(11)->changes.get() != 0); - EXPECT_TRUE(getSnapshot(1)->changes.get() == 0); + EXPECT_EQ(getSnapshot(11)->changes, RequestedLayerState::Changes::Content); + EXPECT_EQ(getSnapshot(11)->clientChanges, layer_state_t::eColorChanged); + EXPECT_EQ(getSnapshot(1)->changes.get(), 0u); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); - EXPECT_TRUE(getSnapshot(11)->changes.get() == 0); + EXPECT_EQ(getSnapshot(11)->changes.get(), 0u); } TEST_F(LayerSnapshotTest, FastPathSetsChangeFlagToContent) { setColor(1, {1._hf, 0._hf, 0._hf}); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); EXPECT_EQ(getSnapshot(1)->changes, RequestedLayerState::Changes::Content); + EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::eColorChanged); } TEST_F(LayerSnapshotTest, GameMode) { @@ -270,7 +273,9 @@ TEST_F(LayerSnapshotTest, GameMode) { transactions.back().states.front().layerId = 1; transactions.back().states.front().state.layerId = static_cast<int32_t>(1); mLifecycleManager.applyTransactions(transactions); + EXPECT_EQ(mLifecycleManager.getGlobalChanges(), RequestedLayerState::Changes::GameMode); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); + EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::eMetadataChanged); EXPECT_EQ(static_cast<int32_t>(getSnapshot(1)->gameMode), 42); EXPECT_EQ(static_cast<int32_t>(getSnapshot(11)->gameMode), 42); } @@ -309,7 +314,7 @@ TEST_F(LayerSnapshotTest, NoLayerVoteForParentWithChildVotes) { EXPECT_EQ(getSnapshot(1)->frameRate.type, scheduler::LayerInfo::FrameRateCompatibility::NoVote); } -TEST_F(LayerSnapshotTest, canCropTouchableRegion) { +TEST_F(LayerSnapshotTest, CanCropTouchableRegion) { // ROOT // ├── 1 // │ ├── 11 |