Raspberry Pi 3 上只有 OpenGL ES 1.1 而不是 2.0

Only OpenGL ES 1.1 and not 2.0 on Raspberry Pi 3

我正在尝试为 Raspberry Pi 3 (Raspbian Jessie) 编写 OpenGL ES 2.0 应用程序。我安装了以下软件包:

sudo apt install mesa-utils libgl1-mesa-dri libgles2-mesa-dev libglfw-dev

我编写的应用程序创建了一个帧缓冲区,将数据加载到其中并读回数据 (texture.c on github):

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#define GL_CHECK(x) \
    x; \
{ \
    GLenum glError = glGetError(); \
    if(glError != GL_NO_ERROR) { \
        printf("glGetError() = %i (0x%.8x) at %s:%i\n", glError, glError, __FILE__, __LINE__); \
        exit(1); \
    } \
}

#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

static const EGLint context_attribs[] = {
    EGL_CONTEXT_CLIENT_VERSION, 2,
    EGL_NONE
};

static const EGLint config_attribs[] = {
    EGL_RED_SIZE, 1,
    EGL_GREEN_SIZE, 1,
    EGL_BLUE_SIZE, 1,
    EGL_DEPTH_SIZE, 1,
    EGL_RENDERABLE_TYPE,
    EGL_OPENGL_ES2_BIT,
    EGL_NONE
};

static const EGLint pbufferAttribs[] = {
    EGL_WIDTH, 9, EGL_HEIGHT, 9, EGL_NONE,
};

int main(int argc, char **argv) {

    printf("start texture\n");

    int i;
    int texSize = 2;

    EGLint major, minor;
    EGLDisplay eglDisplay;
    EGLContext eglContext;
    EGLSurface eglSurface;
    EGLConfig eglConfig;
    EGLint eglConfigCount;

    Display *dpy = NULL;
    char *dpyName = NULL;
    Window window;


    // open display
    dpy = XOpenDisplay (dpyName);
    if(!dpy) {
        fprintf (stderr, "\nERROR: could not open display\n");
        exit (1);
    }

    // create window
    window = XCreateSimpleWindow(dpy, RootWindow (dpy, DefaultScreen (dpy)), 1, 1, WINDOW_WIDTH, WINDOW_HEIGHT, 0, BlackPixel (dpy,DefaultScreen(dpy)), BlackPixel (dpy, DefaultScreen (dpy)));
    XStoreName(dpy, window, "texture");
    XMapWindow(dpy, window);

    // move window to upper left corner
    XMoveWindow(dpy, window, 0, 0);
    XSync(dpy, 0);

    // setup egl
    eglDisplay = eglGetDisplay(dpy);

    if(!eglInitialize(eglDisplay, &major, &minor)) {
        fprintf(stderr, "\nError: failed to initialize EGL\n");
        exit(1);
    }

    printf("Display used %p & EGL versions are %d.%d\n", eglDisplay, major, minor);
    printf("EGL version: %s\n", eglQueryString(eglDisplay, EGL_VERSION));
    printf("EGL vendor: %s\n", eglQueryString(eglDisplay, EGL_VENDOR));

    if(!eglChooseConfig(eglDisplay, config_attribs, &eglConfig, 1, &eglConfigCount)) {
        fprintf(stderr, "\nError: could not get an EGL visual config\n");
        exit(1);
    }

    assert(eglConfig);
    assert(eglConfigCount > 0);

    eglSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, pbufferAttribs);

    if(!eglBindAPI(EGL_OPENGL_ES_API)) {
        fprintf (stderr, "\nError: failed to bind api EGL_OPENGL_ES_API\n");
        exit(1);
    }

    eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, NULL);

    eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);


    // check OpenGL vendor
    printf("OpenGL vendor: %s\n", glGetString(GL_VENDOR));

    // check OpenGL vendor
    printf("OpenGL vendor: %s\n", glGetString(GL_RENDERER));

    // check of OpenGL version
    printf("OpenGL version: %s\n", glGetString(GL_VERSION));

    // check for OpenGL extensions
    //printf("OpenGL extensions: %s\n", glGetString(GL_EXTENSIONS));


    uint8_t* data = (uint8_t*) malloc(4*texSize*texSize*sizeof(uint8_t));
    uint8_t* result = (uint8_t*) malloc(4*texSize*texSize*sizeof(uint8_t));

    // fill data
    for(i = 0; i < texSize*texSize*4; i++) {
        data[i] = i;
        result[i] = 0;
    }

    // create framebuffer and bind it (that is used as offscreen render target)
    GLuint fb;
    GL_CHECK(glGenFramebuffers(1, &fb));
    GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, fb));

    // create texture
    GLuint tex;
    GL_CHECK(glGenTextures(1, &tex));
    GL_CHECK(glBindTexture(GL_TEXTURE_2D, tex));

    // set texture parameters
    GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
    GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
    GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
    GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));

    // define texture with RGBA format with 8Bit (GL_UNSIGNED_BYTE)
    GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texSize, texSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));

    // attach texture
    GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0));

    // transfer data to texture
    GL_CHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texSize, texSize, GL_RGBA, GL_UNSIGNED_BYTE, data));

    // check if framebuffer is complete
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        fprintf (stderr, "\nError: framebuffer not complete\n");
        exit(1);
    }

    // read back texture into result
    GL_CHECK(glReadPixels(0, 0, texSize, texSize, GL_RGBA, GL_UNSIGNED_BYTE, result));

    // print data and result
    printf("data, result:\n");
    for(i = 0; i < texSize*texSize*4; i++) {
        printf("%d, %d\n", data[i], result[i]);
    }

    // clean up
    free(data);
    free(result);

    GL_CHECK(glDeleteFramebuffers(1, &fb));
    eglBindAPI(EGL_OPENGL_ES_API);
    eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
    eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext);
    eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(eglDisplay, eglContext);
    eglDestroySurface(eglDisplay, eglSurface);
    eglTerminate(dpy);

    return 0;
}

我编译它:

gcc texture.c -o texture -lEGL -lX11 -lGLESv2

当我 运行 应用程序时,我得到以下输出:

start texture
Display used 0x6d2168 & EGL versions are 1.4
EGL version: 1.4 (DRI2)
EGL vendor: Mesa Project
OpenGL vendor: Broadcom
OpenGL vendor: Gallium 0.4 on VC4 V3D 2.1
OpenGL version: OpenGL ES-CM 1.1 Mesa 13.0.0
data, result:
0, 0
1, 1
2, 2
3, 3
4, 4
5, 5
6, 6
7, 7
8, 8
9, 9
10, 10
11, 11
12, 12
13, 13
14, 14
15, 15

帧缓冲区的纹理写入和读取似乎有效,但是,我只得到 OpenGL ES-CM 1.1 Mesa 13.0.0。当我 运行 glxinfo 我得到 OpenGL 2.1 Mesa 13.0.0。我使用 GL Full KMS 驱动程序并将 GPU 的内存拆分设置为 256。

如何使用 OpenGL ES 2.0 而不是 OpenGL ES 1.1?

您没有请求任何特定的上下文。您定义了 context_attribs 数组,但您从未使用它并将 NULL 传递给 eglCreateContext.

eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, NULL);
                                                                      ^^

将最后一个参数更改为 context_attribs,它应该可以工作。