diff options
Diffstat (limited to 'services/surfaceflinger/Layer.cpp')
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 1584 |
1 files changed, 831 insertions, 753 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e4a777f3c7..4e3ef2468a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -25,7 +25,6 @@ #include "Layer.h" -#include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android/native_window.h> #include <binder/IPCThreadState.h> @@ -40,7 +39,6 @@ #include <gui/LayerDebugInfo.h> #include <gui/Surface.h> #include <math.h> -#include <private/android_filesystem_config.h> #include <renderengine/RenderEngine.h> #include <stdint.h> #include <stdlib.h> @@ -63,26 +61,18 @@ #include "DisplayDevice.h" #include "DisplayHardware/HWComposer.h" #include "EffectLayer.h" -#include "FrameTimeline.h" #include "FrameTracer/FrameTracer.h" #include "LayerProtoHelper.h" #include "LayerRejecter.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" #include "TimeStats/TimeStats.h" -#include "TunnelModeEnabledReporter.h" -#include "input/InputWindow.h" #define DEBUG_RESIZE 0 namespace android { -namespace { -constexpr int kDumpTableRowLength = 159; -} // namespace using base::StringAppendF; -using namespace android::flag_operators; -using PresentState = frametimeline::SurfaceFrame::PresentState; std::atomic<int32_t> Layer::sSequence{1}; @@ -90,58 +80,56 @@ Layer::Layer(const LayerCreationArgs& args) : mFlinger(args.flinger), mName(args.name), mClientRef(args.client), - mWindowType(static_cast<InputWindowInfo::Type>( - args.metadata.getInt32(METADATA_WINDOW_TYPE, 0))) { + mWindowType(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0)) { uint32_t layerFlags = 0; if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden; if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque; if (args.flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure; - if (args.flags & ISurfaceComposerClient::eSkipScreenshot) - layerFlags |= layer_state_t::eLayerSkipScreenshot; - - mDrawingState.active_legacy.w = args.w; - mDrawingState.active_legacy.h = args.h; - mDrawingState.flags = layerFlags; - mDrawingState.active_legacy.transform.set(0, 0); - mDrawingState.crop.makeInvalid(); - mDrawingState.requestedCrop = mDrawingState.crop; - mDrawingState.z = 0; - mDrawingState.color.a = 1.0f; - mDrawingState.layerStack = 0; - mDrawingState.sequence = 0; - mDrawingState.requested_legacy = mDrawingState.active_legacy; - mDrawingState.width = UINT32_MAX; - mDrawingState.height = UINT32_MAX; - mDrawingState.transform.set(0, 0); - mDrawingState.frameNumber = 0; - mDrawingState.bufferTransform = 0; - mDrawingState.transformToDisplayInverse = false; - mDrawingState.crop.makeInvalid(); - mDrawingState.acquireFence = sp<Fence>::make(-1); - mDrawingState.acquireFenceTime = std::make_shared<FenceTime>(mDrawingState.acquireFence); - mDrawingState.dataspace = ui::Dataspace::UNKNOWN; - mDrawingState.hdrMetadata.validTypes = 0; - mDrawingState.surfaceDamageRegion = Region::INVALID_REGION; - mDrawingState.cornerRadius = 0.0f; - mDrawingState.backgroundBlurRadius = 0; - mDrawingState.api = -1; - mDrawingState.hasColorTransform = false; - mDrawingState.colorSpaceAgnostic = false; - mDrawingState.frameRateSelectionPriority = PRIORITY_UNSET; - mDrawingState.metadata = args.metadata; - mDrawingState.shadowRadius = 0.f; - mDrawingState.fixedTransformHint = ui::Transform::ROT_INVALID; - mDrawingState.frameTimelineInfo = {}; - mDrawingState.postTime = -1; - mDrawingState.destinationFrame.makeInvalid(); + + mCurrentState.active_legacy.w = args.w; + mCurrentState.active_legacy.h = args.h; + mCurrentState.flags = layerFlags; + mCurrentState.active_legacy.transform.set(0, 0); + mCurrentState.crop_legacy.makeInvalid(); + mCurrentState.requestedCrop_legacy = mCurrentState.crop_legacy; + mCurrentState.z = 0; + mCurrentState.color.a = 1.0f; + mCurrentState.layerStack = 0; + mCurrentState.sequence = 0; + mCurrentState.requested_legacy = mCurrentState.active_legacy; + mCurrentState.active.w = UINT32_MAX; + mCurrentState.active.h = UINT32_MAX; + mCurrentState.active.transform.set(0, 0); + mCurrentState.frameNumber = 0; + mCurrentState.transform = 0; + mCurrentState.transformToDisplayInverse = false; + mCurrentState.crop.makeInvalid(); + mCurrentState.acquireFence = new Fence(-1); + mCurrentState.dataspace = ui::Dataspace::UNKNOWN; + mCurrentState.hdrMetadata.validTypes = 0; + mCurrentState.surfaceDamageRegion = Region::INVALID_REGION; + mCurrentState.cornerRadius = 0.0f; + mCurrentState.backgroundBlurRadius = 0; + mCurrentState.api = -1; + mCurrentState.hasColorTransform = false; + mCurrentState.colorSpaceAgnostic = false; + mCurrentState.frameRateSelectionPriority = PRIORITY_UNSET; + mCurrentState.metadata = args.metadata; + mCurrentState.shadowRadius = 0.f; + mCurrentState.treeHasFrameRateVote = false; + mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID; + mCurrentState.isTrustedOverlay = false; if (args.flags & ISurfaceComposerClient::eNoColorFill) { // Set an invalid color so there is no color fill. - mDrawingState.color.r = -1.0_hf; - mDrawingState.color.g = -1.0_hf; - mDrawingState.color.b = -1.0_hf; + mCurrentState.color.r = -1.0_hf; + mCurrentState.color.g = -1.0_hf; + mCurrentState.color.b = -1.0_hf; } + // drawing state & current state are identical + mDrawingState = mCurrentState; + CompositorTiming compositorTiming; args.flinger->getCompositorTiming(&compositorTiming); mFrameEventHistory.initializeCompositorTiming(compositorTiming); @@ -149,16 +137,6 @@ Layer::Layer(const LayerCreationArgs& args) mCallingPid = args.callingPid; mCallingUid = args.callingUid; - - if (mCallingUid == AID_GRAPHICS || mCallingUid == AID_SYSTEM) { - // If the system didn't send an ownerUid, use the callingUid for the ownerUid. - mOwnerUid = args.metadata.getInt32(METADATA_OWNER_UID, mCallingUid); - mOwnerPid = args.metadata.getInt32(METADATA_OWNER_PID, mCallingPid); - } else { - // A create layer request from a non system request cannot specify the owner uid - mOwnerUid = mCallingUid; - mOwnerPid = mCallingPid; - } } void Layer::onFirstRef() { @@ -173,13 +151,6 @@ Layer::~Layer() { mFrameTracker.logAndResetStats(mName); mFlinger->onLayerDestroyed(this); - - if (mDrawingState.sidebandStream != nullptr) { - mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount(); - } - if (mHadClonedChild) { - mFlinger->mNumClones--; - } } LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name, @@ -207,12 +178,25 @@ LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, */ void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {} +void Layer::removeRemoteSyncPoints() { + for (auto& point : mRemoteSyncPoints) { + point->setTransactionApplied(); + } + mRemoteSyncPoints.clear(); + + { + for (State pendingState : mPendingStates) { + pendingState.barrierLayer_legacy = nullptr; + } + } +} + void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) { - if (mDrawingState.zOrderRelativeOf == nullptr) { + if (mCurrentState.zOrderRelativeOf == nullptr) { return; } - sp<Layer> strongRelative = mDrawingState.zOrderRelativeOf.promote(); + sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote(); if (strongRelative == nullptr) { setZOrderRelativeOf(nullptr); return; @@ -226,9 +210,21 @@ void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) { } void Layer::removeFromCurrentState() { - if (!mRemovedFromDrawingState) { - mRemovedFromDrawingState = true; - mFlinger->mScheduler->deregisterLayer(this); + mRemovedFromCurrentState = true; + + // Since we are no longer reachable from CurrentState SurfaceFlinger + // will no longer invoke doTransaction for us, and so we will + // never finish applying transactions. We signal the sync point + // now so that another layer will not become indefinitely + // blocked. + removeRemoteSyncPoints(); + + { + Mutex::Autolock syncLock(mLocalSyncPointMutex); + for (auto& point : mLocalSyncPoints) { + point->setFrameAvailable(); + } + mLocalSyncPoints.clear(); } mFlinger->markLayerPendingRemovalLocked(this); @@ -254,11 +250,7 @@ void Layer::onRemovedFromCurrentState() { } void Layer::addToCurrentState() { - if (mRemovedFromDrawingState) { - mRemovedFromDrawingState = false; - mFlinger->mScheduler->registerLayer(this); - mFlinger->removeFromOffscreenLayers(this); - } + mRemovedFromCurrentState = false; for (const auto& child : mCurrentChildren) { child->addToCurrentState(); @@ -327,6 +319,55 @@ FloatRect Layer::getBounds(const Region& activeTransparentRegion) const { return reduce(mBounds, activeTransparentRegion); } +ui::Transform Layer::getBufferScaleTransform() const { + // If the layer is not using NATIVE_WINDOW_SCALING_MODE_FREEZE (e.g. + // it isFixedSize) then there may be additional scaling not accounted + // for in the layer transform. + if (!isFixedSize() || getBuffer() == nullptr) { + return {}; + } + + // If the layer is a buffer state layer, the active width and height + // could be infinite. In that case, return the effective transform. + const uint32_t activeWidth = getActiveWidth(getDrawingState()); + const uint32_t activeHeight = getActiveHeight(getDrawingState()); + if (activeWidth >= UINT32_MAX && activeHeight >= UINT32_MAX) { + return {}; + } + + int bufferWidth = getBuffer()->getWidth(); + int bufferHeight = getBuffer()->getHeight(); + + if (getBufferTransform() & NATIVE_WINDOW_TRANSFORM_ROT_90) { + std::swap(bufferWidth, bufferHeight); + } + + float sx = activeWidth / static_cast<float>(bufferWidth); + float sy = activeHeight / static_cast<float>(bufferHeight); + + ui::Transform extraParentScaling; + extraParentScaling.set(sx, 0, 0, sy); + return extraParentScaling; +} + +ui::Transform Layer::getTransformWithScale(const ui::Transform& bufferScaleTransform) const { + // We need to mirror this scaling to child surfaces or we will break the contract where WM can + // treat child surfaces as pixels in the parent surface. + if (!isFixedSize() || getBuffer() == nullptr) { + return mEffectiveTransform; + } + return mEffectiveTransform * bufferScaleTransform; +} + +FloatRect Layer::getBoundsPreScaling(const ui::Transform& bufferScaleTransform) const { + // We need the pre scaled layer bounds when computing child bounds to make sure the child is + // cropped to its parent layer after any buffer transform scaling is applied. + if (!isFixedSize() || getBuffer() == nullptr) { + return mBounds; + } + return bufferScaleTransform.inverse().transform(mBounds); +} + void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform, float parentShadowRadius) { const State& s(getDrawingState()); @@ -363,8 +404,11 @@ void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform, // don't pass it to its children. const float childShadowRadius = canDrawShadows() ? 0.f : mEffectiveShadowRadius; + // Add any buffer scaling to the layer's children. + ui::Transform bufferScaleTransform = getBufferScaleTransform(); for (const sp<Layer>& child : mDrawingChildren) { - child->computeBounds(mBounds, mEffectiveTransform, childShadowRadius); + child->computeBounds(getBoundsPreScaling(bufferScaleTransform), + getTransformWithScale(bufferScaleTransform), childShadowRadius); } } @@ -421,8 +465,6 @@ void Layer::prepareBasicGeometryCompositionState() { compositionState->blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode); compositionState->alpha = alpha; compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius; - compositionState->blurRegions = drawingState.blurRegions; - compositionState->stretchEffect = getStretchEffect(); } void Layer::prepareGeometryCompositionState() { @@ -451,6 +493,9 @@ void Layer::prepareGeometryCompositionState() { compositionState->geomUsesSourceCrop = usesSourceCrop(); compositionState->isSecure = isSecure(); + compositionState->type = type; + compositionState->appId = appId; + compositionState->metadata.clear(); const auto& supportedMetadata = mFlinger->getHwComposer().getSupportedLayerGenericMetadata(); for (const auto& [key, mandatory] : supportedMetadata) { @@ -491,10 +536,7 @@ void Layer::preparePerFrameCompositionState() { isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf; // Force client composition for special cases known only to the front-end. - // Rounded corners no longer force client composition, since we may use a - // hole punch so that the layer will appear to have rounded corners. - if (isHdrY410() || drawShadows() || drawingState.blurRegions.size() > 0 || - compositionState->stretchEffect.hasEffect()) { + if (isHdrY410() || usesRoundedCorners || drawShadows()) { compositionState->forceClientComposition = true; } } @@ -577,11 +619,11 @@ std::optional<compositionengine::LayerFE::LayerSettings> Layer::prepareClientCom compositionengine::LayerFE::LayerSettings layerSettings; layerSettings.geometry.boundaries = bounds; - layerSettings.geometry.positionTransform = getTransform().asMatrix4(); - - // skip drawing content if the targetSettings indicate the content will be occluded - const bool drawContent = targetSettings.realContentIsVisible || targetSettings.clearContent; - layerSettings.skipContentDraw = !drawContent; + if (targetSettings.useIdentityTransform) { + layerSettings.geometry.positionTransform = mat4(); + } else { + layerSettings.geometry.positionTransform = getTransform().asMatrix4(); + } if (hasColorTransform()) { layerSettings.colorTransform = getColorTransform(); @@ -593,31 +635,62 @@ std::optional<compositionengine::LayerFE::LayerSettings> Layer::prepareClientCom layerSettings.alpha = alpha; layerSettings.sourceDataspace = getDataSpace(); - switch (targetSettings.blurSetting) { - case LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled: - layerSettings.backgroundBlurRadius = getBackgroundBlurRadius(); - layerSettings.blurRegions = getBlurRegions(); - layerSettings.blurRegionTransform = - getActiveTransform(getDrawingState()).inverse().asMatrix4(); - break; - case LayerFE::ClientCompositionTargetSettings::BlurSetting::BackgroundBlurOnly: - layerSettings.backgroundBlurRadius = getBackgroundBlurRadius(); - break; - case LayerFE::ClientCompositionTargetSettings::BlurSetting::BlurRegionsOnly: - layerSettings.blurRegions = getBlurRegions(); - layerSettings.blurRegionTransform = - getActiveTransform(getDrawingState()).inverse().asMatrix4(); - break; - case LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled: - default: - break; - } - layerSettings.stretchEffect = getStretchEffect(); - // Record the name of the layer for debugging further down the stack. - layerSettings.name = getName(); + layerSettings.backgroundBlurRadius = getBackgroundBlurRadius(); return layerSettings; } +std::optional<compositionengine::LayerFE::LayerSettings> Layer::prepareShadowClientComposition( + const LayerFE::LayerSettings& casterLayerSettings, const Rect& displayViewport, + ui::Dataspace outputDataspace) { + renderengine::ShadowSettings shadow = getShadowSettings(displayViewport); + if (shadow.length <= 0.f) { + return {}; + } + + const float casterAlpha = casterLayerSettings.alpha; + const bool casterIsOpaque = ((casterLayerSettings.source.buffer.buffer != nullptr) && + casterLayerSettings.source.buffer.isOpaque); + + compositionengine::LayerFE::LayerSettings shadowLayer = casterLayerSettings; + + shadowLayer.shadow = shadow; + shadowLayer.geometry.boundaries = mBounds; // ignore transparent region + + // If the casting layer is translucent, we need to fill in the shadow underneath the layer. + // Otherwise the generated shadow will only be shown around the casting layer. + shadowLayer.shadow.casterIsTranslucent = !casterIsOpaque || (casterAlpha < 1.0f); + shadowLayer.shadow.ambientColor *= casterAlpha; + shadowLayer.shadow.spotColor *= casterAlpha; + shadowLayer.sourceDataspace = outputDataspace; + shadowLayer.source.buffer.buffer = nullptr; + shadowLayer.source.buffer.fence = nullptr; + shadowLayer.frameNumber = 0; + shadowLayer.bufferId = 0; + + if (shadowLayer.shadow.ambientColor.a <= 0.f && shadowLayer.shadow.spotColor.a <= 0.f) { + return {}; + } + + float casterCornerRadius = shadowLayer.geometry.roundedCornersRadius; + const FloatRect& cornerRadiusCropRect = shadowLayer.geometry.roundedCornersCrop; + const FloatRect& casterRect = shadowLayer.geometry.boundaries; + + // crop used to set the corner radius may be larger than the content rect. Adjust the corner + // radius accordingly. + if (casterCornerRadius > 0.f) { + float cropRectOffset = std::max(std::abs(cornerRadiusCropRect.top - casterRect.top), + std::abs(cornerRadiusCropRect.left - casterRect.left)); + if (cropRectOffset > casterCornerRadius) { + casterCornerRadius = 0; + } else { + casterCornerRadius -= cropRectOffset; + } + shadowLayer.geometry.roundedCornersRadius = casterCornerRadius; + } + + return shadowLayer; +} + void Layer::prepareClearClientComposition(LayerFE::LayerSettings& layerSettings, bool blackout) const { layerSettings.source.buffer.buffer = nullptr; @@ -628,12 +701,8 @@ void Layer::prepareClearClientComposition(LayerFE::LayerSettings& layerSettings, // If layer is blacked out, force alpha to 1 so that we draw a black color layer. layerSettings.alpha = blackout ? 1.0f : 0.0f; - layerSettings.name = getName(); } -// TODO(b/188891810): This method now only ever returns 0 or 1 layers so we should return -// std::optional instead of a vector. Additionally, we should consider removing -// this method entirely in favor of calling prepareClientComposition directly. std::vector<compositionengine::LayerFE::LayerSettings> Layer::prepareClientCompositionList( compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) { std::optional<compositionengine::LayerFE::LayerSettings> layerSettings = @@ -649,10 +718,21 @@ std::vector<compositionengine::LayerFE::LayerSettings> Layer::prepareClientCompo return {*layerSettings}; } - // set the shadow for the layer if needed - prepareShadowClientComposition(*layerSettings, targetSettings.viewport); + std::optional<compositionengine::LayerFE::LayerSettings> shadowSettings = + prepareShadowClientComposition(*layerSettings, targetSettings.viewport, + targetSettings.dataspace); + // There are no shadows to render. + if (!shadowSettings) { + return {*layerSettings}; + } - return {*layerSettings}; + // If the layer casts a shadow but the content casting the shadow is occluded, skip + // composing the non-shadow content and only draw the shadows. + if (targetSettings.realContentIsVisible) { + return {*shadowSettings, *layerSettings}; + } + + return {*shadowSettings}; } Hwc2::IComposerClient::Composition Layer::getCompositionType(const DisplayDevice& display) const { @@ -667,83 +747,299 @@ Hwc2::IComposerClient::Composition Layer::getCompositionType(const DisplayDevice } } +bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) { + if (point->getFrameNumber() <= mCurrentFrameNumber) { + // Don't bother with a SyncPoint, since we've already latched the + // relevant frame + return false; + } + if (isRemovedFromCurrentState()) { + return false; + } + + Mutex::Autolock lock(mLocalSyncPointMutex); + mLocalSyncPoints.push_back(point); + return true; +} + // ---------------------------------------------------------------------------- // local state // ---------------------------------------------------------------------------- bool Layer::isSecure() const { const State& s(mDrawingState); - if (s.flags & layer_state_t::eLayerSecure) { - return true; - } - - const auto p = mDrawingParent.promote(); - return (p != nullptr) ? p->isSecure() : false; + return (s.flags & layer_state_t::eLayerSecure); } // ---------------------------------------------------------------------------- // transaction // ---------------------------------------------------------------------------- +void Layer::pushPendingState() { + if (!mCurrentState.modified) { + return; + } + ATRACE_CALL(); + + // If this transaction is waiting on the receipt of a frame, generate a sync + // point and send it to the remote layer. + // We don't allow installing sync points after we are removed from the current state + // as we won't be able to signal our end. + if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) { + sp<Layer> barrierLayer = mCurrentState.barrierLayer_legacy.promote(); + if (barrierLayer == nullptr) { + ALOGE("[%s] Unable to promote barrier Layer.", getDebugName()); + // If we can't promote the layer we are intended to wait on, + // then it is expired or otherwise invalid. Allow this transaction + // to be applied as per normal (no synchronization). + mCurrentState.barrierLayer_legacy = nullptr; + } else { + auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy, this); + if (barrierLayer->addSyncPoint(syncPoint)) { + std::stringstream ss; + ss << "Adding sync point " << mCurrentState.frameNumber_legacy; + ATRACE_NAME(ss.str().c_str()); + mRemoteSyncPoints.push_back(std::move(syncPoint)); + } else { + // We already missed the frame we're supposed to synchronize + // on, so go ahead and apply the state update + mCurrentState.barrierLayer_legacy = nullptr; + } + } + + // Wake us up to check if the frame has been received + setTransactionFlags(eTransactionNeeded); + mFlinger->setTransactionFlags(eTraversalNeeded); + } + mPendingStates.push_back(mCurrentState); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); +} + +void Layer::popPendingState(State* stateToCommit) { + ATRACE_CALL(); + *stateToCommit = mPendingStates[0]; + + mPendingStates.removeAt(0); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); +} + +bool Layer::applyPendingStates(State* stateToCommit) { + bool stateUpdateAvailable = false; + while (!mPendingStates.empty()) { + if (mPendingStates[0].barrierLayer_legacy != nullptr) { + if (mRemoteSyncPoints.empty()) { + // If we don't have a sync point for this, apply it anyway. It + // will be visually wrong, but it should keep us from getting + // into too much trouble. + ALOGE("[%s] No local sync point found", getDebugName()); + popPendingState(stateToCommit); + stateUpdateAvailable = true; + continue; + } + + if (mRemoteSyncPoints.front()->getFrameNumber() != + mPendingStates[0].frameNumber_legacy) { + ALOGE("[%s] Unexpected sync point frame number found", getDebugName()); + + // Signal our end of the sync point and then dispose of it + mRemoteSyncPoints.front()->setTransactionApplied(); + mRemoteSyncPoints.pop_front(); + continue; + } + + if (mRemoteSyncPoints.front()->frameIsAvailable()) { + ATRACE_NAME("frameIsAvailable"); + // Apply the state update + popPendingState(stateToCommit); + stateUpdateAvailable = true; + + // Signal our end of the sync point and then dispose of it + mRemoteSyncPoints.front()->setTransactionApplied(); + mRemoteSyncPoints.pop_front(); + } else { + ATRACE_NAME("!frameIsAvailable"); + break; + } + } else { + popPendingState(stateToCommit); + stateUpdateAvailable = true; + } + } + + // If we still have pending updates, we need to ensure SurfaceFlinger + // will keep calling doTransaction, and so we force a traversal. + // However, our pending states won't clear until a frame is available, + // and so there is no need to specifically trigger a wakeup. + if (!mPendingStates.empty()) { + setTransactionFlags(eTransactionNeeded); + mFlinger->setTraversalNeeded(); + } + + mCurrentState.modified = false; + return stateUpdateAvailable; +} + +uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { + const State& s(getDrawingState()); + + const bool sizeChanged = (stateToCommit->requested_legacy.w != s.requested_legacy.w) || + (stateToCommit->requested_legacy.h != s.requested_legacy.h); + + if (sizeChanged) { + // the size changed, we need to ask our client to request a new buffer + ALOGD_IF(DEBUG_RESIZE, + "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n" + " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" + " requested={ wh={%4u,%4u} }}\n" + " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" + " requested={ wh={%4u,%4u} }}\n", + this, getName().c_str(), getBufferTransform(), getEffectiveScalingMode(), + stateToCommit->active_legacy.w, stateToCommit->active_legacy.h, + stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top, + stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom, + stateToCommit->crop_legacy.getWidth(), stateToCommit->crop_legacy.getHeight(), + stateToCommit->requested_legacy.w, stateToCommit->requested_legacy.h, + s.active_legacy.w, s.active_legacy.h, s.crop_legacy.left, s.crop_legacy.top, + s.crop_legacy.right, s.crop_legacy.bottom, s.crop_legacy.getWidth(), + s.crop_legacy.getHeight(), s.requested_legacy.w, s.requested_legacy.h); + } + + // Don't let Layer::doTransaction update the drawing state + // if we have a pending resize, unless we are in fixed-size mode. + // the drawing state will be updated only once we receive a buffer + // with the correct size. + // + // In particular, we want to make sure the clip (which is part + // of the geometry state) is latched together with the size but is + // latched immediately when no resizing is involved. + // + // If a sideband stream is attached, however, we want to skip this + // optimization so that transactions aren't missed when a buffer + // never arrives + // + // In the case that we don't have a buffer we ignore other factors + // and avoid entering the resizePending state. At a high level the + // resizePending state is to avoid applying the state of the new buffer + // to the old buffer. However in the state where we don't have an old buffer + // there is no such concern but we may still be being used as a parent layer. + const bool resizePending = + ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) || + (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) && + (getBuffer() != nullptr); + if (!isFixedSize()) { + if (resizePending && mSidebandStream == nullptr) { + flags |= eDontUpdateGeometryState; + } + } + + // Here we apply various requested geometry states, depending on our + // latching configuration. See Layer.h for a detailed discussion of + // how geometry latching is controlled. + if (!(flags & eDontUpdateGeometryState)) { + State& editCurrentState(getCurrentState()); + + // There is an awkward asymmetry in the handling of the crop states in the position + // states, as can be seen below. Largely this arises from position and transform + // being stored in the same data structure while having different latching rules. + // b/38182305 + // + // Careful that "stateToCommit" and editCurrentState may not begin as equivalent due to + // applyPendingStates in the presence of deferred transactions. + editCurrentState.active_legacy = editCurrentState.requested_legacy; + stateToCommit->active_legacy = stateToCommit->requested_legacy; + } + + return flags; +} + uint32_t Layer::doTransaction(uint32_t flags) { ATRACE_CALL(); - // TODO: This is unfortunate. - mDrawingStateModified = mDrawingState.modified; - mDrawingState.modified = false; + if (mLayerDetached) { + // Ensure BLAST buffer callbacks are processed. + // detachChildren and mLayerDetached were implemented to avoid geometry updates + // to layers in the cases of animation. For BufferQueue layers buffers are still + // consumed as normal. This is useful as otherwise the client could get hung + // inevitably waiting on a buffer to return. We recreate this semantic for BufferQueue + // even though it is a little consistent. detachChildren is shortly slated for removal + // by the hierarchy mirroring work so we don't need to worry about it too much. + forceSendCallbacks(); + mCurrentState.callbackHandles = {}; + return flags; + } + + if (mChildrenChanged) { + flags |= eVisibleRegion; + mChildrenChanged = false; + } + + pushPendingState(); + State c = getCurrentState(); + if (!applyPendingStates(&c)) { + return flags; + } + + flags = doTransactionResize(flags, &c); const State& s(getDrawingState()); - if (updateGeometry()) { + if (getActiveGeometry(c) != getActiveGeometry(s)) { // invalidate and recompute the visible regions if needed flags |= Layer::eVisibleRegion; } - if (s.sequence != mLastCommittedTxSequence) { + if (c.sequence != s.sequence) { // invalidate and recompute the visible regions if needed - mLastCommittedTxSequence = s.sequence; flags |= eVisibleRegion; this->contentDirty = true; // we may use linear filtering, if the matrix scales us - mNeedsFiltering = getActiveTransform(s).needsBilinearFiltering(); + const uint8_t type = getActiveTransform(c).getType(); + mNeedsFiltering = (!getActiveTransform(c).preserveRects() || type >= ui::Transform::SCALE); } - commitTransaction(mDrawingState); + if (mCurrentState.inputInfoChanged) { + flags |= eInputInfoChanged; + mCurrentState.inputInfoChanged = false; + } + + // Commit the transaction + commitTransaction(c); + mPendingStatesSnapshot = mPendingStates; + mCurrentState.callbackHandles = {}; return flags; } -void Layer::commitTransaction(State&) { - // Set the present state for all bufferlessSurfaceFramesTX to Presented. The - // bufferSurfaceFrameTX will be presented in latchBuffer. - for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) { - if (surfaceFrame->getPresentState() != PresentState::Presented) { - // With applyPendingStates, we could end up having presented surfaceframes from previous - // states - surfaceFrame->setPresentState(PresentState::Presented); - mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); - } - } - mDrawingState.bufferlessSurfaceFramesTX.clear(); +void Layer::commitTransaction(const State& stateToCommit) { + mDrawingState = stateToCommit; } uint32_t Layer::getTransactionFlags(uint32_t flags) { - auto ret = mTransactionFlags & flags; - mTransactionFlags &= ~flags; - return ret; + return mTransactionFlags.fetch_and(~flags) & flags; } uint32_t Layer::setTransactionFlags(uint32_t flags) { - return mTransactionFlags |= flags; + return mTransactionFlags.fetch_or(flags); } bool Layer::setPosition(float x, float y) { - if (mDrawingState.transform.tx() == x && mDrawingState.transform.ty() == y) return false; - mDrawingState.sequence++; - mDrawingState.transform.set(x, y); - - mDrawingState.modified = true; + if (mCurrentState.requested_legacy.transform.tx() == x && + mCurrentState.requested_legacy.transform.ty() == y) + return false; + mCurrentState.sequence++; + + // We update the requested and active position simultaneously because + // we want to apply the position portion of the transform matrix immediately, + // but still delay scaling when resizing a SCALING_MODE_FREEZE layer. + mCurrentState.requested_legacy.transform.set(x, y); + // Here we directly update the active state + // unlike other setters, because we store it within + // the transform, but use different latching rules. + // b/38182305 + mCurrentState.active_legacy.transform.set(x, y); + + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -776,16 +1072,14 @@ bool Layer::setChildRelativeLayer(const sp<Layer>& childLayer, } bool Layer::setLayer(int32_t z) { - if (mDrawingState.z == z && !usingRelativeZ(LayerVector::StateSet::Current)) return false; - mDrawingState.sequence++; - mDrawingState.z = z; - mDrawingState.modified = true; - - mFlinger->mSomeChildrenChanged = true; + if (mCurrentState.z == z && !usingRelativeZ(LayerVector::StateSet::Current)) return false; + mCurrentState.sequence++; + mCurrentState.z = z; + mCurrentState.modified = true; // Discard all relative layering. - if (mDrawingState.zOrderRelativeOf != nullptr) { - sp<Layer> strongRelative = mDrawingState.zOrderRelativeOf.promote(); + if (mCurrentState.zOrderRelativeOf != nullptr) { + sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote(); if (strongRelative != nullptr) { strongRelative->removeZOrderRelative(this); } @@ -796,24 +1090,24 @@ bool Layer::setLayer(int32_t z) { } void Layer::removeZOrderRelative(const wp<Layer>& relative) { - mDrawingState.zOrderRelatives.remove(relative); - mDrawingState.sequence++; - mDrawingState.modified = true; + mCurrentState.zOrderRelatives.remove(relative); + mCurrentState.sequence++; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); } void Layer::addZOrderRelative(const wp<Layer>& relative) { - mDrawingState.zOrderRelatives.add(relative); - mDrawingState.modified = true; - mDrawingState.sequence++; + mCurrentState.zOrderRelatives.add(relative); + mCurrentState.modified = true; + mCurrentState.sequence++; setTransactionFlags(eTransactionNeeded); } void Layer::setZOrderRelativeOf(const wp<Layer>& relativeOf) { - mDrawingState.zOrderRelativeOf = relativeOf; - mDrawingState.sequence++; - mDrawingState.modified = true; - mDrawingState.isRelativeOf = relativeOf != nullptr; + mCurrentState.zOrderRelativeOf = relativeOf; + mCurrentState.sequence++; + mCurrentState.modified = true; + mCurrentState.isRelativeOf = relativeOf != nullptr; setTransactionFlags(eTransactionNeeded); } @@ -828,18 +1122,16 @@ bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relati return false; } - if (mDrawingState.z == relativeZ && usingRelativeZ(LayerVector::StateSet::Current) && - mDrawingState.zOrderRelativeOf == relative) { + if (mCurrentState.z == relativeZ && usingRelativeZ(LayerVector::StateSet::Current) && + mCurrentState.zOrderRelativeOf == relative) { return false; } - mFlinger->mSomeChildrenChanged = true; - - mDrawingState.sequence++; - mDrawingState.modified = true; - mDrawingState.z = relativeZ; + mCurrentState.sequence++; + mCurrentState.modified = true; + mCurrentState.z = relativeZ; - auto oldZOrderRelativeOf = mDrawingState.zOrderRelativeOf.promote(); + auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote(); if (oldZOrderRelativeOf != nullptr) { oldZOrderRelativeOf->removeZOrderRelative(this); } @@ -852,10 +1144,10 @@ bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relati } bool Layer::setTrustedOverlay(bool isTrustedOverlay) { - if (mDrawingState.isTrustedOverlay == isTrustedOverlay) return false; - mDrawingState.isTrustedOverlay = isTrustedOverlay; - mDrawingState.modified = true; - mFlinger->mInputInfoChanged = true; + if (mCurrentState.isTrustedOverlay == isTrustedOverlay) return false; + mCurrentState.isTrustedOverlay = isTrustedOverlay; + mCurrentState.modified = true; + mCurrentState.inputInfoChanged = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -869,82 +1161,81 @@ bool Layer::isTrustedOverlay() const { } bool Layer::setSize(uint32_t w, uint32_t h) { - if (mDrawingState.requested_legacy.w == w && mDrawingState.requested_legacy.h == h) + if (mCurrentState.requested_legacy.w == w && mCurrentState.requested_legacy.h == h) return false; - mDrawingState.requested_legacy.w = w; - mDrawingState.requested_legacy.h = h; - mDrawingState.modified = true; + mCurrentState.requested_legacy.w = w; + mCurrentState.requested_legacy.h = h; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); // record the new size, from this point on, when the client request // a buffer, it'll get the new size. - setDefaultBufferSize(mDrawingState.requested_legacy.w, mDrawingState.requested_legacy.h); + setDefaultBufferSize(mCurrentState.requested_legacy.w, mCurrentState.requested_legacy.h); return true; } - bool Layer::setAlpha(float alpha) { - if (mDrawingState.color.a == alpha) return false; - mDrawingState.sequence++; - mDrawingState.color.a = alpha; - mDrawingState.modified = true; + if (mCurrentState.color.a == alpha) return false; + mCurrentState.sequence++; + mCurrentState.color.a = alpha; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace) { - if (!mDrawingState.bgColorLayer && alpha == 0) { + if (!mCurrentState.bgColorLayer && alpha == 0) { return false; } - mDrawingState.sequence++; - mDrawingState.modified = true; + mCurrentState.sequence++; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - if (!mDrawingState.bgColorLayer && alpha != 0) { + if (!mCurrentState.bgColorLayer && alpha != 0) { // create background color layer if one does not yet exist uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect; std::string name = mName + "BackgroundColorLayer"; - mDrawingState.bgColorLayer = mFlinger->getFactory().createEffectLayer( + mCurrentState.bgColorLayer = mFlinger->getFactory().createEffectLayer( LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), 0, 0, flags, LayerMetadata())); // add to child list - addChild(mDrawingState.bgColorLayer); + addChild(mCurrentState.bgColorLayer); mFlinger->mLayersAdded = true; // set up SF to handle added color layer if (isRemovedFromCurrentState()) { - mDrawingState.bgColorLayer->onRemovedFromCurrentState(); + mCurrentState.bgColorLayer->onRemovedFromCurrentState(); } mFlinger->setTransactionFlags(eTransactionNeeded); - } else if (mDrawingState.bgColorLayer && alpha == 0) { - mDrawingState.bgColorLayer->reparent(nullptr); - mDrawingState.bgColorLayer = nullptr; + } else if (mCurrentState.bgColorLayer && alpha == 0) { + mCurrentState.bgColorLayer->reparent(nullptr); + mCurrentState.bgColorLayer = nullptr; return true; } - mDrawingState.bgColorLayer->setColor(color); - mDrawingState.bgColorLayer->setLayer(std::numeric_limits<int32_t>::min()); - mDrawingState.bgColorLayer->setAlpha(alpha); - mDrawingState.bgColorLayer->setDataspace(dataspace); + mCurrentState.bgColorLayer->setColor(color); + mCurrentState.bgColorLayer->setLayer(std::numeric_limits<int32_t>::min()); + mCurrentState.bgColorLayer->setAlpha(alpha); + mCurrentState.bgColorLayer->setDataspace(dataspace); return true; } bool Layer::setCornerRadius(float cornerRadius) { - if (mDrawingState.cornerRadius == cornerRadius) return false; + if (mCurrentState.cornerRadius == cornerRadius) return false; - mDrawingState.sequence++; - mDrawingState.cornerRadius = cornerRadius; - mDrawingState.modified = true; + mCurrentState.sequence++; + mCurrentState.cornerRadius = cornerRadius; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setBackgroundBlurRadius(int backgroundBlurRadius) { - if (mDrawingState.backgroundBlurRadius == backgroundBlurRadius) return false; + if (mCurrentState.backgroundBlurRadius == backgroundBlurRadius) return false; - mDrawingState.sequence++; - mDrawingState.backgroundBlurRadius = backgroundBlurRadius; - mDrawingState.modified = true; + mCurrentState.sequence++; + mCurrentState.backgroundBlurRadius = backgroundBlurRadius; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -955,85 +1246,85 @@ bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix, t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); if (!allowNonRectPreservingTransforms && !t.preserveRects()) { - ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER nor " - "ROTATE_SURFACE_FLINGER ignored"); + ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored"); return false; } - mDrawingState.sequence++; - mDrawingState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - mDrawingState.modified = true; - + mCurrentState.sequence++; + mCurrentState.requested_legacy.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, + matrix.dsdy); + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setTransparentRegionHint(const Region& transparent) { - mDrawingState.requestedTransparentRegion_legacy = transparent; - mDrawingState.modified = true; + mCurrentState.requestedTransparentRegion_legacy = transparent; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -bool Layer::setBlurRegions(const std::vector<BlurRegion>& blurRegions) { - mDrawingState.blurRegions = blurRegions; - mDrawingState.modified = true; +bool Layer::setFlags(uint8_t flags, uint8_t mask) { + const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); + if (mCurrentState.flags == newFlags) return false; + mCurrentState.sequence++; + mCurrentState.flags = newFlags; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -bool Layer::setFlags(uint32_t flags, uint32_t mask) { - const uint32_t newFlags = (mDrawingState.flags & ~mask) | (flags & mask); - if (mDrawingState.flags == newFlags) return false; - mDrawingState.sequence++; - mDrawingState.flags = newFlags; - mDrawingState.modified = true; +bool Layer::setCrop_legacy(const Rect& crop) { + if (mCurrentState.requestedCrop_legacy == crop) return false; + mCurrentState.sequence++; + mCurrentState.requestedCrop_legacy = crop; + mCurrentState.crop_legacy = crop; + + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -bool Layer::setCrop(const Rect& crop) { - if (mDrawingState.requestedCrop == crop) return false; - mDrawingState.sequence++; - mDrawingState.requestedCrop = crop; - mDrawingState.crop = crop; - - mDrawingState.modified = true; +bool Layer::setOverrideScalingMode(int32_t scalingMode) { + if (scalingMode == mOverrideScalingMode) return false; + mOverrideScalingMode = scalingMode; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setMetadata(const LayerMetadata& data) { - if (!mDrawingState.metadata.merge(data, true /* eraseEmpty */)) return false; - mDrawingState.modified = true; + if (!mCurrentState.metadata.merge(data, true /* eraseEmpty */)) return false; + mCurrentState.sequence++; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setLayerStack(uint32_t layerStack) { - if (mDrawingState.layerStack == layerStack) return false; - mDrawingState.sequence++; - mDrawingState.layerStack = layerStack; - mDrawingState.modified = true; + if (mCurrentState.layerStack == layerStack) return false; + mCurrentState.sequence++; + mCurrentState.layerStack = layerStack; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setColorSpaceAgnostic(const bool agnostic) { - if (mDrawingState.colorSpaceAgnostic == agnostic) { + if (mCurrentState.colorSpaceAgnostic == agnostic) { return false; } - mDrawingState.sequence++; - mDrawingState.colorSpaceAgnostic = agnostic; - mDrawingState.modified = true; + mCurrentState.sequence++; + mCurrentState.colorSpaceAgnostic = agnostic; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setFrameRateSelectionPriority(int32_t priority) { - if (mDrawingState.frameRateSelectionPriority == priority) return false; - mDrawingState.frameRateSelectionPriority = priority; - mDrawingState.sequence++; - mDrawingState.modified = true; + if (mCurrentState.frameRateSelectionPriority == priority) return false; + mCurrentState.frameRateSelectionPriority = priority; + mCurrentState.sequence++; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -1065,111 +1356,69 @@ uint32_t Layer::getLayerStack() const { } bool Layer::setShadowRadius(float shadowRadius) { - if (mDrawingState.shadowRadius == shadowRadius) { + if (mCurrentState.shadowRadius == shadowRadius) { return false; } - mDrawingState.sequence++; - mDrawingState.shadowRadius = shadowRadius; - mDrawingState.modified = true; + mCurrentState.sequence++; + mCurrentState.shadowRadius = shadowRadius; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint) { - if (mDrawingState.fixedTransformHint == fixedTransformHint) { + if (mCurrentState.fixedTransformHint == fixedTransformHint) { return false; } - mDrawingState.sequence++; - mDrawingState.fixedTransformHint = fixedTransformHint; - mDrawingState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; -} - -bool Layer::setStretchEffect(const StretchEffect& effect) { - StretchEffect temp = effect; - temp.sanitize(); - if (mDrawingState.stretchEffect == temp) { - return false; - } - mDrawingState.sequence++; - mDrawingState.stretchEffect = temp; - mDrawingState.modified = true; + mCurrentState.sequence++; + mCurrentState.fixedTransformHint = fixedTransformHint; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -StretchEffect Layer::getStretchEffect() const { - if (mDrawingState.stretchEffect.hasEffect()) { - return mDrawingState.stretchEffect; - } - - sp<Layer> parent = getParent(); - if (parent != nullptr) { - auto effect = parent->getStretchEffect(); - if (effect.hasEffect()) { - // TODO(b/179047472): Map it? Or do we make the effect be in global space? - return effect; - } - } - return StretchEffect{}; -} - -bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* transactionNeeded) { - // The frame rate for layer tree is this layer's frame rate if present, or the parent frame rate - const auto frameRate = [&] { - if (mDrawingState.frameRate.rate.isValid() || - mDrawingState.frameRate.type == FrameRateCompatibility::NoVote) { - return mDrawingState.frameRate; +void Layer::updateTreeHasFrameRateVote() { + const auto traverseTree = [&](const LayerVector::Visitor& visitor) { + auto parent = getParent(); + while (parent) { + visitor(parent.get()); + parent = parent->getParent(); } - return parentFrameRate; - }(); - - *transactionNeeded |= setFrameRateForLayerTree(frameRate); - - // The frame rate is propagated to the children - bool childrenHaveFrameRate = false; - for (const sp<Layer>& child : mCurrentChildren) { - childrenHaveFrameRate |= - child->propagateFrameRateForLayerTree(frameRate, transactionNeeded); - } - - // If we don't have a valid frame rate, but the children do, we set this - // layer as NoVote to allow the children to control the refresh rate - if (!frameRate.rate.isValid() && frameRate.type != FrameRateCompatibility::NoVote && - childrenHaveFrameRate) { - *transactionNeeded |= - setFrameRateForLayerTree(FrameRate(Fps(0.0f), FrameRateCompatibility::NoVote)); - } - - // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes for - // the same reason we are allowing touch boost for those layers. See - // RefreshRateConfigs::getBestRefreshRate for more details. - const auto layerVotedWithDefaultCompatibility = - frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Default; - const auto layerVotedWithNoVote = frameRate.type == FrameRateCompatibility::NoVote; - const auto layerVotedWithExactCompatibility = - frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Exact; - return layerVotedWithDefaultCompatibility || layerVotedWithNoVote || - layerVotedWithExactCompatibility || childrenHaveFrameRate; -} - -void Layer::updateTreeHasFrameRateVote() { - const auto root = [&]() -> sp<Layer> { - sp<Layer> layer = this; - while (auto parent = layer->getParent()) { - layer = parent; + traverse(LayerVector::StateSet::Current, visitor); + }; + + // update parents and children about the vote + // First traverse the tree and count how many layers has votes + int layersWithVote = 0; + traverseTree([&layersWithVote](Layer* layer) { + const auto layerVotedWithDefaultCompatibility = layer->mCurrentState.frameRate.rate > 0 && + layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default; + const auto layerVotedWithNoVote = + layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote; + + // We do not count layers that are ExactOrMultiple for the same reason + // we are allowing touch boost for those layers. See + // RefreshRateConfigs::getBestRefreshRate for more details. + if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote) { + layersWithVote++; } - return layer; - }(); + }); + // Now update the other layers bool transactionNeeded = false; - root->propagateFrameRateForLayerTree({}, &transactionNeeded); + traverseTree([layersWithVote, &transactionNeeded](Layer* layer) { + if (layer->mCurrentState.treeHasFrameRateVote != layersWithVote > 0) { + layer->mCurrentState.sequence++; + layer->mCurrentState.treeHasFrameRateVote = layersWithVote > 0; + layer->mCurrentState.modified = true; + layer->setTransactionFlags(eTransactionNeeded); + transactionNeeded = true; + } + }); - // TODO(b/195668952): we probably don't need eTraversalNeeded here if (transactionNeeded) { mFlinger->setTransactionFlags(eTraversalNeeded); } @@ -1179,13 +1428,17 @@ bool Layer::setFrameRate(FrameRate frameRate) { if (!mFlinger->useFrameRateApi) { return false; } - if (mDrawingState.frameRate == frameRate) { + if (mCurrentState.frameRate == frameRate) { return false; } - mDrawingState.sequence++; - mDrawingState.frameRate = frameRate; - mDrawingState.modified = true; + // Activate the layer in Scheduler's LayerHistory + mFlinger->mScheduler->recordLayerHistory(this, systemTime(), + LayerHistory::LayerUpdateType::SetFrameRate); + + mCurrentState.sequence++; + mCurrentState.frameRate = frameRate; + mCurrentState.modified = true; updateTreeHasFrameRateVote(); @@ -1193,132 +1446,43 @@ bool Layer::setFrameRate(FrameRate frameRate) { return true; } -void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, - nsecs_t postTime) { - mDrawingState.postTime = postTime; - - // Check if one of the bufferlessSurfaceFramesTX contains the same vsyncId. This can happen if - // there are two transactions with the same token, the first one without a buffer and the - // second one with a buffer. We promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX - // in that case. - auto it = mDrawingState.bufferlessSurfaceFramesTX.find(info.vsyncId); - if (it != mDrawingState.bufferlessSurfaceFramesTX.end()) { - // Promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX - mDrawingState.bufferSurfaceFrameTX = it->second; - mDrawingState.bufferlessSurfaceFramesTX.erase(it); - mDrawingState.bufferSurfaceFrameTX->promoteToBuffer(); - mDrawingState.bufferSurfaceFrameTX->setActualQueueTime(postTime); - } else { - mDrawingState.bufferSurfaceFrameTX = - createSurfaceFrameForBuffer(info, postTime, mTransactionName); - } -} - -void Layer::setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info, - nsecs_t postTime) { - mDrawingState.frameTimelineInfo = info; - mDrawingState.postTime = postTime; - mDrawingState.modified = true; - setTransactionFlags(eTransactionNeeded); - - if (const auto& bufferSurfaceFrameTX = mDrawingState.bufferSurfaceFrameTX; - bufferSurfaceFrameTX != nullptr) { - if (bufferSurfaceFrameTX->getToken() == info.vsyncId) { - // BufferSurfaceFrame takes precedence over BufferlessSurfaceFrame. If the same token is - // being used for BufferSurfaceFrame, don't create a new one. - return; - } - } - // For Transactions without a buffer, we create only one SurfaceFrame per vsyncId. If multiple - // transactions use the same vsyncId, we just treat them as one SurfaceFrame (unless they are - // targeting different vsyncs). - auto it = mDrawingState.bufferlessSurfaceFramesTX.find(info.vsyncId); - if (it == mDrawingState.bufferlessSurfaceFramesTX.end()) { - auto surfaceFrame = createSurfaceFrameForTransaction(info, postTime); - mDrawingState.bufferlessSurfaceFramesTX[info.vsyncId] = surfaceFrame; - } else { - if (it->second->getPresentState() == PresentState::Presented) { - // If the SurfaceFrame was already presented, its safe to overwrite it since it must - // have been from previous vsync. - it->second = createSurfaceFrameForTransaction(info, postTime); - } +Layer::FrameRate Layer::getFrameRateForLayerTree() const { + const auto frameRate = getDrawingState().frameRate; + if (frameRate.rate > 0 || frameRate.type == FrameRateCompatibility::NoVote) { + return frameRate; } -} -void Layer::addSurfaceFrameDroppedForBuffer( - std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame) { - surfaceFrame->setDropTime(systemTime()); - surfaceFrame->setPresentState(PresentState::Dropped); - mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); -} - -void Layer::addSurfaceFramePresentedForBuffer( - std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame, nsecs_t acquireFenceTime, - nsecs_t currentLatchTime) { - surfaceFrame->setAcquireFenceTime(acquireFenceTime); - surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime); - mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); - mLastLatchTime = currentLatchTime; -} - -std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForTransaction( - const FrameTimelineInfo& info, nsecs_t postTime) { - auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, - getSequence(), mName, - mTransactionName, - /*isBuffer*/ false, getGameMode()); - // For Transactions, the post time is considered to be both queue and acquire fence time. - surfaceFrame->setActualQueueTime(postTime); - surfaceFrame->setAcquireFenceTime(postTime); - const auto fps = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid()); - if (fps) { - surfaceFrame->setRenderRate(*fps); - } - onSurfaceFrameCreated(surfaceFrame); - return surfaceFrame; -} - -std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForBuffer( - const FrameTimelineInfo& info, nsecs_t queueTime, std::string debugName) { - auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, - getSequence(), mName, debugName, - /*isBuffer*/ true, getGameMode()); - // For buffers, acquire fence time will set during latch. - surfaceFrame->setActualQueueTime(queueTime); - const auto fps = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid()); - if (fps) { - surfaceFrame->setRenderRate(*fps); - } - // TODO(b/178542907): Implement onSurfaceFrameCreated for BQLayer as well. - onSurfaceFrameCreated(surfaceFrame); - return surfaceFrame; -} - -bool Layer::setFrameRateForLayerTree(FrameRate frameRate) { - if (mDrawingState.frameRateForLayerTree == frameRate) { - return false; + // This layer doesn't have a frame rate. If one of its ancestors or successors + // have a vote, return a NoVote for ancestors/successors to set the vote + if (getDrawingState().treeHasFrameRateVote) { + return {0, FrameRateCompatibility::NoVote}; } - mDrawingState.frameRateForLayerTree = frameRate; - - // TODO(b/195668952): we probably don't need to dirty visible regions here - // or even store frameRateForLayerTree in mDrawingState - mDrawingState.sequence++; - mDrawingState.modified = true; - setTransactionFlags(eTransactionNeeded); - - mFlinger->mScheduler->recordLayerHistory(this, systemTime(), - LayerHistory::LayerUpdateType::SetFrameRate); + return frameRate; +} - return true; +void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) { + ATRACE_CALL(); + mCurrentState.barrierLayer_legacy = barrierLayer; + mCurrentState.frameNumber_legacy = frameNumber; + // We don't set eTransactionNeeded, because just receiving a deferral + // request without any other state updates shouldn't actually induce a delay + mCurrentState.modified = true; + pushPendingState(); + mCurrentState.barrierLayer_legacy = nullptr; + mCurrentState.frameNumber_legacy = 0; + mCurrentState.modified = false; } -Layer::FrameRate Layer::getFrameRateForLayerTree() const { - return getDrawingState().frameRateForLayerTree; +void Layer::deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle, uint64_t frameNumber) { + sp<Handle> handle = static_cast<Handle*>(barrierHandle.get()); + deferTransactionUntil_legacy(handle->owner.promote(), frameNumber); } +// ---------------------------------------------------------------------------- +// pageflip handling... +// ---------------------------------------------------------------------------- + bool Layer::isHiddenByPolicy() const { const State& s(mDrawingState); const auto& parent = mDrawingParent.promote(); @@ -1376,20 +1540,20 @@ LayerDebugInfo Layer::getLayerDebugInfo(const DisplayDevice* display) const { info.mVisibleRegion = getVisibleRegion(display); info.mSurfaceDamageRegion = surfaceDamageRegion; info.mLayerStack = getLayerStack(); - info.mX = ds.transform.tx(); - info.mY = ds.transform.ty(); + info.mX = ds.active_legacy.transform.tx(); + info.mY = ds.active_legacy.transform.ty(); info.mZ = ds.z; - info.mWidth = ds.width; - info.mHeight = ds.height; - info.mCrop = ds.crop; + info.mWidth = ds.active_legacy.w; + info.mHeight = ds.active_legacy.h; + info.mCrop = ds.crop_legacy; info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); info.mDataSpace = static_cast<android_dataspace>(getDataSpace()); - info.mMatrix[0][0] = ds.transform[0][0]; - info.mMatrix[0][1] = ds.transform[0][1]; - info.mMatrix[1][0] = ds.transform[1][0]; - info.mMatrix[1][1] = ds.transform[1][1]; + info.mMatrix[0][0] = ds.active_legacy.transform[0][0]; + info.mMatrix[0][1] = ds.active_legacy.transform[0][1]; + info.mMatrix[1][0] = ds.active_legacy.transform[1][0]; + info.mMatrix[1][1] = ds.active_legacy.transform[1][1]; { sp<const GraphicBuffer> buffer = getBuffer(); if (buffer != 0) { @@ -1408,13 +1572,15 @@ LayerDebugInfo Layer::getLayerDebugInfo(const DisplayDevice* display) const { info.mRefreshPending = isBufferLatched(); info.mIsOpaque = isOpaque(ds); info.mContentDirty = contentDirty; - info.mStretchEffect = getStretchEffect(); return info; } void Layer::miniDumpHeader(std::string& result) { - result.append(kDumpTableRowLength, '-'); - result.append("\n"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("-------------------\n"); result.append(" Layer name\n"); result.append(" Z | "); result.append(" Window Type | "); @@ -1422,9 +1588,12 @@ void Layer::miniDumpHeader(std::string& result) { result.append(" Transform | "); result.append(" Disp Frame (LTRB) | "); result.append(" Source Crop (LTRB) | "); - result.append(" Frame Rate (Explicit) (Seamlessness) [Focused]\n"); - result.append(kDumpTableRowLength, '-'); - result.append("\n"); + result.append(" Frame Rate (Explicit) [Focused]\n"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("-------------------\n"); } std::string Layer::frameRateCompatibilityString(Layer::FrameRateCompatibility compatibility) { @@ -1435,8 +1604,6 @@ std::string Layer::frameRateCompatibilityString(Layer::FrameRateCompatibility co return "ExactOrMultiple"; case FrameRateCompatibility::NoVote: return "NoVote"; - case FrameRateCompatibility::Exact: - return "Exact"; } } @@ -1475,20 +1642,22 @@ void Layer::miniDump(std::string& result, const DisplayDevice& display) const { const FloatRect& crop = outputLayerState.sourceCrop; StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, crop.bottom); - const auto frameRate = getFrameRateForLayerTree(); - if (frameRate.rate.isValid() || frameRate.type != FrameRateCompatibility::Default) { - StringAppendF(&result, "%s %15s %17s", to_string(frameRate.rate).c_str(), - frameRateCompatibilityString(frameRate.type).c_str(), - toString(frameRate.seamlessness).c_str()); + if (layerState.frameRate.rate != 0 || + layerState.frameRate.type != FrameRateCompatibility::Default) { + StringAppendF(&result, "% 6.2ffps %15s", layerState.frameRate.rate, + frameRateCompatibilityString(layerState.frameRate.type).c_str()); } else { - result.append(41, ' '); + StringAppendF(&result, " "); } const auto focused = isLayerFocusedBasedOnPriority(getFrameRateSelectionPriority()); StringAppendF(&result, " [%s]\n", focused ? "*" : " "); - result.append(kDumpTableRowLength, '-'); - result.append("\n"); + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - - - - - - -\n"); } void Layer::dumpFrameStats(std::string& result) const { @@ -1515,8 +1684,8 @@ void Layer::dumpFrameEvents(std::string& result) { } void Layer::dumpCallingUidPid(std::string& result) const { - StringAppendF(&result, "Layer %s (%s) callingPid:%d callingUid:%d ownerUid:%d\n", - getName().c_str(), getType(), mCallingPid, mCallingUid, mOwnerUid); + StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().c_str(), getType(), + mCallingPid, mCallingUid); } void Layer::onDisconnect() { @@ -1531,8 +1700,7 @@ void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) { if (newTimestamps) { mFlinger->mTimeStats->setPostTime(getSequence(), newTimestamps->frameNumber, - getName().c_str(), mOwnerUid, newTimestamps->postedTime, - getGameMode()); + getName().c_str(), newTimestamps->postedTime); mFlinger->mTimeStats->setAcquireFence(getSequence(), newTimestamps->frameNumber, newTimestamps->acquireFence); } @@ -1562,51 +1730,79 @@ size_t Layer::getChildrenCount() const { return count; } -void Layer::setGameModeForTree(int parentGameMode) { - int gameMode = parentGameMode; - auto& currentState = getDrawingState(); - if (currentState.metadata.has(METADATA_GAME_MODE)) { - gameMode = currentState.metadata.getInt32(METADATA_GAME_MODE, 0); - } - setGameMode(gameMode); - for (const sp<Layer>& child : mCurrentChildren) { - child->setGameModeForTree(gameMode); - } -} - void Layer::addChild(const sp<Layer>& layer) { - mFlinger->mSomeChildrenChanged = true; + mChildrenChanged = true; setTransactionFlags(eTransactionNeeded); mCurrentChildren.add(layer); layer->setParent(this); - layer->setGameModeForTree(mGameMode); updateTreeHasFrameRateVote(); } ssize_t Layer::removeChild(const sp<Layer>& layer) { - mFlinger->mSomeChildrenChanged = true; + mChildrenChanged = true; setTransactionFlags(eTransactionNeeded); layer->setParent(nullptr); const auto removeResult = mCurrentChildren.remove(layer); updateTreeHasFrameRateVote(); - layer->setGameModeForTree(0); layer->updateTreeHasFrameRateVote(); return removeResult; } +void Layer::reparentChildren(const sp<Layer>& newParent) { + if (attachChildren()) { + setTransactionFlags(eTransactionNeeded); + } + + for (const sp<Layer>& child : mCurrentChildren) { + newParent->addChild(child); + } + mCurrentChildren.clear(); + updateTreeHasFrameRateVote(); +} + +bool Layer::reparentChildren(const sp<IBinder>& newParentHandle) { + sp<Handle> handle = nullptr; + sp<Layer> newParent = nullptr; + if (newParentHandle == nullptr) { + return false; + } + handle = static_cast<Handle*>(newParentHandle.get()); + newParent = handle->owner.promote(); + if (newParent == nullptr) { + ALOGE("Unable to promote Layer handle"); + return false; + } + + reparentChildren(newParent); + + return true; +} + void Layer::setChildrenDrawingParent(const sp<Layer>& newParent) { for (const sp<Layer>& child : mDrawingChildren) { child->mDrawingParent = newParent; - child->computeBounds(newParent->mBounds, newParent->mEffectiveTransform, + child->computeBounds(newParent->mBounds, + newParent->getTransformWithScale(newParent->getBufferScaleTransform()), newParent->mEffectiveShadowRadius); } } bool Layer::reparent(const sp<IBinder>& newParentHandle) { + bool callSetTransactionFlags = false; + + // While layers are detached, we allow most operations + // and simply halt performing the actual transaction. However + // for reparent != null we would enter the mRemovedFromCurrentState + // state, regardless of whether doTransaction was called, and + // so we need to prevent the update here. + if (mLayerDetached && newParentHandle == nullptr) { + return false; + } + sp<Layer> newParent; if (newParentHandle != nullptr) { auto handle = static_cast<Handle*>(newParentHandle.get()); @@ -1633,23 +1829,62 @@ bool Layer::reparent(const sp<IBinder>& newParentHandle) { } else { onRemovedFromCurrentState(); } + + if (mLayerDetached) { + mLayerDetached = false; + callSetTransactionFlags = true; + } } else { onRemovedFromCurrentState(); } + if (callSetTransactionFlags || attachChildren()) { + setTransactionFlags(eTransactionNeeded); + } + return true; +} + +bool Layer::detachChildren() { + for (const sp<Layer>& child : mCurrentChildren) { + sp<Client> parentClient = mClientRef.promote(); + sp<Client> client(child->mClientRef.promote()); + if (client != nullptr && parentClient != client) { + child->mLayerDetached = true; + child->detachChildren(); + child->removeRemoteSyncPoints(); + } + } + return true; } +bool Layer::attachChildren() { + bool changed = false; + for (const sp<Layer>& child : mCurrentChildren) { + sp<Client> parentClient = mClientRef.promote(); + sp<Client> client(child->mClientRef.promote()); + if (client != nullptr && parentClient != client) { + if (child->mLayerDetached) { + child->mLayerDetached = false; + changed = true; + } + changed |= child->attachChildren(); + } + } + + return changed; +} + bool Layer::setColorTransform(const mat4& matrix) { static const mat4 identityMatrix = mat4(); - if (mDrawingState.colorTransform == matrix) { + if (mCurrentState.colorTransform == matrix) { return false; } - ++mDrawingState.sequence; - mDrawingState.colorTransform = matrix; - mDrawingState.hasColorTransform = matrix != identityMatrix; - mDrawingState.modified = true; + ++mCurrentState.sequence; + mCurrentState.colorTransform = matrix; + mCurrentState.hasColorTransform = matrix != identityMatrix; + mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -1681,13 +1916,15 @@ void Layer::setParent(const sp<Layer>& layer) { mCurrentParent = layer; } -int32_t Layer::getZ(LayerVector::StateSet) const { - return mDrawingState.z; +int32_t Layer::getZ(LayerVector::StateSet stateSet) const { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const State& state = useDrawing ? mDrawingState : mCurrentState; + return state.z; } bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) const { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; - const State& state = useDrawing ? mDrawingState : mDrawingState; + const State& state = useDrawing ? mDrawingState : mCurrentState; return state.isRelativeOf; } @@ -1697,7 +1934,7 @@ __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::mak "makeTraversalList received invalid stateSet"); const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; - const State& state = useDrawing ? mDrawingState : mDrawingState; + const State& state = useDrawing ? mDrawingState : mCurrentState; if (state.zOrderRelatives.size() == 0) { *outSkipRelativeZUsers = true; @@ -1796,7 +2033,7 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, void Layer::traverse(LayerVector::StateSet state, const LayerVector::Visitor& visitor) { visitor(this); const LayerVector& children = - state == LayerVector::StateSet::Drawing ? mDrawingChildren : mCurrentChildren; + state == LayerVector::StateSet::Drawing ? mDrawingChildren : mCurrentChildren; for (const sp<Layer>& child : children) { child->traverse(state, visitor); } @@ -1808,7 +2045,7 @@ LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet, "makeTraversalList received invalid stateSet"); const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; - const State& state = useDrawing ? mDrawingState : mDrawingState; + const State& state = useDrawing ? mDrawingState : mCurrentState; LayerVector traverse(stateSet); for (const wp<Layer>& weakRelative : state.zOrderRelatives) { @@ -1821,7 +2058,7 @@ LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet, } for (const sp<Layer>& child : children) { - const State& childState = useDrawing ? child->mDrawingState : child->mDrawingState; + const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState; // If a layer has a relativeOf layer, only ignore if the layer it's relative to is a // descendent of the top most parent of the tree. If it's not a descendent, then just add // the child here since it won't be added later as a relative. @@ -1889,7 +2126,7 @@ half Layer::getAlpha() const { } ui::Transform::RotationFlags Layer::getFixedTransformHint() const { - ui::Transform::RotationFlags fixedTransformHint = mDrawingState.fixedTransformHint; + ui::Transform::RotationFlags fixedTransformHint = mCurrentState.fixedTransformHint; if (fixedTransformHint != ui::Transform::ROT_INVALID) { return fixedTransformHint; } @@ -1904,19 +2141,7 @@ half4 Layer::getColor() const { } int32_t Layer::getBackgroundBlurRadius() const { - const auto& p = mDrawingParent.promote(); - - half parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0_hf; - return parentAlpha * getDrawingState().backgroundBlurRadius; -} - -const std::vector<BlurRegion> Layer::getBlurRegions() const { - auto regionsCopy(getDrawingState().blurRegions); - float layerAlpha = getAlpha(); - for (auto& region : regionsCopy) { - region.alpha = region.alpha * layerAlpha; - } - return regionsCopy; + return getDrawingState().backgroundBlurRadius; } Layer::RoundedCornerState Layer::getRoundedCornerState() const { @@ -1938,42 +2163,21 @@ Layer::RoundedCornerState Layer::getRoundedCornerState() const { } } const float radius = getDrawingState().cornerRadius; - return radius > 0 && getCroppedBufferSize(getDrawingState()).isValid() - ? RoundedCornerState(getCroppedBufferSize(getDrawingState()).toFloatRect(), radius) + return radius > 0 && getCrop(getDrawingState()).isValid() + ? RoundedCornerState(getCrop(getDrawingState()).toFloatRect(), radius) : RoundedCornerState(); } -void Layer::prepareShadowClientComposition(LayerFE::LayerSettings& caster, - const Rect& layerStackRect) { +renderengine::ShadowSettings Layer::getShadowSettings(const Rect& viewport) const { renderengine::ShadowSettings state = mFlinger->mDrawingState.globalShadowSettings; - // Note: this preserves existing behavior of shadowing the entire layer and not cropping it if - // transparent regions are present. This may not be necessary since shadows are only cast by - // SurfaceFlinger's EffectLayers, which do not typically use transparent regions. - state.boundaries = mBounds; - // Shift the spot light x-position to the middle of the display and then // offset it by casting layer's screen pos. - state.lightPos.x = (layerStackRect.width() / 2.f) - mScreenBounds.left; + state.lightPos.x = (viewport.width() / 2.f) - mScreenBounds.left; state.lightPos.y -= mScreenBounds.top; state.length = mEffectiveShadowRadius; - - if (state.length > 0.f) { - const float casterAlpha = caster.alpha; - const bool casterIsOpaque = - ((caster.source.buffer.buffer != nullptr) && caster.source.buffer.isOpaque); - - // If the casting layer is translucent, we need to fill in the shadow underneath the layer. - // Otherwise the generated shadow will only be shown around the casting layer. - state.casterIsTranslucent = !casterIsOpaque || (casterAlpha < 1.0f); - state.ambientColor *= casterAlpha; - state.spotColor *= casterAlpha; - - if (state.ambientColor.a > 0.f && state.spotColor.a > 0.f) { - caster.shadow = state; - } - } + return state; } void Layer::commitChildList() { @@ -2001,15 +2205,15 @@ static wp<Layer> extractLayerFromBinder(const wp<IBinder>& weakBinderHandle) { } void Layer::setInputInfo(const InputWindowInfo& info) { - mDrawingState.inputInfo = info; - mDrawingState.touchableRegionCrop = extractLayerFromBinder(info.touchableRegionCropHandle); - mDrawingState.modified = true; - mFlinger->mInputInfoChanged = true; + mCurrentState.inputInfo = info; + mCurrentState.touchableRegionCrop = extractLayerFromBinder(info.touchableRegionCropHandle); + mCurrentState.modified = true; + mCurrentState.inputInfoChanged = true; setTransactionFlags(eTransactionNeeded); } LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags, - const DisplayDevice* display) { + const DisplayDevice* display) const { LayerProto* layerProto = layersProto.add_layers(); writeToProtoDrawingState(layerProto, traceFlags, display); writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags); @@ -2030,10 +2234,18 @@ LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags, } void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, - const DisplayDevice* display) { - const ui::Transform transform = getTransform(); + const DisplayDevice* display) const { + ui::Transform transform = getTransform(); if (traceFlags & SurfaceTracing::TRACE_CRITICAL) { + for (const auto& pendingState : mPendingStatesSnapshot) { + auto barrierLayer = pendingState.barrierLayer_legacy.promote(); + if (barrierLayer != nullptr) { + BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer(); + barrierLayerProto->set_id(barrierLayer->sequence); + barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy); + } + } auto buffer = getBuffer(); if (buffer != nullptr) { @@ -2051,7 +2263,6 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, layerInfo->set_effective_scaling_mode(getEffectiveScalingMode()); layerInfo->set_corner_radius(getRoundedCornerState().radius); - layerInfo->set_background_blur_radius(getBackgroundBlurRadius()); layerInfo->set_is_trusted_overlay(isTrustedOverlay()); LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform()); LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(), @@ -2080,12 +2291,12 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, } void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet, - uint32_t traceFlags) { + uint32_t traceFlags) const { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; - const State& state = useDrawing ? mDrawingState : mDrawingState; + const State& state = useDrawing ? mDrawingState : mCurrentState; - ui::Transform requestedTransform = state.transform; + ui::Transform requestedTransform = state.active_legacy.transform; if (traceFlags & SurfaceTracing::TRACE_CRITICAL) { layerInfo->set_id(sequence); @@ -2114,10 +2325,11 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet return layerInfo->mutable_requested_position(); }); - LayerProtoHelper::writeSizeToProto(state.width, state.height, + LayerProtoHelper::writeSizeToProto(state.active_legacy.w, state.active_legacy.h, [&]() { return layerInfo->mutable_size(); }); - LayerProtoHelper::writeToProto(state.crop, [&]() { return layerInfo->mutable_crop(); }); + LayerProtoHelper::writeToProto(state.crop_legacy, + [&]() { return layerInfo->mutable_crop(); }); layerInfo->set_is_opaque(isOpaque(state)); @@ -2146,19 +2358,10 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet } layerInfo->set_is_relative_of(state.isRelativeOf); - - layerInfo->set_owner_uid(mOwnerUid); } if (traceFlags & SurfaceTracing::TRACE_INPUT) { - InputWindowInfo info; - if (useDrawing) { - info = fillInputInfo({nullptr}); - } else { - info = state.inputInfo; - } - - LayerProtoHelper::writeToProto(info, state.touchableRegionCrop, + LayerProtoHelper::writeToProto(state.inputInfo, state.touchableRegionCrop, [&]() { return layerInfo->mutable_input_window_info(); }); } @@ -2171,149 +2374,65 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet } bool Layer::isRemovedFromCurrentState() const { - return mRemovedFromDrawingState; -} - -ui::Transform Layer::getInputTransform() const { - return getTransform(); + return mRemovedFromCurrentState; } -Rect Layer::getInputBounds() const { - return getCroppedBufferSize(getDrawingState()); -} - -void Layer::fillInputFrameInfo(InputWindowInfo& info, const ui::Transform& toPhysicalDisplay) { - // Transform layer size to screen space and inset it by surface insets. - // If this is a portal window, set the touchableRegion to the layerBounds. - Rect layerBounds = info.portalToDisplayId == ADISPLAY_ID_NONE - ? getInputBounds() - : info.touchableRegion.getBounds(); - if (!layerBounds.isValid()) { - layerBounds = getInputBounds(); +InputWindowInfo Layer::fillInputInfo() { + if (!hasInputInfo()) { + mDrawingState.inputInfo.name = getName(); + mDrawingState.inputInfo.ownerUid = mCallingUid; + mDrawingState.inputInfo.ownerPid = mCallingPid; + mDrawingState.inputInfo.inputFeatures = + InputWindowInfo::INPUT_FEATURE_NO_INPUT_CHANNEL; + mDrawingState.inputInfo.layoutParamsFlags = InputWindowInfo::FLAG_NOT_TOUCH_MODAL; + mDrawingState.inputInfo.displayId = getLayerStack(); } - if (!layerBounds.isValid()) { - // If the layer bounds is empty, set the frame to empty and clear the transform - info.frameLeft = 0; - info.frameTop = 0; - info.frameRight = 0; - info.frameBottom = 0; - info.transform.reset(); - return; + InputWindowInfo info = mDrawingState.inputInfo; + info.id = sequence; + + if (info.displayId == ADISPLAY_ID_NONE) { + info.displayId = getLayerStack(); } - ui::Transform layerToDisplay = getInputTransform(); - // Transform that takes window coordinates to unrotated display coordinates - ui::Transform t = toPhysicalDisplay * layerToDisplay; + ui::Transform t = getTransform(); + const float xScale = t.sx(); + const float yScale = t.sy(); int32_t xSurfaceInset = info.surfaceInset; int32_t ySurfaceInset = info.surfaceInset; - // Bring screenBounds into unrotated space - Rect screenBounds = toPhysicalDisplay.transform(Rect{mScreenBounds}); - - const float xScale = t.getScaleX(); - const float yScale = t.getScaleY(); if (xScale != 1.0f || yScale != 1.0f) { + info.windowXScale *= (xScale != 0.0f) ? 1.0f / xScale : 0.0f; + info.windowYScale *= (yScale != 0.0f) ? 1.0f / yScale : 0.0f; + info.touchableRegion.scaleSelf(xScale, yScale); xSurfaceInset = std::round(xSurfaceInset * xScale); ySurfaceInset = std::round(ySurfaceInset * yScale); } - // Transform the layer bounds from layer coordinate space to display coordinate space. - Rect transformedLayerBounds = t.transform(layerBounds); - - // clamp inset to layer bounds - xSurfaceInset = (xSurfaceInset >= 0) - ? std::min(xSurfaceInset, transformedLayerBounds.getWidth() / 2) - : 0; - ySurfaceInset = (ySurfaceInset >= 0) - ? std::min(ySurfaceInset, transformedLayerBounds.getHeight() / 2) - : 0; - - // inset while protecting from overflow TODO(b/161235021): What is going wrong - // in the overflow scenario? - { - int32_t tmp; - if (!__builtin_add_overflow(transformedLayerBounds.left, xSurfaceInset, &tmp)) - transformedLayerBounds.left = tmp; - if (!__builtin_sub_overflow(transformedLayerBounds.right, xSurfaceInset, &tmp)) - transformedLayerBounds.right = tmp; - if (!__builtin_add_overflow(transformedLayerBounds.top, ySurfaceInset, &tmp)) - transformedLayerBounds.top = tmp; - if (!__builtin_sub_overflow(transformedLayerBounds.bottom, ySurfaceInset, &tmp)) - transformedLayerBounds.bottom = tmp; - } - - // Compute the correct transform to send to input. This will allow it to transform the - // input coordinates from display space into window space. Therefore, it needs to use the - // final layer frame to create the inverse transform. Since surface insets are added later, - // along with the overflow, the best way to ensure we get the correct transform is to use - // the final frame calculated. - // 1. Take the original transform set on the window and get the inverse transform. This is - // used to get the final bounds in display space (ignorning the transform). Apply the - // inverse transform on the layerBounds to get the untransformed frame (in layer space) - // 2. Take the top and left of the untransformed frame to get the real position on screen. - // Apply the layer transform on top/left so it includes any scale or rotation. These will - // be the new translation values for the transform. - // 3. Update the translation of the original transform to the new translation values. - // 4. Send the inverse transform to input so the coordinates can be transformed back into - // window space. - ui::Transform inverseTransform = t.inverse(); - Rect nonTransformedBounds = inverseTransform.transform(transformedLayerBounds); - vec2 translation = t.transform(nonTransformedBounds.left, nonTransformedBounds.top); - ui::Transform inputTransform(t); - inputTransform.set(translation.x, translation.y); - info.transform = inputTransform.inverse(); - - // We need to send the layer bounds cropped to the screenbounds since the layer can be cropped. - // The frame should be the area the user sees on screen since it's used for occlusion - // detection. - transformedLayerBounds.intersect(screenBounds, &transformedLayerBounds); - info.frameLeft = transformedLayerBounds.left; - info.frameTop = transformedLayerBounds.top; - info.frameRight = transformedLayerBounds.right; - info.frameBottom = transformedLayerBounds.bottom; - - // Position the touchable region relative to frame screen location and restrict it to frame - // bounds. - info.touchableRegion = inputTransform.transform(info.touchableRegion); -} - -void Layer::fillTouchOcclusionMode(InputWindowInfo& info) { - sp<Layer> p = this; - while (p != nullptr && !p->hasInputInfo()) { - p = p->mDrawingParent.promote(); - } - if (p != nullptr) { - info.touchOcclusionMode = p->mDrawingState.inputInfo.touchOcclusionMode; - } -} - -InputWindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) { - if (!hasInputInfo()) { - mDrawingState.inputInfo.name = getName(); - mDrawingState.inputInfo.ownerUid = mOwnerUid; - mDrawingState.inputInfo.ownerPid = mOwnerPid; - mDrawingState.inputInfo.inputFeatures = InputWindowInfo::Feature::NO_INPUT_CHANNEL; - mDrawingState.inputInfo.flags = InputWindowInfo::Flag::NOT_TOUCH_MODAL; - mDrawingState.inputInfo.displayId = getLayerStack(); + // Transform layer size to screen space and inset it by surface insets. + // If this is a portal window, set the touchableRegion to the layerBounds. + Rect layerBounds = info.portalToDisplayId == ADISPLAY_ID_NONE + ? getBufferSize(getDrawingState()) + : info.touchableRegion.getBounds(); + if (!layerBounds.isValid()) { + layerBounds = getCroppedBufferSize(getDrawingState()); } + layerBounds = t.transform(layerBounds); - InputWindowInfo info = mDrawingState.inputInfo; - info.id = sequence; + // clamp inset to layer bounds + xSurfaceInset = (xSurfaceInset >= 0) ? std::min(xSurfaceInset, layerBounds.getWidth() / 2) : 0; + ySurfaceInset = (ySurfaceInset >= 0) ? std::min(ySurfaceInset, layerBounds.getHeight() / 2) : 0; - if (info.displayId == ADISPLAY_ID_NONE) { - info.displayId = getLayerStack(); - } + layerBounds.inset(xSurfaceInset, ySurfaceInset, xSurfaceInset, ySurfaceInset); - // Transform that goes from "logical(rotated)" display to physical/unrotated display. - // This is for when inputflinger operates in physical display-space. - ui::Transform toPhysicalDisplay; - if (display) { - toPhysicalDisplay = display->getTransform(); - info.displayWidth = display->getWidth(); - info.displayHeight = display->getHeight(); - } - fillInputFrameInfo(info, toPhysicalDisplay); + // Input coordinate should match the layer bounds. + info.frameLeft = layerBounds.left; + info.frameTop = layerBounds.top; + info.frameRight = layerBounds.right; + info.frameBottom = layerBounds.bottom; + // Position the touchable region relative to frame screen location and restrict it to frame + // bounds. + info.touchableRegion = info.touchableRegion.translate(info.frameLeft, info.frameTop); // For compatibility reasons we let layers which can receive input // receive input before they have actually submitted a buffer. Because // of this we use canReceiveInput instead of isVisible to check the @@ -2323,33 +2442,28 @@ InputWindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) { // InputDispatcher, and obviously if they aren't visible they can't occlude // anything. info.visible = hasInputInfo() ? canReceiveInput() : isVisible(); - info.alpha = getAlpha(); - fillTouchOcclusionMode(info); auto cropLayer = mDrawingState.touchableRegionCrop.promote(); if (info.replaceTouchableRegionWithCrop) { if (cropLayer == nullptr) { - info.touchableRegion = Region(toPhysicalDisplay.transform(Rect{mScreenBounds})); + info.touchableRegion = Region(Rect{mScreenBounds}); } else { - info.touchableRegion = - Region(toPhysicalDisplay.transform(Rect{cropLayer->mScreenBounds})); + info.touchableRegion = Region(Rect{cropLayer->mScreenBounds}); } } else if (cropLayer != nullptr) { - info.touchableRegion = info.touchableRegion.intersect( - toPhysicalDisplay.transform(Rect{cropLayer->mScreenBounds})); + info.touchableRegion = info.touchableRegion.intersect(Rect{cropLayer->mScreenBounds}); } // Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state // if it was set by WM for a known system overlay info.trustedOverlay = info.trustedOverlay || isTrustedOverlay(); - // If the layer is a clone, we need to crop the input region to cloned root to prevent // touches from going outside the cloned area. if (isClone()) { sp<Layer> clonedRoot = getClonedRoot(); if (clonedRoot != nullptr) { - Rect rect = toPhysicalDisplay.transform(Rect{clonedRoot->mScreenBounds}); + Rect rect(clonedRoot->mScreenBounds); info.touchableRegion = info.touchableRegion.intersect(rect); } } @@ -2476,7 +2590,7 @@ void Layer::updateClonedInputInfo(const std::map<sp<Layer>, sp<Layer>>& clonedLa } // Cloned layers shouldn't handle watch outside since their z order is not determined by // WM or the client. - mDrawingState.inputInfo.flags &= ~InputWindowInfo::Flag::WATCH_OUTSIDE_TOUCH; + mDrawingState.inputInfo.layoutParamsFlags &= ~InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH; } void Layer::updateClonedRelatives(const std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) { @@ -2525,50 +2639,14 @@ Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t comp return FrameRateCompatibility::Default; case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE: return FrameRateCompatibility::ExactOrMultiple; - case ANATIVEWINDOW_FRAME_RATE_EXACT: - return FrameRateCompatibility::Exact; default: LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility); return FrameRateCompatibility::Default; } } -scheduler::Seamlessness Layer::FrameRate::convertChangeFrameRateStrategy(int8_t strategy) { - switch (strategy) { - case ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS: - return Seamlessness::OnlySeamless; - case ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS: - return Seamlessness::SeamedAndSeamless; - default: - LOG_ALWAYS_FATAL("Invalid change frame sate strategy value %d", strategy); - return Seamlessness::Default; - } -} - -bool Layer::getPrimaryDisplayOnly() const { - const State& s(mDrawingState); - if (s.flags & layer_state_t::eLayerSkipScreenshot) { - return true; - } - - sp<Layer> parent = mDrawingParent.promote(); - return parent == nullptr ? false : parent->getPrimaryDisplayOnly(); -} - -void Layer::setClonedChild(const sp<Layer>& clonedChild) { - mClonedChild = clonedChild; - mHadClonedChild = true; - mFlinger->mNumClones++; -} - // --------------------------------------------------------------------------- -std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) { - return stream << "{rate=" << rate.rate - << " type=" << Layer::frameRateCompatibilityString(rate.type) - << " seamlessness=" << toString(rate.seamlessness) << "}"; -} - }; // namespace android #if defined(__gl_h_) |