Gorilla.Maguila
Gorilla.Maguila

Reputation: 71

android crash on eglDestroyImageKHR using GraphicBuffer

I'm copying data to the GraphicBuffer using the following code:

uint8_t *ptr;
sp<GraphicBuffer> gBuffer = new GraphicBuffer(width,height,format,usage);
gBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&ptr));
//Copy Data
gBuffer->unlock();

EGLClient clientBuffer = (EGLClientBuffer)gBuffer->getNativeBuffer();

EGLImageKHR img = eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,clientBuffer, NULL);

glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureHandle);
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)img);

//Finished using img, Crash Here:

eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), img);

And the problem comes when calling eglDestroyImageKHR which crashes in some devices and some others not. This is the backtrace:

00 pc 00006488 /system/lib/libui.so
01 pc 00006719 /system/lib/libui.so (android::GraphicBuffer::free_handle()+52)
02 pc 00006813 /system/lib/libui.so (android::GraphicBuffer::~GraphicBuffer()+22)
03 pc 00006841 /system/lib/libui.so (android::GraphicBuffer::~GraphicBuffer()+4)
04 pc 0000f823 /system/lib/libutils.so (android::RefBase::decStrong(void const*) const+40)
05 pc 00003bbb /system/vendor/lib/egl/eglsubAndroid.so
06 pc 0001b5f4 /system/vendor/lib/egl/libEGL_adreno.so (egliDoDestroyEGLImage+80)
07 pc 00006c88 /system/vendor/lib/egl/libEGL_adreno.so (eglDestroyImageKHR+16)
08 pc 0000e749 /system/lib/libEGL.so (eglDestroyImageKHR+44)

Here are a couple of complete backtraces:

http://pastebin.com/S0Ax6eNp

http://pastebin.com/bGWeWruw

Not calling eglDestroyImageKHR causes a leak and when calling again the above routine, gbuffer->lock() fails with an insufficient memory error message.

Crashes for example on a galaxy S4, galaxy s2 , xperia z1 and doesn't crash in a nexus 4, nexus 7, galaxy ace 2...etc

I would appreciate any help.

-EDITED-

The only workaround I have found is to decrease the reference counter to 0 so the GraphicBuffer destructor gets called and frees the memory.

if(gBuffer->getStrongCount() > 0){
    gBuffer->decStrong(gBuffer->handle);
}

Upvotes: 1

Views: 2834

Answers (2)

Adi Shavit
Adi Shavit

Reputation: 17295

FWIW, in the Mozilla AndroidGraphicBuffer.cpp code, the author writes:

/**
 * XXX: eglDestroyImageKHR crashes sometimes due to refcount badness (I think)
 *
 * If you look at egl.cpp (https://github.com/android/platform_frameworks_base/blob/master/opengl/libagl/egl.cpp#L2002)
 * you can see that eglCreateImageKHR just refs the native buffer, and eglDestroyImageKHR
 * just unrefs it. Somehow the ref count gets messed up and things are already destroyed
 * by the time eglDestroyImageKHR gets called. For now, at least, just not calling      
 * eglDestroyImageKHR should be fine since we do free the GraphicBuffer below.
 *
 * Bug 712716
 */

and essentially does not call eglDestroyImageKHR() which is apparently OK in that context. Bug report here. James Willcox the author of the Mozilla code is also the author of the snorp blog post.

Upvotes: 2

Kevin Read
Kevin Read

Reputation: 2193

I had the same issue with EGL surfaces. Since 4.3 Samsung ROMs don't deactivate the active context and surface when destroying either one. The code now looks something like this:

// This line had to be added to prevent crashes:
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);

mEgl.eglDestroyContext(mEglDisplay, mEglContext);
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);

The stack trace looked fairly similar. Have you tried destroying gBuffer before calling eglDestroyImageKHR?

Upvotes: 2

Related Questions