From 9d4d6c101d90d4a1d1ca9413cf3eb89d1f1898d6 Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Sun, 27 Feb 2011 14:10:20 -0800 Subject: [PATCH] Add the MIN_UNDEQUEUED_BUFFERS query to ANW. This change adds a new query to ANativeWindow for getting the minimum number of buffers that must be left un-dequeued during the steady-state operation of the ANativeWindow. Change-Id: Ie8c461fc26b02ecde02ddb4f95bf763662cf1551 Related-Bug: 3356050 --- include/gui/SurfaceTexture.h | 3 ++- include/gui/SurfaceTextureClient.h | 25 +++++++++++++------------ include/surfaceflinger/Surface.h | 4 ++++ include/ui/egl/android_natives.h | 20 ++++++++++++++++++++ libs/gui/SurfaceTexture.cpp | 5 +++++ libs/gui/SurfaceTextureClient.cpp | 17 +++++++++++++++-- libs/surfaceflinger_client/Surface.cpp | 3 +++ 7 files changed, 62 insertions(+), 15 deletions(-) diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h index 31615d008..9bf38f743 100644 --- a/include/gui/SurfaceTexture.h +++ b/include/gui/SurfaceTexture.h @@ -37,7 +37,8 @@ class IGraphicBufferAlloc; class SurfaceTexture : public BnSurfaceTexture { public: - enum { MIN_BUFFER_SLOTS = 3 }; + enum { MIN_UNDEQUEUED_BUFFERS = 2 }; + enum { MIN_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1 }; enum { NUM_BUFFER_SLOTS = 32 }; struct FrameAvailableListener : public virtual RefBase { diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h index ff2251d89..4cdece99e 100644 --- a/include/gui/SurfaceTextureClient.h +++ b/include/gui/SurfaceTextureClient.h @@ -40,40 +40,41 @@ private: SurfaceTextureClient(const SurfaceTextureClient& rhs); // ANativeWindow hooks - static int setSwapInterval(ANativeWindow* window, int interval); - static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer); static int cancelBuffer(ANativeWindow* window, android_native_buffer_t* buffer); + static int dequeueBuffer(ANativeWindow* window, android_native_buffer_t** buffer); static int lockBuffer(ANativeWindow* window, android_native_buffer_t* buffer); - static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer); - static int query(ANativeWindow* window, int what, int* value); static int perform(ANativeWindow* window, int operation, ...); + static int query(ANativeWindow* window, int what, int* value); + static int queueBuffer(ANativeWindow* window, android_native_buffer_t* buffer); + static int setSwapInterval(ANativeWindow* window, int interval); - int setSwapInterval(int interval); + int cancelBuffer(android_native_buffer_t* buffer); int dequeueBuffer(android_native_buffer_t** buffer); int lockBuffer(android_native_buffer_t* buffer); - int queueBuffer(android_native_buffer_t* buffer); - int cancelBuffer(android_native_buffer_t* buffer); - int query(int what, int* value); int perform(int operation, va_list args); + int query(int what, int* value); + int queueBuffer(android_native_buffer_t* buffer); + int setSwapInterval(int interval); - int dispatchSetUsage(va_list args); int dispatchConnect(va_list args); int dispatchDisconnect(va_list args); - int dispatchSetCrop(va_list args); int dispatchSetBufferCount(va_list args); int dispatchSetBuffersGeometry(va_list args); int dispatchSetBuffersTransform(va_list args); + int dispatchSetCrop(va_list args); + int dispatchSetUsage(va_list args); int connect(int api); int disconnect(int api); - int setUsage(uint32_t reqUsage); - int setCrop(Rect const* rect); int setBufferCount(int bufferCount); int setBuffersGeometry(int w, int h, int format); int setBuffersTransform(int transform); + int setCrop(Rect const* rect); + int setUsage(uint32_t reqUsage); void freeAllBuffers(); + enum { MIN_UNDEQUEUED_BUFFERS = SurfaceTexture::MIN_UNDEQUEUED_BUFFERS }; enum { MIN_BUFFER_SLOTS = SurfaceTexture::MIN_BUFFER_SLOTS }; enum { NUM_BUFFER_SLOTS = SurfaceTexture::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index d783caff2..9e0b5bb48 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -242,6 +242,10 @@ private: status_t validate(bool inCancelBuffer = false) const; sp getISurface() const; + // When the buffer pool is a fixed size we want to make sure SurfaceFlinger + // won't stall clients, so we require an extra buffer. + enum { MIN_UNDEQUEUED_BUFFERS = 2 }; + inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; } inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; } diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h index fdc810577..fd83f469c 100644 --- a/include/ui/egl/android_natives.h +++ b/include/ui/egl/android_natives.h @@ -75,6 +75,26 @@ enum { NATIVE_WINDOW_WIDTH = 0, NATIVE_WINDOW_HEIGHT, NATIVE_WINDOW_FORMAT, + + /* The minimum number of buffers that must remain un-dequeued after a buffer + * has been queued. This value applies only if set_buffer_count was used to + * override the number of buffers and if a buffer has since been queued. + * Users of the set_buffer_count ANativeWindow method should query this + * value before calling set_buffer_count. If it is necessary to have N + * buffers simultaneously dequeued as part of the steady-state operation, + * and this query returns M then N+M buffers should be requested via + * native_window_set_buffer_count. + * + * Note that this value does NOT apply until a single buffer has been + * queued. In particular this means that it is possible to: + * + * 1. Query M = min undequeued buffers + * 2. Set the buffer count to N + M + * 3. Dequeue all N + M buffers + * 4. Cancel M buffers + * 5. Queue, dequeue, queue, dequeue, ad infinitum + */ + NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, }; /* valid operations for the (*perform)() hook */ diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 223cf091e..3bed95986 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -96,6 +96,11 @@ SurfaceTexture::~SurfaceTexture() { status_t SurfaceTexture::setBufferCount(int bufferCount) { LOGV("SurfaceTexture::setBufferCount"); + + if (bufferCount < MIN_BUFFER_SLOTS) { + return BAD_VALUE; + } + Mutex::Autolock lock(mMutex); freeAllBuffers(); mBufferCount = bufferCount; diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp index ee14ac900..43b330c79 100644 --- a/libs/gui/SurfaceTextureClient.cpp +++ b/libs/gui/SurfaceTextureClient.cpp @@ -143,8 +143,21 @@ int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { int SurfaceTextureClient::query(int what, int* value) { LOGV("SurfaceTextureClient::query"); Mutex::Autolock lock(mMutex); - // XXX: Implement this! - return INVALID_OPERATION; + switch (what) { + case NATIVE_WINDOW_WIDTH: + case NATIVE_WINDOW_HEIGHT: + // XXX: How should SurfaceTexture behave if setBuffersGeometry didn't + // override the size? + *value = 0; + return NO_ERROR; + case NATIVE_WINDOW_FORMAT: + *value = DEFAULT_FORMAT; + return NO_ERROR; + case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: + *value = MIN_UNDEQUEUED_BUFFERS; + return NO_ERROR; + } + return BAD_VALUE; } int SurfaceTextureClient::perform(int operation, va_list args) diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp index 1e9bd744f..2c77edf8a 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -709,6 +709,9 @@ int Surface::query(int what, int* value) case NATIVE_WINDOW_FORMAT: *value = int(mFormat); return NO_ERROR; + case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: + *value = MIN_UNDEQUEUED_BUFFERS; + return NO_ERROR; } return BAD_VALUE; }