Merge "s/w rendered apps can now use n-buffering (n>2)"

This commit is contained in:
Mathias Agopian 2012-04-16 15:59:39 -07:00 committed by Android (Google) Code Review
commit 82ca93bf66
3 changed files with 31 additions and 13 deletions

View File

@ -26,6 +26,7 @@
#include <utils/RefBase.h> #include <utils/RefBase.h>
#include <utils/threads.h> #include <utils/threads.h>
#include <utils/KeyedVector.h>
struct ANativeWindow_Buffer; struct ANativeWindow_Buffer;
@ -113,6 +114,11 @@ private:
void freeAllBuffers(); void freeAllBuffers();
int getSlotFromBufferLocked(android_native_buffer_t* buffer) const; int getSlotFromBufferLocked(android_native_buffer_t* buffer) const;
struct BufferSlot {
sp<GraphicBuffer> buffer;
Region dirtyRegion;
};
// mSurfaceTexture is the interface to the surface texture server. All // mSurfaceTexture is the interface to the surface texture server. All
// operations on the surface texture client ultimately translate into // operations on the surface texture client ultimately translate into
// interactions with the server using this interface. // 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 // 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 // be replaced if the requested buffer usage or geometry differs from that
// of the buffer allocated to a slot. // of the buffer allocated to a slot.
sp<GraphicBuffer> mSlots[NUM_BUFFER_SLOTS]; BufferSlot mSlots[NUM_BUFFER_SLOTS];
// mReqWidth is the buffer width that will be requested at the next dequeue // mReqWidth is the buffer width that will be requested at the next dequeue
// operation. It is initialized to 1. // operation. It is initialized to 1.
@ -189,8 +195,10 @@ private:
// must be used from the lock/unlock thread // must be used from the lock/unlock thread
sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mLockedBuffer;
sp<GraphicBuffer> mPostedBuffer; sp<GraphicBuffer> mPostedBuffer;
mutable Region mOldDirtyRegion;
bool mConnectedToCpu; bool mConnectedToCpu;
// must be accessed from lock/unlock thread only
Region mDirtyRegion;
}; };
}; // namespace android }; // namespace android

View File

@ -171,7 +171,7 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
result); result);
return result; return result;
} }
sp<GraphicBuffer>& gbuf(mSlots[buf]); sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) { if (result & ISurfaceTexture::RELEASE_ALL_BUFFERS) {
freeAllBuffers(); freeAllBuffers();
} }
@ -204,7 +204,8 @@ int SurfaceTextureClient::getSlotFromBufferLocked(
android_native_buffer_t* buffer) const { android_native_buffer_t* buffer) const {
bool dumpedState = false; bool dumpedState = false;
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 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; return i;
} }
} }
@ -586,7 +587,7 @@ int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
void SurfaceTextureClient::freeAllBuffers() { void SurfaceTextureClient::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { 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) { if (canCopyBack) {
// copy the area that is invalid and not repainted this round // 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()) if (!copyback.isEmpty())
copyBlt(backBuffer, frontBuffer, copyback); copyBlt(backBuffer, frontBuffer, copyback);
} else { } else {
// if we can't copy-back anything, modify the user's dirty // if we can't copy-back anything, modify the user's dirty
// region to make sure they redraw the whole buffer // region to make sure they redraw the whole buffer
newDirtyRegion.set(bounds); newDirtyRegion.set(bounds);
mDirtyRegion.clear();
Mutex::Autolock lock(mMutex);
for (size_t i=0 ; i<NUM_BUFFER_SLOTS ; i++) {
mSlots[i].dirtyRegion.clear();
}
} }
// keep track of the are of the buffer that is "clean"
// (ie: that will be redrawn)
mOldDirtyRegion = newDirtyRegion;
{ // scope for the lock
Mutex::Autolock lock(mMutex);
int backBufferSlot(getSlotFromBufferLocked(backBuffer.get()));
if (backBufferSlot >= 0) {
Region& dirtyRegion(mSlots[backBufferSlot].dirtyRegion);
mDirtyRegion.subtract(dirtyRegion);
dirtyRegion = newDirtyRegion;
}
}
mDirtyRegion.orSelf(newDirtyRegion);
if (inOutDirtyBounds) { if (inOutDirtyBounds) {
*inOutDirtyBounds = newDirtyRegion.getBounds(); *inOutDirtyBounds = newDirtyRegion.getBounds();
} }

View File

@ -40,10 +40,6 @@ status_t SurfaceTextureLayer::connect(int api,
outWidth, outHeight, outTransform); outWidth, outHeight, outTransform);
if (err == NO_ERROR) { if (err == NO_ERROR) {
switch(api) { 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_MEDIA:
case NATIVE_WINDOW_API_CAMERA: case NATIVE_WINDOW_API_CAMERA:
// Camera preview and videos are rate-limited on the producer // Camera preview and videos are rate-limited on the producer