OSDN Git Service

Recreate EGLImage for previously used slots
authorJesse Hall <jessehall@google.com>
Thu, 17 May 2012 06:44:34 +0000 (23:44 -0700)
committerJesse Hall <jessehall@google.com>
Thu, 17 May 2012 18:25:21 +0000 (11:25 -0700)
SurfaceTexture would only create an EGLImage for a buffer slot when
BufferQueue returns a GraphicBuffer, i.e. either the slot was acquired
for the first time ever, or the buffer for the slot was reallocated.
But the EGLImage may also need to be re-created for a
previously-acquired buffer if the slot's EGLImage was destroyed during
detachFromContext(); in this case BufferQueue won't return a
GraphicBuffer since SurfaceTexture already has a reference to the
correct buffer.

Bug: 6461693
Change-Id: Ib95d0d757192efe336c5fda0866f857481a6617d

libs/gui/SurfaceTexture.cpp
libs/gui/tests/SurfaceTexture_test.cpp

index 1e58a21..feaf07a 100644 (file)
@@ -228,14 +228,16 @@ status_t SurfaceTexture::updateTexImage() {
             mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer;
         }
 
-        // Update the GL texture object.
+        // Update the GL texture object. We may have to do this even when
+        // item.mGraphicBuffer == NULL, if we destroyed the EGLImage when
+        // detaching from a context but the buffer has not been re-allocated.
         EGLImageKHR image = mEGLSlots[buf].mEglImage;
         if (image == EGL_NO_IMAGE_KHR) {
-            if (item.mGraphicBuffer == 0) {
+            if (mEGLSlots[buf].mGraphicBuffer == NULL) {
                 ST_LOGE("updateTexImage: buffer at slot %d is null", buf);
                 return BAD_VALUE;
             }
-            image = createImage(dpy, item.mGraphicBuffer);
+            image = createImage(dpy, mEGLSlots[buf].mGraphicBuffer);
             mEGLSlots[buf].mEglImage = image;
             if (image == EGL_NO_IMAGE_KHR) {
                 // NOTE: if dpy was invalid, createImage() is guaranteed to
index d708f6d..078c17b 100644 (file)
@@ -2577,4 +2577,32 @@ TEST_F(SurfaceTextureMultiContextGLTest,
     ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
 }
 
+TEST_F(SurfaceTextureMultiContextGLTest,
+        UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
+    ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true));
+    ASSERT_EQ(NO_ERROR, mST->setBufferCountServer(2));
+
+    // produce two frames and consume them both on the primary context
+    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
+    mFW->waitForFrame();
+    ASSERT_EQ(OK, mST->updateTexImage());
+
+    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
+    mFW->waitForFrame();
+    ASSERT_EQ(OK, mST->updateTexImage());
+
+    // produce one more frame
+    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
+
+    // Detach from the primary context and attach to the secondary context
+    ASSERT_EQ(OK, mST->detachFromContext());
+    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+            mSecondEglContext));
+    ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
+
+    // Consume final frame on secondary context
+    mFW->waitForFrame();
+    ASSERT_EQ(OK, mST->updateTexImage());
+}
+
 } // namespace android