EGL getting started
EGL is used as an interface between OpenGL (and other Khronos API's) and the base system (in this case the pi). It is responsible for accessing the display hardware and other synchronisation of the display / graphics context. In the case of the pi we use it to access the display hardware and use OpenGL or OpenVG with it.
All of the functions for this are stored in the header file egl.h as shown below
#include <EGL/egl.h>On the debian "squeeze" image of the OS these headers can be found in /opt/vc/include, we also need to add the EGL library to our build using the flags -L/opt/vc/lib -lEGL (more on this later in the Makefile section).
Accessing the display
Almost all the EGL functions require a valid display pointer to do their work, this is stored using the EGLDisplay typedef (it's actually a void * ).
We can get one of these using the following code
EGLDisplay display; // get an EGL display connection display = eglGetDisplay(EGL_DEFAULT_DISPLAY); assert(display !=EGL_NO_DISPLAY);If this is successful it should return a valid display, else the EGL_NO_DISPLAY value will be returned.
EGL initialisation
Now we have a valid display connection we can initialise EGL and query what version we have, this is done with the following code.
// now lets initialise EGL and get the versions int major; int minor; EGLBoolean result; result = eglInitialize(display, &major, &minor); assert(result != EGL_FALSE ); std::cout<<"Major version "<<major<<" minor "<<minor<<"\n";On my version of the pi it gives the following output
Major version 1 minor 4
Configurations
Now we have initialised EGL we can query the different configurations available to use. This is done using the eglGetConfigs function which works in two different modes. The first mode will allow us to get how many configs there are, and the second will fill a buffer with all of the different configs. This is done in the the following codeEGLint numConfigs; // first we call getConfigs with a NULL to see how many configs we have result=eglGetConfigs(display,NULL,0,&numConfigs); assert(result != EGL_FALSE ); std::cout<< "number of configs found "<<numConfigs<<"\n"; // now we create a buffer to store all our configs EGLConfig *configs = new EGLConfig[numConfigs]; // and copy them into our buffer (don't forget to delete once done) result=eglGetConfigs(display,configs,numConfigs,&numConfigs); assert(result != EGL_FALSE ); ...... // don't forget to delete once done delete [] configs;We can now gather the information from each of the configs using the eglGetConfigAttrib function. This requires you to pass in the attribute you wish to query and will return the value if set. The following code queries the attributes available on the pi (some that are in the spec are not on the pi)
for(int i=0; i<numConfigs; ++i) { std::cout<<"Config #"<<i<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_BUFFER_SIZE,&value); std::cout<<"Buffer Size "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_RED_SIZE,&value); std::cout<<"Red Size "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_GREEN_SIZE,&value); std::cout<<"Green Size "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_BLUE_SIZE,&value); std::cout<<"Blue Size "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_ALPHA_SIZE,&value); std::cout<<"Alpha Size "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_CONFIG_CAVEAT,&value); switch(value) { case EGL_NONE : std::cout<<"EGL_CONFIG_CAVEAT EGL_NONE\n"; break; case EGL_SLOW_CONFIG : std::cout<<"EGL_CONFIG_CAVEAT EGL_SLOW_CONFIG\n"; break; } eglGetConfigAttrib(display,configs[i],EGL_CONFIG_ID,&value); std::cout<<"Config ID "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_DEPTH_SIZE,&value); std::cout<<"Depth size "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_MAX_PBUFFER_WIDTH,&value); std::cout<<"Max pbuffer width "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_MAX_PBUFFER_HEIGHT,&value); std::cout<<"Max pbuffer height "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_MAX_PBUFFER_PIXELS,&value); std::cout<<"Max pbuffer pixels "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_NATIVE_RENDERABLE,&value); std::cout<<"Native renderable "<<std::string(value ? "true" : "false")<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_NATIVE_VISUAL_ID,&value); std::cout<<"Native visual ID "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_NATIVE_VISUAL_TYPE,&value); std::cout<<"Native visual type "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_SAMPLE_BUFFERS,&value); std::cout<<"Sample Buffers "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_SAMPLES,&value); std::cout<<"Samples "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_SURFACE_TYPE,&value); std::cout<<"Surface type "<<value<<"\n"; eglGetConfigAttrib(display,configs[i],EGL_TRANSPARENT_TYPE,&value); }This give a sample output like this (a full listing can be seen here or in the file output.txt in the code bundle)
Config #0 Buffer Size 32 Red Size 8 Green Size 8 Blue Size 8 Alpha Size 8 EGL_CONFIG_CAVEAT EGL_NONE Config ID 1 Depth size 24 Max pbuffer width 2048 Max pbuffer height 2048 Max pbuffer pixels 4194304 Native renderable true Native visual ID 37928 Native visual type 12344 Sample Buffers 0 Samples 0 Surface type 1639
Makefile
To build the program the following makefile was used, it includes the correct paths and libs
CC=g++ CFLAGS=-c -Wall -O3 -I/usr/local/include -I/opt/vc/include -Iinclude/ngl -Isrc/ngl -Isrc/shaders -DNGL_DEBUG LDFLAGS=-L/opt/vc/lib -lEGL SOURCES=$(shell find ./ -name *.cpp) OBJECTS=$(SOURCES:%.cpp=%.o) EXECUTABLE=EGLgetConfig all: $(SOURCES) $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) $(CC) $(LDFLAGS) $(OBJECTS) -o $@ .cpp.o: $(CC) $(CFLAGS) $< -o $@ clean : rm -f *.o $(EXECUTABLE)That it for now but here is a sneak preview of NGL almost working