Any GLES examples, in C++, on x86 Linux?

14,489

Solution 1

Mesa demos!

Solution 2

GLFW, Mesa, Ubuntu 16.04 AMD64

I'm not sure if GLUT supports GLES, but GLFW does, greatly simplifying window management.

sudo apt-get install libglfw3-dev libgles2-mesa-dev
gcc glfw_triangle.c -lGLESv2 -lglfw

Output:

Source:

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

#define GLFW_INCLUDE_ES2
#include <GLFW/glfw3.h>

static const GLuint WIDTH = 800;
static const GLuint HEIGHT = 600;
static const GLchar* vertex_shader_source =
    "#version 100\n"
    "attribute vec3 position;\n"
    "void main() {\n"
    "   gl_Position = vec4(position, 1.0);\n"
    "}\n";
static const GLchar* fragment_shader_source =
    "#version 100\n"
    "void main() {\n"
    "   gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
    "}\n";
static const GLfloat vertices[] = {
        0.0f,  0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
    -0.5f, -0.5f, 0.0f,
};

GLint common_get_shader_program(const char *vertex_shader_source, const char *fragment_shader_source) {
    enum Consts {INFOLOG_LEN = 512};
    GLchar infoLog[INFOLOG_LEN];
    GLint fragment_shader;
    GLint shader_program;
    GLint success;
    GLint vertex_shader;

    /* Vertex shader */
    vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
    glCompileShader(vertex_shader);
    glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(vertex_shader, INFOLOG_LEN, NULL, infoLog);
        printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);
    }

    /* Fragment shader */
    fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
    glCompileShader(fragment_shader);
    glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
    if (!success) {
        glGetShaderInfoLog(fragment_shader, INFOLOG_LEN, NULL, infoLog);
        printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s\n", infoLog);
    }

    /* Link shaders */
    shader_program = glCreateProgram();
    glAttachShader(shader_program, vertex_shader);
    glAttachShader(shader_program, fragment_shader);
    glLinkProgram(shader_program);
    glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shader_program, INFOLOG_LEN, NULL, infoLog);
        printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s\n", infoLog);
    }

    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    return shader_program;
}

int main(void) {
    GLuint shader_program, vbo;
    GLint pos;
    GLFWwindow* window;

    glfwInit();
    glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    window = glfwCreateWindow(WIDTH, HEIGHT, __FILE__, NULL, NULL);
    glfwMakeContextCurrent(window);

    printf("GL_VERSION  : %s\n", glGetString(GL_VERSION) );
    printf("GL_RENDERER : %s\n", glGetString(GL_RENDERER) );

    shader_program = common_get_shader_program(vertex_shader_source, fragment_shader_source);
    pos = glGetAttribLocation(shader_program, "position");

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glViewport(0, 0, WIDTH, HEIGHT);

    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
    glEnableVertexAttribArray(pos);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();
        glClear(GL_COLOR_BUFFER_BIT);
        glUseProgram(shader_program);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glfwSwapBuffers(window);
    }
    glDeleteBuffers(1, &vbo);
    glfwTerminate();
    return EXIT_SUCCESS;
}

The key line lines of code are:

#define GLFW_INCLUDE_ES2
#include <GLFW/glfw3.h>

GLFW_INCLUDE_ES2 is documented at: http://www.glfw.org/docs/latest/build_guide.html#build_macros and a quick look at the source shows that it forwards to GLES:

 #elif defined(GLFW_INCLUDE_ES2)
  #include <GLES2/gl2.h>
  #if defined(GLFW_INCLUDE_GLEXT)
   #include <GLES2/gl2ext.h>
  #endif

This source seems to be is in the common subset of GLES and OpenGL (like much of GLES), and also compiles with -lGL if we remove the #define GLFW_INCLUDE_ES2.

If we add things which are not in GLES like immediate rendering glBegin, link fails as expected.

See also: How to develop OpenGL ES (GLES) 2.0 applications on Linux?

Credits: genpfult made the code much more correct.

ARM Mali OpenGL ES SDK

Contains several interesting open source examples + windowing system boilerplate (X11 + EGL).

The build system supports easy cross compilation for ARM / Mali SoCs, but I haven't tested that yet.

The key component included seems to be the "OpenGL ES Emulator" http://malideveloper.arm.com/resources/tools/opengl-es-emulator/ which "maps OpenGL ES 3.2 API calls to the OpenGL API". But that does not ship with source, only precompiled.

Uses a custom enterprisey EULA that appears to be permissive, but yeah, ask your lawyer.

Tested on SDK v2.4.4.

Share:
14,489

Related videos on Youtube

Jon Watte
Author by

Jon Watte

Updated on September 15, 2022

Comments

  • Jon Watte
    Jon Watte almost 2 years

    I'm looking for a good source of GLES2 samples for C++ (or C) on x86 Linux with Xorg. The samples I can find are all in Objective C for iOS, or Java for Android, or JavaScript for WebGL. The Kronos web site has a "tutorials" section that contains two lines saying "our tutorials index will go here." Given that GLES2 is 5 years old, I don't have much hope on a sudden surge of content there.

    I already know OpenGL pretty well. I'd just like some convenient source for copy-and-paste context set-up code, really. Where can I find something like that?

  • Jon Watte
    Jon Watte almost 12 years
    Perfect! es2tri.c is just what I need.
  • Alan Corey
    Alan Corey over 4 years
    Grrr, this requires x86 Linux and a Mali (or emulator), but if you're using arm64 Linux you're hosed. Mostly I run arm machines, some with Malis. No Windows for 10 years. So they don't want to release their source and they only have x86 binaries. Which leaves me trying to pull something out of the install.sh file, totally backwards. run install.sh --help > somefile.txt, there are a few options. I just want to do bare metal, compile with gcc, this comes with Eclipse and tons of stuff.
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com over 4 years
    @AlanCorey cool, so you are running ARM machines without GLES? Server machines or a mythical ARM desktop?
  • Alan Corey
    Alan Corey over 4 years
    Not server or mythical. I have several Raspberry Pis, my latest is an Odroid N2. I have a couple old laptops but mostly I'm on a Pi or the Odroid. I've spent most of 2 days looking for programming examples or tutorials that talk about doing OpenGL ES from C under Linux. Everything close at arm eventually comes back to doing it from Windows. Not that I know OpenGL ES. There are Raspberry Pi examples but they're non-standard and don't run on anything else. I have 2 arm machines with Malis now, I want to learn how to use them.
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com over 4 years
    @AlanCorey I see. Hopefully Vulkan will be adopted for all, and someone will just implement GLES in Vulkan. ARM is hiring BTW, if you want to dare and try to improve their setup.
  • Alan Corey
    Alan Corey over 4 years
    I also have a Rock64 pine64.org/devices/single-board-computers/rock64 but I haven't run it in year or so. I have USB hard drives for permanent storage, 128 GB SD cards for everyday, a USB sound card and a CD/DVD burner. Several powered USB hubs. Both the N2 and the Rock64 have 4 GB of RAM (and a Mali), I've built Firefox on both to have the very latest.
  • Alan Corey
    Alan Corey over 4 years
    I'm not qualified, and I'm already 65. This looks closer developer.arm.com/tools-and-software/embedded/…. Probably absurd, I want to do an SDR waterfall and spectrum, but use the GPU to take charge of the updating the display chores. I've explored a few CPU methods but updating the display is expensive even writing directly to the frame buffer. Other that that I'm not very interested in OpenGL. A guy named Peter Onion has already done the SDR thing, used a rotating texture for scrolling the waterfall. On RPI.