diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h index de5487086..ea8391d6a 100644 --- a/include/private/surfaceflinger/SharedBufferStack.h +++ b/include/private/surfaceflinger/SharedBufferStack.h @@ -279,7 +279,8 @@ public: ssize_t retireAndLock(); status_t unlock(int buffer); void setStatus(status_t status); - status_t reallocate(); + status_t reallocateAll(); + status_t reallocateAllExcept(int buffer); status_t assertReallocate(int buffer); int32_t getQueuedCount() const; Region getDirtyRegion(int buffer) const; diff --git a/include/surfaceflinger/ISurface.h b/include/surfaceflinger/ISurface.h index 947668642..18e7950bc 100644 --- a/include/surfaceflinger/ISurface.h +++ b/include/surfaceflinger/ISurface.h @@ -53,7 +53,8 @@ protected: public: DECLARE_META_INTERFACE(Surface); - virtual sp requestBuffer(int bufferIdx, int usage) = 0; + virtual sp requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) = 0; virtual status_t setBufferCount(int bufferCount) = 0; class BufferHeap { diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index e4d60af7c..77e4a61ea 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -36,6 +36,7 @@ namespace android { // --------------------------------------------------------------------------- +class GraphicBuffer; class GraphicBufferMapper; class IOMX; class Rect; @@ -213,12 +214,14 @@ private: int dispatch_disconnect(va_list args); int dispatch_crop(va_list args); int dispatch_set_buffer_count(va_list args); + int dispatch_set_buffers_geometry(va_list args); void setUsage(uint32_t reqUsage); int connect(int api); int disconnect(int api); int crop(Rect const* rect); int setBufferCount(int bufferCount); + int setBuffersGeometry(int w, int h, int format); /* * private stuff... @@ -231,12 +234,34 @@ private: inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; } inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; } - status_t getBufferLocked(int index, int usage); + status_t getBufferLocked(int index, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage); int getBufferIndex(const sp& buffer) const; - uint32_t getUsage() const; - int getConnectedApi() const; + int getConnectedApi() const; + bool needNewBuffer(int bufIdx, + uint32_t *pWidth, uint32_t *pHeight, + uint32_t *pFormat, uint32_t *pUsage) const; + + class BufferInfo { + uint32_t mWidth; + uint32_t mHeight; + uint32_t mFormat; + uint32_t mUsage; + mutable uint32_t mDirty; + enum { + GEOMETRY = 0x01 + }; + public: + BufferInfo(); + void set(uint32_t w, uint32_t h, uint32_t format); + void set(uint32_t usage); + void get(uint32_t *pWidth, uint32_t *pHeight, + uint32_t *pFormat, uint32_t *pUsage) const; + bool validateBuffer(const sp& buffer) const; + }; + // constants sp mClient; sp mSurface; @@ -249,13 +274,12 @@ private: // protected by mSurfaceLock Rect mSwapRectangle; - uint32_t mUsage; int mConnected; Rect mNextBufferCrop; + BufferInfo mBufferInfo; // protected by mSurfaceLock. These are also used from lock/unlock // but in that case, they must be called form the same thread. - sp mBuffers[2]; mutable Region mDirtyRegion; // must be used from the lock/unlock thread @@ -264,6 +288,9 @@ private: mutable Region mOldDirtyRegion; bool mReserved; + // only used from dequeueBuffer() + Vector< sp > mBuffers; + // query() must be called from dequeueBuffer() thread uint32_t mWidth; uint32_t mHeight; diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h index b44901ff5..171f3df3a 100644 --- a/include/ui/egl/android_natives.h +++ b/include/ui/egl/android_natives.h @@ -82,6 +82,7 @@ enum { NATIVE_WINDOW_DISCONNECT, NATIVE_WINDOW_SET_CROP, NATIVE_WINDOW_SET_BUFFER_COUNT, + NATIVE_WINDOW_SET_BUFFERS_GEOMETRY, }; /* parameter for NATIVE_WINDOW_[DIS]CONNECT */ @@ -192,6 +193,7 @@ typedef struct android_native_window_t * NATIVE_WINDOW_DISCONNECT * NATIVE_WINDOW_SET_CROP * NATIVE_WINDOW_SET_BUFFER_COUNT + * NATIVE_WINDOW_SET_BUFFERS_GEOMETRY * */ @@ -273,6 +275,25 @@ static inline int native_window_set_buffer_count( return window->perform(window, NATIVE_WINDOW_SET_BUFFER_COUNT, bufferCount); } +/* + * native_window_set_buffers_geometry(..., int w, int h, int format) + * All buffers dequeued after this call will have the geometry specified. + * In particular, all buffers will have a fixed-size, independent form the + * native-window size. They will be appropriately scaled to the window-size + * upon composition. + * + * If all parameters are 0, the normal behavior is restored. That is, + * dequeued buffers following this call will be sized to the window's size. + * + */ +static inline int native_window_set_buffers_geometry( + android_native_window_t* window, + int w, int h, int format) +{ + return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY, + w, h, format); +} + // --------------------------------------------------------------------------- /* FIXME: this is legacy for pixmaps */ diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp index 621b7e368..84584aa8f 100644 --- a/libs/surfaceflinger/Layer.cpp +++ b/libs/surfaceflinger/Layer.cpp @@ -55,7 +55,8 @@ Layer::Layer(SurfaceFlinger* flinger, DisplayID display, mNeedsBlending(true), mNeedsDithering(false), mTextureManager(mFlags), - mBufferManager(mTextureManager) + mBufferManager(mTextureManager), + mWidth(0), mHeight(0), mFixedSize(false) { // no OpenGL operation is possible here, since we might not be // in the OpenGL thread. @@ -227,10 +228,18 @@ status_t Layer::setBufferCount(int bufferCount) return err; } -sp Layer::requestBuffer(int index, int usage) +sp Layer::requestBuffer(int index, + uint32_t reqWidth, uint32_t reqHeight, uint32_t reqFormat, + uint32_t usage) { sp buffer; + if ((reqWidth | reqHeight | reqFormat) < 0) + return buffer; + + if ((!reqWidth && reqHeight) || (reqWidth && !reqHeight)) + return buffer; + // this ensures our client doesn't go away while we're accessing // the shared area. sp ourClient(client.promote()); @@ -256,23 +265,33 @@ sp Layer::requestBuffer(int index, int usage) return buffer; } - uint32_t w, h; + uint32_t w, h, f; { // scope for the lock Mutex::Autolock _l(mLock); - w = mWidth; - h = mHeight; + const bool fixedSizeChanged = mFixedSize != (reqWidth && reqHeight); + const bool formatChanged = mReqFormat != reqFormat; + mReqWidth = reqWidth; + mReqHeight = reqHeight; + mReqFormat = reqFormat; + mFixedSize = reqWidth && reqHeight; + w = reqWidth ? reqWidth : mWidth; + h = reqHeight ? reqHeight : mHeight; + f = reqFormat ? reqFormat : mFormat; buffer = mBufferManager.detachBuffer(index); + if (fixedSizeChanged || formatChanged) { + lcblk->reallocateAllExcept(index); + } } const uint32_t effectiveUsage = getEffectiveUsage(usage); if (buffer!=0 && buffer->getStrongCount() == 1) { - err = buffer->reallocate(w, h, mFormat, effectiveUsage); + err = buffer->reallocate(w, h, f, effectiveUsage); } else { // here we have to reallocate a new buffer because we could have a // client in our process with a reference to it (eg: status bar), // and we can't release the handle under its feet. buffer.clear(); - buffer = new GraphicBuffer(w, h, mFormat, effectiveUsage); + buffer = new GraphicBuffer(w, h, f, effectiveUsage); err = buffer->initCheck(); } @@ -288,12 +307,7 @@ sp Layer::requestBuffer(int index, int usage) if (err == NO_ERROR && buffer->handle != 0) { Mutex::Autolock _l(mLock); - if (mWidth && mHeight) { - mBufferManager.attachBuffer(index, buffer); - } else { - // oops we got killed while we were allocating the buffer - buffer.clear(); - } + mBufferManager.attachBuffer(index, buffer); } return buffer; } @@ -330,39 +344,46 @@ uint32_t Layer::doTransaction(uint32_t flags) const Layer::State& front(drawingState()); const Layer::State& temp(currentState()); - if ((front.requested_w != temp.requested_w) || - (front.requested_h != temp.requested_h)) { + const bool sizeChanged = (front.requested_w != temp.requested_w) || + (front.requested_h != temp.requested_h); + + if (sizeChanged) { // the size changed, we need to ask our client to request a new buffer LOGD_IF(DEBUG_RESIZE, - "resize (layer=%p), requested (%dx%d), drawing (%d,%d)", - this, - int(temp.requested_w), int(temp.requested_h), - int(front.requested_w), int(front.requested_h)); + "resize (layer=%p), requested (%dx%d), drawing (%d,%d)", + this, + int(temp.requested_w), int(temp.requested_h), + int(front.requested_w), int(front.requested_h)); - // we're being resized and there is a freeze display request, - // acquire a freeze lock, so that the screen stays put - // until we've redrawn at the new size; this is to avoid - // glitches upon orientation changes. - if (mFlinger->hasFreezeRequest()) { - // if the surface is hidden, don't try to acquire the - // freeze lock, since hidden surfaces may never redraw - if (!(front.flags & ISurfaceComposer::eLayerHidden)) { - mFreezeLock = mFlinger->getFreezeLock(); + if (!isFixedSize()) { + // we're being resized and there is a freeze display request, + // acquire a freeze lock, so that the screen stays put + // until we've redrawn at the new size; this is to avoid + // glitches upon orientation changes. + if (mFlinger->hasFreezeRequest()) { + // if the surface is hidden, don't try to acquire the + // freeze lock, since hidden surfaces may never redraw + if (!(front.flags & ISurfaceComposer::eLayerHidden)) { + mFreezeLock = mFlinger->getFreezeLock(); + } } + + // this will make sure LayerBase::doTransaction doesn't update + // the drawing state's size + Layer::State& editDraw(mDrawingState); + editDraw.requested_w = temp.requested_w; + editDraw.requested_h = temp.requested_h; + + // record the new size, form this point on, when the client request + // a buffer, it'll get the new size. + setBufferSize(temp.requested_w, temp.requested_h); + + // all buffers need reallocation + lcblk->reallocateAll(); + } else { + // record the new size + setBufferSize(temp.requested_w, temp.requested_h); } - - // this will make sure LayerBase::doTransaction doesn't update - // the drawing state's size - Layer::State& editDraw(mDrawingState); - editDraw.requested_w = temp.requested_w; - editDraw.requested_h = temp.requested_h; - - // record the new size, form this point on, when the client request a - // buffer, it'll get the new size. - setDrawingSize(temp.requested_w, temp.requested_h); - - // all buffers need reallocation - lcblk->reallocate(); } if (temp.sequence != front.sequence) { @@ -376,12 +397,17 @@ uint32_t Layer::doTransaction(uint32_t flags) return LayerBase::doTransaction(flags); } -void Layer::setDrawingSize(uint32_t w, uint32_t h) { +void Layer::setBufferSize(uint32_t w, uint32_t h) { Mutex::Autolock _l(mLock); mWidth = w; mHeight = h; } +bool Layer::isFixedSize() const { + Mutex::Autolock _l(mLock); + return mFixedSize; +} + // ---------------------------------------------------------------------------- // pageflip handling... // ---------------------------------------------------------------------------- @@ -677,7 +703,8 @@ Layer::SurfaceLayer::~SurfaceLayer() { } -sp Layer::SurfaceLayer::requestBuffer(int index, int usage) +sp Layer::SurfaceLayer::requestBuffer(int index, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { sp buffer; sp owner(getOwner()); @@ -687,7 +714,7 @@ sp Layer::SurfaceLayer::requestBuffer(int index, int usage) * as it could cause a dead-lock, since it may have to wait * on conditions updated my the main thread. */ - buffer = owner->requestBuffer(index, usage); + buffer = owner->requestBuffer(index, w, h, format, usage); } return buffer; } diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h index 247748b03..10b5910ad 100644 --- a/libs/surfaceflinger/Layer.h +++ b/libs/surfaceflinger/Layer.h @@ -57,7 +57,8 @@ public: status_t setBuffers(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags=0); - void setDrawingSize(uint32_t w, uint32_t h); + void setBufferSize(uint32_t w, uint32_t h); + bool isFixedSize() const; virtual void onDraw(const Region& clip) const; virtual uint32_t doTransaction(uint32_t transactionFlags); @@ -88,7 +89,8 @@ private: uint32_t getEffectiveUsage(uint32_t usage) const; - sp requestBuffer(int index, int usage); + sp requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage); status_t setBufferCount(int bufferCount); class SurfaceLayer : public LayerBaseClient::Surface { @@ -97,7 +99,8 @@ private: SurfaceID id, const sp& owner); ~SurfaceLayer(); private: - virtual sp requestBuffer(int index, int usage); + virtual sp requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage); virtual status_t setBufferCount(int bufferCount); sp getOwner() const { return static_cast(Surface::getOwner().get()); @@ -181,6 +184,10 @@ private: mutable Mutex mLock; uint32_t mWidth; uint32_t mHeight; + uint32_t mReqWidth; + uint32_t mReqHeight; + uint32_t mReqFormat; + bool mFixedSize; }; // --------------------------------------------------------------------------- diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index 63b9520e0..51673ffc3 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -616,7 +616,8 @@ status_t LayerBaseClient::Surface::onTransact( return BnSurface::onTransact(code, data, reply, flags); } -sp LayerBaseClient::Surface::requestBuffer(int index, int usage) +sp LayerBaseClient::Surface::requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { return NULL; } diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index 53b848f14..569b0ff2e 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -301,7 +301,8 @@ public: sp getOwner() const; private: - virtual sp requestBuffer(int index, int usage); + virtual sp requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage); virtual status_t setBufferCount(int bufferCount); virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); diff --git a/libs/surfaceflinger_client/ISurface.cpp b/libs/surfaceflinger_client/ISurface.cpp index c5d0c0ecc..7049d9e42 100644 --- a/libs/surfaceflinger_client/ISurface.cpp +++ b/libs/surfaceflinger_client/ISurface.cpp @@ -71,11 +71,15 @@ public: { } - virtual sp requestBuffer(int bufferIdx, int usage) + virtual sp requestBuffer(int bufferIdx, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { Parcel data, reply; data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); data.writeInt32(bufferIdx); + data.writeInt32(w); + data.writeInt32(h); + data.writeInt32(format); data.writeInt32(usage); remote()->transact(REQUEST_BUFFER, data, &reply); sp buffer = new GraphicBuffer(); @@ -150,8 +154,11 @@ status_t BnSurface::onTransact( case REQUEST_BUFFER: { CHECK_INTERFACE(ISurface, data, reply); int bufferIdx = data.readInt32(); - int usage = data.readInt32(); - sp buffer(requestBuffer(bufferIdx, usage)); + uint32_t w = data.readInt32(); + uint32_t h = data.readInt32(); + uint32_t format = data.readInt32(); + uint32_t usage = data.readInt32(); + sp buffer(requestBuffer(bufferIdx, w, h, format, usage)); if (buffer == NULL) return BAD_VALUE; return reply->write(*buffer); diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp index 8681b592f..b45225984 100644 --- a/libs/surfaceflinger_client/SharedBufferStack.cpp +++ b/libs/surfaceflinger_client/SharedBufferStack.cpp @@ -527,13 +527,25 @@ void SharedBufferServer::setStatus(status_t status) } } -status_t SharedBufferServer::reallocate() +status_t SharedBufferServer::reallocateAll() { RWLock::AutoRLock _l(mLock); SharedBufferStack& stack( *mSharedStack ); uint32_t mask = mBufferList.getMask(); - android_atomic_or(mask, &stack.reallocMask); + android_atomic_or(mask, &stack.reallocMask); + return NO_ERROR; +} + +status_t SharedBufferServer::reallocateAllExcept(int buffer) +{ + RWLock::AutoRLock _l(mLock); + + SharedBufferStack& stack( *mSharedStack ); + BufferList temp(mBufferList); + temp.remove(buffer); + uint32_t mask = temp.getMask(); + android_atomic_or(mask, &stack.reallocMask); return NO_ERROR; } diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp index 5f42af012..71504fa79 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -349,15 +349,18 @@ void Surface::init() const_cast(android_native_window_t::maxSwapInterval) = 1; const_cast(android_native_window_t::flags) = 0; // be default we request a hardware surface - mUsage = GRALLOC_USAGE_HW_RENDER; mConnected = 0; + // two buffers by default + mBuffers.setCapacity(2); + mBuffers.insertAt(0, 2); } Surface::~Surface() { // this is a client-side operation, the surface is destroyed, unmap // its buffers in this process. - for (int i=0 ; i<2 ; i++) { + size_t size = mBuffers.size(); + for (size_t i=0 ; ihandle != 0) { getBufferMapper().unregisterBuffer(mBuffers[i]->handle); } @@ -365,6 +368,7 @@ Surface::~Surface() // clear all references and trigger an IPC now, to make sure things // happen without delay, since these resources are quite heavy. + mBuffers.clear(); mClient.clear(); mSurface.clear(); delete mSharedBufferClient; @@ -463,6 +467,22 @@ int Surface::perform(android_native_window_t* window, // ---------------------------------------------------------------------------- +bool Surface::needNewBuffer(int bufIdx, + uint32_t *pWidth, uint32_t *pHeight, + uint32_t *pFormat, uint32_t *pUsage) const +{ + Mutex::Autolock _l(mSurfaceLock); + + // Always call needNewBuffer(), since it clears the needed buffers flags + bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx); + bool validBuffer = mBufferInfo.validateBuffer(mBuffers[bufIdx]); + bool newNeewBuffer = needNewBuffer || !validBuffer; + if (newNeewBuffer) { + mBufferInfo.get(pWidth, pHeight, pFormat, pUsage); + } + return newNeewBuffer; +} + int Surface::dequeueBuffer(android_native_buffer_t** buffer) { sp client(getClient()); @@ -476,27 +496,28 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer) return bufIdx; } - // below we make sure we AT LEAST have the usage flags we want - const uint32_t usage(getUsage()); - const sp& backBuffer(mBuffers[bufIdx]); + // grow the buffer array if needed + const size_t size = mBuffers.size(); + const size_t needed = bufIdx+1; + if (size < needed) { + mBuffers.insertAt(size, needed-size); + } - // Always call needNewBuffer(), since it clears the needed buffers flags - bool needNewBuffer = mSharedBufferClient->needNewBuffer(bufIdx); - if (backBuffer == 0 || - ((uint32_t(backBuffer->usage) & usage) != usage) || - needNewBuffer) - { - err = getBufferLocked(bufIdx, usage); - LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)", - bufIdx, usage, strerror(-err)); + uint32_t w, h, format, usage; + if (needNewBuffer(bufIdx, &w, &h, &format, &usage)) { + err = getBufferLocked(bufIdx, w, h, format, usage); + LOGE_IF(err, "getBufferLocked(%ld, %u, %u, %u, %08x) failed (%s)", + bufIdx, w, h, format, usage, strerror(-err)); if (err == NO_ERROR) { // reset the width/height with the what we get from the buffer + const sp& backBuffer(mBuffers[bufIdx]); mWidth = uint32_t(backBuffer->width); mHeight = uint32_t(backBuffer->height); } } // if we still don't have a buffer here, we probably ran out of memory + const sp& backBuffer(mBuffers[bufIdx]); if (!err && backBuffer==0) { err = NO_MEMORY; } @@ -614,12 +635,17 @@ int Surface::dispatch_set_buffer_count(va_list args) { size_t bufferCount = va_arg(args, size_t); return setBufferCount(bufferCount); } - +int Surface::dispatch_set_buffers_geometry(va_list args) { + int w = va_arg(args, int); + int h = va_arg(args, int); + int f = va_arg(args, int); + return setBuffersGeometry(w, h, f); +} void Surface::setUsage(uint32_t reqUsage) { Mutex::Autolock _l(mSurfaceLock); - mUsage = reqUsage; + mBufferInfo.set(reqUsage); } int Surface::connect(int api) @@ -660,18 +686,6 @@ int Surface::disconnect(int api) return err; } -uint32_t Surface::getUsage() const -{ - Mutex::Autolock _l(mSurfaceLock); - return mUsage; -} - -int Surface::getConnectedApi() const -{ - Mutex::Autolock _l(mSurfaceLock); - return mConnected; -} - int Surface::crop(Rect const* rect) { Mutex::Autolock _l(mSurfaceLock); @@ -700,6 +714,26 @@ int Surface::setBufferCount(int bufferCount) return err; } +int Surface::setBuffersGeometry(int w, int h, int format) +{ + if (w<0 || h<0 || format<0) + return BAD_VALUE; + + if ((w && !h) || (!w && h)) + return BAD_VALUE; + + Mutex::Autolock _l(mSurfaceLock); + mBufferInfo.set(w, h, format); + return NO_ERROR; +} + +// ---------------------------------------------------------------------------- + +int Surface::getConnectedApi() const +{ + Mutex::Autolock _l(mSurfaceLock); + return mConnected; +} // ---------------------------------------------------------------------------- @@ -830,7 +864,8 @@ int Surface::getBufferIndex(const sp& buffer) const return buffer->getIndex(); } -status_t Surface::getBufferLocked(int index, int usage) +status_t Surface::getBufferLocked(int index, + uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { sp s(mSurface); if (s == 0) return NO_INIT; @@ -838,20 +873,21 @@ status_t Surface::getBufferLocked(int index, int usage) status_t err = NO_MEMORY; // free the current buffer - sp& currentBuffer(mBuffers[index]); + sp& currentBuffer(mBuffers.editItemAt(index)); if (currentBuffer != 0) { getBufferMapper().unregisterBuffer(currentBuffer->handle); currentBuffer.clear(); } - sp buffer = s->requestBuffer(index, usage); + sp buffer = s->requestBuffer(index, w, h, format, usage); LOGE_IF(buffer==0, "ISurface::getBuffer(%d, %08x) returned NULL", index, usage); if (buffer != 0) { // this should never happen by construction LOGE_IF(buffer->handle == NULL, - "Surface (identity=%d) requestBuffer(%d, %08x) returned" - "a buffer with a null handle", mIdentity, index, usage); + "Surface (identity=%d) requestBuffer(%d, %u, %u, %u, %08x) " + "returned a buffer with a null handle", + mIdentity, index, w, h, format, usage); err = mSharedBufferClient->getStatus(); LOGE_IF(err, "Surface (identity=%d) state = %d", mIdentity, err); if (!err && buffer->handle != NULL) { @@ -869,5 +905,44 @@ status_t Surface::getBufferLocked(int index, int usage) return err; } +// ---------------------------------------------------------------------------- +Surface::BufferInfo::BufferInfo() + : mWidth(0), mHeight(0), mFormat(0), + mUsage(GRALLOC_USAGE_HW_RENDER), mDirty(0) +{ +} + +void Surface::BufferInfo::set(uint32_t w, uint32_t h, uint32_t format) { + if ((mWidth != w) || (mHeight != h) || (mFormat != format)) { + mWidth = w; + mHeight = h; + mFormat = format; + mDirty |= GEOMETRY; + } +} + +void Surface::BufferInfo::set(uint32_t usage) { + mUsage = usage; +} + +void Surface::BufferInfo::get(uint32_t *pWidth, uint32_t *pHeight, + uint32_t *pFormat, uint32_t *pUsage) const { + *pWidth = mWidth; + *pHeight = mHeight; + *pFormat = mFormat; + *pUsage = mUsage; +} + +bool Surface::BufferInfo::validateBuffer(const sp& buffer) const { + // make sure we AT LEAST have the usage flags we want + if (mDirty || buffer==0 || + ((buffer->usage & mUsage) != mUsage)) { + mDirty = 0; + return false; + } + return true; +} + +// ---------------------------------------------------------------------------- }; // namespace android