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
|
// createIfNeeded creates an EGLImage if required (we haven't created
|
||||||
// one yet, or the EGLDisplay or crop-rect has changed).
|
// 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
|
// This calls glEGLImageTargetTexture2DOES to bind the image to the
|
||||||
// texture in the specified texture target.
|
// texture in the specified texture target.
|
||||||
|
@ -463,23 +463,36 @@ status_t GLConsumer::bindTextureImageLocked() {
|
|||||||
|
|
||||||
status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
|
status_t err = mCurrentTextureImage->createIfNeeded(mEglDisplay,
|
||||||
mCurrentCrop);
|
mCurrentCrop);
|
||||||
|
|
||||||
if (err != NO_ERROR) {
|
if (err != NO_ERROR) {
|
||||||
ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
|
ST_LOGW("bindTextureImage: can't create image on display=%p slot=%d",
|
||||||
mEglDisplay, mCurrentTexture);
|
mEglDisplay, mCurrentTexture);
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentTextureImage->bindToTextureTarget(mTexTarget);
|
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);
|
ST_LOGE("bindTextureImage: error binding external image: %#04x", error);
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for the new buffer to be ready.
|
// Wait for the new buffer to be ready.
|
||||||
return doGLFenceWaitLocked();
|
return doGLFenceWaitLocked();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
|
status_t GLConsumer::checkAndUpdateEglStateLocked(bool contextCheck) {
|
||||||
@ -1056,12 +1069,13 @@ GLConsumer::EglImage::~EglImage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_t GLConsumer::EglImage::createIfNeeded(EGLDisplay eglDisplay,
|
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.
|
// If there's an image and it's no longer valid, destroy it.
|
||||||
bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
|
bool haveImage = mEglImage != EGL_NO_IMAGE_KHR;
|
||||||
bool displayInvalid = mEglDisplay != eglDisplay;
|
bool displayInvalid = mEglDisplay != eglDisplay;
|
||||||
bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
|
bool cropInvalid = hasEglAndroidImageCrop() && mCropRect != cropRect;
|
||||||
if (haveImage && (displayInvalid || cropInvalid)) {
|
if (haveImage && (displayInvalid || cropInvalid || forceCreation)) {
|
||||||
if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
|
if (!eglDestroyImageKHR(mEglDisplay, mEglImage)) {
|
||||||
ALOGE("createIfNeeded: eglDestroyImageKHR failed");
|
ALOGE("createIfNeeded: eglDestroyImageKHR failed");
|
||||||
}
|
}
|
||||||
|
@ -386,4 +386,59 @@ TEST_F(SurfaceTextureMultiContextGLTest,
|
|||||||
ASSERT_EQ(OK, mST->updateTexImage());
|
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
|
} // namespace android
|
||||||
|
Loading…
Reference in New Issue
Block a user