SDL2 ANGLE porting

I have sdl2 app and I need port it to use ANGLE but couldn't find an example on how to do so Please help!!
Code examples are appreciated.

Edited by Shazan Shums on
It's been a while since I have tried using ANGLE with SDL, but if I remember correctly then its all automatic: https://hg.libsdl.org/SDL/file/a512396c9f3f/src/video/SDL_egl.c#l55

As long as you have libGLESv2.dll and libEGL.dll files in same folder, it will just work when you are requesting ES context (of course if SDL binary is compiled to support ES2 and EGL).

Only caveat is that SDL will try to create ES2 context from your native GL driver if it supports it - WGL_EXT_create_context_es2_profile extension (theoretically it should give you better performance than ANGLE). You still can force SDL to use ANGLE library by setting SDL hint: https://hg.libsdl.org/SDL/file/default/include/SDL_hints.h#l748

Edited by Mārtiņš Možeiko on
I seem to have a problem with the code.
I have all DLLs include. But the code is not working. How to se SDL GL attributes and gl vertex array doesn't work.
I just need to render textured quad.
So what error are you getting? Nobody can help you if you don't explain what exactly are you doing and what are the results.

Here's the code I tried just now and it worked for me:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdio.h>
#include <SDL2/SDL.h>
#include <GLES2/gl2.h> // https://www.khronos.org/registry/OpenGL/api/GLES2/gl2.h

#define Assert(x) do {if (!(x)) __debugbreak(); } while (0)

int main(int argc, char* argv[])
{
   Assert(SDL_Init(SDL_INIT_VIDEO) == 0);

   SDL_SetHint(SDL_HINT_OPENGL_ES_DRIVER, "1");

   SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
   SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
   SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);

   SDL_Window* w = SDL_CreateWindow("ANGLE", 100, 100, 640, 480, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE);
   Assert(w);

   SDL_GLContext ctx = SDL_GL_CreateContext(w);
   Assert(ctx);
   
   Assert(SDL_GL_MakeCurrent(w, ctx) == 0);
   SDL_GL_SetSwapInterval(1);

   PFNGLGETSTRINGPROC glGetString = SDL_GL_GetProcAddress("glGetString");
   PFNGLCLEARCOLORPROC glClearColor = SDL_GL_GetProcAddress("glClearColor");
   PFNGLCLEARPROC glClear = SDL_GL_GetProcAddress("glClear");

   printf("GL_VERSION = %s\n",  glGetString(GL_VERSION));
   printf("GL_VENDOR = %s\n",  glGetString(GL_VENDOR));
   printf("GL_RENDERER = %s\n",  glGetString(GL_RENDERER));

   int running = 1;
   while (running)
   {
       SDL_Event ev;
       while (SDL_PollEvent(&ev))
       {
           if (ev.type == SDL_QUIT)
           {
               running = 0;
               break;
           }
       }

       glClearColor(1, 0, 0, 1);
       glClear(GL_COLOR_BUFFER_BIT);

       SDL_GL_SwapWindow(w);
   }

   SDL_GL_DeleteContext(ctx);
   SDL_Quit();

   return 0;
}

It painted screen red (I'm too lazy to now add vertex rendering), and here's how I compiled it and the output it printed:
1
2
3
4
5
6
7
C:\test>cl /nologo /I. test.c SDL2.lib SDL2main.lib /link /subsystem:console
test.c

C:\test>test.exe
GL_VERSION = OpenGL ES 2.0 (ANGLE 2.1.0.b'bc69f3bead49')
GL_VENDOR = Google Inc.
GL_RENDERER = ANGLE (NVIDIA GeForce GTX 970 Direct3D11 vs_5_0 ps_5_0)

That confirms that SDL created OpenGL ES 2.0 context with ANGLE.

Edited by Jeroen van Rijn on Reason: reparse post
Guess the problem is with the header files and the GLES mask.

mmozeiko
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);


But still don't know what header file to include I included

1
#include  <SDL_opengles2.h> 


I use MSVC v.14.00 (VS 15)

And Thanks a lot Mr.Martins for the help upto now.

Edited by Shazan Shums on
Right, you need to inform SDL that you want OpenGL ES context and not the OpenGL one. By default on Windows SDL creates OpenGL desktop context, not ES. But ANGLE supports only GLES2/3 API.

