Search code examples
opengl-esraspberry-piraspbianraspberry-pi3egl

Only OpenGL ES 1.1 and not 2.0 on Raspberry Pi 3


I'm trying to write an OpenGL ES 2.0 application for the Raspberry Pi 3 (Raspbian Jessie). I installed the following packages:

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

The application I've written creates a framebuffer loads data into it and reads the data back (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;
}

I compile it with:

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

When I run the application I get the following output:

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

The texture write and read to the framebuffer seems to work, however, I only get OpenGL ES-CM 1.1 Mesa 13.0.0. When I run glxinfo I get OpenGL 2.1 Mesa 13.0.0. I use the GL Full KMS drivers and set the memory split to 256 for the GPU.

How can I use OpenGL ES 2.0 instead of OpenGL ES 1.1?


Solution

  • You are not requesting any specific context. You defined the context_attribs array, but then you never use it and pass NULL to eglCreateContext.

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

    Change the last parameter to context_attribs and it should work.