From ac6035a12aec38eeb14d0c13636ec980066d9a8f Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Thu, 12 Apr 2012 16:32:37 -0700 Subject: [PATCH] s/w rendered apps can now use n-buffering (n>2) Bug: 6311881 Change-Id: I6e52e281e8d432430aad011f6d9dcf35d7b4ac7d --- include/gui/SurfaceTextureClient.h | 12 ++++++-- libs/gui/SurfaceTextureClient.cpp | 28 ++++++++++++++----- .../surfaceflinger/SurfaceTextureLayer.cpp | 4 --- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h index c0e90b32b..664475126 100644 --- a/include/gui/SurfaceTextureClient.h +++ b/include/gui/SurfaceTextureClient.h @@ -26,6 +26,7 @@ #include #include +#include struct ANativeWindow_Buffer; @@ -113,6 +114,11 @@ private: void freeAllBuffers(); int getSlotFromBufferLocked(android_native_buffer_t* buffer) const; + struct BufferSlot { + sp buffer; + Region dirtyRegion; + }; + // mSurfaceTexture is the interface to the surface texture server. All // operations on the surface texture client ultimately translate into // interactions with the server using this interface. @@ -124,7 +130,7 @@ private: // slot that has not yet been used. The buffer allocated to a slot will also // be replaced if the requested buffer usage or geometry differs from that // of the buffer allocated to a slot. - sp mSlots[NUM_BUFFER_SLOTS]; + BufferSlot mSlots[NUM_BUFFER_SLOTS]; // mReqWidth is the buffer width that will be requested at the next dequeue // operation. It is initialized to 1. @@ -189,8 +195,10 @@ private: // must be used from the lock/unlock thread sp mLockedBuffer; sp mPostedBuffer; - mutable Region mOldDirtyRegion; bool mConnectedToCpu; + + // must be accessed from lock/unlock thread only + Region mDirtyRegion; }; }; // namespace android diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index 99c025f91..b37d821f9 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -171,7 +171,7 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { result); return result; } - sp& gbuf(mSlots[buf]); + sp& gbuf(mSlots[buf].buffer); if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) { freeAllBuffers(); } @@ -204,7 +204,8 @@ int SurfaceTextureClient::getSlotFromBufferLocked( android_native_buffer_t* buffer) const { bool dumpedState = false; for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - if (mSlots[i] != NULL && mSlots[i]->handle == buffer->handle) { + if (mSlots[i].buffer != NULL && + mSlots[i].buffer->handle == buffer->handle) { return i; } } @@ -586,7 +587,7 @@ int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp) void SurfaceTextureClient::freeAllBuffers() { for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { - mSlots[i] = 0; + mSlots[i].buffer = 0; } } @@ -691,19 +692,32 @@ status_t SurfaceTextureClient::lock( if (canCopyBack) { // copy the area that is invalid and not repainted this round - const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion)); + const Region copyback(mDirtyRegion.subtract(newDirtyRegion)); if (!copyback.isEmpty()) copyBlt(backBuffer, frontBuffer, copyback); } else { // if we can't copy-back anything, modify the user's dirty // region to make sure they redraw the whole buffer newDirtyRegion.set(bounds); + mDirtyRegion.clear(); + Mutex::Autolock lock(mMutex); + for (size_t i=0 ; i= 0) { + Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion); + mDirtyRegion.subtract(dirtyRegion); + dirtyRegion = newDirtyRegion; + } + } + + mDirtyRegion.orSelf(newDirtyRegion); if (inOutDirtyBounds) { *inOutDirtyBounds = newDirtyRegion.getBounds(); } diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp index d7fd39e21..2b647bb8a 100644 --- a/services/surfaceflinger/SurfaceTextureLayer.cpp +++ b/services/surfaceflinger/SurfaceTextureLayer.cpp @@ -40,10 +40,6 @@ status_t SurfaceTextureLayer::connect(int api, outWidth, outHeight, outTransform); if (err == NO_ERROR) { switch(api) { - case NATIVE_WINDOW_API_CPU: - // SurfaceTextureClient supports only 2 buffers for CPU connections - this->setBufferCountServer(2); - break; case NATIVE_WINDOW_API_MEDIA: case NATIVE_WINDOW_API_CAMERA: // Camera preview and videos are rate-limited on the producer