diff options
| author | 2020-09-10 17:22:18 +0000 | |
|---|---|---|
| committer | 2020-09-10 17:22:18 +0000 | |
| commit | cdb6b16dec3a541b455be99d075004cb2f0a0cd7 (patch) | |
| tree | f7110d50445c67a337105034b1f2db3946a88fef /services/surfaceflinger/Layer.cpp | |
| parent | 171cac1b603e4bb83412eb596d05a500af5d7a76 (diff) | |
| parent | ac07d0f5ab16bb9e8bbbabb589d1c7d36817baa9 (diff) | |
Merge "Merge Android R"
Diffstat (limited to 'services/surfaceflinger/Layer.cpp')
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 1285 |
1 files changed, 898 insertions, 387 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 3e6ddedf48..03903f6d07 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "Layer" @@ -22,11 +26,11 @@ #include "Layer.h" #include <android-base/stringprintf.h> +#include <android/native_window.h> +#include <binder/IPCThreadState.h> #include <compositionengine/Display.h> -#include <compositionengine/Layer.h> #include <compositionengine/LayerFECompositionState.h> #include <compositionengine/OutputLayer.h> -#include <compositionengine/impl/LayerCompositionState.h> #include <compositionengine/impl/OutputLayerCompositionState.h> #include <cutils/compiler.h> #include <cutils/native_handle.h> @@ -53,10 +57,11 @@ #include <sstream> #include "BufferLayer.h" -#include "ColorLayer.h" #include "Colorizer.h" #include "DisplayDevice.h" #include "DisplayHardware/HWComposer.h" +#include "EffectLayer.h" +#include "FrameTracer/FrameTracer.h" #include "LayerProtoHelper.h" #include "LayerRejecter.h" #include "MonitoredProducer.h" @@ -76,15 +81,11 @@ Layer::Layer(const LayerCreationArgs& args) mName(args.name), mClientRef(args.client), mWindowType(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0)) { - mCurrentCrop.makeInvalid(); - 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; - mTransactionName = String8("TX - ") + mName; - mCurrentState.active_legacy.w = args.w; mCurrentState.active_legacy.h = args.h; mCurrentState.flags = layerFlags; @@ -99,18 +100,31 @@ Layer::Layer(const LayerCreationArgs& args) 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.clear(); + 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; + + if (args.flags & ISurfaceComposerClient::eNoColorFill) { + // Set an invalid color so there is no color fill. + 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; @@ -120,9 +134,12 @@ Layer::Layer(const LayerCreationArgs& args) mFrameEventHistory.initializeCompositorTiming(compositorTiming); mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval); - mSchedulerLayerHandle = mFlinger->mScheduler->registerLayer(mName.c_str(), mWindowType); + mCallingPid = args.callingPid; + mCallingUid = args.callingUid; +} - mFlinger->onLayerCreated(); +void Layer::onFirstRef() { + mFlinger->onLayerFirstRef(this); } Layer::~Layer() { @@ -135,6 +152,20 @@ Layer::~Layer() { mFlinger->onLayerDestroyed(this); } +LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name, + uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata) + : flinger(flinger), + client(std::move(client)), + name(std::move(name)), + w(w), + h(h), + flags(flags), + metadata(std::move(metadata)) { + IPCThreadState* ipc = IPCThreadState::self(); + callingPid = ipc->getCallingPid(); + callingUid = ipc->getCallingUid(); +} + // --------------------------------------------------------------------------- // callbacks // --------------------------------------------------------------------------- @@ -142,7 +173,7 @@ Layer::~Layer() { /* * onLayerDisplayed is only meaningful for BufferLayer, but, is called through * Layer. So, the implementation is done in BufferLayer. When called on a - * ColorLayer object, it's essentially a NOP. + * EffectLayer object, it's essentially a NOP. */ void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {} @@ -198,13 +229,23 @@ void Layer::removeFromCurrentState() { mFlinger->markLayerPendingRemovalLocked(this); } +sp<Layer> Layer::getRootLayer() { + sp<Layer> parent = getParent(); + if (parent == nullptr) { + return this; + } + return parent->getRootLayer(); +} + void Layer::onRemovedFromCurrentState() { - auto layersInTree = getLayersInTree(LayerVector::StateSet::Current); + // Use the root layer since we want to maintain the hierarchy for the entire subtree. + auto layersInTree = getRootLayer()->getLayersInTree(LayerVector::StateSet::Current); std::sort(layersInTree.begin(), layersInTree.end()); - for (const auto& layer : layersInTree) { + + traverse(LayerVector::StateSet::Current, [&](Layer* layer) { layer->removeFromCurrentState(); layer->removeRelativeZ(layersInTree); - } + }); } void Layer::addToCurrentState() { @@ -219,10 +260,6 @@ void Layer::addToCurrentState() { // set-up // --------------------------------------------------------------------------- -const String8& Layer::getName() const { - return mName; -} - bool Layer::getPremultipledAlpha() const { return mPremultipliedAlpha; } @@ -241,37 +278,6 @@ sp<IBinder> Layer::getHandle() { // h/w composer set-up // --------------------------------------------------------------------------- -bool Layer::hasHwcLayer(const sp<const DisplayDevice>& displayDevice) { - auto outputLayer = findOutputLayerForDisplay(displayDevice); - LOG_FATAL_IF(!outputLayer); - return outputLayer->getState().hwc && (*outputLayer->getState().hwc).hwcLayer != nullptr; -} - -HWC2::Layer* Layer::getHwcLayer(const sp<const DisplayDevice>& displayDevice) { - auto outputLayer = findOutputLayerForDisplay(displayDevice); - if (!outputLayer || !outputLayer->getState().hwc) { - return nullptr; - } - return (*outputLayer->getState().hwc).hwcLayer.get(); -} - -Rect Layer::getContentCrop() const { - // this is the crop rectangle that applies to the buffer - // itself (as opposed to the window) - Rect crop; - if (!mCurrentCrop.isEmpty()) { - // if the buffer crop is defined, we use that - crop = mCurrentCrop; - } else if (mActiveBuffer != nullptr) { - // otherwise we use the whole buffer - crop = mActiveBuffer->getBounds(); - } else { - // if we don't have a buffer yet, we use an empty/invalid crop - crop.makeInvalid(); - } - return crop; -} - static Rect reduce(const Rect& win, const Region& exclude) { if (CC_LIKELY(exclude.isEmpty())) { return win; @@ -316,7 +322,7 @@ 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() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return {}; } @@ -328,10 +334,10 @@ ui::Transform Layer::getBufferScaleTransform() const { return {}; } - int bufferWidth = mActiveBuffer->getWidth(); - int bufferHeight = mActiveBuffer->getHeight(); + int bufferWidth = getBuffer()->getWidth(); + int bufferHeight = getBuffer()->getHeight(); - if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { + if (getBufferTransform() & NATIVE_WINDOW_TRANSFORM_ROT_90) { std::swap(bufferWidth, bufferHeight); } @@ -346,7 +352,7 @@ ui::Transform Layer::getBufferScaleTransform() const { 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() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return mEffectiveTransform; } return mEffectiveTransform * bufferScaleTransform; @@ -355,13 +361,14 @@ ui::Transform Layer::getTransformWithScale(const ui::Transform& bufferScaleTrans 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() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return mBounds; } return bufferScaleTransform.inverse().transform(mBounds); } -void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform) { +void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform, + float parentShadowRadius) { const State& s(getDrawingState()); // Calculate effective layer transform @@ -384,11 +391,23 @@ void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform) mBounds = bounds; mScreenBounds = mEffectiveTransform.transform(mBounds); + // Use the layer's own shadow radius if set. Otherwise get the radius from + // parent. + if (s.shadowRadius > 0.f) { + mEffectiveShadowRadius = s.shadowRadius; + } else { + mEffectiveShadowRadius = parentShadowRadius; + } + + // Shadow radius is passed down to only one layer so if the layer can draw shadows, + // 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(getBoundsPreScaling(bufferScaleTransform), - getTransformWithScale(bufferScaleTransform)); + getTransformWithScale(bufferScaleTransform), childShadowRadius); } } @@ -413,15 +432,43 @@ void Layer::setupRoundedCornersCropCoordinates(Rect win, win.bottom -= roundedCornersCrop.top; } -void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositionState) const { +void Layer::prepareBasicGeometryCompositionState() { const auto& drawingState{getDrawingState()}; - auto alpha = static_cast<float>(getAlpha()); - auto blendMode = HWC2::BlendMode::None; - if (!isOpaque(drawingState) || alpha != 1.0f) { - blendMode = - mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage; + const uint32_t layerStack = getLayerStack(); + const auto alpha = static_cast<float>(getAlpha()); + const bool opaque = isOpaque(drawingState); + const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f; + + auto blendMode = Hwc2::IComposerClient::BlendMode::NONE; + if (!opaque || alpha != 1.0f) { + blendMode = mPremultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED + : Hwc2::IComposerClient::BlendMode::COVERAGE; } + auto* compositionState = editCompositionState(); + compositionState->layerStackId = + (layerStack != ~0u) ? std::make_optional(layerStack) : std::nullopt; + compositionState->internalOnly = getPrimaryDisplayOnly(); + compositionState->isVisible = isVisible(); + compositionState->isOpaque = opaque && !usesRoundedCorners && alpha == 1.f; + compositionState->shadowRadius = mEffectiveShadowRadius; + + compositionState->contentDirty = contentDirty; + contentDirty = false; + + compositionState->geomLayerBounds = mBounds; + compositionState->geomLayerTransform = getTransform(); + compositionState->geomInverseLayerTransform = compositionState->geomLayerTransform.inverse(); + compositionState->transparentRegionHint = getActiveTransparentRegion(drawingState); + + compositionState->blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode); + compositionState->alpha = alpha; + compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius; +} + +void Layer::prepareGeometryCompositionState() { + const auto& drawingState{getDrawingState()}; + int type = drawingState.metadata.getInt32(METADATA_WINDOW_TYPE, 0); int appId = drawingState.metadata.getInt32(METADATA_OWNER_UID, 0); sp<Layer> parent = mDrawingParent.promote(); @@ -429,174 +476,274 @@ void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositio auto& parentState = parent->getDrawingState(); const int parentType = parentState.metadata.getInt32(METADATA_WINDOW_TYPE, 0); const int parentAppId = parentState.metadata.getInt32(METADATA_OWNER_UID, 0); - if (parentType >= 0 || parentAppId >= 0) { + if (parentType > 0 && parentAppId > 0) { type = parentType; appId = parentAppId; } } - compositionState.geomLayerTransform = getTransform(); - compositionState.geomInverseLayerTransform = compositionState.geomLayerTransform.inverse(); - compositionState.geomBufferSize = getBufferSize(drawingState); - compositionState.geomContentCrop = getContentCrop(); - compositionState.geomCrop = getCrop(drawingState); - compositionState.geomBufferTransform = mCurrentTransform; - compositionState.geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse(); - compositionState.geomActiveTransparentRegion = getActiveTransparentRegion(drawingState); - compositionState.geomLayerBounds = mBounds; - compositionState.geomUsesSourceCrop = usesSourceCrop(); - compositionState.isSecure = isSecure(); + auto* compositionState = editCompositionState(); - compositionState.blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode); - compositionState.alpha = alpha; - compositionState.type = type; - compositionState.appId = appId; -} + compositionState->geomBufferSize = getBufferSize(drawingState); + compositionState->geomContentCrop = getBufferCrop(); + compositionState->geomCrop = getCrop(drawingState); + compositionState->geomBufferTransform = getBufferTransform(); + compositionState->geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse(); + 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) { + const auto& genericLayerMetadataCompatibilityMap = + mFlinger->getGenericLayerMetadataKeyMap(); + auto compatIter = genericLayerMetadataCompatibilityMap.find(key); + if (compatIter == std::end(genericLayerMetadataCompatibilityMap)) { + continue; + } + const uint32_t id = compatIter->second; + + auto it = drawingState.metadata.mMap.find(id); + if (it == std::end(drawingState.metadata.mMap)) { + continue; + } -void Layer::latchCompositionState(compositionengine::LayerFECompositionState& compositionState, - bool includeGeometry) const { - if (includeGeometry) { - latchGeometry(compositionState); + compositionState->metadata + .emplace(key, compositionengine::GenericLayerMetadataEntry{mandatory, it->second}); } } -const char* Layer::getDebugName() const { - return mName.string(); -} +void Layer::preparePerFrameCompositionState() { + const auto& drawingState{getDrawingState()}; + auto* compositionState = editCompositionState(); -void Layer::forceClientComposition(const sp<DisplayDevice>& display) { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - outputLayer->editState().forceClientComposition = true; -} + compositionState->forceClientComposition = false; -bool Layer::getForceClientComposition(const sp<DisplayDevice>& display) { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - return outputLayer->getState().forceClientComposition; -} + compositionState->isColorspaceAgnostic = isColorSpaceAgnostic(); + compositionState->dataspace = getDataSpace(); + compositionState->colorTransform = getColorTransform(); + compositionState->colorTransformIsIdentity = !hasColorTransform(); + compositionState->surfaceDamage = surfaceDamageRegion; + compositionState->hasProtectedContent = isProtected(); -void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); + const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f; - if (!outputLayer->getState().hwc || - (*outputLayer->getState().hwc).hwcCompositionType != - Hwc2::IComposerClient::Composition::CURSOR) { - return; + compositionState->isOpaque = + isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf; + + // Force client composition for special cases known only to the front-end. + if (isHdrY410() || usesRoundedCorners || drawShadows()) { + compositionState->forceClientComposition = true; } +} - // This gives us only the "orientation" component of the transform - const State& s(getDrawingState()); +void Layer::prepareCursorCompositionState() { + const State& drawingState{getDrawingState()}; + auto* compositionState = editCompositionState(); // Apply the layer's transform, followed by the display's global transform // Here we're guaranteed that the layer's transform preserves rects - Rect win = getCroppedBufferSize(s); + Rect win = getCroppedBufferSize(drawingState); // Subtract the transparent region and snap to the bounds - Rect bounds = reduce(win, getActiveTransparentRegion(s)); + Rect bounds = reduce(win, getActiveTransparentRegion(drawingState)); Rect frame(getTransform().transform(bounds)); - frame.intersect(display->getViewport(), &frame); - auto& displayTransform = display->getTransform(); - auto position = displayTransform.transform(frame); - auto error = - (*outputLayer->getState().hwc).hwcLayer->setCursorPosition(position.left, position.top); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set cursor position " - "to (%d, %d): %s (%d)", - mName.string(), position.left, position.top, to_string(error).c_str(), - static_cast<int32_t>(error)); + compositionState->cursorFrame = frame; } -// --------------------------------------------------------------------------- -// drawing... -// --------------------------------------------------------------------------- +sp<compositionengine::LayerFE> Layer::asLayerFE() const { + return const_cast<compositionengine::LayerFE*>( + static_cast<const compositionengine::LayerFE*>(this)); +} -bool Layer::prepareClientLayer(const RenderArea& renderArea, const Region& clip, - Region& clearRegion, const bool supportProtectedContent, - renderengine::LayerSettings& layer) { - return prepareClientLayer(renderArea, clip, false, clearRegion, supportProtectedContent, layer); +sp<compositionengine::LayerFE> Layer::getCompositionEngineLayerFE() const { + return nullptr; } -bool Layer::prepareClientLayer(const RenderArea& renderArea, bool useIdentityTransform, - Region& clearRegion, const bool supportProtectedContent, - renderengine::LayerSettings& layer) { - return prepareClientLayer(renderArea, Region(renderArea.getBounds()), useIdentityTransform, - clearRegion, supportProtectedContent, layer); +compositionengine::LayerFECompositionState* Layer::editCompositionState() { + return nullptr; } -bool Layer::prepareClientLayer(const RenderArea& /*renderArea*/, const Region& /*clip*/, - bool useIdentityTransform, Region& /*clearRegion*/, - const bool /*supportProtectedContent*/, - renderengine::LayerSettings& layer) { +const compositionengine::LayerFECompositionState* Layer::getCompositionState() const { + return nullptr; +} + +bool Layer::onPreComposition(nsecs_t) { + return false; +} + +void Layer::prepareCompositionState(compositionengine::LayerFE::StateSubset subset) { + using StateSubset = compositionengine::LayerFE::StateSubset; + + switch (subset) { + case StateSubset::BasicGeometry: + prepareBasicGeometryCompositionState(); + break; + + case StateSubset::GeometryAndContent: + prepareBasicGeometryCompositionState(); + prepareGeometryCompositionState(); + preparePerFrameCompositionState(); + break; + + case StateSubset::Content: + preparePerFrameCompositionState(); + break; + + case StateSubset::Cursor: + prepareCursorCompositionState(); + break; + } +} + +const char* Layer::getDebugName() const { + return mName.c_str(); +} + +// --------------------------------------------------------------------------- +// drawing... +// --------------------------------------------------------------------------- + +std::optional<compositionengine::LayerFE::LayerSettings> Layer::prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) { + if (!getCompositionState()) { + return {}; + } + FloatRect bounds = getBounds(); half alpha = getAlpha(); - layer.geometry.boundaries = bounds; - if (useIdentityTransform) { - layer.geometry.positionTransform = mat4(); + + compositionengine::LayerFE::LayerSettings layerSettings; + layerSettings.geometry.boundaries = bounds; + if (targetSettings.useIdentityTransform) { + layerSettings.geometry.positionTransform = mat4(); } else { - const ui::Transform transform = getTransform(); - mat4 m; - m[0][0] = transform[0][0]; - m[0][1] = transform[0][1]; - m[0][3] = transform[0][2]; - m[1][0] = transform[1][0]; - m[1][1] = transform[1][1]; - m[1][3] = transform[1][2]; - m[3][0] = transform[2][0]; - m[3][1] = transform[2][1]; - m[3][3] = transform[2][2]; - layer.geometry.positionTransform = m; + layerSettings.geometry.positionTransform = getTransform().asMatrix4(); } if (hasColorTransform()) { - layer.colorTransform = getColorTransform(); + layerSettings.colorTransform = getColorTransform(); } const auto roundedCornerState = getRoundedCornerState(); - layer.geometry.roundedCornersRadius = roundedCornerState.radius; - layer.geometry.roundedCornersCrop = roundedCornerState.cropRect; + layerSettings.geometry.roundedCornersRadius = roundedCornerState.radius; + layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect; - layer.alpha = alpha; - layer.sourceDataspace = mCurrentDataSpace; - return true; + layerSettings.alpha = alpha; + layerSettings.sourceDataspace = getDataSpace(); + layerSettings.backgroundBlurRadius = getBackgroundBlurRadius(); + return layerSettings; } -void Layer::setCompositionType(const sp<const DisplayDevice>& display, - Hwc2::IComposerClient::Composition type) { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - LOG_FATAL_IF(!outputLayer->getState().hwc); - auto& compositionState = outputLayer->editState(); +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 {}; + } - ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", ((*compositionState.hwc).hwcLayer)->getId(), - toString(type).c_str(), 1); - if ((*compositionState.hwc).hwcCompositionType != type) { - ALOGV(" actually setting"); - (*compositionState.hwc).hwcCompositionType = type; + const float casterAlpha = casterLayerSettings.alpha; + const bool casterIsOpaque = ((casterLayerSettings.source.buffer.buffer != nullptr) && + casterLayerSettings.source.buffer.isOpaque); - auto error = (*compositionState.hwc) - .hwcLayer->setCompositionType(static_cast<HWC2::Composition>(type)); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set " - "composition type %s: %s (%d)", - mName.string(), toString(type).c_str(), to_string(error).c_str(), - static_cast<int32_t>(error)); + 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; } -Hwc2::IComposerClient::Composition Layer::getCompositionType( - const sp<const DisplayDevice>& display) const { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - return outputLayer->getState().hwc ? (*outputLayer->getState().hwc).hwcCompositionType - : Hwc2::IComposerClient::Composition::CLIENT; +void Layer::prepareClearClientComposition(LayerFE::LayerSettings& layerSettings, + bool blackout) const { + layerSettings.source.buffer.buffer = nullptr; + layerSettings.source.solidColor = half3(0.0, 0.0, 0.0); + layerSettings.disableBlending = true; + layerSettings.bufferId = 0; + layerSettings.frameNumber = 0; + + // If layer is blacked out, force alpha to 1 so that we draw a black color layer. + layerSettings.alpha = blackout ? 1.0f : 0.0f; } -bool Layer::getClearClientTarget(const sp<const DisplayDevice>& display) const { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - return outputLayer->getState().clearClientTarget; +std::vector<compositionengine::LayerFE::LayerSettings> Layer::prepareClientCompositionList( + compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) { + std::optional<compositionengine::LayerFE::LayerSettings> layerSettings = + prepareClientComposition(targetSettings); + // Nothing to render. + if (!layerSettings) { + return {}; + } + + // HWC requests to clear this layer. + if (targetSettings.clearContent) { + prepareClearClientComposition(*layerSettings, false /* blackout */); + return {*layerSettings}; + } + + std::optional<compositionengine::LayerFE::LayerSettings> shadowSettings = + prepareShadowClientComposition(*layerSettings, targetSettings.viewport, + targetSettings.dataspace); + // There are no shadows to render. + if (!shadowSettings) { + 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 { + const auto outputLayer = findOutputLayerForDisplay(&display); + if (outputLayer == nullptr) { + return Hwc2::IComposerClient::Composition::INVALID; + } + if (outputLayer->getState().hwc) { + return (*outputLayer->getState().hwc).hwcCompositionType; + } else { + return Hwc2::IComposerClient::Composition::CLIENT; + } } bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) { @@ -618,58 +765,11 @@ bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) { // local state // ---------------------------------------------------------------------------- -void Layer::computeGeometry(const RenderArea& renderArea, - renderengine::Mesh& mesh, - bool useIdentityTransform) const { - const ui::Transform renderAreaTransform(renderArea.getTransform()); - FloatRect win = getBounds(); - - vec2 lt = vec2(win.left, win.top); - vec2 lb = vec2(win.left, win.bottom); - vec2 rb = vec2(win.right, win.bottom); - vec2 rt = vec2(win.right, win.top); - - ui::Transform layerTransform = getTransform(); - if (!useIdentityTransform) { - lt = layerTransform.transform(lt); - lb = layerTransform.transform(lb); - rb = layerTransform.transform(rb); - rt = layerTransform.transform(rt); - } - - renderengine::Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); - position[0] = renderAreaTransform.transform(lt); - position[1] = renderAreaTransform.transform(lb); - position[2] = renderAreaTransform.transform(rb); - position[3] = renderAreaTransform.transform(rt); -} - bool Layer::isSecure() const { const State& s(mDrawingState); return (s.flags & layer_state_t::eLayerSecure); } -void Layer::setVisibleRegion(const Region& visibleRegion) { - // always called from main thread - this->visibleRegion = visibleRegion; -} - -void Layer::setCoveredRegion(const Region& coveredRegion) { - // always called from main thread - this->coveredRegion = coveredRegion; -} - -void Layer::setVisibleNonTransparentRegion(const Region& setVisibleNonTransparentRegion) { - // always called from main thread - this->visibleNonTransparentRegion = setVisibleNonTransparentRegion; -} - -void Layer::clearVisibilityRegions() { - visibleRegion.clear(); - visibleNonTransparentRegion.clear(); - coveredRegion.clear(); -} - // ---------------------------------------------------------------------------- // transaction // ---------------------------------------------------------------------------- @@ -687,7 +787,7 @@ void Layer::pushPendingState() { if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) { sp<Layer> barrierLayer = mCurrentState.barrierLayer_legacy.promote(); if (barrierLayer == nullptr) { - ALOGE("[%s] Unable to promote barrier Layer.", mName.string()); + 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). @@ -711,7 +811,7 @@ void Layer::pushPendingState() { mFlinger->setTransactionFlags(eTraversalNeeded); } mPendingStates.push_back(mCurrentState); - ATRACE_INT(mTransactionName.string(), mPendingStates.size()); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } void Layer::popPendingState(State* stateToCommit) { @@ -719,7 +819,7 @@ void Layer::popPendingState(State* stateToCommit) { *stateToCommit = mPendingStates[0]; mPendingStates.removeAt(0); - ATRACE_INT(mTransactionName.string(), mPendingStates.size()); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } bool Layer::applyPendingStates(State* stateToCommit) { @@ -730,7 +830,7 @@ bool Layer::applyPendingStates(State* stateToCommit) { // 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", mName.string()); + ALOGE("[%s] No local sync point found", getDebugName()); popPendingState(stateToCommit); stateUpdateAvailable = true; continue; @@ -738,7 +838,7 @@ bool Layer::applyPendingStates(State* stateToCommit) { if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber_legacy) { - ALOGE("[%s] Unexpected sync point frame number found", mName.string()); + ALOGE("[%s] Unexpected sync point frame number found", getDebugName()); // Signal our end of the sync point and then dispose of it mRemoteSyncPoints.front()->setTransactionApplied(); @@ -765,11 +865,13 @@ bool Layer::applyPendingStates(State* stateToCommit) { } } - // If we still have pending updates, wake SurfaceFlinger back up and point - // it at this layer so we can process them + // 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->setTransactionFlags(eTraversalNeeded); + mFlinger->setTraversalNeeded(); } mCurrentState.modified = false; @@ -790,7 +892,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { " 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().string(), mCurrentTransform, getEffectiveScalingMode(), + 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, @@ -822,7 +924,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { const bool resizePending = ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) || (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) && - (mActiveBuffer != nullptr); + (getBuffer() != nullptr); if (!isFixedSize()) { if (resizePending && mSidebandStream == nullptr) { flags |= eDontUpdateGeometryState; @@ -835,11 +937,6 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { if (!(flags & eDontUpdateGeometryState)) { State& editCurrentState(getCurrentState()); - // If mFreezeGeometryUpdates is true we are in the setGeometryAppliesWithResize - // mode, which causes attributes which normally latch regardless of scaling mode, - // to be delayed. We copy the requested state to the active state making sure - // to respect these rules (again see Layer.h for a detailed discussion). - // // 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. @@ -847,16 +944,8 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { // // Careful that "stateToCommit" and editCurrentState may not begin as equivalent due to // applyPendingStates in the presence of deferred transactions. - if (mFreezeGeometryUpdates) { - float tx = stateToCommit->active_legacy.transform.tx(); - float ty = stateToCommit->active_legacy.transform.ty(); - stateToCommit->active_legacy = stateToCommit->requested_legacy; - stateToCommit->active_legacy.transform.set(tx, ty); - editCurrentState.active_legacy = stateToCommit->active_legacy; - } else { - editCurrentState.active_legacy = editCurrentState.requested_legacy; - stateToCommit->active_legacy = stateToCommit->requested_legacy; - } + editCurrentState.active_legacy = editCurrentState.requested_legacy; + stateToCommit->active_legacy = stateToCommit->requested_legacy; } return flags; @@ -866,6 +955,15 @@ uint32_t Layer::doTransaction(uint32_t flags) { ATRACE_CALL(); 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; } @@ -908,6 +1006,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { commitTransaction(c); mPendingStatesSnapshot = mPendingStates; mCurrentState.callbackHandles = {}; + return flags; } @@ -923,7 +1022,7 @@ uint32_t Layer::setTransactionFlags(uint32_t flags) { return mTransactionFlags.fetch_or(flags); } -bool Layer::setPosition(float x, float y, bool immediate) { +bool Layer::setPosition(float x, float y) { if (mCurrentState.requested_legacy.transform.tx() == x && mCurrentState.requested_legacy.transform.ty() == y) return false; @@ -933,14 +1032,11 @@ bool Layer::setPosition(float x, float y, bool immediate) { // 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); - if (immediate && !mFreezeGeometryUpdates) { - // 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); - } - mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; + // 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); @@ -1010,6 +1106,8 @@ void Layer::setZOrderRelativeOf(const wp<Layer>& relativeOf) { mCurrentState.zOrderRelativeOf = relativeOf; mCurrentState.sequence++; mCurrentState.modified = true; + mCurrentState.isRelativeOf = relativeOf != nullptr; + setTransactionFlags(eTransactionNeeded); } @@ -1076,10 +1174,11 @@ bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace da if (!mCurrentState.bgColorLayer && alpha != 0) { // create background color layer if one does not yet exist - uint32_t flags = ISurfaceComposerClient::eFXSurfaceColor; - const String8& name = mName + "BackgroundColorLayer"; - mCurrentState.bgColorLayer = new ColorLayer( - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, flags, LayerMetadata())); + uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect; + std::string name = mName + "BackgroundColorLayer"; + mCurrentState.bgColorLayer = mFlinger->getFactory().createEffectLayer( + LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), 0, 0, flags, + LayerMetadata())); // add to child list addChild(mCurrentState.bgColorLayer); @@ -1113,6 +1212,16 @@ bool Layer::setCornerRadius(float cornerRadius) { return true; } +bool Layer::setBackgroundBlurRadius(int backgroundBlurRadius) { + if (mCurrentState.backgroundBlurRadius == backgroundBlurRadius) return false; + + mCurrentState.sequence++; + mCurrentState.backgroundBlurRadius = backgroundBlurRadius; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms) { ui::Transform t; @@ -1136,6 +1245,7 @@ bool Layer::setTransparentRegionHint(const Region& transparent) { setTransactionFlags(eTransactionNeeded); return 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; @@ -1146,14 +1256,11 @@ bool Layer::setFlags(uint8_t flags, uint8_t mask) { return true; } -bool Layer::setCrop_legacy(const Rect& crop, bool immediate) { +bool Layer::setCrop_legacy(const Rect& crop) { if (mCurrentState.requestedCrop_legacy == crop) return false; mCurrentState.sequence++; mCurrentState.requestedCrop_legacy = crop; - if (immediate && !mFreezeGeometryUpdates) { - mCurrentState.crop_legacy = crop; - } - mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; + mCurrentState.crop_legacy = crop; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); @@ -1195,6 +1302,33 @@ bool Layer::setColorSpaceAgnostic(const bool agnostic) { return true; } +bool Layer::setFrameRateSelectionPriority(int32_t priority) { + if (mCurrentState.frameRateSelectionPriority == priority) return false; + mCurrentState.frameRateSelectionPriority = priority; + mCurrentState.sequence++; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +int32_t Layer::getFrameRateSelectionPriority() const { + // Check if layer has priority set. + if (mDrawingState.frameRateSelectionPriority != PRIORITY_UNSET) { + return mDrawingState.frameRateSelectionPriority; + } + // If not, search whether its parents have it set. + sp<Layer> parent = getParent(); + if (parent != nullptr) { + return parent->getFrameRateSelectionPriority(); + } + + return Layer::PRIORITY_UNSET; +} + +bool Layer::isLayerFocusedBasedOnPriority(int32_t priority) { + return priority == PRIORITY_FOCUSED_WITH_MODE || priority == PRIORITY_FOCUSED_WITHOUT_MODE; +}; + uint32_t Layer::getLayerStack() const { auto p = mDrawingParent.promote(); if (p == nullptr) { @@ -1203,6 +1337,112 @@ uint32_t Layer::getLayerStack() const { return p->getLayerStack(); } +bool Layer::setShadowRadius(float shadowRadius) { + if (mCurrentState.shadowRadius == shadowRadius) { + return false; + } + + mCurrentState.sequence++; + mCurrentState.shadowRadius = shadowRadius; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +bool Layer::setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint) { + if (mCurrentState.fixedTransformHint == fixedTransformHint) { + return false; + } + + mCurrentState.sequence++; + mCurrentState.fixedTransformHint = fixedTransformHint; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +void Layer::updateTreeHasFrameRateVote() { + const auto traverseTree = [&](const LayerVector::Visitor& visitor) { + auto parent = getParent(); + while (parent) { + visitor(parent.get()); + parent = parent->getParent(); + } + + 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++; + } + }); + + // Now update the other layers + bool transactionNeeded = false; + 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; + } + }); + + if (transactionNeeded) { + mFlinger->setTransactionFlags(eTraversalNeeded); + } +} + +bool Layer::setFrameRate(FrameRate frameRate) { + if (!mFlinger->useFrameRateApi) { + return false; + } + if (mCurrentState.frameRate == frameRate) { + return false; + } + + // Activate the layer in Scheduler's LayerHistory + mFlinger->mScheduler->recordLayerHistory(this, systemTime(), + LayerHistory::LayerUpdateType::SetFrameRate); + + mCurrentState.sequence++; + mCurrentState.frameRate = frameRate; + mCurrentState.modified = true; + + updateTreeHasFrameRateVote(); + + setTransactionFlags(eTransactionNeeded); + return true; +} + +Layer::FrameRate Layer::getFrameRateForLayerTree() const { + const auto frameRate = getDrawingState().frameRate; + if (frameRate.rate > 0 || frameRate.type == FrameRateCompatibility::NoVote) { + return frameRate; + } + + // 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}; + } + + return frameRate; +} + void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) { ATRACE_CALL(); mCurrentState.barrierLayer_legacy = barrierLayer; @@ -1255,20 +1495,12 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const { return usage; } -void Layer::updateTransformHint(const sp<const DisplayDevice>& display) const { - uint32_t orientation = 0; - // Disable setting transform hint if the debug flag is set. - if (!mFlinger->mDebugDisableTransformHint) { - // The transform hint is used to improve performance, but we can - // only have a single transform hint, it cannot - // apply to all displays. - const ui::Transform& planeTransform = display->getTransform(); - orientation = planeTransform.getOrientation(); - if (orientation & ui::Transform::ROT_INVALID) { - orientation = 0; - } +void Layer::updateTransformHint(ui::Transform::RotationFlags transformHint) { + if (mFlinger->mDebugDisableTransformHint || transformHint & ui::Transform::ROT_INVALID) { + transformHint = ui::Transform::ROT_0; } - setTransformHint(orientation); + + setTransformHint(transformHint); } // ---------------------------------------------------------------------------- @@ -1276,15 +1508,18 @@ void Layer::updateTransformHint(const sp<const DisplayDevice>& display) const { // ---------------------------------------------------------------------------- // TODO(marissaw): add new layer state info to layer debugging -LayerDebugInfo Layer::getLayerDebugInfo() const { +LayerDebugInfo Layer::getLayerDebugInfo(const DisplayDevice* display) const { + using namespace std::string_literals; + LayerDebugInfo info; const State& ds = getDrawingState(); info.mName = getName(); - sp<Layer> parent = getParent(); - info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string()); - info.mType = std::string(getTypeId()); + sp<Layer> parent = mDrawingParent.promote(); + info.mParentName = parent ? parent->getName() : "none"s; + info.mType = getType(); info.mTransparentRegion = ds.activeTransparentRegion_legacy; - info.mVisibleRegion = visibleRegion; + + info.mVisibleRegion = getVisibleRegion(display); info.mSurfaceDamageRegion = surfaceDamageRegion; info.mLayerStack = getLayerStack(); info.mX = ds.active_legacy.transform.tx(); @@ -1296,13 +1531,13 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); - info.mDataSpace = static_cast<android_dataspace>(mCurrentDataSpace); + info.mDataSpace = static_cast<android_dataspace>(getDataSpace()); 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 = mActiveBuffer; + sp<const GraphicBuffer> buffer = getBuffer(); if (buffer != 0) { info.mActiveBufferWidth = buffer->getWidth(); info.mActiveBufferHeight = buffer->getHeight(); @@ -1325,21 +1560,37 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { void Layer::miniDumpHeader(std::string& result) { result.append("-------------------------------"); result.append("-------------------------------"); - result.append("-----------------------------\n"); + result.append("-------------------------------"); + result.append("-------------------------------"); + result.append("-------------------\n"); result.append(" Layer name\n"); result.append(" Z | "); result.append(" Window Type | "); result.append(" Comp Type | "); result.append(" Transform | "); result.append(" Disp Frame (LTRB) | "); - result.append(" Source Crop (LTRB)\n"); + result.append(" Source Crop (LTRB) | "); + result.append(" Frame Rate (Explicit) [Focused]\n"); + result.append("-------------------------------"); result.append("-------------------------------"); result.append("-------------------------------"); - result.append("-----------------------------\n"); + result.append("-------------------------------"); + result.append("-------------------\n"); +} + +std::string Layer::frameRateCompatibilityString(Layer::FrameRateCompatibility compatibility) { + switch (compatibility) { + case FrameRateCompatibility::Default: + return "Default"; + case FrameRateCompatibility::ExactOrMultiple: + return "ExactOrMultiple"; + case FrameRateCompatibility::NoVote: + return "NoVote"; + } } -void Layer::miniDump(std::string& result, const sp<DisplayDevice>& displayDevice) const { - auto outputLayer = findOutputLayerForDisplay(displayDevice); +void Layer::miniDump(std::string& result, const DisplayDevice& display) const { + const auto outputLayer = findOutputLayerForDisplay(&display); if (!outputLayer) { return; } @@ -1347,18 +1598,18 @@ void Layer::miniDump(std::string& result, const sp<DisplayDevice>& displayDevice std::string name; if (mName.length() > 77) { std::string shortened; - shortened.append(mName.string(), 36); + shortened.append(mName, 0, 36); shortened.append("[...]"); - shortened.append(mName.string() + (mName.length() - 36), 36); - name = shortened; + shortened.append(mName, mName.length() - 36); + name = std::move(shortened); } else { - name = std::string(mName.string(), mName.size()); + name = mName; } StringAppendF(&result, " %s\n", name.c_str()); const State& layerState(getDrawingState()); - const auto& compositionState = outputLayer->getState(); + const auto& outputLayerState = outputLayer->getState(); if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) { StringAppendF(&result, " rel %6d | ", layerState.z); @@ -1366,20 +1617,29 @@ void Layer::miniDump(std::string& result, const sp<DisplayDevice>& displayDevice StringAppendF(&result, " %10d | ", layerState.z); } StringAppendF(&result, " %10d | ", mWindowType); - StringAppendF(&result, "%10s | ", toString(getCompositionType(displayDevice)).c_str()); - StringAppendF(&result, "%10s | ", - toString(getCompositionLayer() ? compositionState.bufferTransform - : static_cast<Hwc2::Transform>(0)) - .c_str()); - const Rect& frame = compositionState.displayFrame; + StringAppendF(&result, "%10s | ", toString(getCompositionType(display)).c_str()); + StringAppendF(&result, "%10s | ", toString(outputLayerState.bufferTransform).c_str()); + const Rect& frame = outputLayerState.displayFrame; StringAppendF(&result, "%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); - const FloatRect& crop = compositionState.sourceCrop; - StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, + const FloatRect& crop = outputLayerState.sourceCrop; + StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, crop.bottom); + 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 { + StringAppendF(&result, " "); + } - result.append("- - - - - - - - - - - - - - - -"); - result.append("- - - - - - - - - - - - - - - -"); - result.append("- - - - - - - - - - - - - - -\n"); + const auto focused = isLayerFocusedBasedOnPriority(getFrameRateSelectionPriority()); + StringAppendF(&result, " [%s]\n", focused ? "*" : " "); + + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - - - - - - - - - - - - - - - "); + result.append("- - - - - - - -\n"); } void Layer::dumpFrameStats(std::string& result) const { @@ -1399,16 +1659,23 @@ void Layer::getFrameStats(FrameStats* outStats) const { } void Layer::dumpFrameEvents(std::string& result) { - StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().string(), getTypeId(), this); + StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().c_str(), getType(), this); Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.checkFencesForCompletion(); mFrameEventHistory.dump(result); } +void Layer::dumpCallingUidPid(std::string& result) const { + StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().c_str(), getType(), + mCallingPid, mCallingUid); +} + void Layer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.onDisconnect(); - mFlinger->mTimeStats->onDestroy(getSequence()); + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); } void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, @@ -1416,6 +1683,8 @@ void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, if (newTimestamps) { mFlinger->mTimeStats->setPostTime(getSequence(), newTimestamps->frameNumber, getName().c_str(), newTimestamps->postedTime); + mFlinger->mTimeStats->setAcquireFence(getSequence(), newTimestamps->frameNumber, + newTimestamps->acquireFence); } Mutex::Autolock lock(mFrameEventHistoryMutex); @@ -1449,6 +1718,7 @@ void Layer::addChild(const sp<Layer>& layer) { mCurrentChildren.add(layer); layer->setParent(this); + updateTreeHasFrameRateVote(); } ssize_t Layer::removeChild(const sp<Layer>& layer) { @@ -1456,7 +1726,24 @@ ssize_t Layer::removeChild(const sp<Layer>& layer) { setTransactionFlags(eTransactionNeeded); layer->setParent(nullptr); - return mCurrentChildren.remove(layer); + const auto removeResult = mCurrentChildren.remove(layer); + + updateTreeHasFrameRateVote(); + 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) { @@ -1472,13 +1759,7 @@ bool Layer::reparentChildren(const sp<IBinder>& newParentHandle) { return false; } - if (attachChildren()) { - setTransactionFlags(eTransactionNeeded); - } - for (const sp<Layer>& child : mCurrentChildren) { - newParent->addChild(child); - } - mCurrentChildren.clear(); + reparentChildren(newParent); return true; } @@ -1487,8 +1768,8 @@ void Layer::setChildrenDrawingParent(const sp<Layer>& newParent) { for (const sp<Layer>& child : mDrawingChildren) { child->mDrawingParent = newParent; child->computeBounds(newParent->mBounds, - newParent->getTransformWithScale( - newParent->getBufferScaleTransform())); + newParent->getTransformWithScale(newParent->getBufferScaleTransform()), + newParent->mEffectiveShadowRadius); } } @@ -1608,22 +1889,25 @@ bool Layer::hasColorTransform() const { bool Layer::isLegacyDataSpace() const { // return true when no higher bits are set - return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK | - ui::Dataspace::TRANSFER_MASK | ui::Dataspace::RANGE_MASK)); + return !(getDataSpace() & + (ui::Dataspace::STANDARD_MASK | ui::Dataspace::TRANSFER_MASK | + ui::Dataspace::RANGE_MASK)); } void Layer::setParent(const sp<Layer>& layer) { mCurrentParent = layer; } -int32_t Layer::getZ() 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 : mCurrentState; - return state.zOrderRelativeOf != nullptr; + return state.isRelativeOf; } __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::makeTraversalList( @@ -1648,8 +1932,7 @@ __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::mak } for (const sp<Layer>& child : children) { - const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState; - if (childState.zOrderRelativeOf != nullptr) { + if (child->usingRelativeZ(stateSet)) { continue; } traverse.add(child); @@ -1678,7 +1961,7 @@ void Layer::traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector:: continue; } - if (relative->getZ() >= 0) { + if (relative->getZ(stateSet) >= 0) { break; } relative->traverseInZOrder(stateSet, visitor); @@ -1712,7 +1995,7 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, continue; } - if (relative->getZ() < 0) { + if (relative->getZ(stateSet) < 0) { break; } relative->traverseInReverseZOrder(stateSet, visitor); @@ -1729,6 +2012,15 @@ 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; + for (const sp<Layer>& child : children) { + child->traverse(state, visitor); + } +} + LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet, const std::vector<Layer*>& layersInTree) { LOG_ALWAYS_FATAL_IF(stateSet == LayerVector::StateSet::Invalid, @@ -1770,7 +2062,7 @@ void Layer::traverseChildrenInZOrderInner(const std::vector<Layer*>& layersInTre size_t i = 0; for (; i < list.size(); i++) { const auto& relative = list[i]; - if (relative->getZ() >= 0) { + if (relative->getZ(stateSet) >= 0) { break; } relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); @@ -1815,11 +2107,25 @@ half Layer::getAlpha() const { return parentAlpha * getDrawingState().color.a; } +ui::Transform::RotationFlags Layer::getFixedTransformHint() const { + ui::Transform::RotationFlags fixedTransformHint = mCurrentState.fixedTransformHint; + if (fixedTransformHint != ui::Transform::ROT_INVALID) { + return fixedTransformHint; + } + const auto& p = mCurrentParent.promote(); + if (!p) return fixedTransformHint; + return p->getFixedTransformHint(); +} + half4 Layer::getColor() const { const half4 color(getDrawingState().color); return half4(color.r, color.g, color.b, getAlpha()); } +int32_t Layer::getBackgroundBlurRadius() const { + return getDrawingState().backgroundBlurRadius; +} + Layer::RoundedCornerState Layer::getRoundedCornerState() const { const auto& p = mDrawingParent.promote(); if (p != nullptr) { @@ -1832,7 +2138,9 @@ Layer::RoundedCornerState Layer::getRoundedCornerState() const { // but a transform matrix can define horizontal and vertical scales. // Let's take the average between both of them and pass into the shader, practically we // never do this type of transformation on windows anyway. - parentState.radius *= (t[0][0] + t[1][1]) / 2.0f; + auto scaleX = sqrtf(t[0][0] * t[0][0] + t[0][1] * t[0][1]); + auto scaleY = sqrtf(t[1][0] * t[1][0] + t[1][1] * t[1][1]); + parentState.radius *= (scaleX + scaleY) / 2.0f; return parentState; } } @@ -1842,6 +2150,18 @@ Layer::RoundedCornerState Layer::getRoundedCornerState() const { : RoundedCornerState(); } +renderengine::ShadowSettings Layer::getShadowSettings(const Rect& viewport) const { + renderengine::ShadowSettings state = mFlinger->mDrawingState.globalShadowSettings; + + // 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 = (viewport.width() / 2.f) - mScreenBounds.left; + state.lightPos.y -= mScreenBounds.top; + + state.length = mEffectiveShadowRadius; + return state; +} + void Layer::commitChildList() { for (size_t i = 0; i < mCurrentChildren.size(); i++) { const auto& child = mCurrentChildren[i]; @@ -1874,7 +2194,29 @@ void Layer::setInputInfo(const InputWindowInfo& info) { setTransactionFlags(eTransactionNeeded); } -void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) const { +LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags, + const DisplayDevice* display) const { + LayerProto* layerProto = layersProto.add_layers(); + writeToProtoDrawingState(layerProto, traceFlags, display); + writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags); + + if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) { + // Only populate for the primary display. + if (display) { + const Hwc2::IComposerClient::Composition compositionType = getCompositionType(*display); + layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType)); + } + } + + for (const sp<Layer>& layer : mDrawingChildren) { + layer->writeToProto(layersProto, traceFlags, display); + } + + return layerProto; +} + +void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, + const DisplayDevice* display) const { ui::Transform transform = getTransform(); if (traceFlags & SurfaceTracing::TRACE_CRITICAL) { @@ -1887,17 +2229,16 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) } } - auto buffer = mActiveBuffer; + auto buffer = getBuffer(); if (buffer != nullptr) { LayerProtoHelper::writeToProto(buffer, [&]() { return layerInfo->mutable_active_buffer(); }); - LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform), + LayerProtoHelper::writeToProto(ui::Transform(getBufferTransform()), layerInfo->mutable_buffer_transform()); } layerInfo->set_invalidate(contentDirty); layerInfo->set_is_protected(isProtected()); - layerInfo->set_dataspace( - dataspaceDetails(static_cast<android_dataspace>(mCurrentDataSpace))); + layerInfo->set_dataspace(dataspaceDetails(static_cast<android_dataspace>(getDataSpace()))); layerInfo->set_queued_frames(getQueuedFrameCount()); layerInfo->set_refresh_pending(isBufferLatched()); layerInfo->set_curr_frame(mCurrentFrameNumber); @@ -1908,18 +2249,26 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(), [&]() { return layerInfo->mutable_position(); }); LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); }); - LayerProtoHelper::writeToProto(visibleRegion, - [&]() { return layerInfo->mutable_visible_region(); }); + if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) { + LayerProtoHelper::writeToProto(getVisibleRegion(display), + [&]() { return layerInfo->mutable_visible_region(); }); + } LayerProtoHelper::writeToProto(surfaceDamageRegion, [&]() { return layerInfo->mutable_damage_region(); }); - } - if (traceFlags & SurfaceTracing::TRACE_EXTRA) { - LayerProtoHelper::writeToProto(mSourceBounds, - [&]() { return layerInfo->mutable_source_bounds(); }); - LayerProtoHelper::writeToProto(mScreenBounds, - [&]() { return layerInfo->mutable_screen_bounds(); }); + if (hasColorTransform()) { + LayerProtoHelper::writeToProto(getColorTransform(), + layerInfo->mutable_color_transform()); + } } + + LayerProtoHelper::writeToProto(mSourceBounds, + [&]() { return layerInfo->mutable_source_bounds(); }); + LayerProtoHelper::writeToProto(mScreenBounds, + [&]() { return layerInfo->mutable_screen_bounds(); }); + LayerProtoHelper::writeToProto(getRoundedCornerState().cropRect, + [&]() { return layerInfo->mutable_corner_radius_crop(); }); + layerInfo->set_shadow_radius(mEffectiveShadowRadius); } void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet, @@ -1933,7 +2282,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet if (traceFlags & SurfaceTracing::TRACE_CRITICAL) { layerInfo->set_id(sequence); layerInfo->set_name(getName().c_str()); - layerInfo->set_type(String8(getTypeId())); + layerInfo->set_type(getType()); for (const auto& child : children) { layerInfo->add_children(child->sequence); @@ -1988,6 +2337,8 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet } else { layerInfo->set_z_order_relative_of(-1); } + + layerInfo->set_is_relative_of(state.isRelativeOf); } if (traceFlags & SurfaceTracing::TRACE_INPUT) { @@ -2003,41 +2354,23 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet } } -void Layer::writeToProtoCompositionState(LayerProto* layerInfo, - const sp<DisplayDevice>& displayDevice, - uint32_t traceFlags) const { - auto outputLayer = findOutputLayerForDisplay(displayDevice); - if (!outputLayer) { - return; - } - - writeToProtoDrawingState(layerInfo, traceFlags); - writeToProtoCommonState(layerInfo, LayerVector::StateSet::Drawing, traceFlags); - - const auto& compositionState = outputLayer->getState(); - - const Rect& frame = compositionState.displayFrame; - LayerProtoHelper::writeToProto(frame, [&]() { return layerInfo->mutable_hwc_frame(); }); - - const FloatRect& crop = compositionState.sourceCrop; - LayerProtoHelper::writeToProto(crop, [&]() { return layerInfo->mutable_hwc_crop(); }); - - const int32_t transform = - getCompositionLayer() ? static_cast<int32_t>(compositionState.bufferTransform) : 0; - layerInfo->set_hwc_transform(transform); - - const int32_t compositionType = - static_cast<int32_t>(compositionState.hwc ? (*compositionState.hwc).hwcCompositionType - : Hwc2::IComposerClient::Composition::CLIENT); - layerInfo->set_hwc_composition_type(compositionType); -} - bool Layer::isRemovedFromCurrentState() const { return mRemovedFromCurrentState; } 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(); + } + InputWindowInfo info = mDrawingState.inputInfo; + info.id = sequence; if (info.displayId == ADISPLAY_ID_NONE) { info.displayId = getLayerStack(); @@ -2081,7 +2414,15 @@ InputWindowInfo Layer::fillInputInfo() { // Position the touchable region relative to frame screen location and restrict it to frame // bounds. info.touchableRegion = info.touchableRegion.translate(info.frameLeft, info.frameTop); - info.visible = canReceiveInput(); + // 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 + // policy-visibility, ignoring the buffer state. However for layers with + // hasInputInfo()==false we can use the real visibility state. + // We are just using these layers for occlusion detection in + // InputDispatcher, and obviously if they aren't visible they can't occlude + // anything. + info.visible = hasInputInfo() ? canReceiveInput() : isVisible(); auto cropLayer = mDrawingState.touchableRegionCrop.promote(); if (info.replaceTouchableRegionWithCrop) { @@ -2094,15 +2435,31 @@ InputWindowInfo Layer::fillInputInfo() { info.touchableRegion = info.touchableRegion.intersect(Rect{cropLayer->mScreenBounds}); } + // 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(clonedRoot->mScreenBounds); + info.touchableRegion = info.touchableRegion.intersect(rect); + } + } + return info; } -bool Layer::hasInput() const { - return mDrawingState.inputInfo.token != nullptr; +sp<Layer> Layer::getClonedRoot() { + if (mClonedChild != nullptr) { + return this; + } + if (mDrawingParent == nullptr || mDrawingParent.promote() == nullptr) { + return nullptr; + } + return mDrawingParent.promote()->getClonedRoot(); } -std::shared_ptr<compositionengine::Layer> Layer::getCompositionLayer() const { - return nullptr; +bool Layer::hasInputInfo() const { + return mDrawingState.inputInfo.token != nullptr; } bool Layer::canReceiveInput() const { @@ -2110,8 +2467,159 @@ bool Layer::canReceiveInput() const { } compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( - const sp<const DisplayDevice>& display) const { - return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionLayer().get()); + const DisplayDevice* display) const { + if (!display) return nullptr; + return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionEngineLayerFE()); +} + +Region Layer::getVisibleRegion(const DisplayDevice* display) const { + const auto outputLayer = findOutputLayerForDisplay(display); + return outputLayer ? outputLayer->getState().visibleRegion : Region(); +} + +void Layer::setInitialValuesForClone(const sp<Layer>& clonedFrom) { + // copy drawing state from cloned layer + mDrawingState = clonedFrom->mDrawingState; + mClonedFrom = clonedFrom; +} + +void Layer::updateMirrorInfo() { + if (mClonedChild == nullptr || !mClonedChild->isClonedFromAlive()) { + // If mClonedChild is null, there is nothing to mirror. If isClonedFromAlive returns false, + // it means that there is a clone, but the layer it was cloned from has been destroyed. In + // that case, we want to delete the reference to the clone since we want it to get + // destroyed. The root, this layer, will still be around since the client can continue + // to hold a reference, but no cloned layers will be displayed. + mClonedChild = nullptr; + return; + } + + std::map<sp<Layer>, sp<Layer>> clonedLayersMap; + // If the real layer exists and is in current state, add the clone as a child of the root. + // There's no need to remove from drawingState when the layer is offscreen since currentState is + // copied to drawingState for the root layer. So the clonedChild is always removed from + // drawingState and then needs to be added back each traversal. + if (!mClonedChild->getClonedFrom()->isRemovedFromCurrentState()) { + addChildToDrawing(mClonedChild); + } + + mClonedChild->updateClonedDrawingState(clonedLayersMap); + mClonedChild->updateClonedChildren(this, clonedLayersMap); + mClonedChild->updateClonedRelatives(clonedLayersMap); +} + +void Layer::updateClonedDrawingState(std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) { + // If the layer the clone was cloned from is alive, copy the content of the drawingState + // to the clone. If the real layer is no longer alive, continue traversing the children + // since we may be able to pull out other children that are still alive. + if (isClonedFromAlive()) { + sp<Layer> clonedFrom = getClonedFrom(); + mDrawingState = clonedFrom->mDrawingState; + clonedLayersMap.emplace(clonedFrom, this); + } + + // The clone layer may have children in drawingState since they may have been created and + // added from a previous request to updateMirorInfo. This is to ensure we don't recreate clones + // that already exist, since we can just re-use them. + // The drawingChildren will not get overwritten by the currentChildren since the clones are + // not updated in the regular traversal. They are skipped since the root will lose the + // reference to them when it copies its currentChildren to drawing. + for (sp<Layer>& child : mDrawingChildren) { + child->updateClonedDrawingState(clonedLayersMap); + } +} + +void Layer::updateClonedChildren(const sp<Layer>& mirrorRoot, + std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) { + mDrawingChildren.clear(); + + if (!isClonedFromAlive()) { + return; + } + + sp<Layer> clonedFrom = getClonedFrom(); + for (sp<Layer>& child : clonedFrom->mDrawingChildren) { + if (child == mirrorRoot) { + // This is to avoid cyclical mirroring. + continue; + } + sp<Layer> clonedChild = clonedLayersMap[child]; + if (clonedChild == nullptr) { + clonedChild = child->createClone(); + clonedLayersMap[child] = clonedChild; + } + addChildToDrawing(clonedChild); + clonedChild->updateClonedChildren(mirrorRoot, clonedLayersMap); + } +} + +void Layer::updateClonedInputInfo(const std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) { + auto cropLayer = mDrawingState.touchableRegionCrop.promote(); + if (cropLayer != nullptr) { + if (clonedLayersMap.count(cropLayer) == 0) { + // Real layer had a crop layer but it's not in the cloned hierarchy. Just set to + // self as crop layer to avoid going outside bounds. + mDrawingState.touchableRegionCrop = this; + } else { + const sp<Layer>& clonedCropLayer = clonedLayersMap.at(cropLayer); + mDrawingState.touchableRegionCrop = clonedCropLayer; + } + } + // Cloned layers shouldn't handle watch outside since their z order is not determined by + // WM or the client. + mDrawingState.inputInfo.layoutParamsFlags &= ~InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH; +} + +void Layer::updateClonedRelatives(const std::map<sp<Layer>, sp<Layer>>& clonedLayersMap) { + mDrawingState.zOrderRelativeOf = nullptr; + mDrawingState.zOrderRelatives.clear(); + + if (!isClonedFromAlive()) { + return; + } + + const sp<Layer>& clonedFrom = getClonedFrom(); + for (wp<Layer>& relativeWeak : clonedFrom->mDrawingState.zOrderRelatives) { + const sp<Layer>& relative = relativeWeak.promote(); + if (clonedLayersMap.count(relative) > 0) { + auto& clonedRelative = clonedLayersMap.at(relative); + mDrawingState.zOrderRelatives.add(clonedRelative); + } + } + + // Check if the relativeLayer for the real layer is part of the cloned hierarchy. + // It's possible that the layer it's relative to is outside the requested cloned hierarchy. + // In that case, we treat the layer as if the relativeOf has been removed. This way, it will + // still traverse the children, but the layer with the missing relativeOf will not be shown + // on screen. + const sp<Layer>& relativeOf = clonedFrom->mDrawingState.zOrderRelativeOf.promote(); + if (clonedLayersMap.count(relativeOf) > 0) { + const sp<Layer>& clonedRelativeOf = clonedLayersMap.at(relativeOf); + mDrawingState.zOrderRelativeOf = clonedRelativeOf; + } + + updateClonedInputInfo(clonedLayersMap); + + for (sp<Layer>& child : mDrawingChildren) { + child->updateClonedRelatives(clonedLayersMap); + } +} + +void Layer::addChildToDrawing(const sp<Layer>& layer) { + mDrawingChildren.add(layer); + layer->mDrawingParent = this; +} + +Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t compatibility) { + switch (compatibility) { + case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT: + return FrameRateCompatibility::Default; + case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE: + return FrameRateCompatibility::ExactOrMultiple; + default: + LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility); + return FrameRateCompatibility::Default; + } } // --------------------------------------------------------------------------- @@ -2125,3 +2633,6 @@ compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" #endif + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" |