Monday, 24 September 2012

Getting Started with SDL (Part 2 A Simple Window)

In the last post we talked about how to install SDL in this post we will create a simple program to create initialise SDL and create a simple window.

All the code for this post can be found here and downloaded via version control using bzr

SDL.h

The first thing we need to do when using SDL is to include the SDL.h header file. This is done using the following line
#include <SDL/SDL.h>
Note that the directory prefix SDL/ is part of this path, as we shall see later the sdl-config script will give us the correct include paths when we compile the program relative to this directory.

SDL_main

Depending upon the operating system, SDL uses different native code to generate the window / interactions with the operating system. Under linux this is done be default, however under Mac OSX and Windows we need to include a different version of main. To allow this and make the code portable we can use the C/C++ conditional compilation pre-processor. To do this we use the following code
/// note that under mac osx (and windows) there is a different
/// way to build SDL so we need to use SDL_main under linux
/// normal main is fine so we use this conditional compilation
/// to incude the correct version (DARWIN being mac os x)
#if defined (DARWIN) || defined (WIN32)
  int SDL_main(int argc, char **argv)
#else
  int main(int argc, char **argv)
#endif

SDL_Init

The first thing we need to do when using SDL is to initialise the library, to do this we use the SDL_Init function, this is passed one parameter which is a flag to indicate which sub-systems should be initialised. These values are combined together using a logical or ( | ). The subsystems available are as follows
SDL_INIT_TIMER Initializes the timer sub system.
SDL_INIT_AUDIO Initializes the audio sub system.
SDL_INIT_VIDEO Initializes the video sub system.
SDL_INIT_CDROM Initializes the cdrom sub system.
SDL_INIT_JOYSTICK Initializes the joystick sub system.
SDL_INIT_EVERYTHING Initialize all of the above.
SDL_INIT_NOPARACHUTE Prevents SDL from catching fatal signals.
SDL_INIT_EVENTTHREAD
For example if we wish to initialise both the video and joystick sub sytems we would use the following code 
SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
In the following examples we will use just the video subsystem but we will also check to see if the initialisation actually worked by checking the return value from SDL_init and making sure it's a zero
if (SDL_Init( SDL_INIT_VIDEO ) !=0)
{
    std::cerr <<"error initialising SDL exiting\n";
    exit(EXIT_FAILURE);
}

Setting Video mode

To give us a video surface we use the SDL_SetVideoMode function, it has 4 parameters width and height, bits per pixel (bpp) and flags.

If the bpp value is set to 0 it will attempt to use the system value for the current display, the flags parameter can be a logical or combination of the values below, however some of these flags will cancel each other out.

SDL_SWSURFACE Surface is stored in system memory
SDL_HWSURFACE Surface is stored in video memory
SDL_ASYNCBLIT Surface uses asynchronous blits if possible
SDL_ANYFORMAT Allows any pixel-format (Display surface)
SDL_HWPALETTE Surface has exclusive palette
SDL_DOUBLEBUF Surface is double buffered (Display surface)
SDL_FULLSCREEN Surface is full screen (Display Surface)
SDL_OPENGL Surface has an OpenGL context (Display Surface)
SDL_OPENGLBLIT Surface supports OpenGL blitting (Display Surface)
SDL_RESIZABLE Surface is resizable (Display Surface)
SDL_HWACCEL Surface blit uses hardware acceleration
SDL_SRCCOLORKEY Surface use colorkey blitting
SDL_RLEACCEL Colorkey blitting is accelerated with RLE
SDL_SRCALPHA Surface blit uses alpha blending
SDL_PREALLOC Surface uses preallocated memory

This function will return an SDL_Surface structure if successful which will be referred to in other drawing functions. If this fails NULL will be returned to we can check if there was an error.

/// @brief the width of the window
const int WINDOW_WIDTH = 1024;
/// @brief the height of the window
const int WINDOW_HEIGHT = 720;
SDL_Surface* screen = SDL_SetVideoMode( WINDOW_WIDTH, WINDOW_HEIGHT, 
                                        0,SDL_HWSURFACE | SDL_DOUBLEBUF );
