繁体   English   中英

Android NDK OpenGL glDeleteTextures导致错误:在没有当前上下文的情况下调用OpenGL ES API

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM