8

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;
    }
}
1
  • Sounds like it doesn't like the SurfaceTexture object you're passing in.
    – fadden
    Mar 30, 2016 at 17:10

2 Answers 2

1
+200

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

-1

I solved the OpenGL error EGL_BAD_ALLOC

This error occurs due to I am not handling renderer properly with activity life cycle.

1
  • 1
    I'm interested in solution pls Jan 14, 2019 at 13:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.