OpenGL ES calls across multiple threads

I am developing a graphics framework and I would like to have a separate thread for my 3D rendering.
I would like to render my 2D stuff from the application’s main thread (or something like UI thread) and all 3D from a separate thread.

I am using opengl es textures for rendering the 2D surface after it is created. So this makes me to use OpenGL ES calls from 2 threads. I am creating separate contexts from both threads and making the context current in their corresponding thread. When eglmakecurrent() is called for the first time from thread 1 it succeeds. When eglmakecurrent() is called again from thread 2 it fails. Any suggestions?

I am using the same surface created from eglCreateWindowSurface() on both the threads.
Is there any other way to mix the 3D and 2D is this environment?

The OS used is Linux.


You can’t have the same surface bound to two contexts at the same time. It would cause lots of issues.

Why exactly do you want to use two threads for the rendering?

The only time that comes to mind of when you might have more then one thread render at the same time, would be to different surfaces. Usually with the intention of doing some sort of composition of surfaces before outputing to the framebuffer.

You could have multiple threads rendering to the same surface, just not at the same time. So some sort of synchronization mechanisms (e.g. mutex) would need to be used, and the resources freed prior to another threads acquiring the resources.

Note that EGL does not require implementations to support binding a GLES context to more than one thread at a time.

So to summarize:
Binding the same context in 2 threads is NEVER allowed.
Binding 2 different contexts in 2 different threads to the same surface is NEVER allowed.
Binding 2 different contexts in 2 different threads to 2 different surfaces MAY be allowed, but MAY fail (depending on the implementation you are using).

So if you want your app to be portable, you should avoid binding 2 GLES contexts at the same time.


If it works like OpenGL not ES, what you need to do is call eglMakeCurrent(No Context, no surface) in the thread that is currently using the context and surface, so they are freed from the thread, and made available for use in another thread.

then call eglMakeCurrent(Context, suface) on the thread where you want to start rendering and do your rendering.

Then you will have to call eglMakeCurrent(No Context, no surface) in that other thread to free your resources again so we will once again be able to make it current in any another thread.

so you do

Thread A:
eglMakeCurrent(context, surface);
eglMakeCurrent(NULL, NULL);

Thread B:
eglMakeCurrent(context, surface);
eglMakeCurrent(NULL, NULL);

And you have to implement a synch mechanism to make sure you are not making the same context and/or surface as the current on 2 threads at the same time.


I have similar question but with a little difference.What would happen if i try to do the same thing across two separate processes.

Let’s say i am working in a linux environment where each app is running as a separate process.In both the app, i am using exactly same code to create a EGL context with the same EGL config value & then creating an EGLwindowsurface & then making that EGl context current to the EGL surface. E.g.

Eglinit() //My own function
} And my App1 & App2 both calls this EglInit(); So, when both App1 & App2 will be running simultaneously, what would happen.

I would like to bring to your notice a quote from EGL Spec v1.4 which says “If there is already an EGLConfig associated with win (as a result of a previous eglCreateWindow-Surface call), then an EGL BAD ALLOC error is generated. Finally, if the imple- mentation cannot allocate resources for the new EGL window, an EGL BAD ALLOC error is generated.”

So, this means if i have already created a EGLwindowsurface in the same app, then i can’t create it again.AM i correct? What is the way around here? Call eglDestroySurface(prev_surface) and then call eglCreateWindowSurface again? but i remember, once this approach did not help me, it still gave me EGL_BAD_ALLOC error. Any idea on this?


In a windowed environment this may or may not work, depending on whether the implementation supports multiple simultaneous rendering contexts. In a fullscreen environment the second app will always fail to create a window surface.