This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

glEGLImageTargetTexture2DOES

Other Parts Discussed in Thread: TEST2

 

I am trying to use a cmem -- backed texture to share image data between processes.

 

So far I've been able to get a cmem backed framebuffer (pbuffer) to work OK, but I've not been able to get a texture to work. Is it supported?

The only example of this use case I've found is from sgxperf2.c that I found. When I try this in my own test, it returns error 500 and 502.

EGL_VERSION = 1.4 build 1.4.14.2616
EGL_VENDOR = Imagination Technologies
EGL_EXTENSIONS = EGL_KHR_image EGL_KHR_image_base EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_gl_renderbuffer_image EGL_KHR
EGL_CLIENT_APIS = OpenGL_ES OpenVG

 

It is doing the mapping like so ( and I copied this in my test):

-----

    eglImage = peglCreateImageKHR(
                            eglDisplay,
                            EGL_NO_CONTEXT, //eglContext,
                            EGL_NATIVE_PIXMAP_KHR, //EGL_GL_TEXTURE_2D_KHR,
                            pNativePixmap, //(void*)textureId0,//
                            NULL //miplevel 0 is fine, thank you
                            );
    SGX_PERF_printf("peglCreateImageKHR returned %x\n", eglImage);
    if((err = eglGetError()) != EGL_SUCCESS)
    {
        SGX_PERF_printf("Error after peglCreateImageKHR!, error = %x\n", err);
        return 3;
    }

    //bind this to a texture
    pFnEGLImageTargetTexture2DOES =
        (PFNGLEGLIMAGETARGETTEXTURE2DOES)eglGetProcAddress("glEGLImageTargetTexture2DOES");
    if(pFnEGLImageTargetTexture2DOES == NULL)
        SGX_PERF_printf("pFnEGLImageTargetTexture2DOES not found!\n");
    pFnEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage);
    if((err = glGetError()) != 0)
    {
        SGX_PERF_printf("Error after glEGLImageTargetTexture2DOES!, error = %x\n", err);
        return 4;
    }
    SGX_PERF_printf("Destroying eglimage!\n");
    pEGLDestroyImage = (PEGLDESTROYIMAGE)eglGetProcAddress("eglDestroyImageKHR");
    //destroy the eglimage
    pEGLDestroyImage(eglDisplay, eglImage);
    if((err = eglGetError()) != EGL_SUCCESS)
    {
        SGX_PERF_printf("Error after pEGLDestroyImage!, error = %x\n", err);
        return 5;
    }

  • At what step are you seeing these errors ? Would need to see the full code as well including the initialisation. Are you able to get the sgxperf eglimage test case to function ?

  • Hello Prabindh,

    I threw together a simple test that initializes and runs similar to my real application with the same error, see below.

    I also ran the test scripts from your e-mail, see below. ( the forum would not allow me to attach for some reason).

    This is the cmem module load command I used:

    /sbin/insmod /usr/local/network/beagle/angstrom/angstrom-setup-scripts/build/tmp-angstrom_2008_1/sysroots/beagleboard-angstrom-linux-gnueabi/usr/share/ti/ti-linuxutils-tree/packages/ti/sdo/linuxutils/cmem/src/module/cmemk.ko phys_start=0x85000000 phys_end=0x86000000 pools=1x3932160

     

    Jamie

     

     

    esBeagleTest2.cpp:

    -----------

    #include <stdio.h>

    #include <EGL/egl.h>
    #include <EGL/eglext.h>
    #include <GLES2/gl2.h>
    #include <GLES2/gl2ext.h>

    #include <cmem.h> //for contiguous physical memory allocation. Always used.
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>

    #define ON_SCREEN 1
    #define CMEM_TEXTURE 1



    /******************************************************************************
     Defines
    ******************************************************************************/

    // Index to bind the attributes to vertex shaders
    #define VERTEX_ARRAY    0
    #define TEXCOORD_ARRAY    1

    // Width and height of the window
    #define WINDOW_WIDTH     640
    #define WINDOW_HEIGHT     480
    #define TEXTURE_WIDTH    64
    #define TEXTURE_HEIGHT   64
    #define SGXPERF_RGB565   0
    #define SGXPERF_ARGB8888 2

    void writeppm(char *data, int w, int h, char *filename){
      const int dimx = w;
      const int dimy = h;
     
      FILE * fp = fopen(filename, "w");

      fprintf(fp, "P6\n%d %d\n255\n", dimx, dimy);

      static unsigned char color[3];
      for(int i=0; i<w*h; i++){
        color[2] = *(data++);
        color[1] = *(data++);
        color[0] = *(data++);
        data++;
        fwrite(color,1,3,fp);
      }

      fclose(fp);
     
    }

    bool TestEGLError(const char* pszLocation){

      /*
        eglGetError returns the last error that has happened using egl,
        not the status of the last called function. The user has to
        check after every single egl call or at least once every frame.
      */
      EGLint iErr = eglGetError();
      if (iErr != EGL_SUCCESS)
        {
          printf("%s failed (%d).\n", pszLocation, iErr);
          return false;
        }

      return true;
    }

    typedef struct _NATIVE_PIXMAP_STRUCT{
      long ePixelFormat;
      long eRotation;
      long lWidth;
      long lHeight;
      long lStride;
      long lSizeInBytes;
      long pvAddress;
      long lAddress;
    }NATIVE_PIXMAP_STRUCT;


    void common_create_native_pixmap(unsigned long         width,
                     unsigned long         height,
                     NATIVE_PIXMAP_STRUCT *cMemPixmap){
      struct CMEM_AllocParams  params;

      params.type                  = CMEM_HEAP;
      params.flags                 = CMEM_CACHED; //CMEM_NONCACHED; //CMEM_CACHED;
      params.alignment             = 0x32;

      cMemPixmap->lAddress         = (long) CMEM_alloc  (width*height*4, &params);
      cMemPixmap->pvAddress        = CMEM_getPhys((void*)cMemPixmap->lAddress);

      cMemPixmap->ePixelFormat     = SGXPERF_ARGB8888;
      cMemPixmap->eRotation        = 0;
      cMemPixmap->lWidth           = width;
      cMemPixmap->lHeight          = height;
      cMemPixmap->lStride          = width * 4;
      cMemPixmap->lSizeInBytes     = width * height * 4;


      if(cMemPixmap->pvAddress & 0xFFF){
        printf("PVR2DMemWrap may have issues with this non-aligned address!\n");
      }
    }

    void common_delete_native_pixmap(NATIVE_PIXMAP_STRUCT *pNativePixmap){
      if(!pNativePixmap) return;
      if(pNativePixmap->lAddress)
        CMEM_free((void*)pNativePixmap->lAddress, NULL);
      //delete the pixmap itself
      free(pNativePixmap);
    }

    int main(int argc, char **argv){
      // EGL variables
      EGLDisplay    eglDisplay = 0;
      EGLConfig     eglConfig  = 0;
      EGLSurface    eglSurface = 0;
      EGLContext    eglContext = 0;
      GLuint    ui32Vbo    = 0; // Vertex buffer object handle
      GLuint        ui32Tbo    = 0; // TexCoord buffer object handle
      int inTextureWidth       = WINDOW_WIDTH;
      int inTextureHeight      = WINDOW_HEIGHT;
      float         r          = 0;
      char *ptr;
      int i32Location;

      CMEM_init();

      /*
        EGL has to create a context for OpenGL ES. Our OpenGL ES resources
        like textures will only be valid inside this context
        (or shared contexts).
        Creation of this context takes place at step 7.
      */
      EGLint ai32ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };

      // Matrix used for projection model view (PMVMatrix)
      float pfIdentity[] =
        {
          1.0f,0.0f,0.0f,0.0f,
          0.0f,1.0f,0.0f,0.0f,
          0.0f,0.0f,1.0f,0.0f,
          0.0f,0.0f,0.0f,1.0f
        };

      // Fragment and vertex shaders code
      const char* pszFragShader = "\
                    uniform sampler2D    sampler2d; \
                    varying mediump vec2 TexCoord; \
            void main (void)\
            {\
                            gl_FragColor   = texture2D(sampler2d, TexCoord); \
            }";

      const char* pszVertShader = "\
            attribute highp vec4   myVertex;\
            uniform mediump mat4   myPMVMatrix;\
                    attribute mediump vec2 myUV; \
                    varying   mediump vec2 TexCoord; \
            void main(void)\
            {\
                gl_Position = myPMVMatrix * myVertex;\
                            TexCoord    = myUV; \
            }";

      /*
        Step 1 - Get the default display.
        EGL uses the concept of a "display" which in most environments
        corresponds to a single physical screen. Since we usually want
        to draw to the main screen or only have a single screen to begin
        with, we let EGL pick the default display.
        Querying other displays is platform specific.
      */
      eglDisplay = eglGetDisplay((EGLNativeDisplayType)0);

      /*
        Step 2 - Initialize EGL.
        EGL has to be initialized with the display obtained in the
        previous step. We cannot use other EGL functions except
        eglGetDisplay and eglGetError before eglInitialize has been
        called.
        If we're not interested in the EGL version number we can just
        pass NULL for the second and third parameters.
      */
      EGLint iMajorVersion, iMinorVersion;
      if (!eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion))
        {
          printf("Error: eglInitialize() failed.\n");
          exit(1);
        }

      /*
        Step 3 - Make OpenGL ES the current API.
        EGL provides ways to set up OpenGL ES and OpenVG contexts
        (and possibly other graphics APIs in the future), so we need
        to specify the "current API".
      */
      eglBindAPI(EGL_OPENGL_ES_API);

      if (!TestEGLError("eglBindAPI"))
        {
          exit(1);
        }

      /*
        Step 4 - Specify the required configuration attributes.
        An EGL "configuration" describes the pixel format and type of
        surfaces that can be used for drawing.
        For now we just want to use a 16 bit RGB surface that is a
        Window surface, i.e. it will be visible on screen. The list
        has to contain key/value pairs, terminated with EGL_NONE.
      */
      EGLint pi32ConfigAttribs[5];
      pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;
      pi32ConfigAttribs[1] = EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT;
      pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE;
      pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT;
      pi32ConfigAttribs[4] = EGL_NONE;

      /*
        Step 5 - Find a config that matches all requirements.
        eglChooseConfig provides a list of all available configurations
        that meet or exceed the requirements given as the second
        argument. In most cases we just want the first config that meets
        all criteria, so we can limit the number of configs returned to 1.
      */
      int iConfigs;
      if (!eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1))
        {
          printf("Error: eglChooseConfig() failed.\n");
          exit(1);
        }

      /*
        Step 6 - Create a surface to draw to.
        Use the config picked in the previous step and the native window
        handle when available to create a window surface. A window surface
        is one that will be visible on screen inside the native display (or
        fullscreen if there is no windowing system).
        Pixmaps and pbuffers are surfaces which only exist in off-screen
        memory.
      */

    #ifdef ON_SCREEN

      // On screen
      eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (EGLNativeWindowType) NULL, NULL);

    #else

      // offscreen
      NATIVE_PIXMAP_STRUCT pNativePixmap;
      EGLint pbuf_attribs[15];
      int ci=0;

      pbuf_attribs[ci++] = EGL_WIDTH;
      pbuf_attribs[ci++] = WINDOW_WIDTH;
      pbuf_attribs[ci++] = EGL_HEIGHT;
      pbuf_attribs[ci++] = WINDOW_HEIGHT;
      pbuf_attribs[ci++] = EGL_NONE;

      common_create_native_pixmap(inTextureWidth, inTextureHeight, &pNativePixmap);
      eglSurface = eglCreatePixmapSurface(eglDisplay, eglConfig, &pNativePixmap, NULL);

      int windowWidth;
      int windowHeight;

      eglQuerySurface(eglDisplay, eglSurface, EGL_WIDTH, &windowWidth);
      eglQuerySurface(eglDisplay, eglSurface, EGL_HEIGHT, &windowHeight);

      printf("Pixmap: %i, %i \n", windowWidth, windowHeight);

    #endif 


      if (!TestEGLError("eglCreateWindowSurface"))
        {
          exit(1);
        }

      /*
        Step 7 - Create a context.
      */
      eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, ai32ContextAttribs);
      if (!TestEGLError("eglCreateContext"))
        {
          exit(1);
        }

      /*
        Step 8 - Bind the context to the current thread and use our
        window surface for drawing and reading.
        Contexts are bound to a thread. This means you don't have to
        worry about other threads and processes interfering with your
        OpenGL ES application.
        We need to specify a surface that will be the target of all
        subsequent drawing operations, and one that will be the source
        of read operations. They can be the same surface.
      */
      eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
      if (!TestEGLError("eglMakeCurrent"))
        {
          exit(1);
        }

      /*
        Step 9 - Draw something with OpenGL ES.
        At this point everything is initialized and we're ready to use
        OpenGL ES to draw something on the screen.
      */

      GLuint uiFragShader, uiVertShader;        // Used to hold the fragment and vertex shader handles
      GLuint uiProgramObject;                    // Used to hold the program handle (made out of the two previous shaders

      // Create the fragment shader object
      uiFragShader = glCreateShader(GL_FRAGMENT_SHADER);

      // Load the source code into it
      glShaderSource(uiFragShader, 1, (const char**)&pszFragShader, NULL);

      // Compile the source code
      glCompileShader(uiFragShader);

      // Check if compilation succeeded
      GLint bShaderCompiled;
      glGetShaderiv(uiFragShader, GL_COMPILE_STATUS, &bShaderCompiled);

      if (!bShaderCompiled)
        {
          // An error happened, first retrieve the length of the log message
          int i32InfoLogLength, i32CharsWritten;
          glGetShaderiv(uiFragShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);

          // Allocate enough space for the message and retrieve it
          char* pszInfoLog = new char[i32InfoLogLength];
          glGetShaderInfoLog(uiFragShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);

          // Displays the error
          printf("Failed to compile fragment shader: %s\n", pszInfoLog);
          delete [] pszInfoLog;
          exit(1);
        }

      // Loads the vertex shader in the same way
      uiVertShader = glCreateShader(GL_VERTEX_SHADER);
      glShaderSource(uiVertShader, 1, (const char**)&pszVertShader, NULL);
      glCompileShader(uiVertShader);
      glGetShaderiv(uiVertShader, GL_COMPILE_STATUS, &bShaderCompiled);

      if (!bShaderCompiled)
        {
          int i32InfoLogLength, i32CharsWritten;
          glGetShaderiv(uiVertShader, GL_INFO_LOG_LENGTH, &i32InfoLogLength);
          char* pszInfoLog = new char[i32InfoLogLength];
          glGetShaderInfoLog(uiVertShader, i32InfoLogLength, &i32CharsWritten, pszInfoLog);
          printf("Failed to compile vertex shader: %s\n", pszInfoLog);
          delete [] pszInfoLog;
          exit(1);
        }

      // Create the shader program
      uiProgramObject = glCreateProgram();

      // Attach the fragment and vertex shaders to it
      glAttachShader(uiProgramObject, uiFragShader);
      glAttachShader(uiProgramObject, uiVertShader);

      // Bind the custom vertex attribute "myVertex" to location VERTEX_ARRAY
      glBindAttribLocation(uiProgramObject, VERTEX_ARRAY, "myVertex");

      // Bind the custom vertex attribute "myVertex" to location VERTEX_ARRAY
      glBindAttribLocation(uiProgramObject, TEXCOORD_ARRAY, "myUV");

      // Link the program
      glLinkProgram(uiProgramObject);

      // Check if linking succeeded in the same way we checked for compilation success
      GLint bLinked;
      glGetProgramiv(uiProgramObject, GL_LINK_STATUS, &bLinked);

      if (!bLinked)
        {
          int ui32InfoLogLength, ui32CharsWritten;
          glGetProgramiv(uiProgramObject, GL_INFO_LOG_LENGTH, &ui32InfoLogLength);
          char* pszInfoLog = new char[ui32InfoLogLength];
          glGetProgramInfoLog(uiProgramObject, ui32InfoLogLength, &ui32CharsWritten, pszInfoLog);
          printf("Failed to link program: %s\n", pszInfoLog);
          delete [] pszInfoLog;
          exit(1);
        }

      // Actually use the created program
      glUseProgram(uiProgramObject);

      // Sets the clear color.
      // The colours are passed per channel (red,green,blue,alpha) as float values from 0.0 to 1.0
      glClearColor(0.6f, 0.8f, 1.0f, 1.0f); // clear blue

      // We're going to draw a triangle to the screen so create a vertex buffer object for our triangle
      {
        // Interleaved vertex data
        GLfloat afVertices[] = {   -0.4f, -0.4f, 0.0f, // Position
                    0.4f, -0.4f, 0.0f,
                    0.0f, 0.4f , 0.0f};

        GLfloat afTexCoords[] = {   0.0f, 0.0f,
                    1.0f, 0.0f,
                    0.0f, 1.0f};
       
        // Generate the vertex buffer object (VBO)
        glGenBuffers(1, &ui32Vbo);

        // Bind the VBO so we can fill it with data
        glBindBuffer(GL_ARRAY_BUFFER, ui32Vbo);

        // Set the buffer's data
        unsigned int uiSize = 3 * (sizeof(GLfloat) * 3); // Calc afVertices size (3 vertices * stride (3 GLfloats per vertex))
        glBufferData(GL_ARRAY_BUFFER, uiSize, afVertices, GL_STATIC_DRAW);

        // Generate the texcoord buffer object (TBO)
        glGenBuffers(1, &ui32Tbo);

        // Bind the TBO so we can fill it with data
        glBindBuffer(GL_ARRAY_BUFFER, ui32Tbo);

        // Set the buffer's data
        uiSize = 3 * (sizeof(GLfloat) * 2); // Calc afTexCoords size (3 coords * stride (2 GLfloats per vertex))
        glBufferData(GL_ARRAY_BUFFER, uiSize, afTexCoords, GL_STATIC_DRAW);

        // Bind the VBO so we can fill it with data
        glBindBuffer(GL_ARRAY_BUFFER, ui32Vbo);

      }

      GLuint texId;

      glEnable(GL_TEXTURE_2D);
      glGenTextures(1, &texId);
      glBindTexture(GL_TEXTURE_2D, texId);


    #ifndef CMEM_TEXTURE
      int buff[TEXTURE_WIDTH*TEXTURE_HEIGHT];
     
      for(int i=0; i<(TEXTURE_WIDTH*TEXTURE_HEIGHT); i++){
        buff[i] = rand();
      }

      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexImage2D(GL_TEXTURE_2D,
               0,
               GL_RGBA,
               TEXTURE_WIDTH,
               TEXTURE_HEIGHT,
               0,
               GL_RGBA,
               GL_UNSIGNED_BYTE,
               &buff[0]);

    #else
      int err;
     
      NATIVE_PIXMAP_STRUCT cMemPixmap;
      int i=0;

      common_create_native_pixmap(TEXTURE_WIDTH, TEXTURE_HEIGHT, &cMemPixmap);

      PFNEGLCREATEIMAGEKHRPROC peglCreateImageKHR =
        (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
     
      if(peglCreateImageKHR == NULL){
        printf("eglCreateImageKHR not found!\n");
      }

      PFNGLEGLIMAGETARGETTEXTURE2DOESPROC pglEGLImageTargetTexture2DOES =
        (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");

      if(pglEGLImageTargetTexture2DOES == NULL){
        printf("glEGLImageTargetTexture2DOES not found!\n");
      }
     
      //create an egl image
      EGLImageKHR eglImage = peglCreateImageKHR(eglDisplay,
                            EGL_NO_CONTEXT,  
                            EGL_NATIVE_PIXMAP_KHR,
                            &cMemPixmap,
                            NULL);
     
      if((err = eglGetError()) != EGL_SUCCESS){
        printf("Error after peglCreateImageKHR!, error = %x\n", err);
      } else {
        printf("peglCreateImageKHR Success! \n");
      }
     
      pglEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage);
      if((err = glGetError()) != 0){
        printf("Error after glEGLImageTargetTexture2DOES!, error = %x\n", err);
      }

    #endif // CMEM_TEXTURE



      // Draws a triangle
      while(1){
        if(r<1.0){
          r+=0.01;
        } else {
          r=0;
        }
        glClearColor(r, 0.8f, 1.0f, 1.0f); // clear blue

        /*
          Clears the color buffer.
          glClear() can also be used to clear the depth or stencil buffer
          (GL_DEPTH_BUFFER_BIT or GL_STENCIL_BUFFER_BIT)
        */
        glClear(GL_COLOR_BUFFER_BIT);
        if (!TestEGLError("glClear"))
          {
        exit(1);
          }

        /*
          Bind the projection model view matrix (PMVMatrix) to
          the associated uniform variable in the shader
        */

        // First gets the location of that variable in the shader using its name
        i32Location = glGetUniformLocation(uiProgramObject, "myPMVMatrix");

        // Then passes the matrix to that variable
        glUniformMatrix4fv( i32Location, 1, GL_FALSE, pfIdentity);

        /*
          Enable the custom vertex attribute at index VERTEX_ARRAY.
          We previously binded that index to the variable in our shader "vec4 MyVertex;"
        */
        glEnableVertexAttribArray(VERTEX_ARRAY);

        // Sets the vertex data to this attribute index
        glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, 0);

        /*
          Enable the custom texcoord attribute at index TEXCOORD_ARRAY.
          We previously binded that index to the variable in our shader "vec4 MyTexcoord;"
        */
        glEnableVertexAttribArray(TEXCOORD_ARRAY);

        // Sets the texcoord data to this attribute index
        glVertexAttribPointer(TEXCOORD_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, 0);

        /*
          Draws a non-indexed triangle array from the pointers previously given.
          This function allows the use of other primitive types : triangle strips, lines, ...
          For indexed geometry, use the function glDrawElements() with an index list.
        */
        glDrawArrays(GL_TRIANGLES, 0, 3);
        if (!TestEGLError("glDrawArrays"))
          {
        exit(1);
          }

        /*
          Swap Buffers.
          Brings to the native display the current render surface.
        */
        eglSwapBuffers(eglDisplay, eglSurface);


    #ifndef ON_SCREEN
        ptr = (char*)pNativePixmap.lAddress;
        writeppm(ptr,
             (int)pNativePixmap.lWidth,
             (int)pNativePixmap.lHeight,
             "test2.ppm");
        // Frees the OpenGL handles for the program and the 2 shaders
        glDeleteProgram(uiProgramObject);
        glDeleteShader(uiFragShader);
        glDeleteShader(uiVertShader);
       
        // Delete the VBO as it is no longer needed
        glDeleteBuffers(1, &ui32Vbo);
       
        /*
          Step 10 - Terminate OpenGL ES and destroy the window (if present).
          eglTerminate takes care of destroying any context or surface created
          with this display, so we don't need to call eglDestroySurface or
          eglDestroyContext here.
        */
       
       
        eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        eglTerminate(eglDisplay);
        exit(1);
    #endif
      }

      if (!TestEGLError("eglSwapBuffers")){
        exit(1);
      }

      // Frees the OpenGL handles for the program and the 2 shaders
      glDeleteProgram(uiProgramObject);
      glDeleteShader(uiFragShader);
      glDeleteShader(uiVertShader);

      // Delete the VBO as it is no longer needed
      glDeleteBuffers(1, &ui32Vbo);

      /*
        Step 10 - Terminate OpenGL ES and destroy the window (if present).
        eglTerminate takes care of destroying any context or surface created
        with this display, so we don't need to call eglDestroySurface or
        eglDestroyContext here.
      */

     
      eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
      eglTerminate(eglDisplay);
      return 0;
    }

    ---------------------------

     

    results of sgxperf_check.sh

    ----------------------------

    WSEGL settings
    [default]
    WindowSystem=libpvrPVR2D_FRONTWSEGL.so.1
    ------
    ARM CPU information
    Processor    : ARMv7 Processor rev 3 (v7l)
    BogoMIPS    : 475.76
    Features    : swp half thumb fastmult vfp edsp thumbee neon vfpv3
    CPU implementer    : 0x41
    CPU architecture: 7
    CPU variant    : 0x1
    CPU part    : 0xc08
    CPU revision    : 3

    Hardware    : OMAP3 Beagle Board
    Revision    : 0020
    Serial        : 0000000000000000
    ------
    SGX driver information
    Version 1.4.14.2616 (release) /home/jamie/beagle/angstrom/angstrom-setup-scripts/build/tmp-angstrom_2008_1/work/beagleboard-angstrom-linux-gnueabi/omap3-sgx-modules-1.4.14.2616-r88/OMAP35x_Graphics_SDK_3_01_00_06/GFX_Linux_KM
    System Version String: SGX revision = 1.2.1
    ------
    Framebuffer settings

    mode "640x480-59"
        # D: 23.500 MHz, H: 29.375 kHz, V: 59.464 Hz
        geometry 640 480 640 480 32
        timings 42553 48 80 3 7 32 4
        rgba 8/16,8/8,8/0,8/24
    endmode

    Frame buffer device information:
        Name        : omapfb
        Address     : 0x8076c000
        Size        : 1228800
        Type        : PACKED PIXELS
        Visual      : TRUECOLOR
        XPanStep    : 1
        YPanStep    : 1
        YWrapStep   : 0
        LineLength  : 2560
        Accelerator : No
    ------
    Rotation settings
    0
    ------
    Kernel Module information
    Module                  Size  Used by
    cmemk                  21038  0
    bufferclass_ti          4600  0
    omaplfb                 8749  0
    pvrsrvkm              126567  2 bufferclass_ti,omaplfb
    rfcomm                 33488  0
    ircomm_tty             30305  0
    ircomm                 16429  1 ircomm_tty
    irda                  162965  2 ircomm_tty,ircomm
    ipv6                  249063  12
    hidp                   11193  0
    l2cap                  30104  4 rfcomm,hidp
    bluetooth              49221  3 rfcomm,hidp,l2cap
    rfkill                 14838  1 bluetooth
    ------
    Boot settings
    console=ttyS2,115200n8 root=/dev/mmcblk0p2 rw rootfstype=ext3 rootwait omapfb.video_mode=640x480MR-16@60 mem=80M
    ------
    Linux Kernel version
    Linux beagleboard 2.6.32 #3 PREEMPT Wed Sep 22 09:37:57 PDT 2010 armv7l unknown