As for headers, you can use SDL_opengles2.h header, but then you need to link directly to libGLESv2.dll file. It may be OK to do that, but in some cases (where you want to use GLES2 API from your native OpenGL driver) then you need to load functions dynamically, because you don't know where they come from - libGLESv2.dll or from some driver dlls.

Edited by Mārtiņš Možeiko on
When i run your code using SDL opngles headers I get these errors.
I have all DLLs in the build directory

e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(259): error C2065: 'SDL_HINT_OPENGL_ES_DRIVER': undeclared identifier
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(276): error C2065: 'PFNGLGETSTRINGPROC': undeclared identifier
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(276): error C2146: syntax error: missing ';' before identifier 'glGetString'
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(276): error C2659: '=': function as left operand
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(277): error C2065: 'PFNGLCLEARCOLORPROC': undeclared identifier
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(277): error C2146: syntax error: missing ';' before identifier 'glClearColor'
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(277): error C2659: '=': function as left operand
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(278): error C2065: 'PFNGLCLEARPROC': undeclared identifier
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(278): error C2146: syntax error: missing ';' before identifier 'glClear'
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(278): error C2659: '=': function as left operand


and here is the modified code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <stdio.h>
#include <SDL.h>
#include  <SDL_opengles2.h> 
#define Assert(x) do {if (!(x)) __debugbreak(); } while (0)

int main(int argc, char* argv[])
{
   Assert(SDL_Init(SDL_INIT_VIDEO) == 0);

   SDL_SetHint(SDL_HINT_OPENGL_ES_DRIVER, "1");

   SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
   SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
   SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);

   SDL_Window* w = SDL_CreateWindow("ANGLE", 100, 100, 640, 480, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE);
   Assert(w);

   SDL_GLContext ctx = SDL_GL_CreateContext(w);
   Assert(ctx);
   
   Assert(SDL_GL_MakeCurrent(w, ctx) == 0);
   SDL_GL_SetSwapInterval(1);

   PFNGLGETSTRINGPROC glGetString = SDL_GL_GetProcAddress("glGetString");
   PFNGLCLEARCOLORPROC glClearColor = SDL_GL_GetProcAddress("glClearColor");
   PFNGLCLEARPROC glClear = SDL_GL_GetProcAddress("glClear");

   printf("GL_VERSION = %s\n",  glGetString(GL_VERSION));
   printf("GL_VENDOR = %s\n",  glGetString(GL_VENDOR));
   printf("GL_RENDERER = %s\n",  glGetString(GL_RENDERER));

   int running = 1;
   while (running)
   {
       SDL_Event ev;
       while (SDL_PollEvent(&ev))
       {
           if (ev.type == SDL_QUIT)
           {
               running = 0;
               break;
           }
       }

       glClearColor(1, 0, 0, 1);
       glClear(GL_COLOR_BUFFER_BIT);

       SDL_GL_SwapWindow(w);
   }

   SDL_GL_DeleteContext(ctx);
   SDL_Quit();

   return 0;
}

Edited by Shazan Shums on
1
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(259): error C2065: 'SDL_HINT_OPENGL_ES_DRIVER': undeclared identifier

This means that your SDL version is not new enough to support this hint. You probably want to update your SDL version. I'm not sure if SDL had a way to force ANGLE before this hint was introduced (I think the only way was to compile SDL without desktop GL, just with EGL+GLES support, but I may be remembering something wrong).

Rest of errors are because you are using SDL_opengles2.h header. It doesn't define OpenGL function pointer typedefs. You have two options - either define them yourself. Or don't query functions dynamically - just include ANGLE <GLES2/gl2.h> header and link directly to libGLESv2.lib library.

Edited by Mārtiņš Možeiko on
What SDL2 version you are you using because I am using SDL-2.0.5.
And how can I static link the libraries and where to get it.
And adding the headers still didn't help.

Heres the code,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <stdio.h>
#include <SDL2/SDL.h>
#include  <SDL2/SDL_opengles2.h>
#include <SDL2/SDL_hints.h>
#include <GLES2/gl2.h> 
#define Assert(x) do {if (!(x)) __debugbreak(); } while (0)

