summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2011-03-31 19:10:24 -0700
committerMathias Agopian <mathias@google.com>2011-04-01 14:43:35 -0700
commite5a1bffd9106b1d82259de1a202e1f2f28742392 (patch)
tree5db6b7eb4b1b32395aae1950e2bcec1c6a80fd4d /libs
parent616fb9a38a5b558b1245b0e7f6dc0c4e5ef1a985 (diff)
downloadframeworks_base-e5a1bffd9106b1d82259de1a202e1f2f28742392.zip
frameworks_base-e5a1bffd9106b1d82259de1a202e1f2f28742392.tar.gz
frameworks_base-e5a1bffd9106b1d82259de1a202e1f2f28742392.tar.bz2
SurfaceTexture can now force the client to request a buffer
SurfaceTexture now has the concept of default size a new method, setDefaultBufferSize() to set it. When the default size is changed, dequeueBuffer() will return a value telling the client that it must ask for a new buffer. The above only applies if the client has not overriden the buffer size with setGeometry. Change-Id: I520dc40363054b7e37fdb67d6a2e7bce70326e81
Diffstat (limited to 'libs')
-rw-r--r--libs/gui/SurfaceTexture.cpp51
-rw-r--r--libs/gui/SurfaceTextureClient.cpp7
-rw-r--r--libs/gui/tests/SurfaceTextureClient_test.cpp147
3 files changed, 200 insertions, 5 deletions
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index cdaca47..f4e2a67 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -76,6 +76,10 @@ static float mtxRot270[16] = {
static void mtxMul(float out[16], const float a[16], const float b[16]);
SurfaceTexture::SurfaceTexture(GLuint tex) :
+ mDefaultWidth(1),
+ mDefaultHeight(1),
+ mPixelFormat(PIXEL_FORMAT_RGBA_8888),
+ mUseDefaultSize(true),
mBufferCount(MIN_BUFFER_SLOTS),
mCurrentTexture(INVALID_BUFFER_SLOT),
mCurrentTransform(0),
@@ -115,6 +119,16 @@ status_t SurfaceTexture::setBufferCount(int bufferCount) {
return OK;
}
+status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
+{
+ Mutex::Autolock lock(mMutex);
+ if ((w != mDefaultWidth) || (h != mDefaultHeight)) {
+ mDefaultWidth = w;
+ mDefaultHeight = h;
+ }
+ return OK;
+}
+
sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
LOGV("SurfaceTexture::requestBuffer");
@@ -124,12 +138,34 @@ sp<GraphicBuffer> SurfaceTexture::requestBuffer(int buf,
mBufferCount, buf);
return 0;
}
+ if ((w && !h) || (!w & h)) {
+ LOGE("requestBuffer: invalid size: w=%u, h=%u: %d", w, h, buf);
+ return 0;
+ }
+
+ const bool useDefaultSize = !w && !h;
+ if (useDefaultSize) {
+ // use the default size
+ w = mDefaultWidth;
+ h = mDefaultHeight;
+ }
+
+ const bool updateFormat = (format != 0);
+ if (!updateFormat) {
+ // keep the current (or default) format
+ format = mPixelFormat;
+ }
+
usage |= GraphicBuffer::USAGE_HW_TEXTURE;
sp<GraphicBuffer> graphicBuffer(
mGraphicBufferAlloc->createGraphicBuffer(w, h, format, usage));
if (graphicBuffer == 0) {
LOGE("requestBuffer: SurfaceComposer::createGraphicBuffer failed");
} else {
+ mUseDefaultSize = useDefaultSize;
+ if (updateFormat) {
+ mPixelFormat = format;
+ }
mSlots[buf].mGraphicBuffer = graphicBuffer;
if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(mSlots[buf].mEglDisplay, mSlots[buf].mEglImage);
@@ -155,7 +191,18 @@ status_t SurfaceTexture::dequeueBuffer(int *buf) {
if (found == INVALID_BUFFER_SLOT) {
return -EBUSY;
}
+
*buf = found;
+
+ const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
+ if (buffer == NULL) {
+ return ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
+ }
+ if ((mUseDefaultSize) &&
+ ((uint32_t(buffer->width) != mDefaultWidth) ||
+ (uint32_t(buffer->height) != mDefaultHeight))) {
+ return ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
+ }
return OK;
}
@@ -312,10 +359,10 @@ void SurfaceTexture::getTransformMatrix(float mtx[16]) {
} else {
tx = 0.0f;
}
- if (mCurrentCrop.right < buf->getWidth()) {
+ if (mCurrentCrop.right < int32_t(buf->getWidth())) {
xshrink++;
}
- if (mCurrentCrop.bottom < buf->getHeight()) {
+ if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
float(buf->getHeight());
yshrink++;
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index a4812d0..29fc4d3 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -25,8 +25,8 @@ namespace android {
SurfaceTextureClient::SurfaceTextureClient(
const sp<ISurfaceTexture>& surfaceTexture):
- mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(1),
- mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0),
+ mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(0),
+ mReqHeight(0), mReqFormat(DEFAULT_FORMAT), mReqUsage(0),
mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mMutex() {
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = setSwapInterval;
@@ -100,7 +100,8 @@ int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) {
return err;
}
sp<GraphicBuffer>& gbuf(mSlots[buf]);
- if (gbuf == 0 || gbuf->getWidth() != mReqWidth ||
+ if (err == ISurfaceTexture::BUFFER_NEEDS_REALLOCATION ||
+ gbuf == 0 || gbuf->getWidth() != mReqWidth ||
gbuf->getHeight() != mReqHeight ||
uint32_t(gbuf->getPixelFormat()) != mReqFormat ||
(gbuf->getUsage() & mReqUsage) != mReqUsage) {
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 94b05bc..348171d 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -100,4 +100,151 @@ TEST_F(SurfaceTextureClientTest, EglCreateWindowSurfaceFails) {
eglTerminate(dpy);
}
+TEST_F(SurfaceTextureClientTest, BufferGeometryInvalidSizesFail) {
+ sp<ANativeWindow> anw(mSTC);
+
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), -1, 0, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 0, -1, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, -1));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), -1, -1, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 0, 8, 0));
+ EXPECT_GT(OK, native_window_set_buffers_geometry(anw.get(), 8, 0, 0));
+}
+
+TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) {
+ sp<ANativeWindow> anw(mSTC);
+ android_native_buffer_t* buf;
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(1, buf->width);
+ EXPECT_EQ(1, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) {
+ sp<ANativeWindow> anw(mSTC);
+ android_native_buffer_t* buf;
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, PIXEL_FORMAT_RGB_565));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(16, buf->width);
+ EXPECT_EQ(8, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) {
+ sp<ANativeWindow> anw(mSTC);
+ android_native_buffer_t* buf;
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(1, buf->width);
+ EXPECT_EQ(1, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) {
+ sp<ANativeWindow> anw(mSTC);
+ android_native_buffer_t* buf;
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(16, buf->width);
+ EXPECT_EQ(8, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) {
+ sp<ANativeWindow> anw(mSTC);
+ android_native_buffer_t* buf;
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(16, buf->width);
+ EXPECT_EQ(8, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, 0));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(1, buf->width);
+ EXPECT_EQ(1, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) {
+ sp<ANativeWindow> anw(mSTC);
+ android_native_buffer_t* buf;
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 0, 0, PIXEL_FORMAT_RGB_565));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(1, buf->width);
+ EXPECT_EQ(1, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 16, 8, 0));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(16, buf->width);
+ EXPECT_EQ(8, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGB_565, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSize) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ android_native_buffer_t* buf;
+ EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf));
+ EXPECT_EQ(16, buf->width);
+ EXPECT_EQ(8, buf->height);
+ EXPECT_EQ(PIXEL_FORMAT_RGBA_8888, buf->format);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeAfterDequeue) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ android_native_buffer_t* buf[2];
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ EXPECT_NE(buf[0], buf[1]);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+ EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ EXPECT_NE(buf[0], buf[1]);
+ EXPECT_EQ(16, buf[0]->width);
+ EXPECT_EQ(16, buf[1]->width);
+ EXPECT_EQ(8, buf[0]->height);
+ EXPECT_EQ(8, buf[1]->height);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+}
+
+TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) {
+ sp<ANativeWindow> anw(mSTC);
+ sp<SurfaceTexture> st(mST);
+ android_native_buffer_t* buf[2];
+ EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ EXPECT_NE(buf[0], buf[1]);
+ EXPECT_EQ(16, buf[0]->width);
+ EXPECT_EQ(16, buf[1]->width);
+ EXPECT_EQ(8, buf[0]->height);
+ EXPECT_EQ(8, buf[1]->height);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+ EXPECT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 12, 24, 0));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+ ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1]));
+ EXPECT_NE(buf[0], buf[1]);
+ EXPECT_EQ(12, buf[0]->width);
+ EXPECT_EQ(12, buf[1]->width);
+ EXPECT_EQ(24, buf[0]->height);
+ EXPECT_EQ(24, buf[1]->height);
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0]));
+ ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1]));
+}
+
}