簡體   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