summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-08-07 03:07:38 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-08-07 03:07:38 +0000
commit3e846409f064570d19769748a3050882c29fa999 (patch)
treef9ac849149b67c3a82bb1b881f6af42f7fe7fd4f
parent3c88bbdae7b0e47372e744183d4bec2d54a22d44 (diff)
parent810d19378edc7bbd87d738d96c4bb49ed45b3d0c (diff)
downloadnative-android12-s3-release.tar.gz
Change-Id: Ie20fa26a11aa973909bfc0b42e7b861df4039b24
-rw-r--r--services/surfaceflinger/BufferStateLayer.cpp19
-rw-r--r--services/surfaceflinger/BufferStateLayer.h1
-rw-r--r--services/surfaceflinger/Layer.cpp126
-rw-r--r--services/surfaceflinger/Layer.h10
-rw-r--r--services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp35
5 files changed, 99 insertions, 92 deletions
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 6253036c41..8bc51dfa5d 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -425,7 +425,8 @@ bool BufferStateLayer::setBuffer(const std::shared_ptr<renderengine::ExternalTex
if (mDrawingState.buffer) {
mReleasePreviousBuffer = true;
- if (mDrawingState.buffer != mBufferInfo.mBuffer) {
+ if (mDrawingState.buffer != 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
@@ -963,22 +964,6 @@ void BufferStateLayer::tracePendingBufferCount(int32_t pendingBuffers) {
ATRACE_INT(mBlastTransactionName.c_str(), pendingBuffers);
}
-void BufferStateLayer::bufferMayChange(const sp<GraphicBuffer>& newBuffer) {
- if (mDrawingState.buffer != nullptr &&
- (!mBufferInfo.mBuffer ||
- mDrawingState.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) &&
- newBuffer != mDrawingState.buffer->getBuffer()) {
- // If we are about to update mDrawingState.buffer but it has not yet latched
- // then we will drop a buffer and should decrement the pending buffer count and
- // call any release buffer callbacks if set.
- callReleaseBufferCallback(mDrawingState.releaseBufferListener,
- mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber,
- mDrawingState.acquireFence, mTransformHint,
- mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(
- mOwnerUid));
- decrementPendingBufferCount();
- }
-}
/*
* We don't want to send the layer's transform to input, but rather the
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index e5674785af..cab48994b3 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -97,7 +97,6 @@ public:
// See mPendingBufferTransactions
void decrementPendingBufferCount();
- void bufferMayChange(const sp<GraphicBuffer>& newBuffer) override;
std::atomic<int32_t>* getPendingBufferCounter() override { return &mPendingBufferTransactions; }
std::string getPendingBufferCounterName() override { return mBlastTransactionName; }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index dbd2793276..e4a777f3c7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1117,46 +1117,59 @@ StretchEffect Layer::getStretchEffect() const {
return StretchEffect{};
}
-void Layer::updateTreeHasFrameRateVote() {
- const auto traverseTree = [&](const LayerVector::Visitor& visitor) {
- auto parent = getParent();
- while (parent) {
- visitor(parent.get());
- parent = parent->getParent();
+bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* transactionNeeded) {
+ // The frame rate for layer tree is this layer's frame rate if present, or the parent frame rate
+ const auto frameRate = [&] {
+ if (mDrawingState.frameRate.rate.isValid() ||
+ mDrawingState.frameRate.type == FrameRateCompatibility::NoVote) {
+ return mDrawingState.frameRate;
}
- 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->mDrawingState.frameRate.rate.isValid() &&
- layer->mDrawingState.frameRate.type == FrameRateCompatibility::Default;
- const auto layerVotedWithNoVote =
- layer->mDrawingState.frameRate.type == FrameRateCompatibility::NoVote;
- const auto layerVotedWithExactCompatibility =
- layer->mDrawingState.frameRate.type == FrameRateCompatibility::Exact;
-
- // 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 ||
- layerVotedWithExactCompatibility) {
- layersWithVote++;
+ return parentFrameRate;
+ }();
+
+ *transactionNeeded |= setFrameRateForLayerTree(frameRate);
+
+ // The frame rate is propagated to the children
+ bool childrenHaveFrameRate = false;
+ for (const sp<Layer>& child : mCurrentChildren) {
+ childrenHaveFrameRate |=
+ child->propagateFrameRateForLayerTree(frameRate, transactionNeeded);
+ }
+
+ // If we don't have a valid frame rate, but the children do, we set this
+ // layer as NoVote to allow the children to control the refresh rate
+ if (!frameRate.rate.isValid() && frameRate.type != FrameRateCompatibility::NoVote &&
+ childrenHaveFrameRate) {
+ *transactionNeeded |=
+ setFrameRateForLayerTree(FrameRate(Fps(0.0f), FrameRateCompatibility::NoVote));
+ }
+
+ // We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes for
+ // the same reason we are allowing touch boost for those layers. See
+ // RefreshRateConfigs::getBestRefreshRate for more details.
+ const auto layerVotedWithDefaultCompatibility =
+ frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Default;
+ const auto layerVotedWithNoVote = frameRate.type == FrameRateCompatibility::NoVote;
+ const auto layerVotedWithExactCompatibility =
+ frameRate.rate.isValid() && frameRate.type == FrameRateCompatibility::Exact;
+ return layerVotedWithDefaultCompatibility || layerVotedWithNoVote ||
+ layerVotedWithExactCompatibility || childrenHaveFrameRate;
+}
+
+void Layer::updateTreeHasFrameRateVote() {
+ const auto root = [&]() -> sp<Layer> {
+ sp<Layer> layer = this;
+ while (auto parent = layer->getParent()) {
+ layer = parent;
}
- });
+ return layer;
+ }();
- // Now we can update the tree frame rate vote for each layer in the tree
- const bool treeHasFrameRateVote = layersWithVote > 0;
bool transactionNeeded = false;
+ root->propagateFrameRateForLayerTree({}, &transactionNeeded);
- traverseTree([treeHasFrameRateVote, &transactionNeeded](Layer* layer) {
- transactionNeeded = layer->updateFrameRateForLayerTree(treeHasFrameRateVote);
- });
-
+ // TODO(b/195668952): we probably don't need eTraversalNeeded here
if (transactionNeeded) {
mFlinger->setTransactionFlags(eTraversalNeeded);
}
@@ -1283,42 +1296,23 @@ std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForBuffer(
return surfaceFrame;
}
-bool Layer::updateFrameRateForLayerTree(bool treeHasFrameRateVote) {
- const auto updateDrawingState = [&](FrameRate frameRate) {
- if (mDrawingState.frameRateForLayerTree == frameRate) {
- return false;
- }
-
- mDrawingState.frameRateForLayerTree = frameRate;
- mDrawingState.sequence++;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
-
- mFlinger->mScheduler->recordLayerHistory(this, systemTime(),
- LayerHistory::LayerUpdateType::SetFrameRate);
-
- return true;
- };
-
- const auto frameRate = mDrawingState.frameRate;
- if (frameRate.rate.isValid() || frameRate.type == FrameRateCompatibility::NoVote) {
- return updateDrawingState(frameRate);
+bool Layer::setFrameRateForLayerTree(FrameRate frameRate) {
+ if (mDrawingState.frameRateForLayerTree == frameRate) {
+ return false;
}
- // This layer doesn't have a frame rate. Check if its ancestors have a vote
- for (sp<Layer> parent = getParent(); parent; parent = parent->getParent()) {
- if (parent->mDrawingState.frameRate.rate.isValid()) {
- return updateDrawingState(parent->mDrawingState.frameRate);
- }
- }
+ mDrawingState.frameRateForLayerTree = frameRate;
- // This layer and its ancestors don't have a frame rate. If one of successors
- // has a vote, return a NoVote for successors to set the vote
- if (treeHasFrameRateVote) {
- return updateDrawingState(FrameRate(Fps(0.0f), FrameRateCompatibility::NoVote));
- }
+ // TODO(b/195668952): we probably don't need to dirty visible regions here
+ // or even store frameRateForLayerTree in mDrawingState
+ mDrawingState.sequence++;
+ mDrawingState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+
+ mFlinger->mScheduler->recordLayerHistory(this, systemTime(),
+ LayerHistory::LayerUpdateType::SetFrameRate);
- return updateDrawingState(frameRate);
+ return true;
}
Layer::FrameRate Layer::getFrameRateForLayerTree() const {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c5cb17ffc7..59f5b0dc73 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -703,12 +703,6 @@ public:
virtual uint32_t doTransaction(uint32_t transactionFlags);
/*
- * Called before updating the drawing state buffer. Used by BufferStateLayer to release any
- * unlatched buffers in the drawing state.
- */
- virtual void bufferMayChange(const sp<GraphicBuffer>& /* newBuffer */){};
-
- /*
* Remove relative z for the layer if its relative parent is not part of the
* provided layer tree.
*/
@@ -1053,6 +1047,8 @@ private:
const std::vector<Layer*>& layersInTree);
void updateTreeHasFrameRateVote();
+ bool propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* transactionNeeded);
+ bool setFrameRateForLayerTree(FrameRate);
void setZOrderRelativeOf(const wp<Layer>& relativeOf);
bool isTrustedOverlay() const;
@@ -1071,8 +1067,6 @@ private:
// Fills in the frame and transform info for the InputWindowInfo
void fillInputFrameInfo(InputWindowInfo& info, const ui::Transform& toPhysicalDisplay);
- bool updateFrameRateForLayerTree(bool treeHasFrameRateVote);
-
// Cached properties computed from drawing state
// Effective transform taking into account parent transforms and any parent scaling, which is
// a transform from the current layer coordinate space to display(screen) coordinate space.
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index 1ed52ea389..2761470c31 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -485,5 +485,40 @@ TEST_P(SetFrameRateTest, SetOnParentActivatesTree) {
EXPECT_TRUE(FRAME_RATE_VOTE1.rate.equalsWithMargin(layerHistorySummary[1].desiredRefreshRate));
}
+TEST_P(SetFrameRateTest, addChildForParentWithTreeVote) {
+ EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
+
+ const auto& layerFactory = GetParam();
+
+ const auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger));
+ const auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger));
+ const auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger));
+ const auto childOfChild1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger));
+
+ addChild(parent, child1);
+ addChild(child1, childOfChild1);
+
+ childOfChild1->setFrameRate(FRAME_RATE_VOTE1);
+ commitTransaction();
+ EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, childOfChild1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree());
+
+ addChild(parent, child2);
+ commitTransaction();
+ EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_VOTE1, childOfChild1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree());
+
+ childOfChild1->setFrameRate(FRAME_RATE_NO_VOTE);
+ commitTransaction();
+ EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_NO_VOTE, childOfChild1->getFrameRateForLayerTree());
+ EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree());
+}
+
} // namespace
} // namespace android