1 /* This file is part of SDL_gles - SDL addon for OpenGL|ES
2 * Copyright (C) 2010 Javier S. Pedro
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 3 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA or see <http://www.gnu.org/licenses/>.
29 #include <SDL_syswm.h>
33 typedef struct SDL_GLES_ContextPriv
38 EGLContext egl_context;
39 } SDL_GLES_ContextPriv;
41 static const char * default_libgl[] = {
42 [SDL_GLES_VERSION_1_1] = "/usr/lib/libGLES_CM.so",
43 [SDL_GLES_VERSION_2_0] = "/usr/lib/libGLESv2.so"
46 static SDL_GLES_Version gl_version = SDL_GLES_VERSION_NONE;
47 static void* gl_handle = NULL;
48 static EGLint egl_major, egl_minor;
50 static Display *display = NULL;
51 static EGLDisplay *egl_display = EGL_NO_DISPLAY;
52 static EGLSurface egl_surface = EGL_NO_SURFACE;
53 static EGLint attrib_list[] = {
59 EGL_CONFIG_CAVEAT, EGL_DONT_CARE,
60 EGL_CONFIG_ID, EGL_DONT_CARE,
63 EGL_NATIVE_RENDERABLE, EGL_DONT_CARE,
64 EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE,
65 EGL_SAMPLE_BUFFERS, 0,
68 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
69 EGL_TRANSPARENT_TYPE, EGL_NONE,
70 EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE,
71 EGL_TRANSPARENT_GREEN_VALUE,EGL_DONT_CARE,
72 EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE,
75 static SDL_GLES_ContextPriv *cur_context = NULL;
77 static const char * get_error_string(int error) {
81 case EGL_NOT_INITIALIZED:
82 return "EGL_NOT_INITIALIZED";
84 return "EGL_BAD_ACCESS";
86 return "EGL_BAD_ALLOC";
87 case EGL_BAD_ATTRIBUTE:
88 return "EGL_BAD_ATTRIBUTE";
90 return "EGL_BAD_CONFIG";
92 return "EGL_BAD_CONTEXT";
93 case EGL_BAD_CURRENT_SURFACE:
94 return "EGL_BAD_CURRENT_SURFACE";
96 return "EGL_BAD_DISPLAY";
98 return "EGL_BAD_MATCH";
99 case EGL_BAD_NATIVE_PIXMAP:
100 return "EGL_BAD_NATIVE_PIXMAP";
101 case EGL_BAD_NATIVE_WINDOW:
102 return "EGL_BAD_NATIVE_WINDOW";
103 case EGL_BAD_PARAMETER:
104 return "EGL_BAD_PARAMETER";
105 case EGL_BAD_SURFACE:
106 return "EGL_BAD_SURFACE";
107 case EGL_CONTEXT_LOST:
108 return "EGL_CONTEXT_LOST";
110 return "EGL_UNKNOWN_ERROR";
114 int SDL_GLES_LoadLibrary(const char *path)
117 path = getenv("SDL_VIDEO_GL_DRIVER");
119 switch (gl_version) {
120 case SDL_GLES_VERSION_1_1:
121 case SDL_GLES_VERSION_2_0:
122 path = default_libgl[gl_version];
125 SDL_SetError("No GL version specific and SDL_VIDEO_GL_DRIVER set");
131 /* Dynamically load the desired GL library */
132 gl_handle = dlopen(path, RTLD_LAZY|RTLD_GLOBAL);
134 SDL_SetError("Failed to open GL library: %s (%s)", path, dlerror());
141 void* SDL_GLES_GetProcAddress(const char *proc)
143 if (!gl_handle) return NULL;
144 return dlsym(gl_handle, proc);
147 int SDL_GLES_Init(SDL_GLES_Version version)
152 SDL_VERSION(&info.version);
153 if (SDL_GetWMInfo(&info) != 1) {
154 SDL_SetError("SDL_gles is incompatible with this SDL version");
158 display = info.info.x11.gfxdisplay;
160 egl_display = eglGetDisplay((EGLNativeDisplayType)display);
161 if (egl_display == EGL_NO_DISPLAY) {
162 SDL_SetError("EGL found no available displays");
166 res = eglInitialize(egl_display, &egl_major, &egl_minor);
168 SDL_SetError("EGL failed to initialize: %s",
169 get_error_string(eglGetError()));
173 gl_version = version;
183 if (egl_display != EGL_NO_DISPLAY) {
184 eglTerminate(egl_display);
185 egl_display = EGL_NO_DISPLAY;
189 int SDL_GLES_SetVideoMode()
193 SDL_VERSION(&info.version);
194 if (SDL_GetWMInfo(&info) != 1) {
195 SDL_SetError("SDL_gles is incompatible with this SDL version");
199 /* Destroy previous surface, if any. */
200 if (egl_surface != EGL_NO_SURFACE) {
201 eglDestroySurface(egl_display, egl_surface);
202 egl_surface = EGL_NO_SURFACE;
205 /* No current context? Quietly defer surface creation. */
210 egl_surface = eglCreateWindowSurface(egl_display, cur_context->egl_config,
211 (EGLNativeWindowType)info.info.x11.window, NULL);
212 if (egl_surface == EGL_NO_SURFACE) {
213 SDL_SetError("EGL failed to create a window surface: %s",
214 get_error_string(eglGetError()));
221 SDL_GLES_Context* SDL_GLES_CreateContext(void)
223 SDL_GLES_ContextPriv *context = malloc(sizeof(SDL_GLES_ContextPriv));
225 SDL_Error(SDL_ENOMEM);
230 EGLConfig configs[1];
233 res = eglChooseConfig(egl_display, attrib_list, configs, 1, &num_config);
234 if (!res || num_config < 1) {
235 SDL_SetError("EGL failed to find any valid config with required attributes: %s",
236 get_error_string(eglGetError()));
240 context->egl_config = configs[0];
241 context->egl_context = eglCreateContext(egl_display, configs[0],
242 EGL_NO_CONTEXT, NULL);
244 return (SDL_GLES_Context*) context;
247 void SDL_GLES_DeleteContext(SDL_GLES_Context* c)
249 SDL_GLES_ContextPriv *context = (SDL_GLES_ContextPriv*)c;
250 if (!context) return;
252 if (cur_context == context) {
253 /* Deleting the active context */
254 SDL_GLES_MakeCurrent(NULL);
257 eglDestroyContext(egl_display, context->egl_context);
261 int SDL_GLES_MakeCurrent(SDL_GLES_Context* c)
263 SDL_GLES_ContextPriv *context = (SDL_GLES_ContextPriv*)c;
267 cur_context = context;
269 res = SDL_GLES_SetVideoMode();
270 if (res != 0) return res; /* Surface (re-)creation failed. */
272 res = eglMakeCurrent(egl_display, egl_surface, egl_surface,
273 context->egl_context);
276 SDL_SetError("EGL failed to make current: %s",
277 get_error_string(eglGetError()));
282 eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
285 SDL_GLES_SetVideoMode(); /* Will clear current surface. */
288 // TODO Update attrib_list
290 switch (gl_version) {
291 case SDL_GLES_VERSION_1_1:
292 case SDL_GLES_VERSION_2_0:
293 res = eglBindAPI(EGL_OPENGL_ES_API);
295 SDL_SetError("EGL failed to bind the required API: %s",
296 get_error_string(eglGetError()));
307 void SDL_GLES_SwapBuffers()
309 eglSwapBuffers(egl_display, egl_surface);