一、介绍
相同点:
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_KHR,
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 管理,线程管理等做好了,直接使用即可。文章来源:https://www.toymoban.com/news/detail-784597.html
下面的示例参考演示我们自己应该如何使用 eglCreateWindowSurface。文章来源地址https://www.toymoban.com/news/detail-784597.html
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);
}
到了这里,关于OpenGL ES eglCreatePbufferSurface() 和 eglCreateWindowSurface() 的对比和使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!