src/video/SDL_egl.c
author Tomeu Vizoso <tomeu.vizoso@collabora.com>
Thu, 14 Jun 2018 06:12:12 +0000
changeset 12028 8aa5a79c8805
parent 11983 3a50eb90e4b2
child 12201 8bdc4d340419
permissions -rw-r--r--
egl: Don't change context when deleting current.

If we change the current context behind the app's back, those tracking
the current context to minimize context changes are going to get
confused.

This brings the EGL backend in line with the GLX one.

Fixes Bugzilla #4199.
gabomdq@7659
     1
/*
gabomdq@7659
     2
 *  Simple DirectMedia Layer
slouken@11811
     3
 *  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
gabomdq@7659
     4
 * 
gabomdq@7659
     5
 *  This software is provided 'as-is', without any express or implied
gabomdq@7659
     6
 *  warranty.  In no event will the authors be held liable for any damages
gabomdq@7659
     7
 *  arising from the use of this software.
gabomdq@7659
     8
 * 
gabomdq@7659
     9
 *  Permission is granted to anyone to use this software for any purpose,
gabomdq@7659
    10
 *  including commercial applications, and to alter it and redistribute it
gabomdq@7659
    11
 *  freely, subject to the following restrictions:
gabomdq@7659
    12
 * 
gabomdq@7659
    13
 *  1. The origin of this software must not be misrepresented; you must not
gabomdq@7659
    14
 *     claim that you wrote the original software. If you use this software
gabomdq@7659
    15
 *     in a product, an acknowledgment in the product documentation would be
gabomdq@7659
    16
 *     appreciated but is not required.
gabomdq@7659
    17
 *  2. Altered source versions must be plainly marked as such, and must not be
gabomdq@7659
    18
 *     misrepresented as being the original software.
gabomdq@7659
    19
 *  3. This notice may not be removed or altered from any source distribution.
gabomdq@7659
    20
 */
icculus@8093
    21
#include "../SDL_internal.h"
gabomdq@7659
    22
gabomdq@7659
    23
#if SDL_VIDEO_OPENGL_EGL
gabomdq@7659
    24
slouken@8734
    25
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
slouken@8734
    26
#include "../core/windows/SDL_windows.h"
slouken@8734
    27
#endif
slouken@10878
    28
#if SDL_VIDEO_DRIVER_ANDROID
slouken@10878
    29
#include <android/native_window.h>
slouken@10878
    30
#endif
slouken@8734
    31
gabomdq@7659
    32
#include "SDL_sysvideo.h"
slouken@11175
    33
#include "SDL_log.h"
gabomdq@8021
    34
#include "SDL_egl_c.h"
gabomdq@8021
    35
#include "SDL_loadso.h"
gabomdq@8021
    36
#include "SDL_hints.h"
gabomdq@7782
    37
slime73@9595
    38
#ifdef EGL_KHR_create_context
slime73@9595
    39
/* EGL_OPENGL_ES3_BIT_KHR was added in version 13 of the extension. */
slime73@9595
    40
#ifndef EGL_OPENGL_ES3_BIT_KHR
slime73@9595
    41
#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
slime73@9595
    42
#endif
slime73@9595
    43
#endif /* EGL_KHR_create_context */
slime73@9595
    44
gabomdq@7753
    45
#if SDL_VIDEO_DRIVER_RPI
gabomdq@7782
    46
/* Raspbian places the OpenGL ES/EGL binaries in a non standard path */
g@11829
    47
#define DEFAULT_EGL ( vc4 ? "libEGL.so.1" : "libbrcmEGL.so" )
g@11829
    48
#define DEFAULT_OGL_ES2 ( vc4 ? "libGLESv2.so.2" : "libbrcmGLESv2.so" )
g@11829
    49
#define ALT_EGL "libEGL.so"
g@11829
    50
#define ALT_OGL_ES2 "libGLESv2.so"
g@11829
    51
#define DEFAULT_OGL_ES_PVR ( vc4 ? "libGLES_CM.so.1" : "libbrcmGLESv2.so" )
g@11829
    52
#define DEFAULT_OGL_ES ( vc4 ? "libGLESv1_CM.so.1" : "libbrcmGLESv2.so" )
gabomdq@7782
    53
slouken@9164
    54
#elif SDL_VIDEO_DRIVER_ANDROID || SDL_VIDEO_DRIVER_VIVANTE
gabomdq@7782
    55
/* Android */
gabomdq@7782
    56
#define DEFAULT_EGL "libEGL.so"
gabomdq@7782
    57
#define DEFAULT_OGL_ES2 "libGLESv2.so"
gabomdq@7782
    58
#define DEFAULT_OGL_ES_PVR "libGLES_CM.so"
gabomdq@7782
    59
#define DEFAULT_OGL_ES "libGLESv1_CM.so"
gabomdq@7782
    60
dludwig@8545
    61
#elif SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
gabomdq@8021
    62
/* EGL AND OpenGL ES support via ANGLE */
gabomdq@8021
    63
#define DEFAULT_EGL "libEGL.dll"
gabomdq@8021
    64
#define DEFAULT_OGL_ES2 "libGLESv2.dll"
gabomdq@8021
    65
#define DEFAULT_OGL_ES_PVR "libGLES_CM.dll"
gabomdq@8021
    66
#define DEFAULT_OGL_ES "libGLESv1_CM.dll"
gabomdq@8021
    67
slouken@11723
    68
#elif SDL_VIDEO_DRIVER_COCOA
slouken@11723
    69
/* EGL AND OpenGL ES support via ANGLE */
slouken@11723
    70
#define DEFAULT_EGL "libEGL.dylib"
slouken@11723
    71
#define DEFAULT_OGL_ES2 "libGLESv2.dylib"
slouken@11723
    72
#define DEFAULT_OGL_ES_PVR "libGLES_CM.dylib"   //???
slouken@11723
    73
#define DEFAULT_OGL_ES "libGLESv1_CM.dylib"     //???
slouken@11723
    74
gabomdq@7753
    75
#else
gabomdq@7782
    76
/* Desktop Linux */
gabomdq@8062
    77
#define DEFAULT_OGL "libGL.so.1"
gabomdq@7753
    78
#define DEFAULT_EGL "libEGL.so.1"
gabomdq@7753
    79
#define DEFAULT_OGL_ES2 "libGLESv2.so.2"
gabomdq@7753
    80
#define DEFAULT_OGL_ES_PVR "libGLES_CM.so.1"
gabomdq@7753
    81
#define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
gabomdq@7753
    82
#endif /* SDL_VIDEO_DRIVER_RPI */
gabomdq@7659
    83
slouken@11363
    84
#ifdef SDL_VIDEO_STATIC_ANGLE
slouken@11363
    85
#define LOAD_FUNC(NAME) \
slouken@11363
    86
_this->egl_data->NAME = (void *)NAME;
slouken@11363
    87
#else
gabomdq@7659
    88
#define LOAD_FUNC(NAME) \
sezero@11872
    89
