diff options
author | Ramkumar Radhakrishnan <ramkumar@codeaurora.org> | 2012-11-06 20:44:04 -0800 |
---|---|---|
committer | Gerrit Code Review <gerrit@cyanogenmod.org> | 2013-03-10 22:55:58 -0700 |
commit | bbef29560e318cbdb0d4107b7fce6a2a64fd641b (patch) | |
tree | fa25faa6fdf12cc6de6dd74b24ca9405088cc891 /libs/gui/BufferQueue.cpp | |
parent | 31152b94cd0471a3853fb658e9aff507d4eec384 (diff) | |
download | frameworks_native-bbef29560e318cbdb0d4107b7fce6a2a64fd641b.tar.gz frameworks_native-bbef29560e318cbdb0d4107b7fce6a2a64fd641b.tar.bz2 frameworks_native-bbef29560e318cbdb0d4107b7fce6a2a64fd641b.zip |
libgui: Add support to update buffer geometry.
Add native window properties NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY
to the perform function of SurfaceTextureClient and SurfaceTexture
to update the width, height and format of the buffer dynamically
from the client before queue buffer call.
Change-Id: I62447fcf523b507d534085cd0835f55a978c4ead
Diffstat (limited to 'libs/gui/BufferQueue.cpp')
-rw-r--r-- | libs/gui/BufferQueue.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 5226037f8..acf6cec6c 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -64,6 +64,70 @@ static const char* scalingModeName(int scalingMode) { } } +#ifdef QCOM_BSP +/* + * Checks if memory needs to be reallocated for this buffer. + * + * @param: Geometry of the current buffer. + * @param: Required Geometry. + * @param: Geometry of the updated buffer. + * + * @return True if a memory reallocation is required. + */ +static bool needNewBuffer(const QBufGeometry currentGeometry, + const QBufGeometry requiredGeometry, + const QBufGeometry updatedGeometry) +{ + // no allocation required if there is change in resoultion or format. + if (updatedGeometry.mWidth && updatedGeometry.mHeight && + updatedGeometry.mFormat) { + return false; + } + // If the current buffer info matches the updated info, + // we do not require any memory allocation. + if (currentGeometry.mWidth != requiredGeometry.mWidth || + currentGeometry.mHeight != requiredGeometry.mHeight || + currentGeometry.mFormat != requiredGeometry.mFormat) { + // Current and required geometry do not match. Allocation + // required. + return true; + } + return false; +} + +/* + * Geometry update for the currently queued buffer is required or not. + * + * @param: buffer currently queued buffer. + * @param: Updated width + * @param: Updated height + * @param: Updated format + * + * @return True if a buffer needs to be updated with new attributes. + */ +static bool isBufferGeometryUpdateRequired(sp<GraphicBuffer> buffer, + const QBufGeometry updatedGeometry) +{ + if (buffer == 0) { + ALOGW("isBufferGeometryUpdateRequired: graphic buffer is NULL"); + return false; + } + + if (!updatedGeometry.mWidth || !updatedGeometry.mHeight || + !updatedGeometry.mFormat) { + // No update required. Return. + return false; + } + if (buffer->width == updatedGeometry.mWidth && + buffer->height == updatedGeometry.mHeight && + buffer->format == updatedGeometry.mFormat) { + // The buffer has already been updated. Return. + return false; + } + return true; +} +#endif + BufferQueue::BufferQueue(bool allowSynchronousMode, const sp<IGraphicBufferAlloc>& allocator) : mDefaultWidth(1), @@ -94,6 +158,9 @@ BufferQueue::BufferQueue(bool allowSynchronousMode, } else { mGraphicBufferAlloc = allocator; } +#ifdef QCOM_BSP + mNextBufferInfo.set(0, 0, 0); +#endif } BufferQueue::~BufferQueue() { @@ -387,10 +454,29 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, mSlots[buf].mBufferState = BufferSlot::DEQUEUED; const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer); +#ifdef QCOM_BSP + QBufGeometry currentGeometry; + if (buffer != NULL) + currentGeometry.set(buffer->width, buffer->height, buffer->format); + else + currentGeometry.set(0, 0, 0); + + QBufGeometry requiredGeometry; + requiredGeometry.set(w, h, format); + + QBufGeometry updatedGeometry; + updatedGeometry.set(mNextBufferInfo.mWidth, mNextBufferInfo.mHeight, + mNextBufferInfo.mFormat); +#endif + if ((buffer == NULL) || +#ifdef QCOM_BSP + needNewBuffer(currentGeometry, requiredGeometry, updatedGeometry) || +#else (uint32_t(buffer->width) != w) || (uint32_t(buffer->height) != h) || (uint32_t(buffer->format) != format) || +#endif ((uint32_t(buffer->usage) & usage) != usage)) { mSlots[buf].mAcquireCalled = false; @@ -453,6 +539,15 @@ status_t BufferQueue::dequeueBuffer(int *outBuf, sp<Fence>& outFence, return returnFlags; } +#ifdef QCOM_BSP +status_t BufferQueue::updateBuffersGeometry(int w, int h, int f) { + ST_LOGV("updateBuffersGeometry: w=%d h=%d f=%d", w, h, f); + Mutex::Autolock lock(mMutex); + mNextBufferInfo.set(w, h, f); + return NO_ERROR; +} +#endif + status_t BufferQueue::setSynchronousMode(bool enabled) { ATRACE_CALL(); ST_LOGV("setSynchronousMode: enabled=%d", enabled); @@ -526,7 +621,31 @@ status_t BufferQueue::queueBuffer(int buf, return -EINVAL; } +#ifdef QCOM_BSP + // Update the buffer Geometry if required + QBufGeometry updatedGeometry; + updatedGeometry.set(mNextBufferInfo.mWidth, + mNextBufferInfo.mHeight, mNextBufferInfo.mFormat); +#endif const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer); +#ifdef QCOM_BSP + // Update the geometry of this buffer without reallocation. + if(isBufferGeometryUpdateRequired(graphicBuffer, updatedGeometry)) { + status_t res = graphicBuffer->perform(graphicBuffer->handle, + GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_GEOMETRY, + updatedGeometry.mWidth, + updatedGeometry.mHeight, + updatedGeometry.mFormat); + if(res == NO_ERROR) { + graphicBuffer->width = updatedGeometry.mWidth; + graphicBuffer->height = updatedGeometry.mHeight; + graphicBuffer->format = updatedGeometry.mFormat; + // set flags to destroy old eglImage and create new eglImage. + mSlots[buf].mAcquireCalled = false; + mSlots[buf].mEglDisplay = EGL_NO_DISPLAY; + } + } +#endif Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight()); Rect croppedCrop; crop.intersect(bufferRect, &croppedCrop); @@ -691,6 +810,9 @@ status_t BufferQueue::disconnect(int api) { if (mConnectedApi == api) { drainQueueAndFreeBuffersLocked(); mConnectedApi = NO_CONNECTED_API; +#ifdef QCOM_BSP + mNextBufferInfo.set(0, 0, 0); +#endif mDequeueCondition.broadcast(); listener = mConsumerListener; } else { |