if( screen == NULL)
{
  std::cerr<<"error setting SDL Video Mode\n";
  exit(EXIT_FAILURE);
}

In this example we are setting the video to be a Hardware surface (in GPU memory) and to use double buffering which should give use better graphics performance in the later examples.

Setting the window caption

To set the text in the titlebar of the window created by SDL we can use the following code
// next we set the window bar caption to the text 2nd param is for an icon
// this is a char * to a pixmap data but if we use 0 none is loaded
SDL_WM_SetCaption( "A Simple SDL Window", 0 );

Event processing

SDL uses an event structure called SDL_Event to store all the information about the various events the host system / Windows manager is passing. This structure is actually a structure or many other structures and we can process the information in a number of ways. For these first simple examples we are going to look for a key down press and the windows system passing a Quit message. The structure of this is a continuous while loop, where we check a flag to see if we should exit.
SDL_Event event;
bool quit=false;
// now we loop until the quit flag is set to true
while(!quit)
{
 // process SDL events, in this case we are looking for keys
  while ( SDL_PollEvent(&event) )  
  {
    switch (event.type)
    {
    // this is the window x being clicked.
    case SDL_QUIT : quit = true; break;

    // now we look for a keydown event
    case SDL_KEYDOWN:
    {
      switch( event.key.keysym.sym )
      {
        // if it's the escape key quit
        case SDLK_ESCAPE :  quit = true; break;
        default : break;
      }
    }

    default : break;
  }
 }
} // end processing loop

Exiting SDL

Once processing has finished it is important to shutdown SDL as it may have grabbed resources that other programs need access. To do this we use the SDL_Quit function.

Compiling the program

To compile our completed program we need to pass several flags to the c++ compiler we are using, this is what the sdl-config program is for. If we run sdl-config we get the following 
sdl-config --cflags --libs
-I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
-L/usr/lib/arm-linux-gnueabihf -lSDL
We can combine this into the call to g++ by using the single back quotes as follows
g++ InitSDL.cpp -o InitSDL `sdl-config --cflags --libs`
The full listing of the program can be downloaded from the bzr repository at the top of the page, however here is the source for the basic demo (without comments)
#include <SDL/SDL.h>
#include <cstdlib>
#include <iostream>

const int WINDOW_WIDTH = 1024;
const int WINDOW_HEIGHT = 720;

#if defined (DARWIN) || defined (WIN32)
  int SDL_main(int argc, char **argv)
#else
  int main(int argc, char **argv)
#endif
{
 if (SDL_Init( SDL_INIT_VIDEO ) !=0)
 {
  std::cerr <<"error initialising SDL exiting\n";
  exit(EXIT_FAILURE);
 }
 SDL_Surface* screen = SDL_SetVideoMode( WINDOW_WIDTH, WINDOW_HEIGHT, 0,SDL_HWSURFACE | SDL_DOUBLEBUF );
 if( screen == NULL)
 {
  std::cerr<<"error setting SDL Video Mode\n";
  exit(EXIT_FAILURE);
 }
 SDL_WM_SetCaption( "A Simple SDL Window", 0 );

 SDL_Event event;
 bool quit=false;
 while(!quit)
 {
  while ( SDL_PollEvent(&event) )
  {
   switch (event.type)
   {
    case SDL_QUIT : quit = true; break;

    case SDL_KEYDOWN:
    {
     switch( event.key.keysym.sym )
     {
      case SDLK_ESCAPE :  quit = true; break;
      default : break;
     }
    }

    default : break;
   }
  }
 } // end processing loop

 SDL_Quit();

 return EXIT_SUCCESS;
}

Getting Started with SDL (Part 1 installation)

SDL is an ideal cross platform API for basic games development and other non GUI graphics systems. To quote the website above

 "Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer. It is used by MPEG playback software, emulators, and many popular games, including the award winning Linux port of "Civilization: Call To Power."

