~ubuntu-branches/ubuntu/vivid/libsdl2/vivid

« back to all changes in this revision

Viewing changes to src/video/SDL_egl.c

  • Committer: Package Import Robot
  • Author(s): Manuel A. Fernandez Montecelo, Felix Geyer
  • Date: 2013-12-28 12:31:19 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20131228123119-e0k27gckmnzskfgb
Tags: 2.0.1+dfsg1-1
* New upstream release (Closes: #728974)
  - Remove patch applied upstream:
    bug-723797-false_positives_in_mouse_wheel_code.patch
* Bump Standards-Version to 3.9.5, no changes needed.

[ Felix Geyer ]
* Import upstream gpg key for uscan to verify the orig tarball.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
29
#if SDL_VIDEO_DRIVER_RPI
 
30
/* Raspbian places the OpenGL ES/EGL binaries in a non standard path */
 
31
#define DEFAULT_EGL "/opt/vc/lib/libEGL.so"
 
32
#define DEFAULT_OGL_ES2 "/opt/vc/lib/libGLESv2.so"
 
33
#define DEFAULT_OGL_ES_PVR "/opt/vc/lib/libGLES_CM.so"
 
34
#define DEFAULT_OGL_ES "/opt/vc/lib/libGLESv1_CM.so"
 
35
 
 
36
#elif SDL_VIDEO_DRIVER_ANDROID
 
37
/* Android */
 
38
#define DEFAULT_EGL "libEGL.so"
 
39
#define DEFAULT_OGL_ES2 "libGLESv2.so"
 
40
#define DEFAULT_OGL_ES_PVR "libGLES_CM.so"
 
41
#define DEFAULT_OGL_ES "libGLESv1_CM.so"
 
42
 
 
43
#else
 
44
/* Desktop Linux */
 
45
#define DEFAULT_EGL "libEGL.so.1"
 
46
#define DEFAULT_OGL_ES2 "libGLESv2.so.2"
 
47
#define DEFAULT_OGL_ES_PVR "libGLES_CM.so.1"
 
48
#define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
 
49
#endif /* SDL_VIDEO_DRIVER_RPI */
 
50
 
 
51
#define LOAD_FUNC(NAME) \
 
52
*((void**)&_this->egl_data->NAME) = dlsym(dll_handle, #NAME); \
 
53
if (!_this->egl_data->NAME) \
 
54
{ \
 
55
    return SDL_SetError("Could not retrieve EGL function " #NAME); \
 
56
}
 
57
    
 
58
/* EGL implementation of SDL OpenGL ES support */
 
59
 
 
60
void *
 
61
SDL_EGL_GetProcAddress(_THIS, const char *proc)
 
62
{
 
63
    static char procname[1024];
 
64
    void *handle;
 
65
    void *retval;
 
66
    
 
67
    /* eglGetProcAddress is busted on Android http://code.google.com/p/android/issues/detail?id=7681 */
 
68
#if !defined(SDL_VIDEO_DRIVER_ANDROID)
 
69
    handle = _this->egl_data->egl_dll_handle;
 
70
    if (_this->egl_data->eglGetProcAddress) {
 
71
        retval = _this->egl_data->eglGetProcAddress(proc);
 
72
        if (retval) {
 
73
            return retval;
 
74
        }
 
75
    }
 
76
#endif
 
77
    
 
78
    handle = _this->gl_config.dll_handle;
 
79
    #if defined(__OpenBSD__) && !defined(__ELF__)
 
80
    #undef dlsym(x,y);
 
81
    #endif
 
82
    retval = dlsym(handle, proc);
 
83
    if (!retval && strlen(proc) <= 1022) {
 
84
        procname[0] = '_';
 
85
        strcpy(procname + 1, proc);
 
86
        retval = dlsym(handle, procname);
 
87
    }
 
88
    return retval;
 
89
}
 
90
 
 
91
void
 
92
SDL_EGL_UnloadLibrary(_THIS)
 
93
{
 
94
    if (_this->egl_data) {
 
95
        if (_this->egl_data->egl_display) {
 
96
            _this->egl_data->eglTerminate(_this->egl_data->egl_display);
 
97
            _this->egl_data->egl_display = NULL;
 
98
        }
 
99
 
 
100
        if (_this->gl_config.dll_handle) {
 
101
            dlclose(_this->gl_config.dll_handle);
 
102
            _this->gl_config.dll_handle = NULL;
 
103
        }
 
104
        if (_this->egl_data->egl_dll_handle) {
 
105
            dlclose(_this->egl_data->egl_dll_handle);
 
106
            _this->egl_data->egl_dll_handle = NULL;
 
107
        }
 
108
        
 
109
        SDL_free(_this->egl_data);
 
110
        _this->egl_data = NULL;
 
111
    }
 
112
}
 
113
 
 
114
int
 
115
SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display)
 
116
{
 
117
    void *dll_handle, *egl_dll_handle; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */
 
118
    char *path;
 
119
    int dlopen_flags;
 
120
    
 
121
    if (_this->egl_data) {
 
122
        return SDL_SetError("OpenGL ES context already created");
 
123
    }
 
124
 
 
125
    _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
 
126
    if (!_this->egl_data) {
 
127
        return SDL_OutOfMemory();
 
128
    }
 
129
 
 
130
#ifdef RTLD_GLOBAL
 
131
    dlopen_flags = RTLD_LAZY | RTLD_GLOBAL;
 
132
#else
 
133
    dlopen_flags = RTLD_LAZY;
 
134
#endif
 
135
 
 
136
    /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */
 
137
    path = getenv("SDL_VIDEO_GL_DRIVER");
 
138
    egl_dll_handle = dlopen(path, dlopen_flags);
 
139
    if ((path == NULL) | (egl_dll_handle == NULL)) {
 
140
        if (_this->gl_config.major_version > 1) {
 
141
            path = DEFAULT_OGL_ES2;
 
142
            egl_dll_handle = dlopen(path, dlopen_flags);
 
143
        } else {
 
144
            path = DEFAULT_OGL_ES;
 
145
            egl_dll_handle = dlopen(path, dlopen_flags);
 
146
            if (egl_dll_handle == NULL) {
 
147
                path = DEFAULT_OGL_ES_PVR;
 
148
                egl_dll_handle = dlopen(path, dlopen_flags);
 
149
            }
 
150
        }
 
151
    }
 
152
    _this->egl_data->egl_dll_handle = egl_dll_handle;
 
153
 
 
154
    if (egl_dll_handle == NULL) {
 
155
        return SDL_SetError("Could not initialize OpenGL ES library: %s", dlerror());
 
156
    }
 
157
    
 
158
    /* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */
 
159
    dll_handle = dlopen(egl_path, dlopen_flags);
 
160
    /* Catch the case where the application isn't linked with EGL */
 
161
    if ((dlsym(dll_handle, "eglChooseConfig") == NULL) && (egl_path == NULL)) {
 
162
        dlclose(dll_handle);
 
163
        path = getenv("SDL_VIDEO_EGL_DRIVER");
 
164
        if (path == NULL) {
 
165
            path = DEFAULT_EGL;
 
166
        }
 
167
        dll_handle = dlopen(path, dlopen_flags);
 
168
    }
 
169
    _this->gl_config.dll_handle = dll_handle;
 
170
 
 
171
    if (dll_handle == NULL) {
 
172
        return SDL_SetError("Could not load EGL library: %s", dlerror());
 
173
    }
 
174
 
 
175
    /* Load new function pointers */
 
176
    LOAD_FUNC(eglGetDisplay);
 
177
    LOAD_FUNC(eglInitialize);
 
178
    LOAD_FUNC(eglTerminate);
 
179
    LOAD_FUNC(eglGetProcAddress);
 
180
    LOAD_FUNC(eglChooseConfig);
 
181
    LOAD_FUNC(eglGetConfigAttrib);
 
182
    LOAD_FUNC(eglCreateContext);
 
183
    LOAD_FUNC(eglDestroyContext);
 
184
    LOAD_FUNC(eglCreateWindowSurface);
 
185
    LOAD_FUNC(eglDestroySurface);
 
186
    LOAD_FUNC(eglMakeCurrent);
 
187
    LOAD_FUNC(eglSwapBuffers);
 
188
    LOAD_FUNC(eglSwapInterval);
 
189
    LOAD_FUNC(eglWaitNative);
 
190
    LOAD_FUNC(eglWaitGL);
 
191
    
 
192
    _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
 
193
    if (!_this->egl_data->egl_display) {
 
194
        return SDL_SetError("Could not get EGL display");
 
195
    }
 
196
    
 
197
    if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
 
198
        return SDL_SetError("Could not initialize EGL");
 
199
    }
 
200
 
 
201
    _this->gl_config.dll_handle = dll_handle;
 
202
    _this->egl_data->egl_dll_handle = egl_dll_handle;
 
203
    _this->gl_config.driver_loaded = 1;
 
204
 
 
205
    if (path) {
 
206
        strncpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
 
207
    } else {
 
208
        strcpy(_this->gl_config.driver_path, "");
 
209
    }
 
210
    
 
211
    /* We need to select a config here to satisfy some video backends such as X11 */
 
212
    SDL_EGL_ChooseConfig(_this);
 
213
    
 
214
    return 0;
 
215
}
 
216
 
 
217
int
 
218
SDL_EGL_ChooseConfig(_THIS) 
 
219
{
 
220
    /* 64 seems nice. */
 
221
    EGLint attribs[64];
 
222
    EGLint found_configs = 0;
 
223
    int i;
 
224
    
 
225
    if (!_this->egl_data) {
 
226
        /* The EGL library wasn't loaded, SDL_GetError() should have info */
 
227
        return -1;
 
228
    }
 
229
  
 
230
    /* Get a valid EGL configuration */
 
231
    i = 0;
 
232
    attribs[i++] = EGL_RED_SIZE;
 
233
    attribs[i++] = _this->gl_config.red_size;
 
234
    attribs[i++] = EGL_GREEN_SIZE;
 
235
    attribs[i++] = _this->gl_config.green_size;
 
236
    attribs[i++] = EGL_BLUE_SIZE;
 
237
    attribs[i++] = _this->gl_config.blue_size;
 
238
    
 
239
    if (_this->gl_config.alpha_size) {
 
240
        attribs[i++] = EGL_ALPHA_SIZE;
 
241
        attribs[i++] = _this->gl_config.alpha_size;
 
242
    }
 
243
    
 
244
    if (_this->gl_config.buffer_size) {
 
245
        attribs[i++] = EGL_BUFFER_SIZE;
 
246
        attribs[i++] = _this->gl_config.buffer_size;
 
247
    }
 
248
    
 
249
    attribs[i++] = EGL_DEPTH_SIZE;
 
250
    attribs[i++] = _this->gl_config.depth_size;
 
251
    
 
252
    if (_this->gl_config.stencil_size) {
 
253
        attribs[i++] = EGL_STENCIL_SIZE;
 
254
        attribs[i++] = _this->gl_config.stencil_size;
 
255
    }
 
256
    
 
257
    if (_this->gl_config.multisamplebuffers) {
 
258
        attribs[i++] = EGL_SAMPLE_BUFFERS;
 
259
        attribs[i++] = _this->gl_config.multisamplebuffers;
 
260
    }
 
261
    
 
262
    if (_this->gl_config.multisamplesamples) {
 
263
        attribs[i++] = EGL_SAMPLES;
 
264
        attribs[i++] = _this->gl_config.multisamplesamples;
 
265
    }
 
266
    
 
267
    attribs[i++] = EGL_RENDERABLE_TYPE;
 
268
    if (_this->gl_config.major_version == 2) {
 
269
        attribs[i++] = EGL_OPENGL_ES2_BIT;
 
270
    } else {
 
271
        attribs[i++] = EGL_OPENGL_ES_BIT;
 
272
    }
 
273
    
 
274
    attribs[i++] = EGL_NONE;
 
275
    
 
276
    if (_this->egl_data->eglChooseConfig(_this->egl_data->egl_display,
 
277
        attribs,
 
278
        &_this->egl_data->egl_config, 1,
 
279
        &found_configs) == EGL_FALSE ||
 
280
        found_configs == 0) {
 
281
        return SDL_SetError("Couldn't find matching EGL config");
 
282
    }
 
283
    
 
284
    return 0;
 
285
}
 
286
 
 
287
SDL_GLContext
 
288
SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
 
289
{
 
290
    EGLint context_attrib_list[] = {
 
291
        EGL_CONTEXT_CLIENT_VERSION,
 
292
        1,
 
293
        EGL_NONE
 
294
    };
 
295
    
 
296
    EGLContext egl_context;
 
297
    
 
298
    if (!_this->egl_data) {
 
299
        /* The EGL library wasn't loaded, SDL_GetError() should have info */
 
300
        return NULL;
 
301
    }
 
302
    
 
303
    if (_this->gl_config.major_version) {
 
304
        context_attrib_list[1] = _this->gl_config.major_version;
 
305
    }
 
306
 
 
307
    egl_context =
 
308
    _this->egl_data->eglCreateContext(_this->egl_data->egl_display,
 
309
                                      _this->egl_data->egl_config,
 
310
                                      EGL_NO_CONTEXT, context_attrib_list);
 
311
    
 
312
    if (egl_context == EGL_NO_CONTEXT) {
 
313
        SDL_SetError("Could not create EGL context");
 
314
        return NULL;
 
315
    }
 
316
    
 
317
    _this->egl_data->egl_swapinterval = 0;
 
318
    
 
319
    if (SDL_EGL_MakeCurrent(_this, egl_surface, egl_context) < 0) {
 
320
        SDL_EGL_DeleteContext(_this, egl_context);
 
321
        SDL_SetError("Could not make EGL context current");
 
322
        return NULL;
 
323
    }
 
324
  
 
325
    return (SDL_GLContext) egl_context;
 
326
}
 
327
 
 
328
int
 
329
SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context)
 
