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
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 31615d0..9bf38f7 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -37,7 +37,8 @@
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 ff2251d..4cdece9 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -40,40 +40,41 @@
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 d783caf..9e0b5bb 100644
--- a/include/surfaceflinger/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -242,6 +242,10 @@
status_t validate(bool inCancelBuffer = false) const;
sp<ISurface> 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 fdc8105..fd83f46 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -75,6 +75,26 @@
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 223cf09..3bed959 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -96,6 +96,11 @@
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 ee14ac9..43b330c 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -143,8 +143,21 @@
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 1e9bd74..2c77edf 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -709,6 +709,9 @@
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;
}