diff options
author | 2015-10-07 16:32:12 -0700 | |
---|---|---|
committer | 2015-11-03 12:04:10 -0800 | |
commit | 063121849890da78b1ad7fb96c54c795de5d1fd6 (patch) | |
tree | 47e2449faae2ae494528edecb4ba5cdb55fdda85 | |
parent | ccdfd60d79a8b7f1ed6401d0f2e8e29166a10584 (diff) |
SF: Force refresh when in single buffer mode
- Add a boolean to BufferItem to track whether single buffer mode is
enabled. When it is, force SurfaceFlinger to acquire a new buffer
and refresh on every vsync.
Bug 24940410
Change-Id: Iea67330c416b6fb14500865f98c67f1c12f23197
-rw-r--r-- | include/gui/BufferItem.h | 7 | ||||
-rw-r--r-- | libs/gui/BufferItem.cpp | 4 | ||||
-rw-r--r-- | libs/gui/BufferQueueConsumer.cpp | 4 | ||||
-rw-r--r-- | libs/gui/BufferQueueProducer.cpp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 30 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlingerConsumer.cpp | 12 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlingerConsumer.h | 1 |
8 files changed, 51 insertions, 14 deletions
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h index 504ac64e38..370f5d52f7 100644 --- a/include/gui/BufferItem.h +++ b/include/gui/BufferItem.h @@ -118,6 +118,13 @@ class BufferItem : public Flattenable<BufferItem> { // Describes the portion of the surface that has been modified since the // previous frame Region mSurfaceDamage; + + // Indicates that the BufferQueue is in single buffer mode + bool mSingleBufferMode; + + // Indicates that this buffer was queued by the producer. When in single + // buffer mode acquire() can return a BufferItem that wasn't in the queue. + bool mQueuedBuffer; }; } // namespace android diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp index 7305861657..de8ff70846 100644 --- a/libs/gui/BufferItem.cpp +++ b/libs/gui/BufferItem.cpp @@ -37,7 +37,9 @@ BufferItem::BufferItem() : mIsDroppable(false), mAcquireCalled(false), mTransformToDisplayInverse(false), - mSurfaceDamage() { + mSurfaceDamage(), + mSingleBufferMode(false), + mQueuedBuffer(true) { } BufferItem::~BufferItem() {} diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp index 8e2afd0012..6f9f21f296 100644 --- a/libs/gui/BufferQueueConsumer.cpp +++ b/libs/gui/BufferQueueConsumer.cpp @@ -203,11 +203,15 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, (mCore->mSingleBufferCache.transform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0; outBuffer->mSurfaceDamage = Region::INVALID_REGION; + outBuffer->mSingleBufferMode = true; + outBuffer->mQueuedBuffer = false; } else { slot = front->mSlot; *outBuffer = *front; } + outBuffer->mSingleBufferMode = mCore->mSingleBufferMode; + ATRACE_BUFFER_INDEX(slot); BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }", diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 268c9da0de..ef01745355 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -744,6 +744,8 @@ status_t BufferQueueProducer::queueBuffer(int slot, mCore->mDequeueBufferCannotBlock || (mCore->mSingleBufferMode && mCore->mSingleBufferSlot == slot); item.mSurfaceDamage = surfaceDamage; + item.mSingleBufferMode = mCore->mSingleBufferMode; + item.mQueuedBuffer = true; mStickyTransform = stickyTransform; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a7b167fbc3..ad53226c64 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1254,7 +1254,7 @@ void Layer::useEmptyDamage() { // ---------------------------------------------------------------------------- bool Layer::shouldPresentNow(const DispSync& dispSync) const { - if (mSidebandStreamChanged) { + if (mSidebandStreamChanged || mSingleBufferMode) { return true; } @@ -1278,7 +1278,7 @@ bool Layer::shouldPresentNow(const DispSync& dispSync) const { bool Layer::onPreComposition() { mRefreshPending = false; - return mQueuedFrames > 0 || mSidebandStreamChanged; + return mQueuedFrames > 0 || mSidebandStreamChanged || mSingleBufferMode; } void Layer::onPostComposition() { @@ -1335,7 +1335,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) } Region outDirtyRegion; - if (mQueuedFrames > 0) { + if (mQueuedFrames > 0 || mSingleBufferMode) { // if we've already called updateTexImage() without going through // a composition step, we have to skip this layer at this point @@ -1492,8 +1492,14 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) } } + // This boolean is used to make sure that SurfaceFlinger's shadow copy + // of the buffer queue isn't modified when the buffer queue is returning + // BufferItem's that weren't actually queued. This can happen in single + // buffer mode. + bool queuedBuffer = false; status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r, - mFlinger->mPrimaryDispSync, maxFrameNumber); + mFlinger->mPrimaryDispSync, &mSingleBufferMode, &queuedBuffer, + maxFrameNumber); if (updateResult == BufferQueue::PRESENT_LATER) { // Producer doesn't want buffer to be displayed yet. Signal a // layer update so we check again at the next opportunity. @@ -1502,16 +1508,18 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) { // If the buffer has been rejected, remove it from the shadow queue // and return early - Mutex::Autolock lock(mQueueItemLock); - mQueueItems.removeAt(0); - android_atomic_dec(&mQueuedFrames); + if (queuedBuffer) { + Mutex::Autolock lock(mQueueItemLock); + mQueueItems.removeAt(0); + android_atomic_dec(&mQueuedFrames); + } return outDirtyRegion; } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) { // This can occur if something goes wrong when trying to create the // EGLImage for this buffer. If this happens, the buffer has already // been released, so we need to clean up the queue and bug out // early. - { + if (queuedBuffer) { Mutex::Autolock lock(mQueueItemLock); mQueueItems.clear(); android_atomic_and(0, &mQueuedFrames); @@ -1526,7 +1534,8 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) return outDirtyRegion; } - { // Autolock scope + if (queuedBuffer) { + // Autolock scope auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber(); Mutex::Autolock lock(mQueueItemLock); @@ -1544,7 +1553,8 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) // Decrement the queued-frames count. Signal another event if we // have more frames pending. - if (android_atomic_dec(&mQueuedFrames) > 1) { + if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) + || mSingleBufferMode) { mFlinger->signalLayerUpdate(); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 4ff900672b..9e3c4db434 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -306,7 +306,8 @@ public: /* * Returns if a frame is queued. */ - bool hasQueuedFrame() const { return mQueuedFrames > 0 || mSidebandStreamChanged; } + bool hasQueuedFrame() const { return mQueuedFrames > 0 || + mSidebandStreamChanged || mSingleBufferMode; } // ----------------------------------------------------------------------- @@ -489,6 +490,8 @@ private: Vector<BufferItem> mQueueItems; uint64_t mLastFrameNumberReceived; bool mUpdateTexImageFailed; // This is only modified from the main thread + + bool mSingleBufferMode; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp index 930e7c764c..5722fb446c 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp +++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp @@ -32,7 +32,8 @@ namespace android { // --------------------------------------------------------------------------- status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter, - const DispSync& dispSync, uint64_t maxFrameNumber) + const DispSync& dispSync, bool* singleBufferMode, bool* queuedBuffer, + uint64_t maxFrameNumber) { ATRACE_CALL(); ALOGV("updateTexImage"); @@ -68,7 +69,6 @@ status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter, return err; } - // We call the rejecter here, in case the caller has a reason to // not accept this buffer. This is used by SurfaceFlinger to // reject buffers which have the wrong size @@ -78,6 +78,14 @@ status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter, return BUFFER_REJECTED; } + if (singleBufferMode) { + *singleBufferMode = item.mSingleBufferMode; + } + + if (queuedBuffer) { + *queuedBuffer = item.mQueuedBuffer; + } + // Release the previous buffer. err = updateAndReleaseLocked(item); if (err != NO_ERROR) { diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h index 779e5b77b2..207c243c12 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.h +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h @@ -57,6 +57,7 @@ public: // this does not guarantee that the buffer has been bound to the GL // texture. status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync, + bool* singleBufferMode, bool* queuedBuffer, uint64_t maxFrameNumber = 0); // See GLConsumer::bindTextureImageLocked(). |