Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opengls eglCreateWindowSurface GL Error EGL_BAD_ALLOC

I am getting eglCreateWindowSurface GL Error EGL_BAD_ALLOC when open app first time after installing in Samsung Galaxy S6 and same code working fine in other device.

I tried to clean memory and destroy texture and deinitialize all opengl object on destroy but that cant help me.

03-30 09:21:32.983 21942-26083/com.example E/TextureSurfaceRenderer: createContext: EGL10.EGL_YES_CONTEXT com.google.android.gles_jni.GLImpl@24406d0
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

Here is my code.

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;
    }
}
like image 411
Jitesh Dalsaniya Avatar asked Mar 30 '16 14:03

Jitesh Dalsaniya


People also ask

What does EGL_bad_alloc fail to do?

01-04 06:15:10.836 32736 32756 E Unity : [EGL] Failed to create window surface: EGL_BAD_ALLOC: EGL failed to allocate resources for the requested operation.

What is EGL_bad_alloc error in eglcreatewindowsurface?

*/ Opengls eglCreateWindowSurface GL Error EGL_BAD_ALLOC from : A GLSurfaceView must be notified when to pause and resume rendering. GLSurfaceView clients are required to call onPause () when the activity stops and onResume () when the activity starts.

What happens when the EGL context is lost?

This typically happens when device wakes up after going to sleep. When the EGL context is lost, all OpenGL resources (such as textures) that are associated with that context will be automatically deleted. In order to keep rendering correctly, a renderer must recreate any lost resources that it still needs.

Why does my OpenGL crash when I try to open it?

Try use OpenglView Visible always and startPreview when you get permissions. An invisible holder is not valid for opengl and this could cause your crash. Bad release of Opengl ?


1 Answers

Workaround-to-losing-the-opengl-context-when-android-pauses

So your Activity's onPause() should look like this:

@Override
public void onPause() {
    eglSurface.setVisibility(View.GONE);
    super.onPause();
    ...
}

And you restore your GLSurfaceView to the hierarchy not from onResume() but from onWindowFocusChanged() :

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus && eglSurface.getVisibility() == View.GONE) {
         eglSurface.setVisibility(View.VISIBLE);
    }
    ...
}

See also:

eglCreateWindowSurface: native_window_api_connect failed

fixing-common-android-lifecycle-issues

Links

GLSurfaceView, GLSurfaceView.Renderer

like image 98
Jon Goodwin Avatar answered Nov 02 '22 23:11

Jon Goodwin