summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);