Reputation: 86
I'm writing a certain OpenGL application where I'd specifically like to draw frames incrementally. For this, I'd like to disable automatic clearing of buffer which I understand, is default behavior of GLSurfaceView.Renderer#onDrawFrame()
. Can someone please help me on how to do this? I need to write the application in Java, not using native SDK.
I understand that I could possibly do this by :-
EGL_SWAP_BEHAVIOR_PRESERVED_BIT
bit for EGL_SURFACE_TYPE
attribute while doing eglChooseConfig
, andEGL_SWAP_BEHAVIOR
attribute to EGL_BUFFER_PRESERVED
by calling eglSurfaceAttrib
on the EGLSurface objectHowever, I gather from the Khronos doc that:-
EGL_SWAP_BEHAVIOR_PRESERVED_BIT
are supported only if the EGL
version is 1.4 or greater.EGL_SWAP_BEHAVIOR
is supported only if the EGL version is 1.2 or greater.Now, I understand that I could access EGL in two ways in my Android application:-
EGL10
in
javax.microedition.khronos.egl
package (EGL11
doesn't seem to be implemented yet)EGL14
in android.opengl package
(similar to using class android.opengl.GLES20
)The problem with (1) is that the version is < 1.4 so it doesn't support the functionality I need.
The problem with (2) is that my application simply crashes the moment I call any method in EGL14, and I'm not sure how I'm supposed to use it (I could not find a single example program / tutorial on how EGL14 is supposed to be used in an app). In particular, I'd like to learn how to get a valid GL context from EGL14: in the case of EGL10, I could do that by calling javax.microedition.khronos.egl.EGLContext.getGL()
. However, I see no equivalent method in class android.opengl.EGLContext
. In fact, all EGL-related classes in android.opengl
except EGL14 seem to be mostly empty.
My best bet was to follow the same line of reasoning as in case of GLES20: to call the methods only inside the GLSurfaceView.Renderer
methods: onDrawFrame()
, onSurfaceCreated()
, onSurfaceChanged()
, because these supply valid GL (GL10) and EGL (EGLConfig) contexts as arguments. So I put following code inside onDrawFrame()
:-
public void onDrawFrame(GL10 gl) {
...
android.opengl.EGLDisplay d = null;
if ( (d = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)) == EGL14.EGL_NO_DISPLAY) {
Log.i("Triangle", "EGL14.eglGetDisplay() failed!");
} else {
Log.i("Triangle", "EGL14.eglGetDisplay() succeeded!");
}
...
}
I believe I won't have to instantiate EGL14 before calling the above since all methods are static. However, the call to EGL14.eglGetDisplay()
crashes the app.
Any help would be much appreciated, thanks:)
Upvotes: 6
Views: 2589
Reputation: 2348
To build upon Jesse Hall's solution:
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import android.opengl.EGL14;
You can have an inner class in your GLSurfaceView
subclass that implements an EGLConfigChooser:
private static class MyEGLConfigChooser implements GLSurfaceView.EGLConfigChooser {
public EGLConfig chooseConfig (EGL10 egl, EGLDisplay display) {
EGLConfig [] configs = new EGLConfig[1];
int [] num_config = new int[1];
int [] attrib_list = new int[] {
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
// ... + anything else you want ...
EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT | EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT,
EGL10.EGL_NONE,
};
if (egl.eglChooseConfig(display, attrib_list, configs, configs.length, num_config) && num_config[0] > 0) {
// We just pick the first here, but you could interrogate all
return configs[0];
}
return null;
}
}
In your constructor of the GLSurfaceView
subclass, add:
setEGLConfigChooser(new MyEGLConfigChooser());
Then, in the implementation of your GLSurfaceView.Renderer
, whenever the surface changes, you can set the attributes on it:
public void onSurfaceChanged(GL10 gl, int width, int height) {
EGL14.eglSurfaceAttrib(EGL14.eglGetCurrentDisplay(),
EGL14.getCurrentSurface(EGL14.EGL_DRAW),
EGL14.EGL_SWAP_BEHAVIOR,
EGL14.EGL_BUFFER_PRESERVED);
}
Upvotes: 1
Reputation: 787
You simply can render to texture and then draw that texture to screen.
Upvotes: 0
Reputation: 6807
The EGL version implemented may be higher than the interface you're using. The actual version is returned by EGL10.eglInitialize(). If it's [1,4] or higher, you can pass [EGL10.EGL_SURFACE_TYPE, EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT] when you call EGL10.eglChooseConfig(). It's okay to use the EGL14 definition of EGL_SWAP_BEHAVIOR_PRESERVED_BIT here -- it's just an int defined by the EGL spec.
How does EGL14.eglGetDisplay() crash the app. Is it throwing an exception that isn't getting caught? Might be worth filing a bug (with as much detail about what you're doing, and on what device) at https://code.google.com/p/android/issues/list.
Upvotes: 1
Reputation: 445
Instead of using EGL directly, you could extend GLSurfaceView and call
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
on init.
This setting prevents the GLSurfaceView frame from being redrawn until you call requestRender(), which is more efficient for this sample app.
See the android docs 1 on how to setup GLES with Java.
Building an OpenGL ES Environment
Upvotes: 1