Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b207e95b authored by Eric Penner's avatar Eric Penner Committed by Android Git Automerger
Browse files

am 57782cd2: am 5c4a1566: Merge "GLConsumer: Fix eglTerminate/eglInit edge case." into lmp-dev

* commit '57782cd2':
  GLConsumer: Fix eglTerminate/eglInit edge case.
parents afde76c0 57782cd2
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -287,7 +287,9 @@ private:

        // createIfNeeded creates an EGLImage if required (we haven't created
        // one yet, or the EGLDisplay or crop-rect has changed).
        status_t createIfNeeded(EGLDisplay display, const Rect& cropRect);
        status_t createIfNeeded(EGLDisplay display,
                                const Rect& cropRect,
                                bool forceCreate = false);

        // This calls glEGLImageTargetTexture2DOES to bind the image to the
        // texture in the specified texture target.
+23 −9
Original line number Diff line number Diff line
@@ -463,23 +463,36 @@ status_t GLConsumer::bindTextureImageLocked() {

    status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
                                                        mCurrentCrop);

    if (err != NO_ERROR) {
        ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
                mEglDisplay, mCurrentTexture);
        return UNKNOWN_ERROR;
    }

    mCurrentTextureImage->bindToTextureTarget(mTexTarget);

    while ((error = glGetError()) != GL_NO_ERROR) {
    // In the rare case that the display is terminated and then initialized
    // again, we can't detect that the display changed (it didn't), but the
    // image is invalid. In this case, repeat the exact same steps while
    // forcing the creation of a new image.
    if ((error = glGetError()) != GL_NO_ERROR) {
        glBindTexture(mTexTarget, mTexName);
        status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
                                                            mCurrentCrop,
                                                            true);
        if (err != NO_ERROR) {
            ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
                    mEglDisplay, mCurrentTexture);
            return UNKNOWN_ERROR;
        }
        mCurrentTextureImage->bindToTextureTarget(mTexTarget);
        if ((error = glGetError()) != GL_NO_ERROR) {
            ST_LOGE("bindTextureImage: error binding external image: %#04x", error);
            return UNKNOWN_ERROR;
        }
    }

    // Wait for the new buffer to be ready.
    return doGLFenceWaitLocked();

}

status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
@@ -1056,12 +1069,13 @@ GLConsumer::EglImage::~EglImage() {
}

status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
                                              const Rect& cropRect) {
                                              const Rect& cropRect,
                                              bool forceCreation) {
    // If there's an image and it's no longer valid, destroy it.
    bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
    bool displayInvalid = mEglDisplay != eglDisplay;
    bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
    if (haveImage && (displayInvalid || cropInvalid)) {
    if (haveImage && (displayInvalid || cropInvalid || forceCreation)) {
        if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
           ALOGE("createIfNeeded: eglDestroyImageKHR failed");
        }
+55 −0
Original line number Diff line number Diff line
@@ -386,4 +386,59 @@ TEST_F(SurfaceTextureMultiContextGLTest,
    ASSERT_EQ(OK, mST->updateTexImage());
}

TEST_F(SurfaceTextureMultiContextGLTest,
       AttachAfterDisplayTerminatedSucceeds) {
    ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(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.
    ASSERT_EQ(OK, mST->releaseTexImage());
    ASSERT_EQ(OK, mST->detachFromContext());

    // Terminate and then initialize the display. All contexts, surfaces
    // and images are invalid at this point.
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
    EGLint majorVersion = 0;
    EGLint minorVersion = 0;
    EXPECT_TRUE(eglTerminate(display));
    EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
    ASSERT_EQ(EGL_SUCCESS, eglGetError());

    // The surface is invalid so create it again.
    EGLint pbufferAttribs[] = {
        EGL_WIDTH, 64,
        EGL_HEIGHT, 64,
        EGL_NONE };
    mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
            pbufferAttribs);

    // The second context is invalid so create it again.
    mSecondEglContext = eglCreateContext(mEglDisplay, mGlConfig,
            EGL_NO_CONTEXT, getContextAttribs());
    ASSERT_EQ(EGL_SUCCESS, eglGetError());
    ASSERT_NE(EGL_NO_CONTEXT, mSecondEglContext);

    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
            mSecondEglContext));
    ASSERT_EQ(EGL_SUCCESS, eglGetError());

    // Now attach to and consume final frame on secondary context.
    ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
    mFW->waitForFrame();
    ASSERT_EQ(OK, mST->updateTexImage());
}


} // namespace android