330
{
 
331
    EGLContext egl_context = (EGLContext) context;
 
332
 
 
333
    if (!_this->egl_data) {
 
334
        return SDL_SetError("OpenGL not initialized");
 
335
    }
 
336
    
 
337
    /* The android emulator crashes badly if you try to eglMakeCurrent 
 
338
     * with a valid context and invalid surface, so we have to check for both here.
 
339
     */
 
340
    if (!egl_context || !egl_surface) {
 
341
         _this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 
342
    }
 
343
    else {
 
344
        if (!_this->egl_data->eglMakeCurrent(_this->egl_data->egl_display,
 
345
            egl_surface, egl_surface, egl_context)) {
 
346
            return SDL_SetError("Unable to make EGL context current");
 
347
        }
 
348
    }
 
349
      
 
350
    return 0;
 
351
}
 
352
 
 
353
int
 
354
SDL_EGL_SetSwapInterval(_THIS, int interval)
 
355
{
 
356
    EGLBoolean status;
 
357
    
 
358
    if (!_this->egl_data) {
 
359
        return SDL_SetError("EGL not initialized");
 
360
    }
 
361
    
 
362
    status = _this->egl_data->eglSwapInterval(_this->egl_data->egl_display, interval);
 
363
    if (status == EGL_TRUE) {
 
364
        _this->egl_data->egl_swapinterval = interval;
 
365
        return 0;
 
366
    }
 
367
    
 
368
    return SDL_SetError("Unable to set the EGL swap interval");
 
369
}
 
