summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vishnu Nair <vishnun@google.com> 2021-01-27 22:02:11 -0800
committer Vishnu Nair <vishnun@google.com> 2021-01-28 11:54:57 -0800
commitf6eddb6b42a9548f1298e899ea06a7a042182783 (patch)
tree3c3cfcc5c4589cc80069a25de8a362f7f5434599
parentdd5bfa93b0c6633b7372c87fc8d7a83a73a5cd1c (diff)
Enable backpressure for BufferStateLayer
The default behaviour of buffer state layer is to drop older buffers if there are newer buffers that are ready to be presented. When emulating BufferQueue behavior via the adapter, we want to queue up buffers without any present timestamps. To solve this, we introduce a layer state flag to keep the buffer in the transaction queue if there is already a buffer that is ready to be applied. Test: atest SurfaceViewBufferTests:BufferPresentationTests Bug: 176967609 Change-Id: I33f6347bd1c7a2d80dc4214e596bb864abe8c6bf
-rw-r--r--libs/gui/BLASTBufferQueue.cpp21
-rw-r--r--libs/gui/LayerState.cpp8
-rw-r--r--libs/gui/SurfaceComposerClient.cpp3
-rw-r--r--libs/gui/include/gui/LayerState.h8
-rw-r--r--services/surfaceflinger/Layer.cpp2
-rw-r--r--services/surfaceflinger/Layer.h7
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp29
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h2
8 files changed, 55 insertions, 25 deletions
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 0a3d44d336..490495596b 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -146,6 +146,10 @@ BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceCont
mTransformHint = mSurfaceControl->getTransformHint();
mBufferItemConsumer->setTransformHint(mTransformHint);
+ SurfaceComposerClient::Transaction()
+ .setFlags(surface, layer_state_t::eEnableBackpressure,
+ layer_state_t::eEnableBackpressure)
+ .apply();
mNumAcquired = 0;
mNumFrameAvailable = 0;
@@ -169,13 +173,20 @@ BLASTBufferQueue::~BLASTBufferQueue() {
void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, uint32_t height,
int32_t format) {
std::unique_lock _lock{mMutex};
- mSurfaceControl = surface;
-
if (mFormat != format) {
mFormat = format;
mBufferItemConsumer->setDefaultBufferFormat(format);
}
+ SurfaceComposerClient::Transaction t;
+ bool applyTransaction = false;
+ if (!SurfaceControl::isSameSurface(mSurfaceControl, surface)) {
+ mSurfaceControl = surface;
+ t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure,
+ layer_state_t::eEnableBackpressure);
+ applyTransaction = true;
+ }
+
ui::Size newSize(width, height);
if (mRequestedSize != newSize) {
mRequestedSize.set(newSize);
@@ -184,13 +195,15 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
// If the buffer supports scaling, update the frame immediately since the client may
// want to scale the existing buffer to the new size.
mSize = mRequestedSize;
- SurfaceComposerClient::Transaction t;
t.setFrame(mSurfaceControl,
{0, 0, static_cast<int32_t>(mSize.width),
static_cast<int32_t>(mSize.height)});
- t.apply();
+ applyTransaction = true;
}
}
+ if (applyTransaction) {
+ t.apply();
+ }
}
static void transactionCallbackThunk(void* context, nsecs_t latchTime,
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index e5e10a0014..2946aaed37 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -183,12 +183,9 @@ status_t layer_state_t::read(const Parcel& input)
SAFE_PARCEL(input.readUint32, &layerStack);
SAFE_PARCEL(input.readFloat, &alpha);
- uint32_t tmpUint32 = 0;
- SAFE_PARCEL(input.readUint32, &tmpUint32);
- flags = static_cast<uint8_t>(tmpUint32);
+ SAFE_PARCEL(input.readUint32, &flags);
- SAFE_PARCEL(input.readUint32, &tmpUint32);
- mask = static_cast<uint8_t>(tmpUint32);
+ SAFE_PARCEL(input.readUint32, &mask);
SAFE_PARCEL(matrix.read, input);
SAFE_PARCEL(input.read, crop_legacy);
@@ -229,6 +226,7 @@ status_t layer_state_t::read(const Parcel& input)
SAFE_PARCEL(input.read, *acquireFence);
}
+ uint32_t tmpUint32 = 0;
SAFE_PARCEL(input.readUint32, &tmpUint32);
dataspace = static_cast<ui::Dataspace>(tmpUint32);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 78f655a71b..96c099be23 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -934,7 +934,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags
return *this;
}
if ((mask & layer_state_t::eLayerOpaque) || (mask & layer_state_t::eLayerHidden) ||
- (mask & layer_state_t::eLayerSecure) || (mask & layer_state_t::eLayerSkipScreenshot)) {
+ (mask & layer_state_t::eLayerSecure) || (mask & layer_state_t::eLayerSkipScreenshot) ||
+ (mask & layer_state_t::eEnableBackpressure)) {
s->what |= layer_state_t::eFlagsChanged;
}
s->flags &= ~mask;
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 83a9d3356e..b1305c6607 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -82,6 +82,10 @@ struct layer_state_t {
eLayerOpaque = 0x02, // SURFACE_OPAQUE
eLayerSkipScreenshot = 0x40, // SKIP_SCREENSHOT
eLayerSecure = 0x80, // SECURE
+ // Queue up BufferStateLayer buffers instead of dropping the oldest buffer when this flag is
+ // set. This blocks the client until all the buffers have been presented. If the buffers
+ // have presentation timestamps, then we may drop buffers.
+ eEnableBackpressure = 0x100, // ENABLE_BACKPRESSURE
};
enum {
@@ -157,8 +161,8 @@ struct layer_state_t {
uint32_t h;
uint32_t layerStack;
float alpha;
- uint8_t flags;
- uint8_t mask;
+ uint32_t flags;
+ uint32_t mask;
uint8_t reserved;
matrix22_t matrix;
Rect crop_legacy;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 66ce3f1a44..177a81a7bc 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1312,7 +1312,7 @@ bool Layer::setBlurRegions(const std::vector<BlurRegion>& blurRegions) {
return true;
}
-bool Layer::setFlags(uint8_t flags, uint8_t mask) {
+bool Layer::setFlags(uint32_t flags, uint32_t mask) {
const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
if (mCurrentState.flags == newFlags) return false;
mCurrentState.sequence++;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 359340eb64..357c4a4dee 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -207,7 +207,7 @@ public:
// to achieve mirroring.
uint32_t layerStack;
- uint8_t flags;
+ uint32_t flags;
uint8_t reserved[2];
int32_t sequence; // changes when visible regions can change
bool modified;
@@ -425,7 +425,7 @@ public:
virtual bool setBackgroundBlurRadius(int backgroundBlurRadius);
virtual bool setBlurRegions(const std::vector<BlurRegion>& effectRegions);
virtual bool setTransparentRegionHint(const Region& transparent);
- virtual bool setFlags(uint8_t flags, uint8_t mask);
+ virtual bool setFlags(uint32_t flags, uint32_t mask);
virtual bool setLayerStack(uint32_t layerStack);
virtual uint32_t getLayerStack() const;
virtual void deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle,
@@ -906,6 +906,9 @@ public:
bool mPendingHWCDestroy{false};
+ bool backpressureEnabled() { return mDrawingState.flags & layer_state_t::eEnableBackpressure; }
+ bool hasPendingBuffer() { return mCurrentState.buffer != mDrawingState.buffer; };
+
protected:
class SyncPoint {
public:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index c1fabf8322..bf0c2d69f5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3258,7 +3258,8 @@ bool SurfaceFlinger::flushTransactionQueues() {
while (!transactionQueue.empty()) {
const auto& transaction = transactionQueue.front();
- if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime,
+ if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
+ transaction.desiredPresentTime,
transaction.states)) {
setTransactionFlags(eTransactionFlushNeeded);
break;
@@ -3291,16 +3292,14 @@ bool SurfaceFlinger::transactionFlushNeeded() {
return !mTransactionQueues.empty();
}
-
-bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
+bool SurfaceFlinger::transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
const Vector<ComposerState>& states,
bool updateTransactionCounters) {
-
const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
bool ready = true;
// Do not present if the desiredPresentTime has not passed unless it is more than one second
// in the future. We ignore timestamps more than 1 second in the future for stability reasons.
- if (desiredPresentTime > 0 && desiredPresentTime >= expectedPresentTime &&
+ if (!isAutoTimestamp && desiredPresentTime >= expectedPresentTime &&
desiredPresentTime < expectedPresentTime + s2ns(1)) {
ready = false;
}
@@ -3320,14 +3319,26 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
ALOGW("Transaction with buffer, but no Layer?");
continue;
}
- if (layer && !mScheduler->isVsyncValid(expectedPresentTime, layer->getOwnerUid())) {
+ if (!layer) {
+ continue;
+ }
+
+ if (!mScheduler->isVsyncValid(expectedPresentTime, layer->getOwnerUid())) {
ATRACE_NAME("!isVsyncValidForUid");
ready = false;
}
if (updateTransactionCounters) {
- // See BufferStateLayer::mPendingBufferTransactions
- if (layer) layer->incrementPendingBufferCount();
+ // See BufferStateLayer::mPendingBufferTransactions
+ layer->incrementPendingBufferCount();
+ }
+ // If backpressure is enabled and we already have a buffer to commit, keep the transaction
+ // in the queue.
+ bool hasBuffer = s.what & layer_state_t::eBufferChanged ||
+ s.what & layer_state_t::eCachedBufferChanged;
+ if (hasBuffer && layer->backpressureEnabled() && layer->hasPendingBuffer() &&
+ isAutoTimestamp) {
+ ready = false;
}
}
return ready;
@@ -3385,7 +3396,7 @@ status_t SurfaceFlinger::setTransactionState(
// Call transactionIsReadyToBeApplied first in case we need to incrementPendingBufferCount
// if the transaction contains a buffer.
- if (!transactionIsReadyToBeApplied(isAutoTimestamp ? 0 : desiredPresentTime, states, true) ||
+ if (!transactionIsReadyToBeApplied(isAutoTimestamp, desiredPresentTime, states, true) ||
pendingTransactions) {
mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags,
desiredPresentTime, isAutoTimestamp, uncacheBuffer,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c90fb4aca3..194131db32 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -751,7 +751,7 @@ private:
uint32_t setTransactionFlags(uint32_t flags, TransactionSchedule);
void commitTransaction() REQUIRES(mStateLock);
void commitOffscreenLayers();
- bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
+ bool transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
const Vector<ComposerState>& states,
bool updateTransactionCounters = false) REQUIRES(mStateLock);
uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);