1

Can one run the same program (unmodified) on both the "desktop" OpenGL and OpenGL ES 2.0 platforms, provided that this program only performs 2D accelerated rendering?

An average Windows desktop PC and Raspberry Pi will run the program. The GL context is obtained via the functions provided by the excellent SDL2 library. And for the drawing routines a texture atlas will be used.

It would be convenient if a program could be developed/debugged on a PC and then simply be recompiled to run on the raspberry Pi. This would be no issue if both OGL platforms were mostly compatible.

Since I'm a beginner when it comes to OpenGL, I of course started experimenting with the "hello triangle" program first.

To my big surprise this triangle program works on both the desktop and the Raspberry Pi (GLES2). Save for some #include file differences.

Dazzled by all the different OpenGL headers - and function pointer gymnastics - now I'm not sure anymore if my desktop somehow provided GLES2 (which seems unlikely to me) or that the "desktop" OpenGL version I have is simply "compatible enough" with GLES2.

It's especially unclear to me whether GLES2 is just a stripped down version of OpenGL or completely different.

Is avoiding "advanced" or missing extensions/features enough to ensure compatibility across these platforms? Or are there more things to take into account?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
E. van Putten
  • 615
  • 7
  • 17
  • 1
    Why rely on [`ARB_ES2_compatibility`](https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_ES2_compatibility.txt) when you can develop against a proper OpenGL ES implementation like [ANGLE](https://chromium.googlesource.com/angle/angle/) or [Swift Shader](https://swiftshader.googlesource.com/SwiftShader)? – genpfault Aug 16 '19 at 01:21
  • Thanks @genpfault, very interesting. That looks promising! – E. van Putten Aug 16 '19 at 07:53

1 Answers1

2

OpenGLES is (more or less) a stripped down version of OpenGL (which mainly removes the old legacy cruft, and any features that may hurt battery life). There are a few very minor differences here and there, but that's largely the case.

On the Pi, you are limited to GLES. However on desktop, both NVidia and ATI support OpenGL and OpenGLES. I would imagine your SDL based app is targetting an EGL context with GLES, and since SDL wraps all of the platform specific Windowing APIs, that should just work on desktop.

If you really want to know the gory details, read on...

The way you initialise OpenGL (and GLES) is to query the graphics driver for a pointer to a function. So lets take a rubbish example:

// This will typically be in gl.h

// some magic to prevent C++ name mangling, and use 
// C naming conventions. 
#ifdef __cplusplus
# define EXTERN extern "C"
#else
# define EXTERN extern
#endif

// declare a function pointer type that matches void glFinish()
typedef void (*GL_FINISH_PTR_TYPE)();

// now declare a function pointer that will hold the address. 
// The actual pointer will be buried away within OpenGL.lib, 
// or GLES2.lib (i.e. within a C file somewhere)
EXTERN GL_FINISH_PTR_TYPE glFinish;

Basically that process will be repeated for the entire GL API.

Then within some source file, we'll declare the pointer...

#include "gl.h"

// here is our function pointer, which we will set to NULL initially
GL_FINISH_PTR_TYPE glFinish = NULL;

Now the following tends to be platform specific, but on each platform we want to pull the address for those GL methods from the driver. So on windows it looks a bit like:

#ifdef _WIN32
void initGL()
{
  // extract pointer for glFinish from the driver
  glFinish = (GL_FINISH_PTR_TYPE)wglGetProcAddress("glFinish");
}
#endif

and on the raspberry pi, it would look like:

#ifdef RASPBERRY_PI
void initGL()
{
  // extract pointer for glFinish from the driver
  glFinish = (GL_FINISH_PTR_TYPE)eglGetProcAddress("glFinish");
}
#endif

So the only things that differ between the platforms are:

  • The APIs needed to create the window
  • The APIs needed to create the OpenGL (or GLES context)
  • The function you need to call to extract the function pointers.

Handily all of the platform specific stuff is wrapped up nicely within SDL, so you really don't need to care about it. Just target SDL, and so long as you restrict yourself to the GLES API calls, it should just work on both platforms...

caveat: You may encounter minor driver differences between NVidia/ATI/Intel hardware (e.g. max supported textures size, etc), and obviously differing hardware will have differing specs for amount of RAM, etc. If your app works on the lesser hardware platform, it will usually work on the better hardware as well...

robthebloke
  • 9,331
  • 9
  • 12
  • Thanks for this nice answer. I use SDL2 to avoid all those details you speak of (function pointers, extension wrangling etc.). I may have misunderstood some aspects of SDL2 in combination with EGL, because for my simple test program I still had to work with function pointers on Windows (think `GetProcAddress`). On the RPI the EGL functions where already available through some header function. If there is some way to get rid of this 'glue' then that would be even better. – E. van Putten Aug 16 '19 at 07:49