_this->egl_data->NAME = SDL_LoadFunction(_this->egl_data->dll_handle, #NAME); \
gabomdq@7659
    90
if (!_this->egl_data->NAME) \
gabomdq@7659
    91
{ \
gabomdq@7659
    92
    return SDL_SetError("Could not retrieve EGL function " #NAME); \
gabomdq@7659
    93
}
slouken@11363
    94
#endif
dludwig@10740
    95
dludwig@10740
    96
static const char * SDL_EGL_GetErrorName(EGLint eglErrorCode)
dludwig@10740
    97
{
dludwig@10740
    98
#define SDL_EGL_ERROR_TRANSLATE(e) case e: return #e;
dludwig@10740
    99
    switch (eglErrorCode) {
dludwig@10740
   100
        SDL_EGL_ERROR_TRANSLATE(EGL_SUCCESS);
dludwig@10740
   101
        SDL_EGL_ERROR_TRANSLATE(EGL_NOT_INITIALIZED);
dludwig@10740
   102
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_ACCESS);
dludwig@10740
   103
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_ALLOC);
dludwig@10740
   104
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_ATTRIBUTE);
dludwig@10740
   105
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_CONTEXT);
dludwig@10740
   106
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_CONFIG);
dludwig@10740
   107
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_CURRENT_SURFACE);
dludwig@10740
   108
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_DISPLAY);
dludwig@10740
   109
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_SURFACE);
dludwig@10740
   110
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_MATCH);
dludwig@10740
   111
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_PARAMETER);
dludwig@10740
   112
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_NATIVE_PIXMAP);
dludwig@10740
   113
        SDL_EGL_ERROR_TRANSLATE(EGL_BAD_NATIVE_WINDOW);
dludwig@10740
   114
        SDL_EGL_ERROR_TRANSLATE(EGL_CONTEXT_LOST);
dludwig@10740
   115
    }
dludwig@10740
   116
    return "";
dludwig@10740
   117
}
dludwig@10740
   118
dludwig@10740
   119
int SDL_EGL_SetErrorEx(const char * message, const char * eglFunctionName, EGLint eglErrorCode)
dludwig@10740
   120
{
dludwig@10740
   121
    const char * errorText = SDL_EGL_GetErrorName(eglErrorCode);
dludwig@10740
   122
    char altErrorText[32];
dludwig@10740
   123
    if (errorText[0] == '\0') {
dludwig@10740
   124
        /* An unknown-to-SDL error code was reported.  Report its hexadecimal value, instead of its name. */
dludwig@10740
   125
        SDL_snprintf(altErrorText, SDL_arraysize(altErrorText), "0x%x", (unsigned int)eglErrorCode);
dludwig@10740
   126
        errorText = altErrorText;
dludwig@10740
   127
    }
dludwig@10740
   128
    return SDL_SetError("%s (call to %s failed, reporting an error of %s)", message, eglFunctionName, errorText);
dludwig@10740
   129
}
dludwig@10740
   130
gabomdq@7659
   131
/* EGL implementation of SDL OpenGL ES support */
slouken@11175
   132
typedef enum {
slouken@11175
   133
    SDL_EGL_DISPLAY_EXTENSION,
slouken@11175
   134
    SDL_EGL_CLIENT_EXTENSION
slouken@11175
   135
} SDL_EGL_ExtensionType;
slouken@11175
   136
slouken@11175
   137
static SDL_bool SDL_EGL_HasExtension(_THIS, SDL_EGL_ExtensionType type, const char *ext)
knut@8962
   138
{
slouken@9821
   139
    size_t ext_len;
slouken@11175
   140
    const char *ext_override;
slouken@11175
   141
    const char *egl_extstr;
slouken@11175
   142
    const char *ext_start;
slouken@11175
   143
slouken@11175
   144
    /* Invalid extensions can be rejected early */
slouken@11175
   145
    if (ext == NULL || *ext == 0 || SDL_strchr(ext, ' ') != NULL) {
slouken@11175
   146
        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SDL_EGL_HasExtension: Invalid EGL extension"); */
slouken@11175
   147
        return SDL_FALSE;
slouken@11175
   148
    }
slouken@11175
   149
slouken@11175
   150
    /* Extensions can be masked with an environment variable.
slouken@11175
   151
     * Unlike the OpenGL override, this will use the set bits of an integer
slouken@11175
   152
     * to disable the extension.
slouken@11175
   153
     *  Bit   Action
slouken@11175
   154
     *  0     If set, the display extension is masked and not present to SDL.
slouken@11175
   155
     *  1     If set, the client extension is masked and not present to SDL.
slouken@11175
   156
     */
slouken@11175
   157
    ext_override = SDL_getenv(ext);
slouken@11175
   158
    if (ext_override != NULL) {
slouken@11175
   159
        int disable_ext = SDL_atoi(ext_override);
slouken@11175
   160
        if (disable_ext & 0x01 && type == SDL_EGL_DISPLAY_EXTENSION) {
slouken@11175
   161
            return SDL_FALSE;
slouken@11175
   162
        } else if (disable_ext & 0x02 && type == SDL_EGL_CLIENT_EXTENSION) {
slouken@11175
   163
            return SDL_FALSE;
slouken@11175
   164
        }
slouken@11175
   165
    }
knut@8962
   166
knut@8962
   167
    ext_len = SDL_strlen(ext);
slouken@11175
   168
    switch (type) {
slouken@11175
   169
    case SDL_EGL_DISPLAY_EXTENSION:
slouken@11175
   170
        egl_extstr = _this->egl_data->eglQueryString(_this->egl_data->egl_display, EGL_EXTENSIONS);
slouken@11175
   171
        break;
slouken@11175
   172
    case SDL_EGL_CLIENT_EXTENSION:
slouken@11175
   173
        /* EGL_EXT_client_extensions modifies eglQueryString to return client extensions
slouken@11175
   174
         * if EGL_NO_DISPLAY is passed. Implementations without it are required to return NULL.
slouken@11175
   175
         * This behavior is included in EGL 1.5.
slouken@11175
   176
         */
slouken@11175
   177
        egl_extstr = _this->egl_data->eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
slouken@11175
   178
        break;
slouken@11175
   179
    default:
slouken@11175
   180
        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SDL_EGL_HasExtension: Invalid extension type"); */
slouken@11175
   181
        return SDL_FALSE;
slouken@11175
   182
    }
knut@8962
   183
slouken@11175
   184
    if (egl_extstr != NULL) {
slouken@11175
   185
        ext_start = egl_extstr;
knut@8962
   186
slouken@11175
   187
        while (*ext_start) {
slouken@11175
   188
            ext_start = SDL_strstr(ext_start, ext);
slouken@11175
   189
            if (ext_start == NULL) {
slouken@11175
   190
                return SDL_FALSE;
slouken@11175
   191
            }
slouken@11175
   192
            /* Check if the match is not just a substring of one of the extensions */
slouken@11175
   193
            if (ext_start == egl_extstr || *(ext_start - 1) == ' ') {
slouken@11175
   194
                if (ext_start[ext_len] == ' ' || ext_start[ext_len] == 0) {
slouken@11175
   195
                    return SDL_TRUE;
knut@8962
   196
                }
slouken@11175
   197
            }
slouken@11175
   198
            /* If the search stopped in the middle of an extension, skip to the end of it */
slouken@11175
   199
            ext_start += ext_len;
slouken@11175
   200
            while (*ext_start != ' ' && *ext_start != 0) {
slouken@11175
   201
                ext_start++;
knut@8962
   202
            }
knut@8962
   203
        }
knut@8962
   204
    }
knut@8962
   205
slouken@11175
   206
    return SDL_FALSE;
knut@8962
   207
}
gabomdq@7659
   208
