【问题标题】:Why egl pixmap surface works with opengl es but not with opengl?为什么 egl pixmap 表面适用于 opengl es 但不适用于 opengl?
【发布时间】:2025-11-25 05:35:01
【问题描述】:

我将 EGL 与 Xlib 和 OpenGL 一起使用。当我直接在窗户上画画时,一切都很好。现在我尝试使用像素图作为 EGL 表面,但 OpenGL 根本没有改变它。

我使用 OpenGL 用蓝色清洁背景。这就是我得到的:

这里是演示问题的最小示例(绘制这个垃圾)。

更新:我添加了错误检查并发现eglCopyBuffers 产生EGL_BAD_NATIVE_PIXMAPDocs 告诉这可能在两种情况下发生:如果实现不支持本机像素图或本机像素图参数无效。他们似乎都不太可能。如果我可以无错误地创建像素图表面,我相信实现支持本机像素图。如果我可以使用像 XFillRectangle 这样的本机方法在像素图上绘图,我相信像素图是有效的。

更新:我正在使用 Ubuntu Gnome 的笔记本电脑上运行它。它有两个显卡:Intel HD Graphics 5500(driver=i915) 和 Nvidia GeForce 920m(driver=nvidia)。来自 es2_info 输出的主要行(full version):

EGL_VERSION: 1.4
EGL_VENDOR: NVIDIA
EGL_CLIENT_APIS: OpenGL_ES OpenGL
GL_VERSION: OpenGL ES 3.2 NVIDIA 375.66
GL_RENDERER: GeForce 920M/PCIe/SSE2

代码:

// main.c
// cc main.c -lX11 -lEGL -lGL
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <GL/gl.h>
#include <EGL/egl.h>
#include <X11/Xlib.h>

void
die(const char * errstr, ...) {
    va_list ap;
    va_start(ap, errstr);
    vfprintf(stderr, errstr, ap);
    va_end(ap);
    exit(1);
}

int main() {
    Display * display = XOpenDisplay(NULL);
    if (!display) die("Can't create xlib display.\n");
    int screen = XDefaultScreen(display);
    GC gc = XDefaultGC(display, screen);
    Window root_window = XRootWindow(display, screen);
    unsigned long black_pixel = XBlackPixel(display, screen);
    unsigned long white_pixel = XWhitePixel(display, screen);
    Window window = XCreateSimpleWindow(display, root_window, 0, 0, 640, 480,
        0, black_pixel, white_pixel);
    if (!window) die("Can't create window.\n");
    int res = XSelectInput(display, window, ExposureMask);
    if (!res) die("XSelectInput failed.\n");
    Pixmap pixmap = XCreatePixmap(display, window, 400, 400, 24);
    if (!pixmap) die("Can't create pixmap.\n");
    EGLDisplay egldisplay = eglGetDisplay(display);
    if (EGL_NO_DISPLAY == egldisplay) die("Can't cate egl display.\n");
    res = eglInitialize(egldisplay, NULL, NULL);
    if (!res) die("eglInitialize failed.\n");
    EGLConfig config;
    int num_configs;
    static int attrib_list[] = {
        EGL_RED_SIZE,           8,
        EGL_GREEN_SIZE,         8,
        EGL_BLUE_SIZE,          8,
        EGL_ALPHA_SIZE,         0,
        EGL_RENDERABLE_TYPE,    EGL_OPENGL_BIT,
        EGL_SURFACE_TYPE,       EGL_PIXMAP_BIT,
        EGL_NONE
    };
    res = eglChooseConfig(egldisplay, attrib_list, &config, 1, &num_configs);
    if (!res) die("eglChooseConfig failed.\n");
    if (0 == num_configs) die("No appropriate egl config found.\n");
    EGLSurface surface =
        eglCreatePixmapSurface(egldisplay, config, pixmap, NULL);
    if (EGL_NO_SURFACE == surface) die("Can't create egl pixmap surface.\n");
    res = eglBindAPI(EGL_OPENGL_API);
    if (!res) die("eglBindApi failed.\n");
    EGLContext context =
        eglCreateContext(egldisplay, config, EGL_NO_CONTEXT, NULL);
    if (EGL_NO_CONTEXT == config) die("Can't create egl context.\n");
    res = eglMakeCurrent(egldisplay, surface, surface, context);
    if (!res) die("eglMakeCurrent failed.\n");
    res = XMapWindow(display, window);
    if (!res) die("XMapWindow failed.\n");
    while (1) {
        XEvent event;
        res = XNextEvent(display, &event);
        if (Expose != event.type) continue;
        glClearColor(0, 0, 1, 1);
        glClear(GL_COLOR_BUFFER_BIT);
        glFinish();
        res = eglWaitGL();
        if (!res) die("eglWaitGL failed.\n");
        res = XCopyArea(display, pixmap, window, gc, 0, 0, 400, 400, 0, 0);
        if (!res) die("XCopyArea failed.\n");
    }
}

【问题讨论】:

  • 您确认eglCreatePixmapSurface() 没有返回EGL_NO_SURFACE? '因为这就是它在我的 Debian Stable 机器上返回的内容。
  • 根据the docsattrib_list 属性对eglCreatePixmapSurface() 均无效。
  • This 在我的系统上工作。
  • @genpfault 它确实返回了 EGL_NO_SURFACE。将 attrib_list 更改为 NULL 并没有解决问题。而且您的代码在我的系统上不起作用,这让我认为问题在库中而不是在我的代码中。
  • @genpfault 我添加了错误检查。他们显示eglCopyBuffers 失败。我用详细信息更新了问题。

标签: c opengl xlib egl


【解决方案1】:

原来eglBindApi(EGL_OPENGL_API) 是问题的根源。当您删除一个时,您会得到预期的蓝色方块。

默认情况下,EGL 使用 OpenGL ES 作为渲染 API,它根本无法与 OpenGL 渲染 API 一起使用。我找不到使用 EGL 和 OpenGL 渲染 API 的单个代码示例,但我找到了 this 答案。这让我觉得 EGL 不应该与 OpenGL 一起工作,即使 eglBindApi(EGL_OPENGL_API) 不返回 EGL_BAD_PARAMETER 必须根据 docs “如果 EGL 实现不支持指定的客户端 API”返回。

所以我不接受这个作为答案,因为将 OpenGL 设置为渲染 API 会破坏代码的实际原因仍然未知。

【讨论】: