OSDN Git Service

SurfaceTexture: add a deadlock scenario test
authorJamie Gennis <jgennis@google.com>
Thu, 21 Jul 2011 21:31:31 +0000 (14:31 -0700)
committerJamie Gennis <jgennis@google.com>
Fri, 22 Jul 2011 21:03:31 +0000 (14:03 -0700)
This change adds a test to ensure that a GL driver that's blocking on a
call to dequeueBuffer does not block other GL threads from rendering and
queueing buffers.

Change-Id: Ifdd234effc534b6a9cf8522ca87f64da5bb0bbd6

libs/gui/tests/SurfaceTexture_test.cpp

index 9abe89d..2b55e83 100644 (file)
@@ -1205,7 +1205,7 @@ protected:
     sp<FrameCondition> mFC;
 };
 
-TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedCompletes) {
     class PT : public ProducerThread {
         virtual void render() {
             glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1223,7 +1223,7 @@ TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedWorks) {
     // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
 }
 
-TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedCompletes) {
     class PT : public ProducerThread {
         virtual void render() {
             glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1241,7 +1241,7 @@ TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) {
     // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
 }
 
-TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedCompletes) {
     enum { NUM_ITERATIONS = 1024 };
 
     class PT : public ProducerThread {
@@ -1269,7 +1269,7 @@ TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedWorks)
     }
 }
 
-TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedWorks) {
+TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedCompletes) {
     enum { NUM_ITERATIONS = 1024 };
 
     class PT : public ProducerThread {
@@ -1297,4 +1297,70 @@ TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedWorks)
     }
 }
 
+// XXX: This test is disabled because it is currently hanging on some devices.
+TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) {
+    enum { NUM_ITERATIONS = 64 };
+
+    class PT : public ProducerThread {
+        virtual void render() {
+            for (int i = 0; i < NUM_ITERATIONS; i++) {
+                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+                glClear(GL_COLOR_BUFFER_BIT);
+                LOGV("+swapBuffers");
+                swapBuffers();
+                LOGV("-swapBuffers");
+            }
+        }
+    };
+
+    ASSERT_EQ(OK, mST->setSynchronousMode(true));
+    ASSERT_EQ(OK, mST->setBufferCountServer(2));
+
+    runProducerThread(new PT());
+
+    // Allow three frames to be rendered and queued before starting the
+    // rendering in this thread.  For the latter two frames we don't call
+    // updateTexImage so the next dequeue from the producer thread will block
+    // waiting for a frame to become available.
+    mFC->waitForFrame();
+    mFC->finishFrame();
+
+    // We must call updateTexImage to consume the first frame so that the
+    // SurfaceTexture is able to reduce the buffer count to 2.  This is because
+    // the GL driver may dequeue a buffer when the EGLSurface is created, and
+    // that happens before we call setBufferCountServer.  It's possible that the
+    // driver does not dequeue a buffer at EGLSurface creation time, so we
+    // cannot rely on this to cause the second dequeueBuffer call to block.
+    mST->updateTexImage();
+
+    mFC->waitForFrame();
+    mFC->finishFrame();
+    mFC->waitForFrame();
+    mFC->finishFrame();
+
+    // Sleep for 100ms to allow the producer thread's dequeueBuffer call to
+    // block waiting for a buffer to become available.
+    usleep(100000);
+
+    // Render and present a number of images.  This thread should not be blocked
+    // by the fact that the producer thread is blocking in dequeue.
+    for (int i = 0; i < NUM_ITERATIONS; i++) {
+        glClear(GL_COLOR_BUFFER_BIT);
+        eglSwapBuffers(mEglDisplay, mEglSurface);
+    }
+
+    // Consume the two pending buffers to unblock the producer thread.
+    mST->updateTexImage();
+    mST->updateTexImage();
+
+    // Consume the remaining buffers from the producer thread.
+    for (int i = 0; i < NUM_ITERATIONS-3; i++) {
+        mFC->waitForFrame();
+        mFC->finishFrame();
+        LOGV("+updateTexImage");
+        mST->updateTexImage();
+        LOGV("-updateTexImage");
+    }
+}
+
 } // namespace android