gabomdq@7659
   209
void *
gabomdq@7659
   210
SDL_EGL_GetProcAddress(_THIS, const char *proc)
gabomdq@7659
   211
{
gabomdq@7659
   212
    static char procname[1024];
gabomdq@7659
   213
    void *retval;
gabomdq@7659
   214
    
gabomdq@7659
   215
    /* eglGetProcAddress is busted on Android http://code.google.com/p/android/issues/detail?id=7681 */
brandon@11516
   216
#if !defined(SDL_VIDEO_DRIVER_ANDROID)
gabomdq@7659
   217
    if (_this->egl_data->eglGetProcAddress) {
gabomdq@7659
   218
        retval = _this->egl_data->eglGetProcAddress(proc);
gabomdq@7659
   219
        if (retval) {
gabomdq@7659
   220
            return retval;
gabomdq@7659
   221
        }
gabomdq@7659
   222
    }
gabomdq@7659
   223
#endif
gabomdq@7659
   224
    
gabomdq@8021
   225
    retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, proc);
gabomdq@8021
   226
    if (!retval && SDL_strlen(proc) <= 1022) {
gabomdq@7659
   227
        procname[0] = '_';
gabomdq@8021
   228
        SDL_strlcpy(procname + 1, proc, 1022);
gabomdq@8021
   229
        retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, procname);
gabomdq@7659
   230
    }
gabomdq@7659
   231
    return retval;
gabomdq@7659
   232
}
gabomdq@7659
   233
gabomdq@7659
   234
void
gabomdq@7659
   235
SDL_EGL_UnloadLibrary(_THIS)
gabomdq@7659
   236
{
slouken@7865
   237
    if (_this->egl_data) {
slouken@7865
   238
        if (_this->egl_data->egl_display) {
slouken@7865
   239
            _this->egl_data->eglTerminate(_this->egl_data->egl_display);
slouken@7865
   240
            _this->egl_data->egl_display = NULL;
slouken@7865
   241
        }
slouken@7865
   242
gabomdq@8021
   243
        if (_this->egl_data->dll_handle) {
gabomdq@8021
   244
            SDL_UnloadObject(_this->egl_data->dll_handle);
gabomdq@8021
   245
            _this->egl_data->dll_handle = NULL;
slouken@7865
   246
        }
slouken@7865
   247
        if (_this->egl_data->egl_dll_handle) {
gabomdq@8021
   248
            SDL_UnloadObject(_this->egl_data->egl_dll_handle);
slouken@7865
   249
            _this->egl_data->egl_dll_handle = NULL;
slouken@7865
   250
        }
gabomdq@7659
   251
        
gabomdq@7659
   252
        SDL_free(_this->egl_data);
gabomdq@7659
   253
        _this->egl_data = NULL;
gabomdq@7659
   254
    }
gabomdq@7659
   255
}
gabomdq@7659
   256
gabomdq@7659
   257
int
slouken@11175
   258
SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display, EGLenum platform)
gabomdq@7659
   259
{
gabomdq@8021
   260
    void *dll_handle = NULL, *egl_dll_handle = NULL; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */
slouken@10461
   261
    const char *path = NULL;
slouken@11175
   262
    int egl_version_major = 0, egl_version_minor = 0;
dludwig@8545
   263
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
gabomdq@8021
   264
    const char *d3dcompiler;
gabomdq@8021
   265
#endif
connogriofa@11676
   266
#if SDL_VIDEO_DRIVER_RPI
connogriofa@11676
   267
    SDL_bool vc4 = (0 == access("/sys/module/vc4/", F_OK));
connogriofa@11676
   268
#endif
gabomdq@8021
   269
gabomdq@7659
   270
    if (_this->egl_data) {
slouken@11718
   271
        return SDL_SetError("EGL context already created");
gabomdq@7659
   272
    }
slouken@7865
   273
slouken@7865
   274
    _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
slouken@7865
   275
    if (!_this->egl_data) {
slouken@7865
   276
        return SDL_OutOfMemory();
slouken@7865
   277
    }
slouken@7865
   278
dludwig@8545
   279
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
gabomdq@8021
   280
    d3dcompiler = SDL_GetHint(SDL_HINT_VIDEO_WIN_D3DCOMPILER);
gabomdq@8021
   281
    if (!d3dcompiler) {
slouken@8733
   282
        if (WIN_IsWindowsVistaOrGreater()) {
slouken@8733
   283
            d3dcompiler = "d3dcompiler_46.dll";
slouken@8733
   284
        } else {
slouken@8740
   285
            d3dcompiler = "d3dcompiler_43.dll";
slouken@8733
   286
        }
gabomdq@8021
   287
    }
gabomdq@8021
   288
    if (SDL_strcasecmp(d3dcompiler, "none") != 0) {
slouken@11219
   289
        if (SDL_LoadObject(d3dcompiler) == NULL) {
slouken@11219
   290
            SDL_ClearError();
slouken@11219
   291
        }
gabomdq@8021
   292
    }
slouken@7865
   293
#endif
slouken@7865
   294
slouken@11363
   295
#ifndef SDL_VIDEO_STATIC_ANGLE
gabomdq@7753
   296
    /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */
gabomdq@8021
   297
    path = SDL_getenv("SDL_VIDEO_GL_DRIVER");
gabomdq@8021
   298
    if (path != NULL) {
gabomdq@8021
   299
        egl_dll_handle = SDL_LoadObject(path);
gabomdq@8021
   300
    }
gabomdq@8021
   301
gabomdq@8021
   302
    if (egl_dll_handle == NULL) {
slime73@9595
   303
        if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
gabomdq@8062
   304
            if (_this->gl_config.major_version > 1) {
gabomdq@8062
   305
                path = DEFAULT_OGL_ES2;
gabomdq@8062
   306
                egl_dll_handle = SDL_LoadObject(path);
icculus@11462
   307
#ifdef ALT_OGL_ES2
connogriofa@11676
   308
                if (egl_dll_handle == NULL && !vc4) {
icculus@11462
   309
                    path = ALT_OGL_ES2;
icculus@11462
   310
                    egl_dll_handle = SDL_LoadObject(path);
icculus@11462
   311
                }
icculus@11462
   312
#endif
icculus@11462
   313
slime73@9595
   314
            } else {
gabomdq@8062
   315
                path = DEFAULT_OGL_ES;
gabomdq@8062
   316
                egl_dll_handle = SDL_LoadObject(path);
gabomdq@8062
   317
                if (egl_dll_handle == NULL) {
gabomdq@8062
   318
                    path = DEFAULT_OGL_ES_PVR;
gabomdq@8062
   319
                    egl_dll_handle = SDL_LoadObject(path);
gabomdq@8062
   320
                }
connogriofa@11676
   321
#ifdef ALT_OGL_ES2
connogriofa@11676
   322
                if (egl_dll_handle == NULL && !vc4) {
connogriofa@11676
   323
                    path = ALT_OGL_ES2;
connogriofa@11676
   324
                    egl_dll_handle = SDL_LoadObject(path);
connogriofa@11676
   325
                }
connogriofa@11676
   326
#endif
gabomdq@8062
   327
            }
gabomdq@8062
   328
        }
gabomdq@8062
   329
#ifdef DEFAULT_OGL         
gabomdq@8062
   330
        else {
gabomdq@8062
   331
            path = DEFAULT_OGL;
gabomdq@8021
   332
            egl_dll_handle = SDL_LoadObject(path);
gabomdq@8021
   333
        }
gabomdq@8062
   334
#endif        
gabomdq@7753
   335
    }
slouken@7865
   336
    _this->egl_data->egl_dll_handle = egl_dll_handle;
gabomdq@7753
   337
gabomdq@7753
   338
    if (egl_dll_handle == NULL) {
gabomdq@8062
   339
        return SDL_SetError("Could not initialize OpenGL / GLES library");
gabomdq@7753
   340
    }
gabomdq@8021
   341
gabomdq@7753
   342
    /* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */
gabomdq@8021
   343
    if (egl_path != NULL) {
gabomdq@8021
   344
        dll_handle = SDL_LoadObject(egl_path);
gabomdq@8021
   345
    }   
gabomdq@8105
   346
    /* Try loading a EGL symbol, if it does not work try the default library paths */
gabomdq@8872
   347
    if (dll_handle == NULL || SDL_LoadFunction(dll_handle, "eglChooseConfig") == NULL) {
gabomdq@8021
   348
        if (dll_handle != NULL) {
gabomdq@8021
   349
            SDL_UnloadObject(dll_handle);
gabomdq@8021
   350
        }
gabomdq@8021
   351
        path = SDL_getenv("SDL_VIDEO_EGL_DRIVER");
gabomdq@7659
   352
        if (path == NULL) {
gabomdq@7659
   353
            path = DEFAULT_EGL;
gabomdq@7659
   354
        }
gabomdq@8021
   355
        dll_handle = SDL_LoadObject(path);
icculus@11462
   356
icculus@11462
   357
#ifdef ALT_EGL
connogriofa@11676
   358
        if (dll_handle == NULL && !vc4) {
icculus@11462
   359
            path = ALT_EGL;
icculus@11462
   360
            dll_handle = SDL_LoadObject(path);
icculus@11462
   361
        }
icculus@11462
   362
#endif
icculus@11462
   363
gabomdq@8872
   364
        if (dll_handle == NULL || SDL_LoadFunction(dll_handle, "eglChooseConfig") == NULL) {
gabomdq@8872
   365
            if (dll_handle != NULL) {
gabomdq@8872
   366
                SDL_UnloadObject(dll_handle);
gabomdq@8872
   367
            }
gabomdq@8021
   368
            return SDL_SetError("Could not load EGL library");
gabomdq@8021
   369
        }
gabomdq@8763
   370
        SDL_ClearError();
gabomdq@7753
   371
    }
slouken@11363
   372
#endif
slouken@7865
   373
gabomdq@8021
   374
    _this->egl_data->dll_handle = dll_handle;
gabomdq@7659
   375
gabomdq@7659
   376
    /* Load new function pointers */
gabomdq@7659
   377
    LOAD_FUNC(eglGetDisplay);
gabomdq@7659
   378
    LOAD_FUNC(eglInitialize);
gabomdq@7659
   379
    LOAD_FUNC(eglTerminate);
gabomdq@7659
   380
    LOAD_FUNC(eglGetProcAddress);
gabomdq@7659
   381
    LOAD_FUNC(eglChooseConfig);
gabomdq@7659
   382
    LOAD_FUNC(eglGetConfigAttrib);
gabomdq@7659
   383
    LOAD_FUNC(eglCreateContext);
gabomdq@7659
   384
    LOAD_FUNC(eglDestroyContext);
slouken@11719
   385
    LOAD_FUNC(eglCreatePbufferSurface);
gabomdq@7659
   386
    LOAD_FUNC(eglCreateWindowSurface);
gabomdq@7659
   387
    LOAD_FUNC(eglDestroySurface);
gabomdq@7659
   388
    LOAD_FUNC(eglMakeCurrent);
gabomdq@7659
   389
    LOAD_FUNC(eglSwapBuffers);
gabomdq@7659
   390
    LOAD_FUNC(eglSwapInterval);
gabomdq@7659
   391
    LOAD_FUNC(eglWaitNative);
gabomdq@7659
   392
    LOAD_FUNC(eglWaitGL);
gabomdq@8062
   393
    LOAD_FUNC(eglBindAPI);
knut@8962
   394
    LOAD_FUNC(eglQueryString);
dludwig@10740
   395
    LOAD_FUNC(eglGetError);
dludwig@10740
   396
slouken@11175
   397
    if (_this->egl_data->eglQueryString) {
slouken@11175
   398
        /* EGL 1.5 allows querying for client version */
slouken@11175
   399
        const char *egl_version = _this->egl_data->eglQueryString(EGL_NO_DISPLAY, EGL_VERSION);
slouken@11175
   400
        if (egl_version != NULL) {
slouken@11175
   401
            if (SDL_sscanf(egl_version, "%d.%d", &egl_version_major, &egl_version_minor) != 2) {
slouken@11175
   402
                egl_version_major = 0;
slouken@11175
   403
                egl_version_minor = 0;
slouken@11175
   404
                SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not parse EGL version string: %s", egl_version);
slouken@11175
   405
            }
slouken@11175
   406
        }
slouken@11175
   407
    }
slouken@11175
   408
slouken@11175
   409
    if (egl_version_major == 1 && egl_version_minor == 5) {
slouken@11175
   410
        LOAD_FUNC(eglGetPlatformDisplay);
slouken@11175
   411
    }
slouken@11175
   412
slouken@11175
   413
    _this->egl_data->egl_display = EGL_NO_DISPLAY;
dludwig@8663
   414
#if !defined(__WINRT__)
slouken@11175
   415
    if (platform) {
slouken@11175
   416
        if (egl_version_major == 1 && egl_version_minor == 5) {
icculus@11418
   417
            _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(size_t)native_display, NULL);
slouken@11175
   418
        } else {
slouken@11175
   419
            if (SDL_EGL_HasExtension(_this, SDL_EGL_CLIENT_EXTENSION, "EGL_EXT_platform_base")) {
sezero@11872
   420
                _this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddress(_this, "eglGetPlatformDisplayEXT");
slouken@11175
   421
                if (_this->egl_data->eglGetPlatformDisplayEXT) {
icculus@11418
   422
                    _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(platform, (void *)(size_t)native_display, NULL);
slouken@11175
   423
                }
slouken@11175
   424
            }
slouken@11175
   425
        }
slouken@11175
   426
    }
slouken@11175
   427
    /* Try the implementation-specific eglGetDisplay even if eglGetPlatformDisplay fails */
slouken@11175
   428
    if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
slouken@11175
   429
        _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
slouken@11175
   430
    }
slouken@11175
   431
    if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
gabomdq@7659
   432
        return SDL_SetError("Could not get EGL display");
gabomdq@7659
   433
    }
gabomdq@7659
   434
    
gabomdq@7659
   435
    if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
gabomdq@7659
   436
        return SDL_SetError("Could not initialize EGL");
gabomdq@7659
   437
    }
dludwig@8663
   438
#endif
gabomdq@7659
   439
gabomdq@7659
   440
    if (path) {
gabomdq@8021
   441
        SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
gabomdq@7659
   442
    } else {
gabomdq@8021
   443
        *_this->gl_config.driver_path = '\0';
gabomdq@7659
   444
    }
gabomdq@7659
   445
    
gabomdq@8041
   446
    return 0;
gabomdq@7659
   447
}
gabomdq@7659
   448
slouken@11983
   449
#ifdef DUMP_EGL_CONFIG
slouken@11983
   450
slouken@11983
   451
#define ATTRIBUTE(_attr) { _attr, #_attr }
slouken@11983
   452
slouken@11983
   453
typedef struct {
slouken@11983
   454
    EGLint attribute;
slouken@11983
   455
    char const* name;
slouken@11983
   456
} Attribute;
slouken@11983
   457
slouken@11983
   458
Attribute attributes[] = {
slouken@11983
   459
        ATTRIBUTE( EGL_BUFFER_SIZE ),
slouken@11983
   460
        ATTRIBUTE( EGL_ALPHA_SIZE ),
slouken@11983
   461
        ATTRIBUTE( EGL_BLUE_SIZE ),
slouken@11983
   462
        ATTRIBUTE( EGL_GREEN_SIZE ),
slouken@11983
   463
        ATTRIBUTE( EGL_RED_SIZE ),
slouken@11983
   464
        ATTRIBUTE( EGL_DEPTH_SIZE ),
slouken@11983
   465
        ATTRIBUTE( EGL_STENCIL_SIZE ),
slouken@11983
   466
        ATTRIBUTE( EGL_CONFIG_CAVEAT ),
slouken@11983
   467
        ATTRIBUTE( EGL_CONFIG_ID ),
slouken@11983
   468
        ATTRIBUTE( EGL_LEVEL ),
slouken@11983
   469
        ATTRIBUTE( EGL_MAX_PBUFFER_HEIGHT ),
slouken@11983
   470
        ATTRIBUTE( EGL_MAX_PBUFFER_WIDTH ),
slouken@11983
   471
        ATTRIBUTE( EGL_MAX_PBUFFER_PIXELS ),
slouken@11983
   472
        ATTRIBUTE( EGL_NATIVE_RENDERABLE ),
slouken@11983
   473
        ATTRIBUTE( EGL_NATIVE_VISUAL_ID ),
slouken@11983
   474
        ATTRIBUTE( EGL_NATIVE_VISUAL_TYPE ),
slouken@11983
   475
        ATTRIBUTE( EGL_SAMPLES ),
slouken@11983
   476
        ATTRIBUTE( EGL_SAMPLE_BUFFERS ),
slouken@11983
   477
        ATTRIBUTE( EGL_SURFACE_TYPE ),
slouken@11983
   478
        ATTRIBUTE( EGL_TRANSPARENT_TYPE ),
slouken@11983
   479
        ATTRIBUTE( EGL_TRANSPARENT_BLUE_VALUE ),
slouken@11983
   480
        ATTRIBUTE( EGL_TRANSPARENT_GREEN_VALUE ),
slouken@11983
   481
        ATTRIBUTE( EGL_TRANSPARENT_RED_VALUE ),
slouken@11983
   482
        ATTRIBUTE( EGL_BIND_TO_TEXTURE_RGB ),
slouken@11983
   483
        ATTRIBUTE( EGL_BIND_TO_TEXTURE_RGBA ),
slouken@11983
   484
        ATTRIBUTE( EGL_MIN_SWAP_INTERVAL ),
slouken@11983
   485
        ATTRIBUTE( EGL_MAX_SWAP_INTERVAL ),
slouken@11983
   486
        ATTRIBUTE( EGL_LUMINANCE_SIZE ),
slouken@11983
   487
        ATTRIBUTE( EGL_ALPHA_MASK_SIZE ),
slouken@11983
   488
        ATTRIBUTE( EGL_COLOR_BUFFER_TYPE ),
slouken@11983
   489
        ATTRIBUTE( EGL_RENDERABLE_TYPE ),
slouken@11983
   490
        ATTRIBUTE( EGL_MATCH_NATIVE_PIXMAP ),
slouken@11983
   491
        ATTRIBUTE( EGL_CONFORMANT ),
slouken@11983
   492
};
slouken@11983
   493
slouken@11983
   494
slouken@11983
   495
static void dumpconfig(_THIS, EGLConfig config)
slouken@11983
   496
{
slouken@11983
   497
    int attr;
slouken@11983
   498
    for (attr = 0 ; attr<sizeof(attributes)/sizeof(Attribute) ; attr++) {
slouken@11983
   499
        EGLint value;
slouken@11983
   500
        _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, config, attributes[attr].attribute, &value);
slouken@11983
   501
        SDL_Log("\t%-32s: %10d (0x%08x)\n", attributes[attr].name, value, value);
slouken@11983
   502
    }
slouken@11983
   503
}
slouken@11983
   504
slouken@11983
   505
#endif /* DUMP_EGL_CONFIG */
slouken@11983
   506
gabomdq@7659
   507
int
gabomdq@7659
   508
