summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/Layer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/Layer.cpp')
-rw-r--r--services/surfaceflinger/Layer.cpp437
1 files changed, 267 insertions, 170 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2c8d559cc1..c8b1059b94 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -27,7 +27,6 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
-#include <android/native_window.h>
#include <binder/IPCThreadState.h>
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/Display.h>
@@ -101,7 +100,7 @@ TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate
using FrameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility;
using Seamlessness = TimeStats::SetFrameRateVote::Seamlessness;
const auto frameRateCompatibility = [frameRate] {
- switch (frameRate.type) {
+ switch (frameRate.vote.type) {
case Layer::FrameRateCompatibility::Default:
return FrameRateCompatibility::Default;
case Layer::FrameRateCompatibility::ExactOrMultiple:
@@ -112,7 +111,7 @@ TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate
}();
const auto seamlessness = [frameRate] {
- switch (frameRate.seamlessness) {
+ switch (frameRate.vote.seamlessness) {
case scheduler::Seamlessness::OnlySeamless:
return Seamlessness::ShouldBeSeamless;
case scheduler::Seamlessness::SeamedAndSeamless:
@@ -122,7 +121,7 @@ TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate
}
}();
- return TimeStats::SetFrameRateVote{.frameRate = frameRate.rate.getValue(),
+ return TimeStats::SetFrameRateVote{.frameRate = frameRate.vote.rate.getValue(),
.frameRateCompatibility = frameRateCompatibility,
.seamlessness = seamlessness};
}
@@ -137,10 +136,11 @@ using frontend::RoundedCornerState;
using gui::GameMode;
using gui::LayerMetadata;
using gui::WindowInfo;
+using ui::Size;
using PresentState = frametimeline::SurfaceFrame::PresentState;
-Layer::Layer(const LayerCreationArgs& args)
+Layer::Layer(const surfaceflinger::LayerCreationArgs& args)
: sequence(args.sequence),
mFlinger(sp<SurfaceFlinger>::fromExisting(args.flinger)),
mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)),
@@ -149,7 +149,6 @@ Layer::Layer(const LayerCreationArgs& args)
args.metadata.getInt32(gui::METADATA_WINDOW_TYPE, 0))),
mLayerCreationFlags(args.flags),
mBorderEnabled(false),
- mTextureName(args.textureName),
mLegacyLayerFE(args.flinger->getFactory().createLayerFE(mName)) {
ALOGV("Creating Layer %s", getDebugName());
@@ -167,6 +166,7 @@ Layer::Layer(const LayerCreationArgs& args)
mDrawingState.sequence = 0;
mDrawingState.transform.set(0, 0);
mDrawingState.frameNumber = 0;
+ mDrawingState.previousFrameNumber = 0;
mDrawingState.barrierFrameNumber = 0;
mDrawingState.producerId = 0;
mDrawingState.barrierProducerId = 0;
@@ -193,6 +193,7 @@ Layer::Layer(const LayerCreationArgs& args)
mDrawingState.dropInputMode = gui::DropInputMode::NONE;
mDrawingState.dimmingEnabled = true;
mDrawingState.defaultFrameRateCompatibility = FrameRateCompatibility::Default;
+ mDrawingState.frameRateSelectionStrategy = FrameRateSelectionStrategy::Propagate;
if (args.flags & ISurfaceComposerClient::eNoColorFill) {
// Set an invalid color so there is no color fill.
@@ -206,6 +207,7 @@ Layer::Layer(const LayerCreationArgs& args)
mOwnerUid = args.ownerUid;
mOwnerPid = args.ownerPid;
+ mOwnerAppId = mOwnerUid % PER_USER_RANGE;
mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow;
@@ -213,7 +215,6 @@ Layer::Layer(const LayerCreationArgs& args)
mSnapshot->sequence = sequence;
mSnapshot->name = getDebugName();
- mSnapshot->textureName = mTextureName;
mSnapshot->premultipliedAlpha = mPremultipliedAlpha;
mSnapshot->parentTransform = {};
}
@@ -235,13 +236,6 @@ Layer::~Layer() {
mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFrameNumber,
mBufferInfo.mFence);
}
- if (!isClone()) {
- // The original layer and the clone layer share the same texture. Therefore, only one of
- // the layers, in this case the original layer, needs to handle the deletion. The original
- // layer and the clone should be removed at the same time so there shouldn't be any issue
- // with the clone layer trying to use the deleted texture.
- mFlinger->deleteTextureAsync(mTextureName);
- }
const int32_t layerId = getSequence();
mFlinger->mTimeStats->onDestroy(layerId);
mFlinger->mFrameTracer->onDestroy(layerId);
@@ -401,7 +395,7 @@ void Layer::updateTrustedPresentationState(const DisplayDevice* display,
mLastComputedTrustedPresentationState = false;
if (!leaveState) {
- const auto outputLayer = findOutputLayerForDisplay(display);
+ const auto outputLayer = findOutputLayerForDisplay(display, snapshot->path);
if (outputLayer != nullptr) {
if (outputLayer->getState().coveredRegionExcludingDisplayOverlays) {
Region coveredRegion =
@@ -580,7 +574,7 @@ void Layer::prepareBasicGeometryCompositionState() {
snapshot->outputFilter = getOutputFilter();
snapshot->isVisible = isVisible();
snapshot->isOpaque = opaque && !usesRoundedCorners && alpha == 1.f;
- snapshot->shadowRadius = mEffectiveShadowRadius;
+ snapshot->shadowSettings.length = mEffectiveShadowRadius;
snapshot->contentDirty = contentDirty;
contentDirty = false;
@@ -593,8 +587,8 @@ void Layer::prepareBasicGeometryCompositionState() {
snapshot->localTransformInverse = snapshot->localTransform.inverse();
snapshot->blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode);
snapshot->alpha = alpha;
- snapshot->backgroundBlurRadius = drawingState.backgroundBlurRadius;
- snapshot->blurRegions = drawingState.blurRegions;
+ snapshot->backgroundBlurRadius = getBackgroundBlurRadius();
+ snapshot->blurRegions = getBlurRegions();
snapshot->stretchEffect = getStretchEffect();
}
@@ -658,13 +652,12 @@ void Layer::preparePerFrameCompositionState() {
// 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 ||
- snapshot->stretchEffect.hasEffect()) {
+ if (drawShadows() || snapshot->stretchEffect.hasEffect()) {
snapshot->forceClientComposition = true;
}
// If there are no visible region changes, we still need to update blur parameters.
- snapshot->blurRegions = drawingState.blurRegions;
- snapshot->backgroundBlurRadius = drawingState.backgroundBlurRadius;
+ snapshot->blurRegions = getBlurRegions();
+ snapshot->backgroundBlurRadius = getBackgroundBlurRadius();
// Layer framerate is used in caching decisions.
// Retrieve it from the scheduler which maintains an instance of LayerHistory, and store it in
@@ -740,6 +733,11 @@ const char* Layer::getDebugName() const {
aidl::android::hardware::graphics::composer3::Composition Layer::getCompositionType(
const DisplayDevice& display) const {
const auto outputLayer = findOutputLayerForDisplay(&display);
+ return getCompositionType(outputLayer);
+}
+
+aidl::android::hardware::graphics::composer3::Composition Layer::getCompositionType(
+ const compositionengine::OutputLayer* outputLayer) const {
if (outputLayer == nullptr) {
return aidl::android::hardware::graphics::composer3::Composition::INVALID;
}
@@ -791,8 +789,9 @@ void Layer::transferAvailableJankData(const std::deque<sp<CallbackHandle>>& hand
if (includeJankData) {
std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame =
mPendingJankClassifications.front();
- jankData.emplace_back(
- JankData(surfaceFrame->getToken(), surfaceFrame->getJankType().value()));
+ jankData.emplace_back(JankData(surfaceFrame->getToken(),
+ surfaceFrame->getJankType().value(),
+ surfaceFrame->getRenderRate().getPeriodNsecs()));
}
mPendingJankClassifications.pop_front();
}
@@ -830,12 +829,12 @@ uint32_t Layer::doTransaction(uint32_t flags) {
mFlinger->mUpdateInputInfo = true;
}
- commitTransaction(mDrawingState);
+ commitTransaction();
return flags;
}
-void Layer::commitTransaction(State&) {
+void Layer::commitTransaction() {
// Set the present state for all bufferlessSurfaceFramesTX to Presented. The
// bufferSurfaceFrameTX will be presented in latchBuffer.
for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) {
@@ -1005,8 +1004,8 @@ bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace da
uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect;
std::string name = mName + "BackgroundColorLayer";
mDrawingState.bgColorLayer = mFlinger->getFactory().createEffectLayer(
- LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags,
- LayerMetadata()));
+ surfaceflinger::LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags,
+ LayerMetadata()));
// add to child list
addChild(mDrawingState.bgColorLayer);
@@ -1159,12 +1158,12 @@ bool Layer::setDefaultFrameRateCompatibility(FrameRateCompatibility compatibilit
if (mDrawingState.defaultFrameRateCompatibility == compatibility) return false;
mDrawingState.defaultFrameRateCompatibility = compatibility;
mDrawingState.modified = true;
- mFlinger->mScheduler->setDefaultFrameRateCompatibility(this);
+ mFlinger->mScheduler->setDefaultFrameRateCompatibility(sequence, compatibility);
setTransactionFlags(eTransactionNeeded);
return true;
}
-scheduler::LayerInfo::FrameRateCompatibility Layer::getDefaultFrameRateCompatibility() const {
+scheduler::FrameRateCompatibility Layer::getDefaultFrameRateCompatibility() const {
return mDrawingState.defaultFrameRateCompatibility;
}
@@ -1256,43 +1255,53 @@ const half4& Layer::getBorderColor() {
return mBorderColor;
}
-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
+bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool overrideChildren,
+ bool* transactionNeeded) {
+ // Gets the frame rate to propagate to children.
const auto frameRate = [&] {
- if (mDrawingState.frameRate.rate.isValid() ||
- mDrawingState.frameRate.type == FrameRateCompatibility::NoVote) {
+ if (overrideChildren && parentFrameRate.isValid()) {
+ return parentFrameRate;
+ }
+
+ if (mDrawingState.frameRate.isValid()) {
return mDrawingState.frameRate;
}
return parentFrameRate;
}();
- *transactionNeeded |= setFrameRateForLayerTreeLegacy(frameRate);
+ auto now = systemTime();
+ *transactionNeeded |= setFrameRateForLayerTreeLegacy(frameRate, now);
- // The frame rate is propagated to the children
+ // The frame rate is propagated to the children by default, but some properties may override it.
bool childrenHaveFrameRate = false;
+ const bool overrideChildrenFrameRate = overrideChildren || shouldOverrideChildrenFrameRate();
+ const bool canPropagateFrameRate = shouldPropagateFrameRate() || overrideChildrenFrameRate;
for (const sp<Layer>& child : mCurrentChildren) {
childrenHaveFrameRate |=
- child->propagateFrameRateForLayerTree(frameRate, transactionNeeded);
+ child->propagateFrameRateForLayerTree(canPropagateFrameRate ? frameRate
+ : FrameRate(),
+ overrideChildrenFrameRate, transactionNeeded);
}
- // If we don't have a valid frame rate, but the children do, we set this
+ // If we don't have a valid frame rate specification, 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) {
+ if (!frameRate.isValid() && childrenHaveFrameRate) {
*transactionNeeded |=
- setFrameRateForLayerTreeLegacy(FrameRate(Fps(), FrameRateCompatibility::NoVote));
+ setFrameRateForLayerTreeLegacy(FrameRate(Fps(), FrameRateCompatibility::NoVote),
+ now);
}
- // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes for
+ // We return whether this layer or its children has a vote. We ignore ExactOrMultiple votes for
// the same reason we are allowing touch boost for those layers. See
// RefreshRateSelector::rankFrameRates for details.
const auto layerVotedWithDefaultCompatibility =
- frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Default;
- const auto layerVotedWithNoVote = frameRate.type == FrameRateCompatibility::NoVote;
+ frameRate.vote.rate.isValid() && frameRate.vote.type == FrameRateCompatibility::Default;
+ const auto layerVotedWithNoVote = frameRate.vote.type == FrameRateCompatibility::NoVote;
+ const auto layerVotedWithCategory = frameRate.category != FrameRateCategory::Default;
const auto layerVotedWithExactCompatibility =
- frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Exact;
- return layerVotedWithDefaultCompatibility || layerVotedWithNoVote ||
+ frameRate.vote.rate.isValid() && frameRate.vote.type == FrameRateCompatibility::Exact;
+ return layerVotedWithDefaultCompatibility || layerVotedWithNoVote || layerVotedWithCategory ||
layerVotedWithExactCompatibility || childrenHaveFrameRate;
}
@@ -1306,7 +1315,7 @@ void Layer::updateTreeHasFrameRateVote() {
}();
bool transactionNeeded = false;
- root->propagateFrameRateForLayerTree({}, &transactionNeeded);
+ root->propagateFrameRateForLayerTree({}, false, &transactionNeeded);
// TODO(b/195668952): we probably don't need eTraversalNeeded here
if (transactionNeeded) {
@@ -1314,13 +1323,13 @@ void Layer::updateTreeHasFrameRateVote() {
}
}
-bool Layer::setFrameRate(FrameRate frameRate) {
- if (mDrawingState.frameRate == frameRate) {
+bool Layer::setFrameRate(FrameRate::FrameRateVote frameRateVote) {
+ if (mDrawingState.frameRate.vote == frameRateVote) {
return false;
}
mDrawingState.sequence++;
- mDrawingState.frameRate = frameRate;
+ mDrawingState.frameRate.vote = frameRateVote;
mDrawingState.modified = true;
updateTreeHasFrameRateVote();
@@ -1329,6 +1338,34 @@ bool Layer::setFrameRate(FrameRate frameRate) {
return true;
}
+bool Layer::setFrameRateCategory(FrameRateCategory category, bool smoothSwitchOnly) {
+ if (mDrawingState.frameRate.category == category &&
+ mDrawingState.frameRate.categorySmoothSwitchOnly == smoothSwitchOnly) {
+ return false;
+ }
+
+ mDrawingState.sequence++;
+ mDrawingState.frameRate.category = category;
+ mDrawingState.frameRate.categorySmoothSwitchOnly = smoothSwitchOnly;
+ mDrawingState.modified = true;
+
+ updateTreeHasFrameRateVote();
+
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool Layer::setFrameRateSelectionStrategy(FrameRateSelectionStrategy strategy) {
+ if (mDrawingState.frameRateSelectionStrategy == strategy) return false;
+ mDrawingState.frameRateSelectionStrategy = strategy;
+ mDrawingState.sequence++;
+ mDrawingState.modified = true;
+
+ updateTreeHasFrameRateVote();
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info,
nsecs_t postTime) {
mDrawingState.postTime = postTime;
@@ -1463,7 +1500,7 @@ void Layer::setFrameTimelineVsyncForSkippedFrames(const FrameTimelineInfo& info,
addSurfaceFrameDroppedForBuffer(surfaceFrame, postTime);
}
-bool Layer::setFrameRateForLayerTreeLegacy(FrameRate frameRate) {
+bool Layer::setFrameRateForLayerTreeLegacy(FrameRate frameRate, nsecs_t now) {
if (mDrawingState.frameRateForLayerTree == frameRate) {
return false;
}
@@ -1477,19 +1514,20 @@ bool Layer::setFrameRateForLayerTreeLegacy(FrameRate frameRate) {
setTransactionFlags(eTransactionNeeded);
mFlinger->mScheduler
- ->recordLayerHistory(sequence, getLayerProps(), systemTime(),
+ ->recordLayerHistory(sequence, getLayerProps(), now, now,
scheduler::LayerHistory::LayerUpdateType::SetFrameRate);
return true;
}
-bool Layer::setFrameRateForLayerTree(FrameRate frameRate, const scheduler::LayerProps& layerProps) {
+bool Layer::setFrameRateForLayerTree(FrameRate frameRate, const scheduler::LayerProps& layerProps,
+ nsecs_t now) {
if (mDrawingState.frameRateForLayerTree == frameRate) {
return false;
}
mDrawingState.frameRateForLayerTree = frameRate;
mFlinger->mScheduler
- ->recordLayerHistory(sequence, layerProps, systemTime(),
+ ->recordLayerHistory(sequence, layerProps, now, now,
scheduler::LayerHistory::LayerUpdateType::SetFrameRate);
return true;
}
@@ -1610,7 +1648,7 @@ void Layer::miniDumpHeader(std::string& result) {
result.append("\n");
}
-void Layer::miniDump(std::string& result, const DisplayDevice& display) const {
+void Layer::miniDumpLegacy(std::string& result, const DisplayDevice& display) const {
const auto outputLayer = findOutputLayerForDisplay(&display);
if (!outputLayer) {
return;
@@ -1646,10 +1684,10 @@ void Layer::miniDump(std::string& result, const DisplayDevice& display) const {
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(),
- ftl::enum_string(frameRate.type).c_str(),
- ftl::enum_string(frameRate.seamlessness).c_str());
+ if (frameRate.vote.rate.isValid() || frameRate.vote.type != FrameRateCompatibility::Default) {
+ StringAppendF(&result, "%s %15s %17s", to_string(frameRate.vote.rate).c_str(),
+ ftl::enum_string(frameRate.vote.type).c_str(),
+ ftl::enum_string(frameRate.vote.seamlessness).c_str());
} else {
result.append(41, ' ');
}
@@ -1661,6 +1699,49 @@ void Layer::miniDump(std::string& result, const DisplayDevice& display) const {
result.append("\n");
}
+void Layer::miniDump(std::string& result, const frontend::LayerSnapshot& snapshot,
+ const DisplayDevice& display) const {
+ const auto outputLayer = findOutputLayerForDisplay(&display, snapshot.path);
+ if (!outputLayer) {
+ return;
+ }
+
+ StringAppendF(&result, " %s\n", snapshot.debugName.c_str());
+ StringAppendF(&result, " %10zu | ", snapshot.globalZ);
+ StringAppendF(&result, " %10d | ",
+ snapshot.layerMetadata.getInt32(gui::METADATA_WINDOW_TYPE, 0));
+ StringAppendF(&result, "%10s | ", toString(getCompositionType(outputLayer)).c_str());
+ const auto& outputLayerState = outputLayer->getState();
+ 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 = outputLayerState.sourceCrop;
+ StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right,
+ crop.bottom);
+ const auto frameRate = snapshot.frameRate;
+ std::string frameRateStr;
+ if (frameRate.vote.rate.isValid()) {
+ StringAppendF(&frameRateStr, "%.2f", frameRate.vote.rate.getValue());
+ }
+ if (frameRate.vote.rate.isValid() || frameRate.vote.type != FrameRateCompatibility::Default) {
+ StringAppendF(&result, "%6s %15s %17s", frameRateStr.c_str(),
+ ftl::enum_string(frameRate.vote.type).c_str(),
+ ftl::enum_string(frameRate.vote.seamlessness).c_str());
+ } else if (frameRate.category != FrameRateCategory::Default) {
+ StringAppendF(&result, "%6s %15s %17s", frameRateStr.c_str(),
+ (std::string("Cat::") + ftl::enum_string(frameRate.category)).c_str(),
+ ftl::enum_string(frameRate.vote.seamlessness).c_str());
+ } else {
+ result.append(41, ' ');
+ }
+
+ const auto focused = isLayerFocusedBasedOnPriority(snapshot.frameRateSelectionPriority);
+ StringAppendF(&result, " [%s]\n", focused ? "*" : " ");
+
+ result.append(kDumpTableRowLength, '-');
+ result.append("\n");
+}
+
void Layer::dumpFrameStats(std::string& result) const {
mFrameTracker.dumpStats(result);
}
@@ -2070,6 +2151,13 @@ const std::vector<BlurRegion> Layer::getBlurRegions() const {
}
RoundedCornerState Layer::getRoundedCornerState() const {
+ // Today's DPUs cannot do rounded corners. If RenderEngine cannot render
+ // protected content, remove rounded corners from protected content so it
+ // can be rendered by the DPU.
+ if (isProtected() && !mFlinger->getRenderEngine().supportsProtectedContent()) {
+ return {};
+ }
+
// Get parent settings
RoundedCornerState parentSettings;
const auto& parent = mDrawingParent.promote();
@@ -2152,8 +2240,9 @@ void Layer::setInputInfo(const WindowInfo& info) {
setTransactionFlags(eTransactionNeeded);
}
-LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) {
- LayerProto* layerProto = layersProto.add_layers();
+perfetto::protos::LayerProto* Layer::writeToProto(perfetto::protos::LayersProto& layersProto,
+ uint32_t traceFlags) {
+ perfetto::protos::LayerProto* layerProto = layersProto.add_layers();
writeToProtoDrawingState(layerProto);
writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
@@ -2170,20 +2259,22 @@ LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) {
return layerProto;
}
-void Layer::writeCompositionStateToProto(LayerProto* layerProto, ui::LayerStack layerStack) {
+void Layer::writeCompositionStateToProto(perfetto::protos::LayerProto* layerProto,
+ ui::LayerStack layerStack) {
ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread.
ftl::FakeGuard mainThreadGuard(kMainThreadContext);
// Only populate for the primary display.
if (const auto display = mFlinger->getDisplayFromLayerStack(layerStack)) {
const auto compositionType = getCompositionType(*display);
- layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
+ layerProto->set_hwc_composition_type(
+ static_cast<perfetto::protos::HwcCompositionType>(compositionType));
LayerProtoHelper::writeToProto(getVisibleRegion(display),
[&]() { return layerProto->mutable_visible_region(); });
}
}
-void Layer::writeToProtoDrawingState(LayerProto* layerInfo) {
+void Layer::writeToProtoDrawingState(perfetto::protos::LayerProto* layerInfo) {
const ui::Transform transform = getTransform();
auto buffer = getExternalTexture();
if (buffer != nullptr) {
@@ -2222,8 +2313,8 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo) {
layerInfo->set_shadow_radius(mEffectiveShadowRadius);
}
-void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
- uint32_t traceFlags) {
+void Layer::writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo,
+ LayerVector::StateSet stateSet, uint32_t traceFlags) {
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
const State& state = useDrawing ? mDrawingState : mDrawingState;
@@ -2271,15 +2362,11 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet
auto parent = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote();
if (parent != nullptr) {
layerInfo->set_parent(parent->sequence);
- } else {
- layerInfo->set_parent(-1);
}
auto zOrderRelativeOf = state.zOrderRelativeOf.promote();
if (zOrderRelativeOf != nullptr) {
layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence);
- } else {
- layerInfo->set_z_order_relative_of(-1);
}
layerInfo->set_is_relative_of(state.isRelativeOf);
@@ -2351,11 +2438,7 @@ void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& screenToDi
info.touchableRegion.clear();
}
- const Rect roundedFrameInDisplay = getInputBoundsInDisplaySpace(inputBounds, screenToDisplay);
- info.frameLeft = roundedFrameInDisplay.left;
- info.frameTop = roundedFrameInDisplay.top;
- info.frameRight = roundedFrameInDisplay.right;
- info.frameBottom = roundedFrameInDisplay.bottom;
+ info.frame = getInputBoundsInDisplaySpace(inputBounds, screenToDisplay);
ui::Transform inputToLayer;
inputToLayer.set(inputBounds.left, inputBounds.top);
@@ -2519,6 +2602,9 @@ WindowInfo Layer::fillInputInfo(const InputDisplayArgs& displayArgs) {
}
}
+ Rect bufferSize = getBufferSize(getDrawingState());
+ info.contentSize = Size(bufferSize.width(), bufferSize.height());
+
return info;
}
@@ -2577,14 +2663,33 @@ compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
return display->getCompositionDisplay()->getOutputLayerForLayer(layerFE);
}
+compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
+ const DisplayDevice* display, const frontend::LayerHierarchy::TraversalPath& path) const {
+ if (!display) return nullptr;
+ if (!mFlinger->mLayerLifecycleManagerEnabled) {
+ return display->getCompositionDisplay()->getOutputLayerForLayer(
+ getCompositionEngineLayerFE());
+ }
+ sp<LayerFE> layerFE;
+ for (auto& [p, layer] : mLayerFEs) {
+ if (p == path) {
+ layerFE = layer;
+ }
+ }
+
+ if (!layerFE) return nullptr;
+ return display->getCompositionDisplay()->getOutputLayerForLayer(layerFE);
+}
+
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, uint32_t mirrorRootId) {
+ if (mFlinger->mLayerLifecycleManagerEnabled) return;
mSnapshot->path.id = clonedFrom->getSequence();
- mSnapshot->path.mirrorRootId = mirrorRootId;
+ mSnapshot->path.mirrorRootIds.emplace_back(mirrorRootId);
cloneDrawingState(clonedFrom.get());
mClonedFrom = clonedFrom;
@@ -2758,36 +2863,6 @@ void Layer::addChildToDrawing(const sp<Layer>& layer) {
layer->mDrawingParent = sp<Layer>::fromExisting(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;
- case ANATIVEWINDOW_FRAME_RATE_EXACT:
- return FrameRateCompatibility::Exact;
- case ANATIVEWINDOW_FRAME_RATE_MIN:
- return FrameRateCompatibility::Min;
- case ANATIVEWINDOW_FRAME_RATE_NO_VOTE:
- return FrameRateCompatibility::NoVote;
- 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::isInternalDisplayOverlay() const {
const State& s(mDrawingState);
if (s.flags & layer_state_t::eLayerSkipScreenshot) {
@@ -2871,18 +2946,18 @@ void Layer::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,
break;
}
}
-
- // Prevent tracing the same release multiple times.
- if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
- mPreviousReleasedFrameNumber = mPreviousFrameNumber;
- }
-
if (ch != nullptr) {
ch->previousReleaseCallbackId = mPreviousReleaseCallbackId;
ch->previousReleaseFences.emplace_back(std::move(futureFenceResult));
ch->name = mName;
}
- mPreviouslyPresentedLayerStacks.push_back(layerStack);
+ if (mBufferInfo.mBuffer) {
+ mPreviouslyPresentedLayerStacks.push_back(layerStack);
+ }
+
+ if (mDrawingState.frameNumber > 0) {
+ mDrawingState.previousFrameNumber = mDrawingState.frameNumber;
+ }
}
void Layer::onSurfaceFrameCreated(
@@ -3058,9 +3133,36 @@ bool Layer::setPosition(float x, float y) {
return true;
}
+void Layer::releasePreviousBuffer() {
+ mReleasePreviousBuffer = true;
+ if (!mBufferInfo.mBuffer ||
+ (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) ||
+ mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) {
+ // If mDrawingState has a buffer, and we are about to update again
+ // before swapping to drawing state, then the first buffer will be
+ // dropped and we should decrement the pending buffer count and
+ // call any release buffer callbacks if set.
+ callReleaseBufferCallback(mDrawingState.releaseBufferListener,
+ mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
+ mDrawingState.acquireFence);
+ decrementPendingBufferCount();
+ if (mDrawingState.bufferSurfaceFrameTX != nullptr &&
+ mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) {
+ addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX, systemTime());
+ mDrawingState.bufferSurfaceFrameTX.reset();
+ }
+ } else if (EARLY_RELEASE_ENABLED && mLastClientCompositionFence != nullptr) {
+ callReleaseBufferCallback(mDrawingState.releaseBufferListener,
+ mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
+ mLastClientCompositionFence);
+ mLastClientCompositionFence = nullptr;
+ }
+}
+
void Layer::resetDrawingStateBufferInfo() {
mDrawingState.producerId = 0;
mDrawingState.frameNumber = 0;
+ mDrawingState.previousFrameNumber = 0;
mDrawingState.releaseBufferListener = nullptr;
mDrawingState.buffer = nullptr;
mDrawingState.acquireFence = sp<Fence>::make(-1);
@@ -3082,29 +3184,7 @@ bool Layer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
ATRACE_FORMAT_INSTANT("setBuffer %s - %" PRIu64, getDebugName(), frameNumber);
if (mDrawingState.buffer) {
- mReleasePreviousBuffer = true;
- if (!mBufferInfo.mBuffer ||
- (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) ||
- mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) {
- // If mDrawingState has a buffer, and we are about to update again
- // before swapping to drawing state, then the first buffer will be
- // dropped and we should decrement the pending buffer count and
- // call any release buffer callbacks if set.
- callReleaseBufferCallback(mDrawingState.releaseBufferListener,
- mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
- mDrawingState.acquireFence);
- decrementPendingBufferCount();
- if (mDrawingState.bufferSurfaceFrameTX != nullptr &&
- mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) {
- addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX, systemTime());
- mDrawingState.bufferSurfaceFrameTX.reset();
- }
- } else if (EARLY_RELEASE_ENABLED && mLastClientCompositionFence != nullptr) {
- callReleaseBufferCallback(mDrawingState.releaseBufferListener,
- mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
- mLastClientCompositionFence);
- mLastClientCompositionFence = nullptr;
- }
+ releasePreviousBuffer();
} else if (buffer) {
// if we are latching a buffer for the first time then clear the mLastLatchTime since
// we don't want to incorrectly classify a frame if we miss the desired present time.
@@ -3122,6 +3202,11 @@ bool Layer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
mDrawingState.bufferSurfaceFrameTX = nullptr;
setFrameTimelineVsyncForBufferlessTransaction(info, postTime);
return true;
+ } else {
+ // release sideband stream if it exists and a non null buffer is being set
+ if (mDrawingState.sidebandStream != nullptr) {
+ setSidebandStream(nullptr, info, postTime);
+ }
}
if ((mDrawingState.producerId > bufferData.producerId) ||
@@ -3162,7 +3247,7 @@ bool Layer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
mOwnerUid, postTime, getGameMode());
if (mFlinger->mLegacyFrontEndEnabled) {
- recordLayerHistoryBufferUpdate(getLayerProps());
+ recordLayerHistoryBufferUpdate(getLayerProps(), systemTime());
}
setFrameTimelineVsyncForBufferTransaction(info, postTime);
@@ -3180,7 +3265,7 @@ bool Layer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
// If the layer had been updated a TextureView, this would make sure the present time could be
// same to TextureView update when it's a small dirty, and get the correct heuristic rate.
- if (mFlinger->mScheduler->supportSmallDirtyDetection()) {
+ if (mFlinger->mScheduler->supportSmallDirtyDetection(mOwnerAppId)) {
if (mDrawingState.useVsyncIdForRefreshRateSelection) {
mUsedVsyncIdForRefreshRateSelection = true;
}
@@ -3193,7 +3278,7 @@ void Layer::setDesiredPresentTime(nsecs_t desiredPresentTime, bool isAutoTimesta
mDrawingState.isAutoTimestamp = isAutoTimestamp;
}
-void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerProps) {
+void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerProps, nsecs_t now) {
ATRACE_CALL();
const nsecs_t presentTime = [&] {
if (!mDrawingState.isAutoTimestamp) {
@@ -3213,7 +3298,7 @@ void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerPro
}
}
- if (!mFlinger->mScheduler->supportSmallDirtyDetection()) {
+ if (!mFlinger->mScheduler->supportSmallDirtyDetection(mOwnerAppId)) {
return static_cast<nsecs_t>(0);
}
@@ -3247,14 +3332,14 @@ void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerPro
ATRACE_FORMAT_INSTANT("presentIn %s", to_string(presentIn).c_str());
}
- mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime,
+ mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime, now,
scheduler::LayerHistory::LayerUpdateType::Buffer);
}
-void Layer::recordLayerHistoryAnimationTx(const scheduler::LayerProps& layerProps) {
+void Layer::recordLayerHistoryAnimationTx(const scheduler::LayerProps& layerProps, nsecs_t now) {
const nsecs_t presentTime =
mDrawingState.isAutoTimestamp ? 0 : mDrawingState.desiredPresentTime;
- mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime,
+ mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime, now,
scheduler::LayerHistory::LayerUpdateType::AnimationTX);
}
@@ -3298,7 +3383,7 @@ bool Layer::setSurfaceDamageRegion(const Region& surfaceDamage) {
mDrawingState.surfaceDamageRegion = surfaceDamage;
mDrawingState.modified = true;
setTransactionFlags(eTransactionNeeded);
- setIsSmallDirty();
+ setIsSmallDirty(surfaceDamage, getTransform());
return true;
}
@@ -3310,7 +3395,8 @@ bool Layer::setApi(int32_t api) {
return true;
}
-bool Layer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
+bool Layer::setSidebandStream(const sp<NativeHandle>& sidebandStream, const FrameTimelineInfo& info,
+ nsecs_t postTime) {
if (mDrawingState.sidebandStream == sidebandStream) return false;
if (mDrawingState.sidebandStream != nullptr && sidebandStream == nullptr) {
@@ -3321,6 +3407,12 @@ bool Layer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
mDrawingState.sidebandStream = sidebandStream;
mDrawingState.modified = true;
+ if (sidebandStream != nullptr && mDrawingState.buffer != nullptr) {
+ releasePreviousBuffer();
+ resetDrawingStateBufferInfo();
+ mDrawingState.bufferSurfaceFrameTX = nullptr;
+ setFrameTimelineVsyncForBufferlessTransaction(info, postTime);
+ }
setTransactionFlags(eTransactionNeeded);
if (!mSidebandStreamChanged.exchange(true)) {
// mSidebandStreamChanged was false
@@ -3347,6 +3439,7 @@ bool Layer::setTransactionCompletedListeners(const std::vector<sp<CallbackHandle
// If this transaction set an acquire fence on this layer, set its acquire time
handle->acquireTimeOrFence = mCallbackHandleAcquireTimeOrFence;
handle->frameNumber = mDrawingState.frameNumber;
+ handle->previousFrameNumber = mDrawingState.previousFrameNumber;
// Store so latched time and release fence can be set
mDrawingState.callbackHandles.push_back(handle);
@@ -3552,7 +3645,7 @@ void Layer::gatherBufferInfo() {
// to upsert RenderEngine's caches. Put in a special workaround to be backwards
// compatible with old vendors, with a ticking clock.
static const int32_t kVendorVersion =
- base::GetIntProperty("ro.vndk.version", __ANDROID_API_FUTURE__);
+ base::GetIntProperty("ro.board.api_level", __ANDROID_API_FUTURE__);
if (const auto format =
static_cast<aidl::android::hardware::graphics::common::PixelFormat>(
mBufferInfo.mBuffer->getPixelFormat());
@@ -3595,8 +3688,8 @@ Rect Layer::computeBufferCrop(const State& s) {
}
sp<Layer> Layer::createClone(uint32_t mirrorRootId) {
- LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata());
- args.textureName = mTextureName;
+ surfaceflinger::LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0,
+ LayerMetadata());
sp<Layer> layer = mFlinger->getFactory().createBufferStateLayer(args);
layer->setInitialValuesForClone(sp<Layer>::fromExisting(this), mirrorRootId);
return layer;
@@ -3859,13 +3952,6 @@ bool Layer::isSimpleBufferUpdate(const layer_state_t& s) const {
return true;
}
-bool Layer::isHdrY410() const {
- // pixel format is HDR Y410 masquerading as RGBA_1010102
- return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ &&
- mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA &&
- mBufferInfo.mPixelFormat == HAL_PIXEL_FORMAT_RGBA_1010102);
-}
-
sp<LayerFE> Layer::getCompositionEngineLayerFE() const {
// There's no need to get a CE Layer if the layer isn't going to draw anything.
return hasSomethingToDraw() ? mLegacyLayerFE : nullptr;
@@ -3958,10 +4044,10 @@ bool Layer::isVisible() const {
return getAlpha() > 0.0f || hasBlur();
}
-void Layer::onPostComposition(const DisplayDevice* display,
- const std::shared_ptr<FenceTime>& glDoneFence,
- const std::shared_ptr<FenceTime>& presentFence,
- const CompositorTiming& compositorTiming) {
+void Layer::onCompositionPresented(const DisplayDevice* display,
+ const std::shared_ptr<FenceTime>& glDoneFence,
+ const std::shared_ptr<FenceTime>& presentFence,
+ const CompositorTiming& compositorTiming) {
// mFrameLatencyNeeded is true when a new frame was latched for the
// composition.
if (!mBufferInfo.mFrameLatencyNeeded) return;
@@ -4007,7 +4093,7 @@ void Layer::onPostComposition(const DisplayDevice* display,
const std::optional<Fps> renderRate =
mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
- const auto vote = frameRateToSetFrameRateVotePayload(mDrawingState.frameRate);
+ const auto vote = frameRateToSetFrameRateVotePayload(getFrameRateForLayerTree());
const auto gameMode = getGameMode();
if (presentFence->isValid()) {
@@ -4164,6 +4250,14 @@ ui::Dataspace Layer::getDataSpace() const {
return hasBufferOrSidebandStream() ? mBufferInfo.mDataspace : mDrawingState.dataspace;
}
+bool Layer::isFrontBuffered() const {
+ if (mBufferInfo.mBuffer == nullptr) {
+ return false;
+ }
+
+ return mBufferInfo.mBuffer->getUsage() & AHARDWAREBUFFER_USAGE_FRONT_BUFFER;
+}
+
ui::Dataspace Layer::translateDataspace(ui::Dataspace dataspace) {
ui::Dataspace updatedDataspace = dataspace;
// translate legacy dataspaces to modern dataspaces
@@ -4266,7 +4360,6 @@ void Layer::updateSnapshot(bool updateGeometry) {
snapshot->contentOpaque = isOpaque(mDrawingState);
snapshot->layerOpaqueFlagSet =
(mDrawingState.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque;
- snapshot->isHdrY410 = isHdrY410();
sp<Layer> p = mDrawingParent.promote();
if (p != nullptr) {
snapshot->parentTransform = p->getTransform();
@@ -4345,8 +4438,10 @@ void Layer::updateLastLatchTime(nsecs_t latchTime) {
mLastLatchTime = latchTime;
}
-void Layer::setIsSmallDirty() {
- if (!mFlinger->mScheduler->supportSmallDirtyDetection()) {
+void Layer::setIsSmallDirty(const Region& damageRegion,
+ const ui::Transform& layerToDisplayTransform) {
+ mSmallDirty = false;
+ if (!mFlinger->mScheduler->supportSmallDirtyDetection(mOwnerAppId)) {
return;
}
@@ -4354,22 +4449,24 @@ void Layer::setIsSmallDirty() {
mWindowType != WindowInfo::Type::BASE_APPLICATION) {
return;
}
- Rect bounds = mDrawingState.surfaceDamageRegion.getBounds();
+
+ Rect bounds = damageRegion.getBounds();
if (!bounds.isValid()) {
return;
}
+ // Transform to screen space.
+ bounds = layerToDisplayTransform.transform(bounds);
+
// If the damage region is a small dirty, this could give the hint for the layer history that
// it could suppress the heuristic rate when calculating.
- mSmallDirty = mFlinger->mScheduler->isSmallDirtyArea(mOwnerUid,
+ mSmallDirty = mFlinger->mScheduler->isSmallDirtyArea(mOwnerAppId,
bounds.getWidth() * bounds.getHeight());
}
-// ---------------------------------------------------------------------------
-
-std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) {
- return stream << "{rate=" << rate.rate << " type=" << ftl::enum_string(rate.type)
- << " seamlessness=" << ftl::enum_string(rate.seamlessness) << '}';
+void Layer::setIsSmallDirty(frontend::LayerSnapshot* snapshot) {
+ setIsSmallDirty(snapshot->surfaceDamage, snapshot->localTransform);
+ snapshot->isSmallDirty = mSmallDirty;
}
} // namespace android