在Android上使用OpenGL时自动清除缓冲区

时间:2013-04-24 11:31:59

标签: android opengl-es egl

我正在编写某个OpenGL应用程序,我特意想逐步绘制帧。为此,我想禁用我理解的缓冲区的自动清除,这是GLSurfaceView.Renderer.onDrawFrame()的默认行为。有人可以帮我解决这个问题吗?我需要用Java编写应用程序,而不是使用本机SDK。

我明白我可以这样做: -

(1) setting EGL_SWAP_BEHAVIOR_PRESERVED_BIT bit for EGL_SURFACE_TYPE attribute while doing [eglChooseConfig][1](), and 
(2) setting EGL_SWAP_BEHAVIOR attribute to EGL_BUFFER_PRESERVED by calling [eglSurfaceAttrib][2] on the EGLSurface object

但是,我从Khronos医生处收集到: -

"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."

现在,我知道我可以在Android应用程序中以两种方式访问​​EGL: -

(1) use the Khronos API class [EGL10][3] in javax.microedition.khronos.egl package (EGL11 doesn't seem to be implemented yet)
(2) use the Android API class [EGL14][4] in android.opengl package (similar to using class android.opengl.GLES20)

(1)的问题是版本是< 1.4所以它不支持我需要的功能。 (2)的问题是我的应用程序只是在我调用EGL14中的任何方法时崩溃,而且我不确定我应该如何使用它(我找不到一个单独的示例程序/教程如何在应用程序中使用EGL14 。特别是,我想学习如何从EGL14获得有效的GL上下文:在EGL10的情况下,我可以通过调用javax.microedition.khronos.egl.EGLContext.getGL()来做到这一点。但是,我在类android.opengl.EGLContext中看不到等效方法。事实上,除了EGL14之外,android.opengl中所有与EGL相关的类似乎都是空的。

我最好的选择是遵循与GLES20相同的推理方法:仅在GLSurfaceView.Renderer方法中调用方法:onDrawFrame(),onSurfaceCreated(),onSurfaceChanged(),因为这些提供有效的GL( GL10)和EGL(EGLConfig)作为参数的上下文。所以我将以下代码放在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!");
    }
    ...
}

我相信在调用上面的内容之前我不必实例化EGL14,因为所有方法都是静态的。但是,对EGL14.eglGetDisplay()的调用会使应用程序崩溃。

非常感谢任何帮助,谢谢:)

4 个答案:

答案 0 :(得分:1)

实施的EGL版本可能高于您正在使用的界面。实际版本由EGL10.eglInitialize()返回。如果它是[1,4]或更高,则可以在调用EGL10.eglChooseConfig()时传递[EGL10.EGL_SURFACE_TYPE,EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT]。在这里使用EGL_SWAP_BEHAVIOR_PRESERVED_BIT的EGL14定义是可以的 - 它只是一个由EGL规范定义的int。

EGL14.eglGetDisplay()如何使应用程序崩溃。它是否会抛出一个未被捕获的异常?可能值得在https://code.google.com/p/android/issues/list提交一个错误(详细了解您正在做什么以及在什么设备上)。

答案 1 :(得分:0)

您可以扩展GLSurfaceView并调用,而不是直接使用EGL 初始化setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

  

此设置可防止重新绘制GLSurfaceView框架,直到您调用requestRender(),这对此示例应用程序更有效。

请参阅android docs 1,了解如何使用Java设置GLES。

Building an OpenGL ES Environment

答案 2 :(得分:0)

你只需render to texture,然后将该纹理绘制到屏幕上。

答案 3 :(得分:0)

以Jesse Hall的解决方案为基础:

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import android.opengl.EGL14;

您可以在GLSurfaceView子类中创建一个实现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;
    }
}

GLSurfaceView子类的构造函数中,添加:

setEGLConfigChooser(new MyEGLConfigChooser());

然后,在GLSurfaceView.Renderer的实现中,只要曲面发生变化,您就可以在其上设置属性:

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);
}