2014-02-19 116 views
1

我用下面的代码将数据复制到GraphicBuffer:调用eglDestroyImageKHR出故障在某些设备和其他一些人不是当Android的崩溃使用GraphicBuffer

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); 

而问题就来了。这是回溯:

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) 

这里有几个完整的回溯的:

http://pastebin.com/S0Ax6eNp

http://pastebin.com/bGWeWruw

不调用eglDestroyImageKHR导致泄漏,再次调用根据上述程序时,gbuffer- > lock()失败并显示内存不足错误消息。

崩溃例如在星系S4,S2星系,XPERIA Z1和不以的Nexus 4,Nexus 7和星系王牌2崩溃...等

我希望得到任何帮助。

-EDITED-

我发现的唯一的解决方法是减少引用计数器为0,这样GraphicBuffer析构函数被调用,并释放内存。

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

回答

1

我与EGL表面有相同的问题。由于4.3三星ROM在销毁任何一个时不会停用活动的上下文和表面。代码现在看起来像这样:

// 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); 

堆栈跟踪看起来非常相似。在调用eglDestroyImageKHR之前,你尝试过销毁gBuffer吗?

+0

嗨我不能销毁gbuffer作为它在android中是私有的析构函数。 graphicBuffer通过eglImageDestroyKHR递减引用计数而被破坏。我会尝试你的解决方案,看看我得到了什么。 –

+0

啊,那很烦人。我不知道我复制的代码是否有帮助,除非你还想销毁上下文(也就是它的Java,对于你必须修改的C等价物)。在黑暗中只是一个狂野的刺:在摧毁图像之前解开纹理有帮助吗?用于复制到GraphicsBuffer的指针是否仍然指向有效内存?你能粘贴整个崩溃日志,特别是寄存器和被捕获的信号吗? –

+0

是的ptr和clientBuffer地址仍然有效。解除绑定根本没有帮助。信号是segv_mapper,这意味着如果我没有误认为某个空指针...我已经包含了几个完整的日志。谢谢 –

2

FWIW,在Mozilla的AndroidGraphicBuffer.cpp代码,笔者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 
*/ 

,基本上不会调用eglDestroyImageKHR()这是在这方面显然OK。错误报告here。 James Willcox author of the Mozilla code也是the snorp blog post的作者。