5 Replies Latest reply on Aug 25, 2009 8:25 PM by JohnBrad

    OpenGL ES 2.0 Emulator Bugs

    JohnBrad
      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.

        • OpenGL ES 2.0 Emulator Bugs
          JohnBrad

          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.  

            • OpenGL ES 2.0 Emulator Bugs
              JohnBrad

              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 ...



               

                • BUG : eglCreateContext is corupting gl state - Part2
                  JohnBrad

                  --- 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;

                  }

                   

                   

                    • BUG : eglCreateContext is corupting gl state - Part3
                      JohnBrad

                      ....  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;

                      }

                       

                    • Only One Config supported in the Emulator
                      JohnBrad

                      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.