SDL_EGL_ChooseConfig(_THIS) 
gabomdq@7659
   509
{
slouken@11175
   510
/* 64 seems nice. */
gabomdq@7659
   511
    EGLint attribs[64];
gabomdq@8021
   512
    EGLint found_configs = 0, value;
slouken@11175
   513
#ifdef SDL_VIDEO_DRIVER_KMSDRM
slouken@11175
   514
    /* Intel EGL on KMS/DRM (al least) returns invalid configs that confuse the bitdiff search used */
slouken@11175
   515
    /* later in this function, so we simply use the first one when using the KMSDRM driver for now. */
slouken@11175
   516
    EGLConfig configs[1];
slouken@11175
   517
#else
gabomdq@8015
   518
    /* 128 seems even nicer here */
gabomdq@8015
   519
    EGLConfig configs[128];
slouken@11175
   520
#endif
gabomdq@8021
   521
    int i, j, best_bitdiff = -1, bitdiff;
slouken@11175
   522
   
gabomdq@7659
   523
    if (!_this->egl_data) {
gabomdq@7659
   524
        /* The EGL library wasn't loaded, SDL_GetError() should have info */
gabomdq@7659
   525
        return -1;
gabomdq@7659
   526
    }
gabomdq@7659
   527
  
gabomdq@7659
   528
    /* Get a valid EGL configuration */
gabomdq@7659
   529
    i = 0;
gabomdq@7659
   530
    attribs[i++] = EGL_RED_SIZE;
gabomdq@7659
   531
    attribs[i++] = _this->gl_config.red_size;
gabomdq@7659
   532
    attribs[i++] = EGL_GREEN_SIZE;
gabomdq@7659
   533
    attribs[i++] = _this->gl_config.green_size;
gabomdq@7659
   534
    attribs[i++] = EGL_BLUE_SIZE;
gabomdq@7659
   535
    attribs[i++] = _this->gl_config.blue_size;
gabomdq@7659
   536
    
gabomdq@7659
   537
    if (_this->gl_config.alpha_size) {
gabomdq@7659
   538
        attribs[i++] = EGL_ALPHA_SIZE;
gabomdq@7659
   539
        attribs[i++] = _this->gl_config.alpha_size;
gabomdq@7659
   540
    }
gabomdq@7659
   541
    
gabomdq@7659
   542
    if (_this->gl_config.buffer_size) {
gabomdq@7659
   543
        attribs[i++] = EGL_BUFFER_SIZE;
gabomdq@7659
   544
        attribs[i++] = _this->gl_config.buffer_size;
gabomdq@7659
   545
    }
gabomdq@7659
   546
    
gabomdq@7659
   547
    attribs[i++] = EGL_DEPTH_SIZE;
gabomdq@7659
   548
    attribs[i++] = _this->gl_config.depth_size;
gabomdq@7659
   549
    
gabomdq@7659
   550
    if (_this->gl_config.stencil_size) {
gabomdq@7659
   551
        attribs[i++] = EGL_STENCIL_SIZE;
gabomdq@7659
   552
        attribs[i++] = _this->gl_config.stencil_size;
gabomdq@7659
   553
    }
gabomdq@7659
   554
    
gabomdq@7659
   555
    if (_this->gl_config.multisamplebuffers) {
gabomdq@7659
   556
        attribs[i++] = EGL_SAMPLE_BUFFERS;
gabomdq@7659
   557
        attribs[i++] = _this->gl_config.multisamplebuffers;
gabomdq@7659
   558
    }
gabomdq@7659
   559
    
gabomdq@7659
   560
    if (_this->gl_config.multisamplesamples) {
gabomdq@7659
   561
        attribs[i++] = EGL_SAMPLES;
gabomdq@7659
   562
        attribs[i++] = _this->gl_config.multisamplesamples;
gabomdq@7659
   563
    }
slime73@9595
   564
gabomdq@7659
   565
    attribs[i++] = EGL_RENDERABLE_TYPE;
slime73@9595
   566
    if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
slime73@9595
   567
#ifdef EGL_KHR_create_context
slime73@9595
   568
        if (_this->gl_config.major_version >= 3 &&
slouken@11175
   569
            SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_create_context")) {
slime73@9595
   570
            attribs[i++] = EGL_OPENGL_ES3_BIT_KHR;
slime73@9595
   571
        } else
slime73@9595
   572
#endif
slime73@9595
   573
        if (_this->gl_config.major_version >= 2) {
gabomdq@8062
   574
            attribs[i++] = EGL_OPENGL_ES2_BIT;
gabomdq@8062
   575
        } else {
gabomdq@8062
   576
            attribs[i++] = EGL_OPENGL_ES_BIT;
gabomdq@8062
   577
        }
gabomdq@8062
   578
        _this->egl_data->eglBindAPI(EGL_OPENGL_ES_API);
slime73@9595
   579
    } else {
gabomdq@8062
   580
        attribs[i++] = EGL_OPENGL_BIT;
gabomdq@8062
   581
        _this->egl_data->eglBindAPI(EGL_OPENGL_API);
gabomdq@7659
   582
    }
slime73@9827
   583
slouken@11677
   584
    if (_this->egl_data->egl_surfacetype) {
slouken@11677
   585
        attribs[i++] = EGL_SURFACE_TYPE;
slouken@11677
   586
        attribs[i++] = _this->egl_data->egl_surfacetype;
slouken@11677
   587
    }
slouken@11677
   588
gabomdq@7659
   589
    attribs[i++] = EGL_NONE;
slime73@9827
   590
gabomdq@7659
   591
    if (_this->egl_data->eglChooseConfig(_this->egl_data->egl_display,
gabomdq@7659
   592
        attribs,
gabomdq@8015
   593
        configs, SDL_arraysize(configs),
gabomdq@7659
   594
        &found_configs) == EGL_FALSE ||
gabomdq@7659
   595
        found_configs == 0) {
dludwig@10740
   596
        return SDL_EGL_SetError("Couldn't find matching EGL config", "eglChooseConfig");
gabomdq@7659
   597
    }
slime73@9827
   598
gabomdq@8015
   599
    /* eglChooseConfig returns a number of configurations that match or exceed the requested attribs. */
gabomdq@8015
   600
    /* From those, we select the one that matches our requirements more closely via a makeshift algorithm */
gabomdq@8021
   601
slime73@9595
   602
    for (i = 0; i < found_configs; i++ ) {
gabomdq@8015
   603
        bitdiff = 0;
gabomdq@8021
   604
        for (j = 0; j < SDL_arraysize(attribs) - 1; j += 2) {
gabomdq@8015
   605
            if (attribs[j] == EGL_NONE) {
gabomdq@8015
   606
               break;
gabomdq@8015
   607
            }
gabomdq@8015
   608
            
gabomdq@8015
   609
            if ( attribs[j+1] != EGL_DONT_CARE && (
gabomdq@8015
   610
                attribs[j] == EGL_RED_SIZE ||
gabomdq@8015
   611
                attribs[j] == EGL_GREEN_SIZE ||
gabomdq@8015
   612
                attribs[j] == EGL_BLUE_SIZE ||
gabomdq@8015
   613
                attribs[j] == EGL_ALPHA_SIZE ||
gabomdq@8015
   614
                attribs[j] == EGL_DEPTH_SIZE ||
gabomdq@8015
   615
                attribs[j] == EGL_STENCIL_SIZE)) {
gabomdq@8015
   616
                _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, configs[i], attribs[j], &value);
gabomdq@8015
   617
                bitdiff += value - attribs[j + 1]; /* value is always >= attrib */
gabomdq@8015
   618
            }
gabomdq@8015
   619
        }
gabomdq@8015
   620
gabomdq@8015
   621
        if (bitdiff < best_bitdiff || best_bitdiff == -1) {
gabomdq@8015
   622
            _this->egl_data->egl_config = configs[i];
gabomdq@8015
   623
            
gabomdq@8015
   624
            best_bitdiff = bitdiff;
gabomdq@8015
   625
        }
slime73@9595
   626
slime73@9595
   627
        if (bitdiff == 0) {
slime73@9595
   628
            break; /* we found an exact match! */
slime73@9595
   629
        }
gabomdq@8015
   630
    }
slouken@11983
   631
slouken@11983
   632
#ifdef DUMP_EGL_CONFIG
slouken@11983
   633
    dumpconfig(_this, _this->egl_data->egl_config);
slouken@11983
   634
#endif
gabomdq@8015
   635
    
gabomdq@7659
   636
    return 0;
gabomdq@7659
   637
}
gabomdq@7659
   638
gabomdq@7659
   639
SDL_GLContext
gabomdq@7659
   640
SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
gabomdq@7659
   641
{
slime73@9595
   642
    /* max 14 values plus terminator. */
slime73@9595
   643
    EGLint attribs[15];
slime73@9595
   644
    int attr = 0;
slime73@9595
   645
gabomdq@8061
   646
    EGLContext egl_context, share_context = EGL_NO_CONTEXT;
slime73@9595
   647
    EGLint profile_mask = _this->gl_config.profile_mask;
slime73@9637
   648
    EGLint major_version = _this->gl_config.major_version;
slime73@9637
   649
    EGLint minor_version = _this->gl_config.minor_version;
slime73@9637
   650
    SDL_bool profile_es = (profile_mask == SDL_GL_CONTEXT_PROFILE_ES);
slime73@9595
   651
gabomdq@7659
   652
    if (!_this->egl_data) {
gabomdq@7659
   653
        /* The EGL library wasn't loaded, SDL_GetError() should have info */
gabomdq@7659
   654
        return NULL;
gabomdq@7659
   655
    }
slime73@9595
   656
gabomdq@8061
   657
    if (_this->gl_config.share_with_current_context) {
gabomdq@8061
   658
        share_context = (EGLContext)SDL_GL_GetCurrentContext();
gabomdq@7659
   659
    }
slime73@9595
   660
slime73@9595
   661
    /* Set the context version and other attributes. */
slime73@9637
   662
    if ((major_version < 3 || (minor_version == 0 && profile_es)) &&
slime73@9637
   663
        _this->gl_config.flags == 0 &&
slime73@9637
   664
        (profile_mask == 0 || profile_es)) {
slime73@9637
   665
        /* Create a context without using EGL_KHR_create_context attribs.
slime73@9637
   666
         * When creating a GLES context without EGL_KHR_create_context we can
slime73@9637
   667
         * only specify the major version. When creating a desktop GL context
slime73@9637
   668
         * we can't specify any version, so we only try in that case when the
slime73@9637
   669
         * version is less than 3.0 (matches SDL's GLX/WGL behavior.)
slime73@9637
   670
         */
slime73@9637
   671
        if (profile_es) {
slime73@9595
   672
            attribs[attr++] = EGL_CONTEXT_CLIENT_VERSION;
slime73@9637
   673
            attribs[attr++] = SDL_max(major_version, 1);
slime73@9595
   674
        }
slime73@9595
   675
    } else {
slime73@9595
   676
#ifdef EGL_KHR_create_context
slime73@9595
   677
        /* The Major/minor version, context profiles, and context flags can
slime73@9595
   678
         * only be specified when this extension is available.
slime73@9595
   679
         */
slouken@11175
   680
        if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_create_context")) {
slime73@9595
   681
            attribs[attr++] = EGL_CONTEXT_MAJOR_VERSION_KHR;
slime73@9637
   682
            attribs[attr++] = major_version;
slime73@9595
   683
            attribs[attr++] = EGL_CONTEXT_MINOR_VERSION_KHR;
slime73@9637
   684
            attribs[attr++] = minor_version;
slime73@9595
   685
slime73@9595
   686
            /* SDL profile bits match EGL profile bits. */
slime73@9595
   687
            if (profile_mask != 0 && profile_mask != SDL_GL_CONTEXT_PROFILE_ES) {
slime73@9595
   688
                attribs[attr++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
slime73@9595
   689
                attribs[attr++] = profile_mask;
slime73@9595
   690
            }
slime73@9595
   691
slime73@9595
   692
            /* SDL flags match EGL flags. */
slime73@9595
   693
            if (_this->gl_config.flags != 0) {
slime73@9595
   694
                attribs[attr++] = EGL_CONTEXT_FLAGS_KHR;
slime73@9595
   695
                attribs[attr++] = _this->gl_config.flags;
slime73@9595
   696
            }
slime73@9595
   697
        } else
slime73@9595
   698
#endif /* EGL_KHR_create_context */
slime73@9595
   699
        {
slime73@9595
   700
            SDL_SetError("Could not create EGL context (context attributes are not supported)");
slime73@9595
   701
            return NULL;
slime73@9595
   702
        }
slime73@9595
   703
    }
slime73@9595
   704
flibitijibibo@11347
   705
    if (_this->gl_config.no_error) {
flibitijibibo@11347
   706
#ifdef EGL_KHR_create_context_no_error
flibitijibibo@11347
   707
        if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_create_context_no_error")) {
flibitijibibo@11347
   708
            attribs[attr++] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
flibitijibibo@11347
   709
            attribs[attr++] = _this->gl_config.no_error;
flibitijibibo@11347
   710
        } else
flibitijibibo@11347
   711
#endif
flibitijibibo@11347
   712
        {
flibitijibibo@11347
   713
            SDL_SetError("EGL implementation does not support no_error contexts");
flibitijibibo@11347
   714
            return NULL;
flibitijibibo@11347
   715
        }
flibitijibibo@11347
   716
    }
flibitijibibo@11347
   717
slime73@9595
   718
    attribs[attr++] = EGL_NONE;
slime73@9595
   719
gabomdq@8062
   720
    /* Bind the API */
slime73@9637
   721
    if (profile_es) {
gabomdq@8062
   722
        _this->egl_data->eglBindAPI(EGL_OPENGL_ES_API);
slime73@9595
   723
    } else {
slime73@9595
   724
        _this->egl_data->eglBindAPI(EGL_OPENGL_API);
slime73@9595
   725
    }
gabomdq@7659
   726
slime73@9595
   727
    egl_context = _this->egl_data->eglCreateContext(_this->egl_data->egl_display,
slime73@9595
   728
                                      _this->egl_data->egl_config,
slime73@9595
   729
                                      share_context, attribs);
knut@8962
   730
gabomdq@7659
   731
    if (egl_context == EGL_NO_CONTEXT) {
dludwig@10740
   732
        SDL_EGL_SetError("Could not create EGL context", "eglCreateContext");
gabomdq@7659
   733
        return NULL;
gabomdq@7659
   734
    }
slime73@9595
   735
gabomdq@7659
   736
    _this->egl_data->egl_swapinterval = 0;
slime73@9595
   737
gabomdq@7659
   738
    if (SDL_EGL_MakeCurrent(_this, egl_surface, egl_context) < 0) {
dludwig@10740
   739
        /* Save the SDL error set by SDL_EGL_MakeCurrent */
dludwig@10740
   740
        char errorText[1024];
dludwig@10740
   741
        SDL_strlcpy(errorText, SDL_GetError(), SDL_arraysize(errorText));
dludwig@10740
   742
dludwig@10740
   743
        /* Delete the context, which may alter the value returned by SDL_GetError() */
gabomdq@7659
   744
        SDL_EGL_DeleteContext(_this, egl_context);
dludwig@10740
   745
dludwig@10740
   746
        /* Restore the SDL error */
dludwig@10740
   747
        SDL_SetError("%s", errorText);
dludwig@10740
   748
gabomdq@7659
   749
        return NULL;
gabomdq@7659
   750
    }
slime73@9595
   751
gabomdq@7659
   752
    return (SDL_GLContext) egl_context;
gabomdq@7659
   753
}
gabomdq@7659
   754
gabomdq@7659
   755
int
gabomdq@7659
   756
SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context)
gabomdq@7659
   757
{
gabomdq@7679
   758
    EGLContext egl_context = (EGLContext) context;
gabomdq@7679
   759
gabomdq@7659
   760
    if (!_this->egl_data) {
gabomdq@7659
   761
        return SDL_SetError("OpenGL not initialized");
gabomdq@7659
   762
    }
gabomdq@7659
   763
    
gabomdq@7659
   764
    /* The android emulator crashes badly if you try to eglMakeCurrent 
gabomdq@7659
   765
     * with a valid context and invalid surface, so we have to check for both here.
gabomdq@7659
   766
     */
gabomdq@7659
   767
    if (!egl_context || !egl_surface) {
gabomdq@7659
   768
         _this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
slime73@9595
   769
    } else {
gabomdq@7659
   770
        if (!_this->egl_data->eglMakeCurrent(_this->egl_data->egl_display,
gabomdq@7659
   771
            egl_surface, egl_surface, egl_context)) {
dludwig@10740
   772
            return SDL_EGL_SetError("Unable to make EGL context current", "eglMakeCurrent");
gabomdq@7659
   773
        }
gabomdq@7659
   774
    }
gabomdq@7659
   775
      
gabomdq@7659
   776
    return 0;
gabomdq@7659
   777
}
gabomdq@7659
   778