In this series of blog posts I will look at the basic use of SDL with a focus on using it on the Raspberry Pi, however all the code should work under all linux distributions as well as Mac OSX ( Windows should also just work, however I don't have a windows machine to test against).

Installing SDL using apt-get

The easiest way to install SDL on the rpi is to use apt-get and install the pre-build development packages. To do this use the following commands

sudo apt-get install libsdl1.2-dev

To check that this has been successful we can now execute the sdl-config script as follows

sdl-config 
Usage: sdl-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--cflags] [--libs] [--static-libs]

Installing from Source

The source code for SDL is available from this link http://www.libsdl.org/download-1.2.php. This is the easiest way to get SDL working on Linux system without apt as well as for Mac OSX.  To build from the .tgz version do the following

tar vfxz SDL-1.2.15.tar.gz
cd SDL-1.2.15
./configure
make
sudo make install

Once this is done we can again check to ensure that things are working by testing the sdl-config program above.

Raspberry Pi user config for the console

If you intend to use SDL on the raspberry pi without using X windows the SDL library will attempt to access the framebuffer directly. By default only the root user has access to the framebuffer device so we need to add the current user (i.e. what you logged in as) to this group.  To do this we need to add the user to the group video, input and audio groups (audio if we use it later) for a minimum you must have video and input.
sudo usermod -a -G video,input,audio [your username]

Once this is done logout and the user will be added to the group on the next login.
part 2

Monday, 9 July 2012

Raspberry Pi and the Kinect

There are several forum posts asking if the Raspberry Pi could be used with the kinect so I decided to give it a try. It is important to note that you will need a powered USB hub, as whilst the kinect does have a PSU this is only used for the motor, the Camera and Audio sub systems still need more power than the Pi can produce.

First you will need to get a couple of libraries, first off libusb is required, I downloaded the latest 1.0.9 tarball and built it using the following commands

tar vfxj libusb-1.0.9.tar.bz2
cd libusb-1.0.9/
./configure
make
sudo make install
This should work fine for both of the debian versions and this will install the developer libraries and headers for libusb. Next I downloaded the OpenKinect source code from git hub unzip this file and change into the source directory.

You may need to install cmake if you have not already done so, this can be done by using sudo apt-get install cmake. Next we need to edit some of the cmake files as for this example I don't want to build the demos which require libraries which will not work properly on the pi.

If you edit the CMakeLists.txt file and search for the following line

OPTION(BUILD_EXAMPLES "Build example programs" ON)
And change the ON to OFF you should now be able to build by typing the following
cmake CMakeLists.txt
make
sudo make install
This will then install the following files
ls /usr/local/include/libfreenect/
libfreenect.h  
libfreenect-registration.h  
libfreenect_sync.h
and
ls /usr/local/lib/libfree*
/usr/local/lib/libfreenect.a
/usr/local/lib/libfreenect.so.0.1
/usr/local/lib/libfreenect_sync.a
/usr/local/lib/libfreenect_sync.so.0.1
/usr/local/lib/libfreenect.so
/usr/local/lib/libfreenect.so.0.1.2
The first demo I've tried is a modified version of the tiltdemo.c There are reports of this working fine for some people, however it didn't for me under the latest wheezy build so I investigated more and found that the sync library wasn't working for me. The following program uses the Normal freenect library calls instead.
#include "libfreenect.h"
#include <cstdlib>
#include <ctime>
#include <iostream>

