2016-03-30 11 views
8

Sto ricevendo eglCreateWindowSurface GL Error EGL_BAD_ALLOC quando apri l'app la prima volta dopo l'installazione in Samsung Galaxy S6 e lo stesso codice funziona bene in altri dispositivi.Opengls eglCreateWindowSurface GL Errore EGL_BAD_ALLOC

Ho provato a pulire la memoria e distruggere la trama e deinitializzare tutti gli oggetti opengl su distruggere, ma questo non può aiutarmi.

03-30 09:21:32.983 21942-26083/com.example E/TextureSurfaceRenderer: createContext: EGL10.EGL_YES_CONTEXT [email protected] 
03-30 09:21:32.983 21942-26083/com.example E/libEGL: eglCreateWindowSurface: native_window_api_connect (win=0x7f7b100e10) failed (0xffffffea) (already connected to another API?) 
03-30 09:21:32.983 21942-26083/com.example E/libEGL: eglCreateWindowSurface:485 error 3003 (EGL_BAD_ALLOC) 
03-30 09:21:32.993 21942-26083/com.example E/GL Error:: EGL_BAD_ALLOC 

Ecco il mio codice.

import android.graphics.SurfaceTexture; 
import android.opengl.GLUtils; 
import android.os.Handler; 
import android.util.Log; 

import javax.microedition.khronos.egl.*; 

/** 
* Renderer which initializes OpenGL 2.0 context on a passed surface and starts 
* a rendering thread 
* 
* This class has to be subclassed to be used properly 
*/ 
public abstract class TextureSurfaceRenderer implements Runnable { 
    private static final int EGL_OPENGL_ES2_BIT = 4; 
    private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; 
    private static final String TAG = TextureSurfaceRenderer.class.getSimpleName(); 
    protected final SurfaceTexture texture; 
    protected Handler myHandler; 
    private EGL10 egl; 
    private EGLDisplay eglDisplay; 
    private EGLContext eglContext; 
    private EGLSurface eglSurface; 

    protected int width; 
    protected int height; 
    private boolean running; 

    /** 
    * @param texture 
    *   Surface texture on which to render. This has to be called 
    *   AFTER the texture became available 
    * @param width 
    *   Width of the passed surface 
    * @param height 
    *   Height of the passed surface 
    */ 
    public TextureSurfaceRenderer(SurfaceTexture texture, int width, int height,Handler myHandler) { 
     this.myHandler = myHandler; 
     this.texture = texture; 
     this.width = width; 
     this.height = height; 
     this.running = true; 
     Thread thrd = new Thread(this); 
     thrd.start(); 
    } 

    @Override 
    public void run() { 
     initGL(); 
     if(eglSurface != null){ 
      initGLComponents(); 
      Log.d(TAG, "OpenGL init OK."); 

      while (running) { 
       long loopStart = System.currentTimeMillis(); 
       pingFps(); 
       boolean isDraw = draw(); 
//   Log.e(TAG, "eglSwapBuffers Before Draw " + isDraw); 
       if (isDraw) { 
        if(!egl.eglSwapBuffers(eglDisplay, eglSurface)){ 
         int error = egl.eglGetError(); 
         Log.e(TAG, "eglSwapBuffers Error " + GLUtils.getEGLErrorString(error)); 
        } 

       } 
       // Targeting 60 fps, no need for faster 
       long waitDelta = 16 - (System.currentTimeMillis() - loopStart); 
       if (waitDelta > 0) { 
        try { 
         Thread.sleep(waitDelta); 
        } catch (InterruptedException e) { 
         MyApplication.getInstance().trackException(e); 
         continue; 
        } 
       } 
      } 

      deInitGLComponents(); 
      deinitGL(); 
     } else { 
      Log.e(TAG, "Egl Surface is null " + GLUtils.getEGLErrorString(egl.eglGetError())); 
     } 
    } 

    /** 
    * Main draw function, subclass this and add custom drawing code here. The 
    * rendering thread will attempt to limit FPS to 60 to keep CPU usage low. 
    */ 
    protected abstract boolean draw(); 

