一、介绍

相同点:

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_KHR,
    EGL_RED_SIZE, 8,
    EGL_GREEN_SIZE, 8,
    EGL_BLUE_SIZE, 8,
    EGL_NONE
};
eglChooseConfig(eglDisplay, configAttribs, &amp;config, 1, &amp;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, &amp;majorVersion, &amp;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, &amp;config, 1, &amp;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);
}

原文地址:https://blog.csdn.net/afei__/article/details/134801356

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_47168.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注