zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_egl.c
Go to the documentation of this file.
1 /*
2  * Simple DirectMedia Layer
3  * Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 #include "SDL_config.h"
22 
23 #if SDL_VIDEO_OPENGL_EGL
24 
25 #include "SDL_sysvideo.h"
26 #include "SDL_egl.h"
27 
28 #if SDL_VIDEO_DRIVER_RPI
29 #define DEFAULT_EGL "/opt/vc/lib/libEGL.so"
30 #define DEFAULT_OGL_ES2 "/opt/vc/lib/libGLESv2.so"
31 #define DEFAULT_OGL_ES_PVR "/opt/vc/lib/libGLES_CM.so"
32 #define DEFAULT_OGL_ES "/opt/vc/lib/libGLESv1_CM.so"
33 #else
34 #define DEFAULT_EGL "libEGL.so.1"
35 #define DEFAULT_OGL_ES2 "libGLESv2.so.2"
36 #define DEFAULT_OGL_ES_PVR "libGLES_CM.so.1"
37 #define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
38 #endif /* SDL_VIDEO_DRIVER_RPI */
39 
40 #define LOAD_FUNC(NAME) \
41 *((void**)&_this->egl_data->NAME) = dlsym(dll_handle, #NAME); \
42 if (!_this->egl_data->NAME) \
43 { \
44  return SDL_SetError("Could not retrieve EGL function " #NAME); \
45 }
46 
47 /* EGL implementation of SDL OpenGL ES support */
48 
49 void *
50 SDL_EGL_GetProcAddress(_THIS, const char *proc)
51 {
52  static char procname[1024];
53  void *handle;
54  void *retval;
55 
56  /* eglGetProcAddress is busted on Android http://code.google.com/p/android/issues/detail?id=7681 */
57 #if !defined(SDL_VIDEO_DRIVER_ANDROID)
58  handle = _this->egl_data->egl_dll_handle;
59  if (_this->egl_data->eglGetProcAddress) {
60  retval = _this->egl_data->eglGetProcAddress(proc);
61  if (retval) {
62  return retval;
63  }
64  }
65 #endif
66 
67  handle = _this->gl_config.dll_handle;
68  #if defined(__OpenBSD__) && !defined(__ELF__)
69  #undef dlsym(x,y);
70  #endif
71  retval = dlsym(handle, proc);
72  if (!retval && strlen(proc) <= 1022) {
73  procname[0] = '_';
74  strcpy(procname + 1, proc);
75  retval = dlsym(handle, procname);
76  }
77  return retval;
78 }
79 
80 void
81 SDL_EGL_UnloadLibrary(_THIS)
82 {
83  if ((_this->egl_data) && (_this->gl_config.driver_loaded)) {
84  _this->egl_data->eglTerminate(_this->egl_data->egl_display);
85 
86  dlclose(_this->gl_config.dll_handle);
87  dlclose(_this->egl_data->egl_dll_handle);
88 
89  SDL_free(_this->egl_data);
90  _this->egl_data = NULL;
91 
94  }
95 }
96 
97 int
98 SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display)
99 {
100  void *dll_handle, *egl_dll_handle; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */
101  char *path;
102  int dlopen_flags;
103 
104  if (_this->egl_data) {
105  return SDL_SetError("OpenGL ES context already created");
106  }
107 
108  /* Unload the old driver and reset the pointers */
109  SDL_EGL_UnloadLibrary(_this);
110 
111  #ifdef RTLD_GLOBAL
112  dlopen_flags = RTLD_LAZY | RTLD_GLOBAL;
113  #else
114  dlopen_flags = RTLD_LAZY;
115  #endif
116 
117  /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */
118  path = getenv("SDL_VIDEO_GL_DRIVER");
119  egl_dll_handle = dlopen(path, dlopen_flags);
120  if ((path == NULL) | (egl_dll_handle == NULL)) {
121  if (_this->gl_config.major_version > 1) {
122  path = DEFAULT_OGL_ES2;
123  egl_dll_handle = dlopen(path, dlopen_flags);
124  } else {
125  path = DEFAULT_OGL_ES;
126  egl_dll_handle = dlopen(path, dlopen_flags);
127  if (egl_dll_handle == NULL) {
128  path = DEFAULT_OGL_ES_PVR;
129  egl_dll_handle = dlopen(path, dlopen_flags);
130  }
131  }
132  }
133 
134  if (egl_dll_handle == NULL) {
135  return SDL_SetError("Could not initialize OpenGL ES library: %s", dlerror());
136  }
137 
138  /* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */
139  dll_handle = dlopen(egl_path, dlopen_flags);
140  /* Catch the case where the application isn't linked with EGL */
141  if ((dlsym(dll_handle, "eglChooseConfig") == NULL) && (egl_path == NULL)) {
142  dlclose(dll_handle);
143  path = getenv("SDL_VIDEO_EGL_DRIVER");
144  if (path == NULL) {
145  path = DEFAULT_EGL;
146  }
147  dll_handle = dlopen(path, dlopen_flags);
148  }
149 
150  if (dll_handle == NULL) {
151  return SDL_SetError("Could not load EGL library: %s", dlerror());
152  }
153 
154  _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
155  if (!_this->egl_data) {
156  return SDL_OutOfMemory();
157  }
158 
159  /* Load new function pointers */
175 
176  _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
177 
178  if (!_this->egl_data->egl_display) {
179  return SDL_SetError("Could not get EGL display");
180  }
181 
182  if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
183  return SDL_SetError("Could not initialize EGL");
184  }
185 
186  _this->gl_config.dll_handle = dll_handle;
187  _this->egl_data->egl_dll_handle = egl_dll_handle;
189 
190  if (path) {
191  strncpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
192  } else {
193  strcpy(_this->gl_config.driver_path, "");
194  }
195 
196  /* We need to select a config here to satisfy some video backends such as X11 */
197  SDL_EGL_ChooseConfig(_this);
198 
199  return 0;
200 }
201 
202 int
203 SDL_EGL_ChooseConfig(_THIS)
204 {
205  /* 64 seems nice. */
206  EGLint attribs[64];
207  EGLint found_configs = 0;
208  int i;
209 
210  if (!_this->egl_data) {
211  /* The EGL library wasn't loaded, SDL_GetError() should have info */
212  return -1;
213  }
214 
215  /* Get a valid EGL configuration */
216  i = 0;
217  attribs[i++] = EGL_RED_SIZE;
218  attribs[i++] = _this->gl_config.red_size;
219  attribs[i++] = EGL_GREEN_SIZE;
220  attribs[i++] = _this->gl_config.green_size;
221  attribs[i++] = EGL_BLUE_SIZE;
222  attribs[i++] = _this->gl_config.blue_size;
223 
224  if (_this->gl_config.alpha_size) {
225  attribs[i++] = EGL_ALPHA_SIZE;
226  attribs[i++] = _this->gl_config.alpha_size;
227  }
228 
229  if (_this->gl_config.buffer_size) {
230  attribs[i++] = EGL_BUFFER_SIZE;
231  attribs[i++] = _this->gl_config.buffer_size;
232  }
233 
234  attribs[i++] = EGL_DEPTH_SIZE;
235  attribs[i++] = _this->gl_config.depth_size;
236 
238  attribs[i++] = EGL_STENCIL_SIZE;
239  attribs[i++] = _this->gl_config.stencil_size;
240  }
241 
243  attribs[i++] = EGL_SAMPLE_BUFFERS;
244  attribs[i++] = _this->gl_config.multisamplebuffers;
245  }
246 
248  attribs[i++] = EGL_SAMPLES;
249  attribs[i++] = _this->gl_config.multisamplesamples;
250  }
251 
252  attribs[i++] = EGL_RENDERABLE_TYPE;
253  if (_this->gl_config.major_version == 2) {
254  attribs[i++] = EGL_OPENGL_ES2_BIT;
255  } else {
256  attribs[i++] = EGL_OPENGL_ES_BIT;
257  }
258 
259  attribs[i++] = EGL_NONE;
260 
261  if (_this->egl_data->eglChooseConfig(_this->egl_data->egl_display,
262  attribs,
263  &_this->egl_data->egl_config, 1,
264  &found_configs) == EGL_FALSE ||
265  found_configs == 0) {
266  return SDL_SetError("Couldn't find matching EGL config");
267  }
268 
269  return 0;
270 }
271 
273 SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
274 {
275  EGLint context_attrib_list[] = {
277  1,
278  EGL_NONE
279  };
280 
281  EGLContext egl_context;
282 
283  if (!_this->egl_data) {
284  /* The EGL library wasn't loaded, SDL_GetError() should have info */
285  return NULL;
286  }
287 
289  context_attrib_list[1] = _this->gl_config.major_version;
290  }
291 
292  egl_context =
293  _this->egl_data->eglCreateContext(_this->egl_data->egl_display,
294  _this->egl_data->egl_config,
295  EGL_NO_CONTEXT, context_attrib_list);
296 
297  if (egl_context == EGL_NO_CONTEXT) {
298  SDL_SetError("Could not create EGL context");
299  return NULL;
300  }
301 
302  _this->egl_data->egl_swapinterval = 0;
303 
304  if (SDL_EGL_MakeCurrent(_this, egl_surface, egl_context) < 0) {
305  SDL_EGL_DeleteContext(_this, egl_context);
306  SDL_SetError("Could not make EGL context current");
307  return NULL;
308  }
309 
310  return (SDL_GLContext) egl_context;
311 }
312 
313 int
314 SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context)
315 {
316  EGLContext egl_context = (EGLContext) context;
317 
318  if (!_this->egl_data) {
319  return SDL_SetError("OpenGL not initialized");
320  }
321 
322  /* The android emulator crashes badly if you try to eglMakeCurrent
323  * with a valid context and invalid surface, so we have to check for both here.
324  */
325  if (!egl_context || !egl_surface) {
326  _this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
327  }
328  else {
329  if (!_this->egl_data->eglMakeCurrent(_this->egl_data->egl_display,
330  egl_surface, egl_surface, egl_context)) {
331  return SDL_SetError("Unable to make EGL context current");
332  }
333  }
334 
335  return 0;
336 }
337 
338 int
339 SDL_EGL_SetSwapInterval(_THIS, int interval)
340 {
341  EGLBoolean status;
342 
343  if (!_this->egl_data) {
344  return SDL_SetError("EGL not initialized");
345  }
346 
347  status = _this->egl_data->eglSwapInterval(_this->egl_data->egl_display, interval);
348  if (status == EGL_TRUE) {
349  _this->egl_data->egl_swapinterval = interval;
350  return 0;
351  }
352 
353  return SDL_SetError("Unable to set the EGL swap interval");
354 }
355 
356 int
357 SDL_EGL_GetSwapInterval(_THIS)
358 {
359  if (!_this->egl_data) {
360  return SDL_SetError("EGL not initialized");
361  }
362 
363  return _this->egl_data->egl_swapinterval;
364 }
365 
366 void
367 SDL_EGL_SwapBuffers(_THIS, EGLSurface egl_surface)
368 {
369  _this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, egl_surface);
370 }
371 
372 void
373 SDL_EGL_DeleteContext(_THIS, SDL_GLContext context)
374 {
375  EGLContext egl_context = (EGLContext) context;
376 
377  /* Clean up GLES and EGL */
378  if (!_this->egl_data) {
379  return;
380  }
381 
382  if (!egl_context && egl_context != EGL_NO_CONTEXT) {
383  SDL_EGL_MakeCurrent(_this, NULL, NULL);
384  _this->egl_data->eglDestroyContext(_this->egl_data->egl_display, egl_context);
385  }
386 
387  /* FIXME: This "crappy fix" comes from the X11 code,
388  * it's required so you can create a GLX context, destroy it and create a EGL one */
389  SDL_EGL_UnloadLibrary(_this);
390 }
391 
392 EGLSurface *
393 SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
394 {
395  return _this->egl_data->eglCreateWindowSurface(
396  _this->egl_data->egl_display,
397  _this->egl_data->egl_config,
398  nw, NULL);
399 }
400 
401 void
402 SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface)
403 {
404  if (!_this->egl_data) {
405  return;
406  }
407 
408  if (egl_surface != EGL_NO_SURFACE) {
409  _this->egl_data->eglDestroySurface(_this->egl_data->egl_display, egl_surface);
410  }
411 }
412 
413 #endif /* SDL_VIDEO_OPENGL_EGL */
414 
415 /* vi: set ts=4 sw=4 expandtab: */
416 
EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy)
#define EGL_RED_SIZE
Definition: egl.h:100
DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size)
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
#define NULL
Definition: ftobjs.h:61
EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
#define EGL_NO_SURFACE
Definition: egl.h:71
#define EGL_SAMPLE_BUFFERS
Definition: egl.h:113
DECLSPEC void SDLCALL SDL_free(void *mem)
#define EGL_ALPHA_SIZE
Definition: egl.h:97
#define EGL_NONE
Definition: egl.h:119
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:161
khronos_int32_t EGLint
Definition: eglplatform.h:127
EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname)
EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
const GLint * attribs
Definition: glew.h:13064
GLsizei const GLchar *const * path
Definition: glew.h:5828
#define EGL_TRUE
Definition: egl.h:65
#define EGL_BLUE_SIZE
Definition: egl.h:98
void * EGLSurface
Definition: egl.h:49
unsigned int EGLBoolean
Definition: egl.h:44
EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
static SDL_VideoDevice * _this
Definition: SDL_video.c:92
EGLNativeWindowType NativeWindowType
Definition: eglplatform.h:117
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
void * EGLContext
Definition: egl.h:47
#define EGL_BUFFER_SIZE
Definition: egl.h:96
#define EGL_NO_CONTEXT
Definition: egl.h:69
#define EGL_OPENGL_ES_BIT
Definition: egl.h:155
#define EGL_CONTEXT_CLIENT_VERSION
Definition: egl.h:214
#define _THIS
char driver_path[256]
Definition: SDL_sysvideo.h:298
#define LOAD_FUNC(f)
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
#define EGL_DEPTH_SIZE
Definition: egl.h:101
#define EGL_FALSE
Definition: egl.h:64
#define EGL_SAMPLES
Definition: egl.h:112
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id)
EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void)
#define EGL_GREEN_SIZE
Definition: egl.h:99
EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval)
#define EGL_STENCIL_SIZE
Definition: egl.h:102
EGLNativeDisplayType NativeDisplayType
Definition: eglplatform.h:115
EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine)
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:284
TParseContext * context
int i
Definition: pngrutil.c:1377
EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
struct SDL_VideoDevice::@87 gl_config
#define EGL_RENDERABLE_TYPE
Definition: egl.h:127
#define EGL_OPENGL_ES2_BIT
Definition: egl.h:157
EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)