Wednesday 20 June 2012

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.

No comments:

Post a Comment