int main(int argc, char *argv[])
{
 // seed rng generator
 srand(time(0));
 // pointer to the freenect context
 freenect_context *ctx;
 // pointer to the device
 freenect_device *dev;


 if (freenect_init(&ctx, NULL) < 0)
 {
  std::cout<<"freenect_init() failed\n";
   exit(EXIT_FAILURE);
 }
 // set the highest log level so we can see what is going on
 freenect_set_log_level(ctx, FREENECT_LOG_SPEW);

 int nr_devices = freenect_num_devices (ctx);
 std::cout<<"Number of devices found: "<<nr_devices<<"\n";
 // I only have one kinect so open device 0
 if (freenect_open_device(ctx, &dev, 0) < 0)
 {
  std::cout<<"could not open device error\n";
  freenect_shutdown(ctx);
  exit(EXIT_FAILURE);
 }
 // now I'm going to loop and set random value
 // these are basically from the tiltdemo.c that comes with
 // the freenect lib modified not to use the sync lib
 while (1)
 {
  // Pick a random tilt and a random LED state
  freenect_led_options led = (freenect_led_options) (rand() % 6); // explicit cast
  int tilt = (rand() % 30)-15;
  freenect_raw_tilt_state *state = 0;
  double dx, dy, dz;
  // Set the LEDs to one of the possible states
  freenect_set_led(dev,led);
  // Set the tilt angle (in degrees)
  freenect_set_tilt_degs(dev,tilt);

  // Get the raw accelerometer values and tilt data
  state=freenect_get_tilt_state(dev);

  std::cout<<"led["<<led<<"] tilt["<<tilt<<"]\r" ;
  std::cout.flush();
  sleep(1);
 }
}

To build this I used the following makefile
CC=g++
CFLAGS=-c -Wall -O3 -I/usr/local/include/libfreenect
LDFLAGS=-L/usr/local/lib -lfreenect
SOURCES=tiltdemo.cpp
OBJECTS=$(SOURCES:%.cpp=%.o)
EXECUTABLE=tiltdemo

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
 $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.cpp.o:
 $(CC) $(CFLAGS) $< -o $@

clean :
 rm -f *.o $(EXECUTABLE)

A video of it in action can be seen here

Thursday, 21 June 2012

Embedding a Python interpreter in C++

In my feedback for the MSc project proposals I suggested it would be a good idea to embed some form of interpreter for the crowd / multi agent systems instead of hard coding them in C++. This allows for a quicker development cycle and a more flexible tool. In this video tutorial I explain the example code (here) and the basic design behind it. For more details I would read this

Wednesday, 20 June 2012

OpenGL ES on the raspberry pi Pt 3 Creating a window

In the previous post I discussed the EGLWindow class, this class is designed as a framework for the user of the library to create consistent windows. This post will look at how we can use the EGLWindow class and extend it.

MyEGLWindow

This class is going to inherit from the main EGLWindow class then implement the two methods initializeGL and paintGL.
#ifndef MYGLWINDOW_H__
#define MYGLWINDOW_H__

#include "EGLWindow.h"
/// @brief this class create our window by inheriting the features of the EGL Window
class MyGLWindow : public EGLWindow
{
  public :
   /// @brief ctor
   /// @param[in] _config an optional configuration for the buffers etc
   MyGLWindow(EGLconfig *_config=0);
   /// @brief dtor will close down the vc and re-set EGL
   ~MyGLWindow();
   /// @brief the is the main drawing function should only be called once initalizeGL has
   /// been called
   virtual void paintGL();
  protected :
   /// @brief one time OpenGL initialisation
   virtual void initializeGL();
};
When using the class the constructor must always call the initializeGL method, as the EGLWindow class is called first this will mean that we have a valid OpenGL context and any GL calls are going to be associated with this context. In this example we just print out that the ctor has been called and then init gl.
MyGLWindow::MyGLWindow(EGLconfig *_config) : EGLWindow(_config)
{
std::cout<<"My GL Window Ctor\n";
srand(time(NULL));
// init GL in this case we are going to create some render buffers
// for colour and depth
initializeGL();
}
The next stage is to implement the initializeGL function, this is where you should do any one off configuration for OpenGL, in this case I'm just going to set the clear colour (which will change later in the draw function)
void MyGLWindow::initializeGL()
{
 // set the clear colour
 glClearColor(1,1,1,1);
}
Next the we will create the paintGL method, this is designed to be called within our main look each time the screen needs to be updated. In this case I'm going to set the screen clear colour and clear the screen.
void MyGLWindow::paintGL()
{
 // scale the colour based on the width
 float r=(float)rand()/(float)RAND_MAX;
 float g=(float)rand()/(float)RAND_MAX;
 float b=(float)rand()/(float)RAND_MAX;
 // set the clear colour
 glClearColor(r,g,b,1);
 // clear screen
 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 // to update we need to swap the buffers
 swapBuffers();
}
Once drawing is complete the swapBuffers() method must be called to tell OpenGL to swap the back buffer with the front to show the re-drawn surface.

