summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRamkumar Radhakrishnan <ramkumar@codeaurora.org>2012-11-06 20:44:04 -0800
committerGerrit Code Review <gerrit@cyanogenmod.org>2013-03-10 22:55:58 -0700
commitbbef29560e318cbdb0d4107b7fce6a2a64fd641b (patch)
treefa25faa6fdf12cc6de6dd74b24ca9405088cc891
parent31152b94cd0471a3853fb658e9aff507d4eec384 (diff)
downloadframeworks_native-bbef29560e318cbdb0d4107b7fce6a2a64fd641b.zip
frameworks_native-bbef29560e318cbdb0d4107b7fce6a2a64fd641b.tar.gz
frameworks_native-bbef29560e318cbdb0d4107b7fce6a2a64fd641b.tar.bz2
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
-rw-r--r--include/gui/BufferQueue.h27
-rw-r--r--include/gui/ISurfaceTexture.h4
-rw-r--r--include/gui/SurfaceTextureClient.h2
-rw-r--r--include/ui/GraphicBuffer.h4
-rw-r--r--include/ui/GraphicBufferMapper.h5
-rw-r--r--libs/gui/BufferQueue.cpp122
-rw-r--r--libs/gui/ISurfaceTexture.cpp25
-rw-r--r--libs/gui/SurfaceTextureClient.cpp26
-rw-r--r--libs/ui/GraphicBuffer.cpp10
-rw-r--r--libs/ui/GraphicBufferMapper.cpp13
10 files changed, 238 insertions, 0 deletions
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 02598b0..cd38cfe 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -33,6 +33,23 @@
namespace android {
// ----------------------------------------------------------------------------
+#ifdef QCOM_BSP
+/*
+ * Structure to hold the buffer geometry
+ */
+struct QBufGeometry {
+ int mWidth;
+ int mHeight;
+ int mFormat;
+ QBufGeometry(): mWidth(0), mHeight(0), mFormat(0) {}
+ void set(int w, int h, int f) {
+ mWidth = w;
+ mHeight = h;
+ mFormat = f;
+ }
+};
+#endif
+
class BufferQueue : public BnSurfaceTexture {
public:
enum { MIN_UNDEQUEUED_BUFFERS = 2 };
@@ -156,6 +173,11 @@ public:
// to calculate the size for the buffer. this will take effect from next
// dequeue buffer.
virtual status_t setBuffersSize(int size);
+
+ // update buffer width, height and format for a native buffer
+ // dynamically from the client which will take effect in the next
+ // queue buffer.
+ virtual status_t updateBuffersGeometry(int w, int h, int f);
#endif
// connect attempts to connect a producer client API to the BufferQueue.
@@ -547,6 +569,11 @@ private:
// mTransformHint is used to optimize for screen rotations
uint32_t mTransformHint;
+
+#ifdef QCOM_BSP
+ // holds the updated buffer geometry info of the new video resolution.
+ QBufGeometry mNextBufferInfo;
+#endif
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
index f0beab6..f2a6510 100644
--- a/include/gui/ISurfaceTexture.h
+++ b/include/gui/ISurfaceTexture.h
@@ -172,6 +172,10 @@ public:
// calculate the size for the buffer. this will take effect from next
// dequeue buffer.
virtual status_t setBuffersSize(int size) = 0;
+
+ // update buffer width, height and format information from the client
+ // which will take effect in the next queue buffer.
+ virtual status_t updateBuffersGeometry(int w, int h, int f) = 0;
#endif
// connect attempts to connect a client API to the SurfaceTexture. This
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 108126d..f2b523d 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -94,6 +94,7 @@ private:
int dispatchSetPostTransformCrop(va_list args);
int dispatchSetUsage(va_list args);
#ifdef QCOM_BSP
+ int dispatchUpdateBuffersGeometry(va_list args);
int dispatchSetBuffersSize(va_list args);
#endif
int dispatchLock(va_list args);
@@ -107,6 +108,7 @@ protected:
virtual int query(int what, int* value) const;
virtual int setSwapInterval(int interval);
#ifdef QCOM_BSP
+ virtual int updateBuffersGeometry(int w, int h, int f);
virtual int setBuffersSize(int size);
#endif
virtual int lockBuffer_DEPRECATED(ANativeWindowBuffer* buffer);
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 60bbf18..af85063 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -103,6 +103,10 @@ public:
status_t lock(uint32_t usage, void** vaddr);
status_t lock(uint32_t usage, const Rect& rect, void** vaddr);
status_t unlock();
+#ifdef QCOM_BSP
+ status_t perform(buffer_handle_t hnd, int operation,
+ uint32_t w, uint32_t h, PixelFormat format);
+#endif
ANativeWindowBuffer* getNativeBuffer() const;
diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h
index 1fdecab..858fb1b 100644
--- a/include/ui/GraphicBufferMapper.h
+++ b/include/ui/GraphicBufferMapper.h
@@ -51,6 +51,11 @@ public:
status_t getphys(buffer_handle_t handle, void** paddr);
#endif
+#ifdef QCOM_BSP
+ status_t perform(buffer_handle_t handle, int operation,
+ uint32_t w, uint32_t h, uint32_t format);
+#endif
+
// dumps information about the mapping of this handle
void dump(buffer_handle_t handle);
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 5226037..acf6cec 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 {
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
index 4b20a36..ce31a5b 100644
--- a/libs/gui/ISurfaceTexture.cpp
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -39,6 +39,7 @@ enum {
QUERY,
SET_SYNCHRONOUS_MODE,
#ifdef QCOM_BSP
+ UPDATE_BUFFERS_GEOMETRY,
SET_BUFFERS_SIZE,
#endif
CONNECT,
@@ -160,6 +161,21 @@ public:
}
#ifdef QCOM_BSP
+ virtual status_t updateBuffersGeometry(int w, int h, int f) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+ data.writeInt32(w);
+ data.writeInt32(h);
+ data.writeInt32(f);
+ status_t result = remote()->transact(UPDATE_BUFFERS_GEOMETRY,
+ data, &reply);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ result = reply.readInt32();
+ return result;
+ }
+
virtual status_t setBuffersSize(int size) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
@@ -284,6 +300,15 @@ status_t BnSurfaceTexture::onTransact(
return NO_ERROR;
} break;
#ifdef QCOM_BSP
+ case UPDATE_BUFFERS_GEOMETRY: {
+ CHECK_INTERFACE(ISurfaceTexture, data, reply);
+ int w = data.readInt32();
+ int h = data.readInt32();
+ int f = data.readInt32();
+ status_t res = updateBuffersGeometry(w, h, f);
+ reply->writeInt32(res);
+ return NO_ERROR;
+ } break;
case SET_BUFFERS_SIZE: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int size = data.readInt32();
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index e33b026..5de963c 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -407,6 +407,9 @@ int SurfaceTextureClient::perform(int operation, va_list args)
case NATIVE_WINDOW_SET_BUFFERS_SIZE:
res = dispatchSetBuffersSize(args);
break;
+ case NATIVE_WINDOW_UPDATE_BUFFERS_GEOMETRY:
+ res = dispatchUpdateBuffersGeometry(args);
+ break;
#endif
case NATIVE_WINDOW_LOCK:
res = dispatchLock(args);
@@ -490,6 +493,13 @@ int SurfaceTextureClient::dispatchSetBuffersSize(va_list args) {
int size = va_arg(args, int);
return setBuffersSize(size);
}
+
+int SurfaceTextureClient::dispatchUpdateBuffersGeometry(va_list args) {
+ int w = va_arg(args, int);
+ int h = va_arg(args, int);
+ int f = va_arg(args, int);
+ return updateBuffersGeometry(w, h, f);
+}
#endif
int SurfaceTextureClient::dispatchSetScalingMode(va_list args) {
@@ -666,6 +676,22 @@ int SurfaceTextureClient::setBuffersSize(int size)
}
return NO_ERROR;
}
+
+int SurfaceTextureClient::updateBuffersGeometry(int w, int h, int f)
+{
+ ATRACE_CALL();
+ ALOGV("SurfaceTextureClient::updateBuffersGeometry");
+
+ if (w<0 || h<0 || f<0)
+ return BAD_VALUE;
+
+ if ((w && !h) || (!w && h))
+ return BAD_VALUE;
+
+ Mutex::Autolock lock(mMutex);
+ status_t err = mSurfaceTexture->updateBuffersGeometry(w, h, f);
+ return err;
+}
#endif
int SurfaceTextureClient::setScalingMode(int mode)
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index b447d00..219375e 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -213,6 +213,16 @@ status_t GraphicBuffer::unlock()
return res;
}
+#ifdef QCOM_BSP
+status_t GraphicBuffer::perform(buffer_handle_t hnd, int operation,
+ uint32_t w, uint32_t h, PixelFormat format)
+{
+ status_t res = getBufferMapper().perform(hnd,
+ GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_GEOMETRY, w, h, format);
+ return res;
+}
+#endif
+
size_t GraphicBuffer::getFlattenedSize() const {
return (8 + (handle ? handle->numInts : 0))*sizeof(int);
}
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 19c549d..d16a1bb 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -108,5 +108,18 @@ status_t GraphicBufferMapper::getphys(buffer_handle_t handle, void** paddr)
}
#endif
+#ifdef QCOM_BSP
+status_t GraphicBufferMapper::perform(buffer_handle_t handle, int operation,
+ uint32_t w, uint32_t h, uint32_t format)
+{
+ ATRACE_CALL();
+ status_t err;
+
+ err = mAllocMod->perform(mAllocMod, operation, w, h, format, handle);
+
+ ALOGW_IF(err, "perform(...) failed %d (%s)", err, strerror(-err));
+ return err;
+}
+#endif
// ---------------------------------------------------------------------------
}; // namespace android