![](/img/trans.png)
[英]“call to OpenGL ES API with no current context” while using imageloader in android
[英]Android NDK OpenGL glDeleteTextures causes error: call to OpenGL ES API with no current context
我正在使用一個可從外部攝像機渲染視頻的android應用程序。 當我們在ndk中與攝像機進行通信時,視頻幀通過NDK層中的opengl渲染到屏幕上,並且速度更快。 我沒有編寫代碼,因為它來自第三方(相機的開發者),並且他們在MyGLSurfaceView中實現了surfaceDestroyed方法,如下所示:
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Inside GL surfaceDestroyed" );
// TODO Auto-generated method stub
myRenderer.surfaceDestroyed(); //call this to clean up the renderer.
super.surfaceDestroyed(holder);
}
myRenderer在哪里
myRenderer = new MyGLRenderer(mContext);
現在,在渲染器中編寫了以下代碼:
public class MyGLRenderer implements Renderer {
public void surfaceDestroyed()
{
Log.d(TAG, "Inside surfaceDestroyed" );
/* Note: As per doc, GLSurfaceView kills the renderer and deletes any textures associated with it.
* However, it does not clean up textures created in NDK. So, we need to do this explicitly.
*/
mGLAdapter.destroyGlTexturesJni(myRenderer);
}
請注意,在NDK中創建的紋理將不會被清除。 這是真的? 我問的原因是從此調用中收到以下錯誤:
01-19 12:01:19.715: E/libEGL(27208): call to OpenGL ES API with no current context (logged once per thread)
我已經放置了一些調試語句,以找出錯誤在NDK代碼中的確切位置,並發現該錯誤位於某個名為ImageRender(調用Clean)的類的析構函數中,這是觸發該錯誤的行:
void ImageRender::Clean()
{
// destruct texture
if (m_unTexture != -1)
glDeleteTextures( 1,&m_unTexture );
....
看起來他們在這里設置了m_unTexture(這是gl上下文嗎?):
int ImageRender::InitTexture( const int nWidth, const int nHeight )
{
// Enable texture 2D first.
glEnable( GL_TEXTURE_2D );
// create texture
glGenTextures( 1,&m_unTexture );
// bind texture to target.
glBindTexture( GL_TEXTURE_2D,m_unTexture );
...
如果他們檢查glGetError並遍歷代碼,如果他們沒有得到GL_NO_ERROR,則將其設置為-1,這樣他們就知道它是無效的。
好的,所以我的問題是我是否真的需要清理在NDK中創建的紋理,如果是的話,如何才能沒有看到的錯誤。 我嘗試使用以下方式致電:
//from MyGLSurfaceView
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Inside GL surfaceDestroyed" );
// TODO Auto-generated method stub
queueEvent(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
myRenderer.surfaceDestroyed(); //call this to clean up the renderer.
}
});
super.surfaceDestroyed(holder);
}
以確保渲染器在opengl線程上被調用,但是存在相同的錯誤。
有什么建議么? 順便說一句,如果我只是簡單地不調用此方法,那么代碼似乎可以正常工作,雖然我已經做了一段時間了,但是我遇到的問題是,當我啟動一個使用opengl框架的活動時,該活動將被初始化為先前的opengl活動。 似乎僅在某些時間,重新接通此電話可以解決問題。
您不能在UI線程上調用myRenderer.surfaceDestroyed,因為它沒有OpenGL上下文。 您必須使用queueEvent在OpenGL線程上運行surfaceDestroyed。 您使用Runnable實現的問題如下-queueEvent是非阻塞的。 因此,最有可能在調用myRenderer.surfaceDestroyed()和GL上下文被銷毀之前,調用任何本機代碼之前調用super.surfaceDestroyed(holder)。
不知道這是否行得通,但是嘗試在queueEvent調用之后阻止UI線程,然后等待Runnable完成其工作。 像這樣:
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Inside GL surfaceDestroyed" );
queueEvent(new Runnable() {
@Override
public void run() {
myRenderer.surfaceDestroyed();
synchronized (myRenderer) {
myRenderer.notify();
}
}
});
synchronized (myRenderer)
{
try { myRenderer.wait(100); }
catch (InterruptedException e) { }
}
super.surfaceDestroyed(holder);
}
這將最多阻止UI線程100毫秒,從而允許您的本機代碼清理上下文。 如果需要,增加100到更多。
在最壞的情況下-只是不要自己釋放GL資源。 讓GL上下文為您釋放它們。
回答另一個問題:m_unTexture是GL紋理名稱(不是GL上下文)。 -1值似乎只是紋理名稱的默認初始化值,如果glGenTextures()無法為紋理分配新名稱,該值將不會被觸及。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.