370
 
 
371
int
 
372
SDL_EGL_GetSwapInterval(_THIS)
 
373
{
 
374
    if (!_this->egl_data) {
 
375
        return SDL_SetError("EGL not initialized");
 
376
    }
 
377
    
 
378
    return _this->egl_data->egl_swapinterval;
 
379
}
 
380
 
 
381
void
 
382
SDL_EGL_SwapBuffers(_THIS, EGLSurface egl_surface)
 
383
{
 
384
    _this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, egl_surface);
 
385
}
 
386
 
 
387
void
 
388
SDL_EGL_DeleteContext(_THIS, SDL_GLContext context)
 
389
{
 
390
    EGLContext egl_context = (EGLContext) context;
 
391
 
 
392
    /* Clean up GLES and EGL */
 
393
    if (!_this->egl_data) {
 
394
        return;
 
395
    }
 
396
    
 
397
    if (!egl_context && egl_context != EGL_NO_CONTEXT) {
 
398
        SDL_EGL_MakeCurrent(_this, NULL, NULL);
 
399
        _this->egl_data->eglDestroyContext(_this->egl_data->egl_display, egl_context);
 
400
    }
 
401
        
 
402
    /* FIXME: This "crappy fix" comes from the X11 code, 
 
403
     * it's required so you can create a GLX context, destroy it and create a EGL one */
 
404
    SDL_EGL_UnloadLibrary(_this);
 
405
}
 
406
 
 
407
EGLSurface *
 
408
SDL_EGL_CreateSurface(_THIS, NativeWindowType nw) 
 
409
{
 
410
    return _this->egl_data->eglCreateWindowSurface(
 
411
            _this->egl_data->egl_display,
 
412
            _this->egl_data->egl_config,
 
413
            nw, NULL);
 
414
}
 
415
 
 
416
void
 
417
SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface) 
 
418
{
 
419
    if (!_this->egl_data) {
 
420
        return;
 
421
    }
 
422
    
 
423
    if (egl_surface != EGL_NO_SURFACE) {
 
424
        _this->egl_data->eglDestroySurface(_this->egl_data->egl_display, egl_surface);
 
425
    }
 
426
}
 
427
 
 
428
#endif /* SDL_VIDEO_OPENGL_EGL */
 
429
 
 
430
/* vi: set ts=4 sw=4 expandtab: */
 
431