diff options
| author | 2011-04-26 14:57:10 -0700 | |
|---|---|---|
| committer | 2011-05-11 18:01:51 -0700 | |
| commit | a6b717b52a79c83e66247ab49050ddf07b4d5126 (patch) | |
| tree | 758169ab548f1c72a332e9d0851a6d65cc0088d3 | |
| parent | 5bbb1cf9d7f9ecb8a2fc5ca8ba51c222c2aaff16 (diff) | |
new tests for SurfaceTexture synchronous mode
Change-Id: Icfdaa625238246f8d0224efe28fdf2c1c24203f8
| -rw-r--r-- | libs/gui/tests/SurfaceTextureClient_test.cpp | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp index 5c37288e78cc..e9c341193499 100644 --- a/libs/gui/tests/SurfaceTextureClient_test.cpp +++ b/libs/gui/tests/SurfaceTextureClient_test.cpp @@ -17,23 +17,78 @@ #include <EGL/egl.h> #include <gtest/gtest.h> #include <gui/SurfaceTextureClient.h> +#include <utils/threads.h> namespace android { class SurfaceTextureClientTest : public ::testing::Test { protected: + SurfaceTextureClientTest(): + mEglDisplay(EGL_NO_DISPLAY), + mEglSurface(EGL_NO_SURFACE), + mEglContext(EGL_NO_CONTEXT) { + } + virtual void SetUp() { mST = new SurfaceTexture(123); mSTC = new SurfaceTextureClient(mST); + + // We need a valid GL context so we can test updateTexImage() + // This initializes EGL and create a dummy GL context with a + // pbuffer render target. + mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay); + + EGLint majorVersion, minorVersion; + EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion)); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + + EGLConfig myConfig; + EGLint numConfigs = 0; + EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), + &myConfig, 1, &numConfigs)); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + + EGLint pbufferAttribs[] = { + EGL_WIDTH, 16, + EGL_HEIGHT, 16, + EGL_NONE }; + mEglSurface = eglCreatePbufferSurface(mEglDisplay, myConfig, pbufferAttribs); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_NE(EGL_NO_SURFACE, mEglSurface); + + mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, 0); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_NE(EGL_NO_CONTEXT, mEglContext); + + EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); } virtual void TearDown() { mST.clear(); mSTC.clear(); + eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(mEglDisplay, mEglContext); + eglDestroySurface(mEglDisplay, mEglSurface); + eglTerminate(mEglDisplay); + } + + virtual EGLint const* getConfigAttribs() { + static EGLint sDefaultConfigAttribs[] = { + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_NONE + }; + + return sDefaultConfigAttribs; } sp<SurfaceTexture> mST; sp<SurfaceTextureClient> mSTC; + EGLDisplay mEglDisplay; + EGLSurface mEglSurface; + EGLContext mEglContext; }; TEST_F(SurfaceTextureClientTest, GetISurfaceTextureIsNotNull) { @@ -247,4 +302,212 @@ TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) { ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[1])); } +TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) { + sp<ANativeWindow> anw(mSTC); + sp<SurfaceTexture> st(mST); + android_native_buffer_t* buf[3]; + ASSERT_EQ(OK, st->setSynchronousMode(false)); + ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3)); + + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0])); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(OK, st->updateTexImage()); + + ASSERT_EQ(OK, st->setSynchronousMode(true)); + ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 2)); + + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0])); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1])); + + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(OK, st->updateTexImage()); +} + +TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) { + sp<ANativeWindow> anw(mSTC); + sp<SurfaceTexture> st(mST); + android_native_buffer_t* buf[3]; + ASSERT_EQ(OK, st->setSynchronousMode(true)); + ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4)); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0])); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1])); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2])); + EXPECT_NE(buf[0], buf[1]); + EXPECT_NE(buf[1], buf[2]); + EXPECT_NE(buf[2], buf[0]); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2])); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]); +} + +TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) { + sp<ANativeWindow> anw(mSTC); + sp<SurfaceTexture> st(mST); + android_native_buffer_t* buf[3]; + ASSERT_EQ(OK, st->setSynchronousMode(true)); + ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4)); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0])); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1])); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2])); + EXPECT_NE(buf[0], buf[1]); + EXPECT_NE(buf[1], buf[2]); + EXPECT_NE(buf[2], buf[0]); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0])); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1])); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2])); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]); +} + +TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) { + sp<ANativeWindow> anw(mSTC); + sp<SurfaceTexture> st(mST); + android_native_buffer_t* buf[3]; + ASSERT_EQ(OK, st->setSynchronousMode(true)); + ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3)); + + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0])); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(st->getCurrentBuffer().get(), buf[0]); + + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1])); + EXPECT_NE(buf[0], buf[1]); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1])); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]); + + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2])); + EXPECT_NE(buf[1], buf[2]); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2])); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(st->getCurrentBuffer().get(), buf[2]); +} + +TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDequeueCurrent) { + sp<ANativeWindow> anw(mSTC); + sp<SurfaceTexture> st(mST); + android_native_buffer_t* buf[3]; + android_native_buffer_t* firstBuf; + ASSERT_EQ(OK, st->setSynchronousMode(true)); + ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3)); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &firstBuf)); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), firstBuf)); + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(st->getCurrentBuffer().get(), firstBuf); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0])); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1])); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2])); + EXPECT_NE(buf[0], buf[1]); + EXPECT_NE(buf[1], buf[2]); + EXPECT_NE(buf[2], buf[0]); + EXPECT_EQ(firstBuf, buf[2]); +} + +TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeTwoBuffers) { + sp<ANativeWindow> anw(mSTC); + sp<SurfaceTexture> st(mST); + ASSERT_EQ(OK, st->setSynchronousMode(true)); + EXPECT_EQ(OK, native_window_set_buffer_count(anw.get(), 3)); + EXPECT_EQ(OK, native_window_set_buffer_count(anw.get(), 2)); + EXPECT_NE(OK, native_window_set_buffer_count(anw.get(), 1)); +} + +TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) { + sp<ANativeWindow> anw(mSTC); + sp<SurfaceTexture> st(mST); + android_native_buffer_t* buf[3]; + ASSERT_EQ(OK, st->setSynchronousMode(true)); + ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 3)); + EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0])); + EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1])); + EXPECT_EQ(-EBUSY, anw->dequeueBuffer(anw.get(), &buf[2])); + + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1])); + + EXPECT_EQ(OK, st->updateTexImage()); + EXPECT_EQ(st->getCurrentBuffer().get(), buf[1]); + + EXPECT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2])); + + ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[0])); + ASSERT_EQ(OK, anw->cancelBuffer(anw.get(), buf[2])); +} + +TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeWaitRetire) { + sp<ANativeWindow> anw(mSTC); + sp<SurfaceTexture> st(mST); + + class MyThread : public Thread { + sp<SurfaceTexture> st; + EGLContext ctx; + EGLSurface sur; + EGLDisplay dpy; + bool mBufferRetired; + Mutex mLock; + virtual bool threadLoop() { + eglMakeCurrent(dpy, sur, sur, ctx); + usleep(20000); + Mutex::Autolock _l(mLock); + st->updateTexImage(); + mBufferRetired = true; + eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + return false; + } + public: + MyThread(const sp<SurfaceTexture>& st) + : st(st), mBufferRetired(false) { + ctx = eglGetCurrentContext(); + sur = eglGetCurrentSurface(EGL_DRAW); + dpy = eglGetCurrentDisplay(); + eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + } + ~MyThread() { + eglMakeCurrent(dpy, sur, sur, ctx); + } + void bufferDequeued() { + Mutex::Autolock _l(mLock); + EXPECT_EQ(true, mBufferRetired); + } + }; + + android_native_buffer_t* buf[3]; + ASSERT_EQ(OK, st->setSynchronousMode(true)); + ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 2)); + // dequeue/queue/update so we have a current buffer + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0])); + st->updateTexImage(); + + MyThread* thread = new MyThread(st); + sp<Thread> threadBase(thread); + + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0])); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[1])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[1])); + thread->run(); + ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[2])); + ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[2])); + thread->bufferDequeued(); + thread->requestExitAndWait(); +} + } |