cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

JohnBrad
Journeyman III

OpenGL ES 2.0 Emulator Bugs

Problems with the OpenGL ES Emulator

The OpenGL ES Emulator allows you to emulate OpenGL ES code on your PC.   It's actually very cool.  You just need a fairly recent AMD video card on your machine. 

The emulator is available at:

http://developer.amd.com/GPU/OpenGL/Pages/default.aspx

Current version is 1.4 (April '09)

Like all products however, there are bugs in this code.  Lacking any other place to put them, I'm going to create a new thread for posting them.  Hopefully someone at AMD will address them in the near future.

0 Likes
5 Replies
JohnBrad
Journeyman III

The emulator doesn't support PBuffers (see separate thread on this).  

At the very least, it would be nice if this was mentioned in the Caveats section of the Developers Document.  

0 Likes

This one is pretty nasty.  Calling eglChooseConfig() a second time causes gl to start failing - it returns non-zero errors and even simple calls to glGenTextures() start functioning incorrectly.  This is particularly annoying since for the life of me I can't figure out why eglCreateContext() should touch gl until I actually

gl Seems to come back to life after calling eglMakeCurrent(), but it's very iffy.  

... Part 1 of 3 .....

 #include "EGL/egl.h"

#include "GLES2/gl2.h"

#include "assert.h"

 BOOL

InitializeEGL(  )

{

    EGLint numConfigs;

    EGLint majorVersion;

    EGLint minorVersion;

 

    EGLDisplay m_eglDsp  = EGL_NO_DISPLAY;       

    EGLConfig m_eglCfg  = 0;

    EGLContext m_eglCxt  = EGL_NO_CONTEXT;

    EGLSurface m_eglSurf = EGL_NO_SURFACE;

 

    // Get Display

    m_eglDsp = eglGetDisplay( EGL_DEFAULT_DISPLAY );

    if ( m_eglDsp == EGL_NO_DISPLAY )

    {

        assert( 0 && "eglGetDisplay failed" );     

        return FALSE;

    }

 

   // Initialize EGL 

    if ( ! eglInitialize( m_eglDsp, &majorVersion, &minorVersion) )

    {

        assert( 0 && "eglInitialize failed" );

        return FALSE;

    }

 

    // Get configs

    if ( ! eglGetConfigs( m_eglDsp, NULL, 0, &numConfigs ) )

    {

        assert( 0 && "eglGetConfigs failed" );     

        return FALSE;

    }

 

   /// Build up a nice standard attribute list (RGBA8888)

    EGLint CfgAttrList[] =

    {

        EGL_RED_SIZE,       8,

        EGL_GREEN_SIZE,     8,

        EGL_BLUE_SIZE,      8,

        EGL_ALPHA_SIZE,     0,

        EGL_DEPTH_SIZE,     24,

        EGL_STENCIL_SIZE,   0,

        EGL_SAMPLES,        0,

        EGL_NONE

    };

 

   // Choose config

    if ( !eglChooseConfig(m_eglDsp, CfgAttrList, &m_eglCfg, 1, &numConfigs) )

    {

        assert( 0 && "eglChooseConfig failed" );     

        return FALSE;

    }

 

  // Create a GL context

    EGLint ctxAttribList[] =

    {

        EGL_CONTEXT_CLIENT_VERSION, 2,

        EGL_NONE

    };

    m_eglCxt = eglCreateContext( m_eglDsp, m_eglCfg, EGL_NO_CONTEXT, ctxAttribList );

    if ( m_eglCxt == EGL_NO_CONTEXT )

    {

        int error = eglGetError();

        assert( 0 && "eglCreateContext failed" );

        return FALSE;

    } 

 

        // because we don't hav a surface to draw into yet, and hence can't call eglMakeCurrent()

        //  even at this point any gl Command will violently assert/throw  (including glGetError();

 

    {

        HANDLE hWnd = CreateHWnd2(400, 300, "TestWnd");                    // CreateHWnd2 code below…

 

        EGLConfig config = m_eglCfg;

        int WSAttrList[] =

        {

            EGL_NONE

        };

 

        EGLSurface hSurf;

        hSurf = eglCreateWindowSurface(m_eglDsp, m_eglCfg, (EGLNativeWindowType) hWnd, WSAttrList);

 

            // finally, make our framebuffer surface current.

        if ( ! eglMakeCurrent( m_eglDsp, hSurf, hSurf, m_eglCxt ) )

        {

            MessageBox( NULL, "Failed to make win surface current.", "ERROR", MB_OK | MB_ICONSTOP );

            return false;

        }

 

            // at this point, everything is running ok

        GLuint hTexture2;

        int err;

 

        err = eglGetError();                // egl Succeeds (returns 0x3000, which is Success)  

        err = glGetError();                 // gl Succeeds (returns 0x0, which is GL_NO_ERROR)

        glGenTextures(1, &hTexture2);       // and this works (hTexture2 is !0)

 

            // now here comes the error

 

              .... see next article in thread ...



 

0 Likes

--- Continuation of code from previous message

            // now here comes the error

 

                    // create a new config in the same thread, and choose it

 

        EGLConfig config2;

        const EGLint configAttrs[] =

        {

            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,

            EGL_SURFACE_TYPE,   EGL_WINDOW_BIT, // | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT,      // EGL_MULTISAMPLE_RESOLVE_BOX_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT

            EGL_RED_SIZE,       8,

            EGL_GREEN_SIZE,     8,

            EGL_BLUE_SIZE,      8,

            EGL_ALPHA_SIZE,     8,

            EGL_DEPTH_SIZE,     24,      // note - changing these to match above config still fails

            EGL_STENCIL_SIZE,   8,

            EGL_SAMPLES,        0,                              // BUG: fails in emulator if > 0

            EGL_NONE

        };   

 

        int numConfigs;

        if(!eglChooseConfig (m_eglDsp, configAttrs, &config2, 1, &numConfigs))

        {

            assert(false && "eglChooseConfig Failed");

            return false;

       

 

        err = eglGetError();                // egl Succeeds (returns 0x3000, which is Success)  

        err = glGetError();                 // but gl fails (returns 0x502, which is InvalidValue)  <--- BUG ALERT!

        glGenTextures(1, &hTexture2);       // and hTexture2 is unchanged!                          <--- SAME BUG

        err = glGetError();                 // and gl still fails (returns 0x502, which is InvalidValue) 

 

 

                // now lets go create a context about this config

        EGLint ctxAttribList[] =

        {

            EGL_CONTEXT_CLIENT_VERSION, 2,

            EGL_NONE

        };

        EGLContext eglCxt = eglCreateContext( m_eglDsp, config, EGL_NO_CONTEXT, ctxAttribList );

 

        err = eglGetError();                // egl Succeeds (returns 0x3000, which is Success)

        err = glGetError();                 // but gl fails (returns 0x502, which is InvalidValue) <--- STILL BUGGY

        glGenTextures(1, &hTexture2);       // and this again fails (hTexture2 still unchanged)

        err = glGetError();                 // and gl still fails (returns 0x502, which is InvalidValue) 

 

                // finally, let's make this context current

 

        if ( ! eglMakeCurrent( m_eglDsp, hSurf, hSurf, eglCxt ) )

        {

            MessageBox( NULL, "Failed to make framebuffer surface current.", "ERROR", MB_OK | MB_ICONSTOP );

            return false;

        }

 

        err = eglGetError();                // egl Succeeds (returns 0x3000, which is Success)

        err = glGetError();                 // this time gl returns 0x501 (GL_INVALID_VALUE). 

        glGenTextures(1, &hTexture2);       // and hTexture stil hasn't changed                 <---- ANOTHER BUG!

 

        err = glGetError();                 // Finally gl returns 0x0 (Success). 

        glGenTextures(1, &hTexture2);       // Finally, we get a new value for hTexture2  

        err = glGetError();                 // this time gl returns 0x501 (GL_INVALID_VALUE). 

 

        err = glGetError();

    }

 

    return TRUE;

}

 

 

0 Likes

....  Part 3, creating the silly hWnd.

 

LRESULT CALLBACK WndProc2( HWND      hWnd,

                          UINT      uMsg,

                          WPARAM    wParam,

                          LPARAM    lParam)

{

  // switch ( uMsg )      // Check For Windows Messages

  // {

  // }

 

   // Pass All Unhandled Messages To DefWindowProc

   return DefWindowProc( hWnd, uMsg, wParam, lParam );

}

 

HWND CreateHWnd2( int width, int height, char *name )

{

   WNDCLASS             wc;                  // Windows Class Structure

   HWND hWnd;

   HINSTANCE hInstance;

 

   hInstance         = GetModuleHandle( NULL );             // Grab An Instance For Our Window

   wc.style          = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;  // Redraw On Size, And Own DC For Window.

   wc.lpfnWndProc    = WNDPROC( WndProc2 );                  // WndProc Handles Messages

   wc.cbClsExtra     = 0;                                   // No Extra Window Data

   wc.cbWndExtra     = 0;                                   // No Extra Window Data

   wc.hInstance      = hInstance;                           // Set The Instance

   wc.hIcon          = LoadIcon( NULL, IDI_WINLOGO );       // Load The Default Icon

   wc.hCursor        = LoadCursor( NULL, IDC_ARROW );       // Load The Arrow Pointer

   wc.hbrBackground  = NULL;                                // No Background Required For GL

   wc.lpszMenuName   = NULL;                                // We Don't Want A Menu

   wc.lpszClassName  = "PsuedoGL2";                         // Set The Class Name

 

   if ( ! RegisterClass( &wc ) )                            // Attempt To Register The Window Class

   {

      MessageBox( NULL, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION );

      return 0;

   }

 

   if ( ! ( hWnd=CreateWindowEx(

      WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,       // Extended Style For The Window

      "PsuedoGL2",                               // Class Name

      name,                                     // Window Title

      WS_OVERLAPPEDWINDOW |                     // Defined Window Style

      WS_CLIPSIBLINGS |                         // Required Window Style

      WS_CLIPCHILDREN,                          // Required Window Style

      0, 0,                                     // Window Position

      width,                                    // Window Width

      height,                                   // Window Height

      NULL,                                     // No Parent Window

      NULL,                                     // No Menu

      hInstance,                                // Instance

      NULL ) ) )                                // Dont Pass Anything To WM_CREATE

   {

      return 0;

   }

 

   return hWnd;

}

 

0 Likes

According to someone at AMD, the emulator only supports one configuration at any one time 

The egl spec (Section 3.7 below) does say an implementation may limit support to just one Context

  • At most one context for each supported client API may be current to a particular thread at a given time, and at most one context may be bound to a particular surface at a given time. The minimum number of current contexts that must be supported by an EGL implementation is one for each supported client API.

Contexts aren't the same and Configs, so I think this lack of support is an emulator bug.

0 Likes