    /** 
    * OpenGL component initialization funcion. This is called after OpenGL 
    * context has been initialized on the rendering thread. Subclass this and 
    * initialize shaders/textures/other GL related components here. 
    */ 
    public abstract void initGLComponents(); 
    public abstract void deInitGLComponents(); 

    private long lastFpsOutput = 0; 
    private int frames; 

    private void pingFps() { 
     if (lastFpsOutput == 0) 
      lastFpsOutput = System.currentTimeMillis(); 

     frames++; 

     if (System.currentTimeMillis() - lastFpsOutput > 1000) { 
      Log.d(TAG, "FPS: " + frames); 
      lastFpsOutput = System.currentTimeMillis(); 
      frames = 0; 
     } 
    } 

    /** 
    * Call when activity pauses. This stops the rendering thread and 
    * deinitializes OpenGL. 
    */ 
    public void onPause() { 
     running = false; 
    } 

    private void initGL() { 
     egl = (EGL10) EGLContext.getEGL(); 
     eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 

     int[] version = new int[2]; 
     egl.eglInitialize(eglDisplay, version); 
     EGLConfig eglConfig = chooseEglConfig(); 
     eglContext = createContext(egl, eglDisplay, eglConfig); 

     eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, texture, 
       null); // Here I am getting null eglSurface first Time. 
     if (eglSurface == null || eglSurface == EGL10.EGL_NO_SURFACE) { 
      myHandler.sendEmptyMessage(0); 
      Log.e("GL Error: " 
        ,""+ GLUtils.getEGLErrorString(egl.eglGetError())); 
      return; 
     } 

     if (!egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { 
      myHandler.sendEmptyMessage(0); 
      Log.e("GL Make current error: " 
        , "" + GLUtils.getEGLErrorString(egl.eglGetError())); 
      return; 
     } 
    } 

    private void deinitGL() { 
     egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, 
       EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); 
     egl.eglDestroySurface(eglDisplay, eglSurface); 
     egl.eglDestroyContext(eglDisplay, eglContext); 
     egl.eglTerminate(eglDisplay); 
     Log.d(TAG, "OpenGL deinit OK."); 
    } 

    private EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, 
      EGLConfig eglConfig) { 
     int[] attribList = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; 
     EGLContext eglContext = egl.eglCreateContext(eglDisplay, eglConfig, 
       EGL10.EGL_NO_CONTEXT, attribList); 
     if(eglContext.getGL().equals(EGL10.EGL_NO_CONTEXT)){ 
      Log.e(TAG, "createContext: EGL10.EGL_NO_CONTEXT"); 
     } else { 
      Log.e(TAG, "createContext: EGL10.EGL_YES_CONTEXT " + eglContext.getGL().toString()); 
     } 
     return eglContext; 
    } 

    private EGLConfig chooseEglConfig() { 
     int[] configsCount = new int[1]; 
     EGLConfig[] configs = new EGLConfig[1]; 
     int[] configSpec = getConfig(); 

     if (!egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, 
       configsCount)) { 
      Log.e(TAG , "Failed to choose config: " + GLUtils.getEGLErrorString(egl.eglGetError())); 
     } else if (configsCount[0] > 0) { 
      return configs[0]; 
     } 
     return null; 
    } 

    private int[] getConfig() { 
     return new int[] { EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 
       EGL10.EGL_RED_SIZE, 8, EGL10.EGL_GREEN_SIZE, 8, 
       EGL10.EGL_BLUE_SIZE, 8, EGL10.EGL_ALPHA_SIZE, 8, 
       EGL10.EGL_DEPTH_SIZE, 0, EGL10.EGL_STENCIL_SIZE, 0, EGL10.EGL_NONE }; 
    } 

    @Override 
    protected void finalize() throws Throwable { 
     super.finalize(); 
     running = false; 
    } 
} 
+0

Sembra che non piaccia l'oggetto SurfaceTexture che stai trasmettendo. – fadden

risposta

2

Ho risolto l'errore GL Errore EGL_BAD_ALLOC. Questo errore si verifica a causa del fatto che non sto gestendo correttamente Renderer con il ciclo di vita delle attività.

+1

per favore pubblica la tua soluzione. Grazie. – RonTLV

Problemi correlati