Merge "GLConsumer: Fix eglTerminate/eglInit edge case." into lmp-dev
This commit is contained in:
commit
5c4a156659
@ -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.
|
||||
|
@ -462,24 +462,37 @@ status_t GLConsumer::bindTextureImageLocked() {
|
||||
}
|
||||
|
||||
status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
|
||||
mCurrentCrop);
|
||||
|
||||
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) {
|
||||
ST_LOGE("bindTextureImage: error binding external image: %#04x", error);
|
||||
return UNKNOWN_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");
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user