2014-02-19 147 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的作者。