GLSurfaceView.Renderer possible to swap buffers multiple times in onDrawFrame()?
Asked Answered
H

4

5

In my openGL game, I draw my scene normally using a GLSurfaceView.Renderer class in the onDrawFrame(). However, when I am displaying a loading screen I would like to force the screen to draw after each item of data is loaded so the loading bar can be displayed.

Is it possible to force a bufferswap during this draw call somehow? My only alternative is to stagger my loading across multiple frames which means a lot of rework..

I guess what I am trying to call is eglSwapBuffers() but I cannot find a way to access the egl context from the GLSurfaceView or GLSurfaceView.Renderer.

Thank you for your time.

Harhay answered 23/6, 2011 at 15:47 Comment(0)
H
5

No you can't (or shouldn't) force swapping buffers in the onDraw method of your Renderer.

What you should do is to make the loading of your data in a separate Thread. Your onDraw method will still be called regularly, which will let you ask to the loading thread how many items were loadede to display a progress bar / message accordingly.

Hatchery answered 24/6, 2011 at 8:38 Comment(3)
Loading data on a separate thread would require calls to gl from the loading thread (glGenTextures etc). As I understand it, this isn't something I should be doing..?Harhay
If you make the onDraw method synchronized, your glGenTexture calls will be made outside the rendering process, so this is not a problem.Hatchery
I got this to work by loading all of my image data on a separate thread. To keep things safe, I actually call all gl functions such as glGenTextures on the renderer thread once the data has been loaded. This works marvellously, and I now have an animated loading bar!Harhay
P
5

You can add also this method to your GLSurfaceView.Renderer class:

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;

public void swapBuffers()
{
    EGL10 curEgl = (EGL10)EGLContext.getEGL();

    EGLDisplay curDisplay = curEgl.eglGetCurrentDisplay();
    if (curDisplay == EGL10.EGL_NO_DISPLAY) { Log.e("myApp","No default display"); return; }    

    EGLSurface curSurface = curEgl.eglGetCurrentSurface(EGL10.EGL_DRAW);
    if (curSurface == EGL10.EGL_NO_SURFACE) { Log.e("myApp","No current surface"); return; }

    curEgl.eglSwapBuffers(curDisplay, curSurface);
}

Much the same as OpenUserX03's answer, just in Java.

Prose answered 29/9, 2012 at 20:51 Comment(0)
T
1

It's been awhile since the answer has been accepted but you can (and there is no reason you shouldn't) force swapping the buffers in the onDrawFrame() method of your Renderer.

I had the exact same problem in my OpenGL app - I needed to render a loading screen while data was being loaded. Here is my pseudo-code example of calling eglSwapBuffers() during a load (I use JNI):

public void onDrawFrame(GL10 gl)
{
    MyJNILib.render();
}

MyJNILib native pseudo-code:

#include <EGL\egl.h>

...

void render()
{
    ...

    while (loading)
    {
        // Do loading stuff
        ...
        eglSwapBuffers( eglGetCurrentDisplay(), eglGetCurrentSurface( EGL_DRAW ) );
    }

    ...
}
Testate answered 1/6, 2012 at 19:4 Comment(0)
C
0

A solution by force is to make your custom version GLSurfaceView class based on the source code of Android.

In the source, you can find a method called swap:

/**
 * Display the current render surface.
 * @return the EGL error code from eglSwapBuffers.
 */
public int swap() {
    if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
        return mEgl.eglGetError();
    }
    return EGL10.EGL_SUCCESS;
}

This should be what you want. Unfortunately, however, it is a method of private inner class called EglHelper.

/**
 * An EGL helper class.
 */

private static class EglHelper {

So in your custom GLSurfaceView class (copied from Google's source), make this EglHelper class public and you can use EglHelper.swap method.

public static class EglHelper {
Castiron answered 24/3, 2021 at 13:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.