阅读量:0
一、介绍
相同点:
eglCreatePbufferSurface
和 eglCreateWindowSurface
都是 OpenGL ES 中用于创建不同类型的EGL表面的函数,以便在OpenGL ES中进行渲染。
不同点:
选择使用哪种表面类型取决于你的需求。如果你只是需要在内存中进行离屏渲染,而不需要将结果显示在屏幕上,那么 eglCreatePbufferSurface
可能更适合。
如果你需要在窗口系统的窗口上显示OpenGL渲染的内容,那么 eglCreateWindowSurface
是更常见的选择。
二、eglCreatePbufferSurface
eglCreatePbufferSurface 用于创建一个离屏渲染表面,也称为Pbuffer表面。Pbuffer表面是一个虚拟的离屏缓冲区,可以在其中进行渲染操作,而不直接与屏幕交互。通常,它用于离屏渲染、渲染到纹理等场景。
1. 函数定义
///< @param [in] dpy EGL显示连接 ///< @param [in] config EGL配置 ///< @param [in] attrib_list 属性列表,用于指定Pbuffer的一些属性,可以为NULL ///< @return 返回EGL表面 EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
2. 使用示例
// 初始化EGL eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(eglDisplay, 0, 0); // 配置EGL EGLConfig config; EGLint numConfigs; EGLint configAttribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_NONE }; eglChooseConfig(eglDisplay, configAttribs, &config, 1, &numConfigs); // 创建EGL窗口表面(可以是Pbuffer等) EGLint attribList[] = {EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE}; eglSurface = eglCreatePbufferSurface(eglDisplay, config, attribList); // 创建EGL上下文 EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; eglContext = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, contextAttribs); // 关联上下文 eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); // 渲染操作... // 交换缓冲区 eglSwapBuffers(eglDisplay, eglSurface); // 销毁 EGLSurface eglDestroySurface(eglDisplay, eglSurface); // 销毁 EGLContext eglDestroyContext(eglDisplay, eglContext); // 终止 EGL eglTerminate(eglDisplay);
三、eglCreateWindowSurface
eglCreateWindowSurface 用于创建一个与屏幕窗口相关的EGL表面。这个表面通常与设备的窗口系统交互,使得OpenGL ES渲染的内容能够显示在屏幕上。
1. 函数定义
///< @param [in] dpy EGL显示连接 ///< @param [in] config EGL配置 ///< @param [in] win 与窗口系统相关的本地窗口类型。在Android中,通常是ANativeWindow*类型 ///< @param [in] attrib_list 属性列表,用于指定Pbuffer的一些属性,可以为NULL ///< @return 返回EGL表面 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
2. 使用示例
注意:
如果你需要渲染到屏幕上,那么建议直接使用封装好的 GLSurfaceView
类,它已经把复杂的 EGL 管理,线程管理等做好了,直接使用即可。
下面的示例参考演示我们自己应该如何使用 eglCreateWindowSurface。
JNI代码
#include <EGL/egl.h> #include <GLES3/gl3.h> #include <android/native_window_jni.h> EGLDisplay eglDisplay; EGLSurface eglSurface; EGLContext eglContext; JNIEXPORT void JNICALL Java_com_afei_opengldemo_MySurfaceView_glDraw(JNIEnv *env, jclass clazz, jobject surface) { // 初始化EGL eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (eglDisplay == EGL_NO_DISPLAY) { // Unable to open connection to local windowing system return; } EGLint majorVersion; EGLint minorVersion; if (!eglInitialize(eglDisplay, &majorVersion, &minorVersion)) { // Unable to initialize EGL. Handle and recover return; } // 配置EGL EGLConfig config; EGLint numConfigs; EGLint configAttribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_DEPTH_SIZE, 1, EGL_NONE }; if (!eglChooseConfig(eglDisplay, configAttribs, &config, 1, &numConfigs)) { return; } // 创建EGL窗口表面(可以是Pbuffer等) EGLint attribList[] = {EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE}; // 这里我们需要在Java层传递一个Surface对象供我们显示 ANativeWindow *window = ANativeWindow_fromSurface(env, surface); eglSurface = eglCreateWindowSurface(eglDisplay, config, window, attribList); if (eglSurface == EGL_NO_SURFACE) { EGLint error = eglGetError(); switch (error) { case EGL_BAD_MATCH: // Check window and EGLConfig attributes to determine // compatibility, or verify that the EGLConfig // supports rendering to a window, break; case EGL_BAD_CONFIG: // Verify that provided EGLConfig is valid break; case EGL_BAD_NATIVE_WINDOW: // Verify that provided EGLNativeWindow is valid break; case EGL_BAD_ALLOC: // Not enough resources available. Handle and recover break; } return; } // 创建EGL上下文 EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; eglContext = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, contextAttribs); if (eglContext == EGL_NO_CONTEXT) { EGLint error = eglGetError(); if (error == EGL_BAD_CONFIG) { // Handle error and recover return; } } // 关联上下文 eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); // 初始化OpenGL和渲染操作... // 交换缓冲区 eglSwapBuffers(eglDisplay, eglSurface); // 销毁 EGLSurface eglDestroySurface(eglDisplay, eglSurface); // 销毁 EGLContext eglDestroyContext(eglDisplay, eglContext); // 终止 EGL eglTerminate(eglDisplay); }
Java调用代码
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mSurfaceHolder; public MyView(Context context) { super(context); mSurfaceHolder = getHolder(); mSurfaceHolder.addCallback(this); } @Override public void surfaceCreated(@NonNull SurfaceHolder holder) { // 初始化操作等 glDraw(holder.getSurface()); } @Override public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {} @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { // 释放操作... } public native static void glDraw(Surface surface); }