gabomdq@7659
   779
int
gabomdq@7659
   780
SDL_EGL_SetSwapInterval(_THIS, int interval)
gabomdq@7659
   781
{
gabomdq@7679
   782
    EGLBoolean status;
gabomdq@7679
   783
    
gabomdq@7702
   784
    if (!_this->egl_data) {
gabomdq@7702
   785
        return SDL_SetError("EGL not initialized");
gabomdq@7659
   786
    }
gabomdq@7659
   787
    
gabomdq@7659
   788
    status = _this->egl_data->eglSwapInterval(_this->egl_data->egl_display, interval);
gabomdq@7659
   789
    if (status == EGL_TRUE) {
gabomdq@7659
   790
        _this->egl_data->egl_swapinterval = interval;
gabomdq@7659
   791
        return 0;
gabomdq@7659
   792
    }
gabomdq@7659
   793
    
dludwig@10740
   794
    return SDL_EGL_SetError("Unable to set the EGL swap interval", "eglSwapInterval");
gabomdq@7659
   795
}
gabomdq@7659
   796
gabomdq@7659
   797
int
gabomdq@7659
   798
SDL_EGL_GetSwapInterval(_THIS)
gabomdq@7659
   799
{
gabomdq@7702
   800
    if (!_this->egl_data) {
philipp@10169
   801
        SDL_SetError("EGL not initialized");
philipp@10169
   802
        return 0;
gabomdq@7659
   803
    }
gabomdq@7659
   804
    
gabomdq@7659
   805
    return _this->egl_data->egl_swapinterval;
gabomdq@7659
   806
}
gabomdq@7659
   807
slouken@10693
   808
int
gabomdq@7659
   809
SDL_EGL_SwapBuffers(_THIS, EGLSurface egl_surface)
gabomdq@7659
   810
{
slouken@10693
   811
    if (!_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, egl_surface)) {
dludwig@10740
   812
        return SDL_EGL_SetError("unable to show color buffer in an OS-native window", "eglSwapBuffers");
slouken@10693
   813
    }
slouken@10693
   814
    return 0;
gabomdq@7659
   815
}
gabomdq@7659
   816
gabomdq@7659
   817
void
gabomdq@7659
   818
SDL_EGL_DeleteContext(_THIS, SDL_GLContext context)
gabomdq@7659
   819
{
gabomdq@7679
   820
    EGLContext egl_context = (EGLContext) context;
gabomdq@7679
   821
gabomdq@7659
   822
    /* Clean up GLES and EGL */
gabomdq@7659
   823
    if (!_this->egl_data) {
gabomdq@7659
   824
        return;
gabomdq@7659
   825
    }
gabomdq@7659
   826
    
gabomdq@7896
   827
    if (egl_context != NULL && egl_context != EGL_NO_CONTEXT) {
gabomdq@7659
   828
        _this->egl_data->eglDestroyContext(_this->egl_data->egl_display, egl_context);
gabomdq@7659
   829
    }
gabomdq@7659
   830
        
gabomdq@7659
   831
}
gabomdq@7659
   832
gabomdq@7659
   833
EGLSurface *
gabomdq@7659
   834
SDL_EGL_CreateSurface(_THIS, NativeWindowType nw) 
gabomdq@7659
   835
{
deveee@11830
   836
    /* max 2 values plus terminator. */
deveee@11830
   837
    EGLint attribs[3];
deveee@11830
   838
    int attr = 0;
deveee@11830
   839
	
dludwig@10740
   840
    EGLSurface * surface;
dludwig@10740
   841
gabomdq@8041
   842
    if (SDL_EGL_ChooseConfig(_this) != 0) {
slouken@8045
   843
        return EGL_NO_SURFACE;
gabomdq@8041
   844
    }
gabomdq@8041
   845
    
slouken@10878
   846
#if SDL_VIDEO_DRIVER_ANDROID
slouken@8976
   847
    {
slouken@8976
   848
        /* Android docs recommend doing this!
slouken@8976
   849
         * Ref: http://developer.android.com/reference/android/app/NativeActivity.html 
slouken@8976
   850
         */
slouken@8976
   851
        EGLint format;
slouken@8976
   852
        _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display,
slouken@8976
   853
                                            _this->egl_data->egl_config, 
slouken@8976
   854
                                            EGL_NATIVE_VISUAL_ID, &format);
gabomdq@8971
   855
slouken@8976
   856
        ANativeWindow_setBuffersGeometry(nw, 0, 0, format);
slouken@8976
   857
    }
gabomdq@8971
   858
#endif    
deveee@11830
   859
    if (_this->gl_config.framebuffer_srgb_capable) {
deveee@11830
   860
#ifdef EGL_KHR_gl_colorspace
deveee@11830
   861
        if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_gl_colorspace")) {
deveee@11830
   862
            attribs[attr++] = EGL_GL_COLORSPACE_KHR;
deveee@11830
   863
            attribs[attr++] = EGL_GL_COLORSPACE_SRGB_KHR;
deveee@11830
   864
        } else
deveee@11830
   865
#endif
deveee@11830
   866
        {
deveee@11830
   867
            SDL_SetError("EGL implementation does not support sRGB system framebuffers");
deveee@11830
   868
            return EGL_NO_SURFACE;
deveee@11830
   869
        }
deveee@11830
   870
    }
deveee@11830
   871
	
deveee@11830
   872
    attribs[attr++] = EGL_NONE;
gabomdq@8971
   873
    
dludwig@10740
   874
    surface = _this->egl_data->eglCreateWindowSurface(
gabomdq@7659
   875
            _this->egl_data->egl_display,
gabomdq@7659
   876
            _this->egl_data->egl_config,
deveee@11830
   877
            nw, &attribs[0]);
dludwig@10740
   878
    if (surface == EGL_NO_SURFACE) {
dludwig@10740
   879
        SDL_EGL_SetError("unable to create an EGL window surface", "eglCreateWindowSurface");
dludwig@10740
   880
    }
dludwig@10740
   881
    return surface;
gabomdq@7659
   882
}
gabomdq@7659
   883
gabomdq@7659
   884
void
gabomdq@7659
   885
SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface) 
gabomdq@7659
   886
{
gabomdq@7659
   887
    if (!_this->egl_data) {
gabomdq@7659
   888
        return;
gabomdq@7659
   889
    }
gabomdq@7659
   890
    
gabomdq@7659
   891
    if (egl_surface != EGL_NO_SURFACE) {
gabomdq@7659
   892
        _this->egl_data->eglDestroySurface(_this->egl_data->egl_display, egl_surface);
gabomdq@7659
   893
    }
gabomdq@7659
   894
}
gabomdq@7659
   895
gabomdq@7659
   896
#endif /* SDL_VIDEO_OPENGL_EGL */
gabomdq@7659
   897
gabomdq@7659
   898
/* vi: set ts=4 sw=4 expandtab: */
philipp@11192
   899