int main(int argc, char* argv[])
{
   Assert(SDL_Init(SDL_INIT_VIDEO) == 0);

   SDL_SetHint(SDL_HINT_OPENGL_ES_DRIVER, "1");

   SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
   SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
   SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);

   SDL_Window* w = SDL_CreateWindow("ANGLE", 100, 100, 640, 480, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE);
   Assert(w);

   SDL_GLContext ctx = SDL_GL_CreateContext(w);
   Assert(ctx);
   
   Assert(SDL_GL_MakeCurrent(w, ctx) == 0);
   SDL_GL_SetSwapInterval(1);

   PFNGLGETSTRINGPROC glGetString = SDL_GL_GetProcAddress("glGetString");
   PFNGLCLEARCOLORPROC glClearColor = SDL_GL_GetProcAddress("glClearColor");
   PFNGLCLEARPROC glClear = SDL_GL_GetProcAddress("glClear");

   printf("GL_VERSION = %s\n",  glGetString(GL_VERSION));
   printf("GL_VENDOR = %s\n",  glGetString(GL_VENDOR));
   printf("GL_RENDERER = %s\n",  glGetString(GL_RENDERER));

   int running = 1;
   while (running)
   {
       SDL_Event ev;
       while (SDL_PollEvent(&ev))
       {
           if (ev.type == SDL_QUIT)
           {
               running = 0;
               break;
           }
       }

       glClearColor(1, 0, 0, 1);
       glClear(GL_COLOR_BUFFER_BIT);

       SDL_GL_SwapWindow(w);
   }

   SDL_GL_DeleteContext(ctx);
   SDL_Quit();

   return 0;
}



the errors

e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(264): error C2065: 'SDL_HINT_OPENGL_ES_DRIVER': undeclared identifier
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(281): error C2065: 'PFNGLGETSTRINGPROC': undeclared identifier
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(281): error C2146: syntax error: missing ';' before identifier 'glGetString'
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(281): error C2659: '=': function as left operand
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(282): error C2065: 'PFNGLCLEARCOLORPROC': undeclared identifier
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(282): error C2146: syntax error: missing ';' before identifier 'glClearColor'
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(282): error C2659: '=': function as left operand
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(283): error C2065: 'PFNGLCLEARPROC': undeclared identifier
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(283): error C2146: syntax error: missing ';' before identifier 'glClear'
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(283): error C2659: '=': function as left operand

and the build file

@echo off
set CompilerFlags= /Z7 /FC /nologo /Od -fp:fast -Gm- -GR- -EHa- /Oi -WX -W4 -wd4189 -wd4505 -wd4100 -wd4127 -wd4201
set LinkerFlags=-subsystem:console

mkdir build > NUL 2> NUL
pushd build
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
del *.pdb > NUL 2> NUL
ctime -begin sdl_opengl.ctm
cl %CompilerFlags% /MTd ..\code\gamecode.cpp -Fmgamecode.map -LD /link -incremental:no -opt:ref -PDB:handmade_%RANDOM%.pdb -EXPORT:Gameupdateandrender -out:GameCode.dll
cl %CompilerFlags% /MD ..\code\sdllayer.cpp /I..\deps\include /link -incremental:no ..\deps\lib\x64\SDL2.lib ..\deps\lib\x64\SDL2main.lib opengl32.lib %LinkerFlags%
ctime -end sdl_opengl.ctm
popd


Plus the docs says this,

SDL has support for OpenGL ES 2.x under Windows via two alternative
implementations.
The most straightforward method consists in running your app in a system with
a graphic card paired with a relatively recent (as of November of 2013) driver
which supports the WGL_EXT_create_context_es2_profile extension. Vendors known
to ship said extension on Windows currently include nVidia and Intel.