Using the window

The following code will create an instance of the MyGLWindow class and execute a loop calling draw.
#include <iostream>
#include "MyGLWindow.h"
#include "bcm_host.h"


int main()
{
 atexit( bcm_host_deinit); 
  
 std::cout<<"starting GL test\n";
 bcm_host_init();
 std::cout<<"done bcm init\n";
 // here I create a config with RGB bit size 5,6,5 and no alpha
 EGLconfig *config = new EGLconfig();
 config->setRGBA(5,6,5,0);
 // set the depth buffer
 config->setDepth(16);
 // now create a new window using the default config
 MyGLWindow win(config);
 // now set the size of the screen in this case I'm going to do a
 // rectangle in the middle (if you don't call this you would get a full
 // screen rect by default)
 uint32_t w=win.getMaxWidth();
 uint32_t h=win.getMaxHeight();
 // set this to true to upscale the dst rect
 win.setUpscale(false);
 win.setScreen(w/4,h/4,w/2,h/2);
 int x,y;
 while(1)
 {
  win.paintGL();
  sleep(1);
 }
}
In this example we create a custom config with R/B of bit depth 5 and green bit depth 6 and a depth buffer of 16 bits. This is then passed to the MyGLWindow ctor and used as the config when creating the EGL window. Next we re-size the screen so that is is half the screen dimensions and centred. (This will call the destroySurface method mentioned in the previous post). Finally we loop calling paintGL for each update and sleeping for 1ms (use ctrl + C to exit the program). We need a Makefile to build this program and it needs to include several libraries to get it working, for more details on this see the blog post here For the full code grab this

OpenGL ES on the raspberry pi Pt 2 EGLWindow Class

In the previous post I created an EGLconfig class to allow the creation of an eglConfig for raspberry pi. In this post I will talk about the design and implementation of an EGLWindow class which allows the user to create a window and then extend the basic window for their own drawing.

EGLWindow 

This class will implement various functions to setup and create an OpenGL drawing context for the user. It is then the users responsibility to implement certain methods in the sub-class to do the basic initialisation of the OpenGL functions, then a drawing class which will be called each frame in the client program.
You will notice from the class diagram there are a number of methods and attributes which are either protected or private, along with several methods which are "pure virtual" this is to force the user of the class to implement them. Full source code for the .h file is here

The constructor takes an EGLConfig class as the main parameter, this by default is set to 0 so if one is not passed a default one will be created. This is shown in the following code
EGLWindow::EGLWindow(EGLconfig *_config)
{
 // toggle we don't yet have an active surface
 m_activeSurface=false;
 // set default to not upscale the screen resolution
 m_upscale=false;
 // set our display values to 0 (not once ported to cx11 will use nullptr but
 // current pi default compiler doesn't support it yet
 m_display=0;
 m_context=0;
 m_surface=0;

 // now find the max display size (we will use this later to assert if the user
 // defined sizes are in the correct bounds
 int32_t success = 0;
 success = graphics_get_display_size(0 , &m_width, &m_height);
 assert( success >= 0 );
 std::cout<<"max width and height "<<m_width<<" "<<m_height<<"\n";
 m_maxWidth=m_width;
 m_maxHeight=m_height;
 // if we have a user defined config we will use that else we need to create one
 if (_config == 0)
 {
  std::cout<<"making new config\n";
  m_config= new EGLconfig();
 }
 else
 {
  m_config=_config;
 }

}

