diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h index a3e85a96a..c446633bc 100644 --- a/include/ui/GraphicBuffer.h +++ b/include/ui/GraphicBuffer.h @@ -72,6 +72,9 @@ public: GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage, uint32_t stride, native_handle_t* handle, bool keepOwnership); + // create a buffer from an existing android_native_buffer_t + GraphicBuffer(android_native_buffer_t* buffer, bool keepOwnership); + // return status status_t initCheck() const; @@ -137,6 +140,10 @@ private: GraphicBufferMapper& mBufferMapper; ssize_t mInitCheck; int mIndex; + + // If we're wrapping another buffer then this reference will make sure it + // doesn't get freed. + sp mWrappedBuffer; }; }; // namespace android diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp index ebb0cc9b8..099498041 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -454,15 +454,6 @@ void Surface::init() Surface::~Surface() { - // this is a client-side operation, the surface is destroyed, unmap - // its buffers in this process. - size_t size = mBuffers.size(); - for (size_t i=0 ; ihandle != 0) { - getBufferMapper().unregisterBuffer(mBuffers[i]->handle); - } - } - // clear all references and trigger an IPC now, to make sure things // happen without delay, since these resources are quite heavy. mBuffers.clear(); @@ -1021,7 +1012,20 @@ void Surface::setSwapRectangle(const Rect& r) { int Surface::getBufferIndex(const sp& buffer) const { - return buffer->getIndex(); + int idx = buffer->getIndex(); + if (idx < 0) { + // The buffer doesn't have an index set. See if the handle the same as + // one of the buffers for which we do know the index. This can happen + // e.g. if GraphicBuffer is used to wrap an android_native_buffer_t that + // was dequeued from an ANativeWindow. + for (int i = 0; i < mBuffers.size(); i++) { + if (buffer->handle == mBuffers[i]->handle) { + idx = mBuffers[i]->getIndex(); + break; + } + } + } + return idx; } status_t Surface::getBufferLocked(int index, @@ -1035,7 +1039,6 @@ status_t Surface::getBufferLocked(int index, // free the current buffer sp& currentBuffer(mBuffers.editItemAt(index)); if (currentBuffer != 0) { - getBufferMapper().unregisterBuffer(currentBuffer->handle); currentBuffer.clear(); } @@ -1043,7 +1046,7 @@ status_t Surface::getBufferLocked(int index, LOGE_IF(buffer==0, "ISurface::getBuffer(%d, %08x) returned NULL", index, usage); - if (buffer != 0) { // this should never happen by construction + if (buffer != 0) { // this should always happen by construction LOGE_IF(buffer->handle == NULL, "Surface (identity=%d) requestBuffer(%d, %u, %u, %u, %08x) " "returned a buffer with a null handle", @@ -1051,13 +1054,8 @@ status_t Surface::getBufferLocked(int index, err = mSharedBufferClient->getStatus(); LOGE_IF(err, "Surface (identity=%d) state = %d", mIdentity, err); if (!err && buffer->handle != NULL) { - err = getBufferMapper().registerBuffer(buffer->handle); - LOGW_IF(err, "registerBuffer(...) failed %d (%s)", - err, strerror(-err)); - if (err == NO_ERROR) { - currentBuffer = buffer; - currentBuffer->setIndex(index); - } + currentBuffer = buffer; + currentBuffer->setIndex(index); } else { err = err<0 ? err : status_t(NO_MEMORY); } diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp index 519c277c6..436e06471 100644 --- a/libs/ui/GraphicBuffer.cpp +++ b/libs/ui/GraphicBuffer.cpp @@ -77,6 +77,19 @@ GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h, handle = inHandle; } +GraphicBuffer::GraphicBuffer(android_native_buffer_t* buffer, bool keepOwnership) + : BASE(), mOwner(keepOwnership ? ownHandle : ownNone), + mBufferMapper(GraphicBufferMapper::get()), + mInitCheck(NO_ERROR), mIndex(-1), mWrappedBuffer(buffer) +{ + width = buffer->width; + height = buffer->height; + stride = buffer->stride; + format = buffer->format; + usage = buffer->usage; + handle = buffer->handle; +} + GraphicBuffer::~GraphicBuffer() { if (handle) { @@ -87,12 +100,14 @@ GraphicBuffer::~GraphicBuffer() void GraphicBuffer::free_handle() { if (mOwner == ownHandle) { + mBufferMapper.unregisterBuffer(handle); native_handle_close(handle); native_handle_delete(const_cast(handle)); } else if (mOwner == ownData) { GraphicBufferAllocator& allocator(GraphicBufferAllocator::get()); allocator.free(handle); } + mWrappedBuffer = 0; } status_t GraphicBuffer::initCheck() const { @@ -253,6 +268,11 @@ status_t GraphicBuffer::unflatten(void const* buffer, size_t size, } mOwner = ownHandle; + + if (handle != 0) { + mBufferMapper.registerBuffer(handle); + } + return NO_ERROR; }