The other method involves using the ANGLE library (https://code.google.com/p/angleproject/)
If an OpenGL ES 2.x context is requested and no WGL_EXT_create_context_es2_profile
extension is found, SDL will try to load the libEGL.dll library provided by
ANGLE.
To obtain the ANGLE binaries, you can either compile from source from
https://chromium.googlesource.com/angle/angle or copy the relevant binaries from
a recent Chrome/Chromium install for Windows. The files you need are:

* libEGL.dll
* libGLESv2.dll
* d3dcompiler_46.dll (supports Windows Vista or later, better shader compiler)
or...
* d3dcompiler_43.dll (supports Windows XP or later)

If you compile ANGLE from source, you can configure it so it does not need the
d3dcompiler_* DLL at all (for details on this, see their documentation).
However, by default SDL will try to preload the d3dcompiler_46.dll to
comply with ANGLE's requirements. If you wish SDL to preload d3dcompiler_43.dll (to
support Windows XP) or to skip this step at all, you can use the
SDL_HINT_VIDEO_WIN_D3DCOMPILER hint (see SDL_hints.h for more details).

Known Bugs:

* SDL_GL_SetSwapInterval is currently a no op when using ANGLE. It appears
that there's a bug in the library which prevents the window contents from
refreshing if this is set to anything other than the default value.


Edited by Shazan Shums on
I sort of fixed it but I get these errors now,

e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(280): error C2440: 'initializing': cannot convert from 'void *' to 'PFNGLGETSTRINGPROC'
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(280): note: Conversion from 'void*' to pointer to non-'void' requires an explicit cast
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(281): error C2440: 'initializing': cannot convert from 'void *' to 'PFNGLCLEARCOLORPROC'
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(281): note: Conversion from 'void*' to pointer to non-'void' requires an explicit cast
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(282): error C2440: 'initializing': cannot convert from 'void *' to 'PFNGLCLEARPROC'
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(282): note: Conversion from 'void*' to pointer to non-'void' requires an explicit cast
Finally it worked.....

But had to change this

1
SDL_SetHint(SDL_HINT_OPENGL_ES_DRIVER, "1");


to this
1
   SDL_SetHint(SDL_HINT_VIDEO_WIN_D3DCOMPILER, "1");


Anyways thanks for the guidance Mr.Martins your really helpful.

Edited by Shazan Shums on
msmshazan
What SDL2 version you are you using because I am using SDL-2.0.5.

I used latest commit from their mercurial repository.

And how can I static link the libraries and where to get it.
I didn't say link statically. I just said don't query GL functions dynamically. Link directly to libGLESv2.dll file by linking with libGLESv2.lib file. Then you can simply call any function in GLES2 spec.

e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(280): error C2440: 'initializing': cannot convert from 'void *' to 'PFNGLGETSTRINGPROC'
e:\shazan\programming\sdl_angle_project\code\sdllayer.cpp(280): note: Conversion from 'void*' to pointer to non-'void' requires an explicit cast
That's because you are compiling code as C++. I used C code (see the filename I used - test.c). C code can cast implicitly from void* pointer to any other pointer. In C++ you cannot do that and need explicit cast.

SDL_SetHint(SDL_HINT_VIDEO_WIN_D3DCOMPILER, "1");
Interesting. It might be that it first tries to use different version of d3dcompiler which you don't have it. And setting this hint makes it to use d3dcompiler version you actually have. This was not a problem for me, because I used ANGLE libraries that I compiled myself, so it was linking to d3dcompiler dll file that I have on my system.

Edited by Mārtiņš Možeiko on
Does all browsers use ANGLE because HTML spec api has angle functions.
Afaik WebGL spec only has extensions from ANGLE project. ANGLE is just one implementation used to provide WebGL in browsers. Implementing core part doesn't depend on any ANGLE specific. Most of extensions also don't. Some of them are actually available on your desktop GPUs/drivers. For example GL_ANGLE_texture_compression_dxt5.

Only because OpenGL supports AMD or NVIDIA GL extensions, it doesn't mean it will work only on AMD or NVIDIA. For example, GL_AMD_multi_draw_indirect. AMD extensions, but most Nvidia cards also support it.

Chrome and Firefox by default uses Angle for their WebGL implementation. On Chrome you can make it to use your native OpenGL if you want. To do so add "–use-gl=desktop" argument to chrome executable. For Firefox you can do that by setting "webgl.disable-angle" to false in about:config page. No idea about other browsers (IE/Edge/Safari/...).


Edited by Mārtiņš Možeiko on
Google Chrome has ".pak" type files does chrome use the quake file format or is it something else or it uses the physics library.