The core method to this class is the makeSurface method. It will create our surface and configure internal class attributes to hold values needed for the drawing etc. It also calls the initializeGL method once the surface has been created to do one off configuration of OpenGL / class attributes.
void EGLWindow::makeSurface(uint32_t _x, uint32_t _y, uint32_t _w, uint32_t _h)
{
// this code does the main window creation
EGLBoolean result;

static EGL_DISPMANX_WINDOW_T nativeWindow;
// our source and destination rect for the screen
VC_RECT_T dstRect;
VC_RECT_T srcRect;

// config you use OpenGL ES2.0 by default
static const EGLint contextAttributes[] =
{
 EGL_CONTEXT_CLIENT_VERSION, 2,
 EGL_NONE
};


// get an EGL display connection
m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if(m_display == EGL_NO_DISPLAY)
{
 std::cerr<<"error getting display\n";
 exit(EXIT_FAILURE);
}
// initialize the EGL display connection
int major,minor;

result = eglInitialize(m_display, &major, &minor);
std::cout<<"EGL init version "<<major<<"."<<minor<<"\n";
if(result == EGL_FALSE)
{
 std::cerr<<"error initialising display\n";
 exit(EXIT_FAILURE);
}
// get our config from the config class
m_config->chooseConfig(m_display);
EGLConfig config=m_config->getConfig();
// bind the OpenGL API to the EGL
result = eglBindAPI(EGL_OPENGL_ES_API);
if(result ==EGL_FALSE)
{
 std::cerr<<"error binding API\n";
 exit(EXIT_FAILURE);
}
// create an EGL rendering context
m_context = eglCreateContext(m_display, config, EGL_NO_CONTEXT, contextAttributes);
if(m_context ==EGL_NO_CONTEXT)
{
 std::cerr<<"couldn't get a valid context\n";
 exit(EXIT_FAILURE);
}
// create an EGL window surface the way this works is we set the dimensions of the srec
// and destination rectangles.
// if these are the same size there is no scaling, else the window will auto scale

dstRect.x = _x;
dstRect.y = _y;
if(m_upscale == false)
{
 dstRect.width = _w;
 dstRect.height = _h;
}
else
{
 dstRect.width = m_maxWidth;
 dstRect.height = m_maxHeight;
}
srcRect.x = 0;
srcRect.y = 0;
srcRect.width = _w << 16;
srcRect.height = _h << 16;
// whilst this is mostly taken from demos I will try to explain what it does
// there are very few documents on this ;-0
// open our display with 0 being the first display, there are also some other versions
// of this function where we can pass in a mode however the mode is not documented as
// far as I can see
m_dispmanDisplay = vc_dispmanx_display_open(0);
// now we signal to the video core we are going to start updating the config
m_dispmanUpdate = vc_dispmanx_update_start(0);
// this is the main setup function where we add an element to the display, this is filled in
// to the src / dst rectangles
m_dispmanElement = vc_dispmanx_element_add ( m_dispmanUpdate, m_dispmanDisplay,
 0, &dstRect, 0,&srcRect, DISPMANX_PROTECTION_NONE, 0 ,0,DISPMANX_NO_ROTATE);
// now we have created this element we pass it to the native window structure ready
// no create our new EGL surface
nativeWindow.element = m_dispmanElement;
nativeWindow.width =_w;
nativeWindow.height =_h;
// we now tell the vc we have finished our update
vc_dispmanx_update_submit_sync( m_dispmanUpdate );

// finally we can create a new surface using this config and window
m_surface = eglCreateWindowSurface( m_display, config, &nativeWindow, NULL );
assert(m_surface != EGL_NO_SURFACE);
// connect the context to the surface
result = eglMakeCurrent(m_display, m_surface, m_surface, m_context);
assert(EGL_FALSE != result);
m_activeSurface=true;
initializeGL();
}
The rest of the class is fairy straight forward, however it is worth mentioning the destroySurface method as it is used to allow re-creation / re-size of the window created. This is a private method and is used by the destructor and the resizeScreen method
void EGLWindow::destroySurface()
{
 if(m_activeSurface == true)
 {
  eglSwapBuffers(m_display, m_surface);
  // here we free up the context and display we made earlier
  eglMakeCurrent( m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
  eglDestroySurface( m_display, m_surface );
  eglDestroyContext( m_display, m_context );
  eglTerminate( m_display );
  m_activeSurface=false;
 }
}
The next post will show how these classes can be used to create a simple OpenGL window.

OpenGL ES on the raspberry pi Pt 1 EGLconfig Class

I've finally ported my graphics library ngl to the raspberry pi and I've released the source on google code. This post is going to be an introduction on getting started with the EGL window and the basic design behind the classes that have been added to pingl to facilitate this window creation.

Initial Design

As most of my desktop NGL demos are based on using Qt, I decided to make the config and running on NGL on the pi to be similar. To that ends I decided to design the EGLWindow class along the same lines as the QGLWidget class in Qt, this would require the splitting of the configuration and the window creation, as well as using inheritance to allow the user a common interface when writing client programs.

I also initially decided to write my own Mouse and Keyboard events stack but in the end decided against this as there are many pre-existing libraries around that allow the user to access this information. An in my case I will be using SDL.

EGLconfig class

The EGLconfig class is used to store the different attributes that may be set for an EGLConfig structure. (for more details see this blog post) The class will by default setup some useable parameters and also allow the user to set their own.

As you can see from the class diagram I use a std::map to store key value pairs for the attributes which will be turned into the appropriate structure when required. The full source for the header file can be seen here

By default the constructor creates the following attributes
EGLconfig::EGLconfig()
{
  m_attributes[EGL_RED_SIZE]=8;
  m_attributes[EGL_GREEN_SIZE]=8;
  m_attributes[EGL_BLUE_SIZE]=8;
  m_attributes[EGL_ALPHA_SIZE]=8;
  m_attributes[EGL_SURFACE_TYPE]=EGL_WINDOW_BIT;
}
To set one of the attributes by value the following code is used
void EGLconfig::setAttribute(EGLint _attrib,EGLint _value)
{
  assert(_attrib >= 0x3020 && _attrib <=0x3042);
  m_attributes[_attrib]=_value;
}
The assert is based on the values of the attribute defines in the egl.h file. This is a hard coded value and will need to be checked from time to time if the egl.h file changes and new attributes are added / removed (this is why enums should be used!) For convenience methods have been added for the most used attributes as shown below
void EGLconfig::setRGBA(EGLint _r,EGLint _g, EGLint _b, EGLint _a)
{
  m_attributes[EGL_RED_SIZE]=_r;
  m_attributes[EGL_GREEN_SIZE]=_g;
  m_attributes[EGL_BLUE_SIZE]=_b;
  m_attributes[EGL_ALPHA_SIZE]=_a;
}
void EGLconfig::setDepth(EGLint _d)
{
  m_attributes[EGL_DEPTH_SIZE]=_d;
}

void EGLconfig::setSurface(EGLint _s)
{
  m_attributes[EGL_SURFACE_TYPE]=_s;
}
Finally to choose the correct config we need to pass a constructed EGLDisplay to the class. We then build from our attribute list an array of key value pairs into a std::vector terminating the list with an EGL_NONE token. This is then passed to the eglChooseConfig function to setup the correct values.

void EGLconfig::chooseConfig(EGLDisplay _display)
{
  std::map<EGLint,EGLint>::const_iterator it;

  std::vector <EGLint> attribs;
  for ( it=m_attributes.begin() ; it != m_attributes.end(); it++ )
  {
    attribs.push_back((*it).first);
    attribs.push_back((*it).second);
  }
  attribs.push_back(EGL_NONE);

  EGLBoolean result;
  EGLint numConfig;

  // get an appropriate EGL frame buffer configuration
  result = eglChooseConfig(_display, &attribs[0], &m_config, 1, &numConfig);
  std::cout<<"got numCofig ="<<numConfig<<"\n";
  if( result==EGL_FALSE )
  {
  std::cerr<<"error setting config check your setting or if you have a valid display\n";
  exit(EXIT_FAILURE);
  }
  std::cout<<"choosing config\n";
}
The full source for the cpp file can be seen here In the next post we will create an EGLWindow class to use this.