OpenGL ES eglCreatePbufferSurface() 和 eglCreateWindowSurface() 的对比和使用

avatar
作者
猴君
阅读量:0

一、介绍

相同点:

eglCreatePbufferSurfaceeglCreateWindowSurface 都是 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); } 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!