sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_egl.c (40641B)


      1 /*
      2  *  Simple DirectMedia Layer
      3  *  Copyright (C) 1997-2020 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_internal.h"
     22 
     23 #if SDL_VIDEO_OPENGL_EGL
     24 
     25 #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
     26 #include "../core/windows/SDL_windows.h"
     27 #endif
     28 #if SDL_VIDEO_DRIVER_ANDROID
     29 #include <android/native_window.h>
     30 #include "../core/android/SDL_android.h"
     31 #endif
     32 
     33 #include "SDL_sysvideo.h"
     34 #include "SDL_egl_c.h"
     35 #include "SDL_loadso.h"
     36 #include "SDL_hints.h"
     37 
     38 #ifdef EGL_KHR_create_context
     39 /* EGL_OPENGL_ES3_BIT_KHR was added in version 13 of the extension. */
     40 #ifndef EGL_OPENGL_ES3_BIT_KHR
     41 #define EGL_OPENGL_ES3_BIT_KHR 0x00000040
     42 #endif
     43 #endif /* EGL_KHR_create_context */
     44 
     45 #if SDL_VIDEO_DRIVER_RPI
     46 /* Raspbian places the OpenGL ES/EGL binaries in a non standard path */
     47 #define DEFAULT_EGL ( vc4 ? "libEGL.so.1" : "libbrcmEGL.so" )
     48 #define DEFAULT_OGL_ES2 ( vc4 ? "libGLESv2.so.2" : "libbrcmGLESv2.so" )
     49 #define ALT_EGL "libEGL.so"
     50 #define ALT_OGL_ES2 "libGLESv2.so"
     51 #define DEFAULT_OGL_ES_PVR ( vc4 ? "libGLES_CM.so.1" : "libbrcmGLESv2.so" )
     52 #define DEFAULT_OGL_ES ( vc4 ? "libGLESv1_CM.so.1" : "libbrcmGLESv2.so" )
     53 
     54 #elif SDL_VIDEO_DRIVER_ANDROID || SDL_VIDEO_DRIVER_VIVANTE
     55 /* Android */
     56 #define DEFAULT_EGL "libEGL.so"
     57 #define DEFAULT_OGL_ES2 "libGLESv2.so"
     58 #define DEFAULT_OGL_ES_PVR "libGLES_CM.so"
     59 #define DEFAULT_OGL_ES "libGLESv1_CM.so"
     60 
     61 #elif SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
     62 /* EGL AND OpenGL ES support via ANGLE */
     63 #define DEFAULT_EGL "libEGL.dll"
     64 #define DEFAULT_OGL_ES2 "libGLESv2.dll"
     65 #define DEFAULT_OGL_ES_PVR "libGLES_CM.dll"
     66 #define DEFAULT_OGL_ES "libGLESv1_CM.dll"
     67 
     68 #elif SDL_VIDEO_DRIVER_COCOA
     69 /* EGL AND OpenGL ES support via ANGLE */
     70 #define DEFAULT_EGL "libEGL.dylib"
     71 #define DEFAULT_OGL_ES2 "libGLESv2.dylib"
     72 #define DEFAULT_OGL_ES_PVR "libGLES_CM.dylib"   //???
     73 #define DEFAULT_OGL_ES "libGLESv1_CM.dylib"     //???
     74 
     75 #elif defined(__OpenBSD__)
     76 #define DEFAULT_OGL "libGL.so"
     77 #define DEFAULT_EGL "libEGL.so"
     78 #define DEFAULT_OGL_ES2 "libGLESv2.so"
     79 #define DEFAULT_OGL_ES_PVR "libGLES_CM.so"
     80 #define DEFAULT_OGL_ES "libGLESv1_CM.so"
     81 
     82 #else
     83 /* Desktop Linux */
     84 #define DEFAULT_OGL "libGL.so.1"
     85 #define DEFAULT_EGL "libEGL.so.1"
     86 #define DEFAULT_OGL_ES2 "libGLESv2.so.2"
     87 #define DEFAULT_OGL_ES_PVR "libGLES_CM.so.1"
     88 #define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
     89 #endif /* SDL_VIDEO_DRIVER_RPI */
     90 
     91 #if SDL_VIDEO_OPENGL
     92 #include "SDL_opengl.h"
     93 #endif
     94 
     95 /** If we happen to not have this defined because of an older EGL version, just define it 0x0
     96     as eglGetPlatformDisplayEXT will most likely be NULL if this is missing
     97 */
     98 #ifndef EGL_PLATFORM_DEVICE_EXT
     99 #define EGL_PLATFORM_DEVICE_EXT 0x0
    100 #endif
    101 
    102 #ifdef SDL_VIDEO_STATIC_ANGLE
    103 #define LOAD_FUNC(NAME) \
    104 _this->egl_data->NAME = (void *)NAME;
    105 #else
    106 #define LOAD_FUNC(NAME) \
    107 _this->egl_data->NAME = SDL_LoadFunction(_this->egl_data->dll_handle, #NAME); \
    108 if (!_this->egl_data->NAME) \
    109 { \
    110     return SDL_SetError("Could not retrieve EGL function " #NAME); \
    111 }
    112 #endif
    113 
    114 /* it is allowed to not have some of the EGL extensions on start - attempts to use them will fail later. */
    115 #define LOAD_FUNC_EGLEXT(NAME) \
    116     _this->egl_data->NAME = _this->egl_data->eglGetProcAddress(#NAME);
    117 
    118 
    119 static const char * SDL_EGL_GetErrorName(EGLint eglErrorCode)
    120 {
    121 #define SDL_EGL_ERROR_TRANSLATE(e) case e: return #e;
    122     switch (eglErrorCode) {
    123         SDL_EGL_ERROR_TRANSLATE(EGL_SUCCESS);
    124         SDL_EGL_ERROR_TRANSLATE(EGL_NOT_INITIALIZED);
    125         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_ACCESS);
    126         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_ALLOC);
    127         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_ATTRIBUTE);
    128         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_CONTEXT);
    129         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_CONFIG);
    130         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_CURRENT_SURFACE);
    131         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_DISPLAY);
    132         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_SURFACE);
    133         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_MATCH);
    134         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_PARAMETER);
    135         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_NATIVE_PIXMAP);
    136         SDL_EGL_ERROR_TRANSLATE(EGL_BAD_NATIVE_WINDOW);
    137         SDL_EGL_ERROR_TRANSLATE(EGL_CONTEXT_LOST);
    138     }
    139     return "";
    140 }
    141 
    142 int SDL_EGL_SetErrorEx(const char * message, const char * eglFunctionName, EGLint eglErrorCode)
    143 {
    144     const char * errorText = SDL_EGL_GetErrorName(eglErrorCode);
    145     char altErrorText[32];
    146     if (errorText[0] == '\0') {
    147         /* An unknown-to-SDL error code was reported.  Report its hexadecimal value, instead of its name. */
    148         SDL_snprintf(altErrorText, SDL_arraysize(altErrorText), "0x%x", (unsigned int)eglErrorCode);
    149         errorText = altErrorText;
    150     }
    151     return SDL_SetError("%s (call to %s failed, reporting an error of %s)", message, eglFunctionName, errorText);
    152 }
    153 
    154 /* EGL implementation of SDL OpenGL ES support */
    155 
    156 SDL_bool SDL_EGL_HasExtension(_THIS, SDL_EGL_ExtensionType type, const char *ext)
    157 {
    158     size_t ext_len;
    159     const char *ext_override;
    160     const char *egl_extstr;
    161     const char *ext_start;
    162 
    163     /* Invalid extensions can be rejected early */
    164     if (ext == NULL || *ext == 0 || SDL_strchr(ext, ' ') != NULL) {
    165         /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SDL_EGL_HasExtension: Invalid EGL extension"); */
    166         return SDL_FALSE;
    167     }
    168 
    169     /* Extensions can be masked with an environment variable.
    170      * Unlike the OpenGL override, this will use the set bits of an integer
    171      * to disable the extension.
    172      *  Bit   Action
    173      *  0     If set, the display extension is masked and not present to SDL.
    174      *  1     If set, the client extension is masked and not present to SDL.
    175      */
    176     ext_override = SDL_getenv(ext);
    177     if (ext_override != NULL) {
    178         int disable_ext = SDL_atoi(ext_override);
    179         if (disable_ext & 0x01 && type == SDL_EGL_DISPLAY_EXTENSION) {
    180             return SDL_FALSE;
    181         } else if (disable_ext & 0x02 && type == SDL_EGL_CLIENT_EXTENSION) {
    182             return SDL_FALSE;
    183         }
    184     }
    185 
    186     ext_len = SDL_strlen(ext);
    187     switch (type) {
    188     case SDL_EGL_DISPLAY_EXTENSION:
    189         egl_extstr = _this->egl_data->eglQueryString(_this->egl_data->egl_display, EGL_EXTENSIONS);
    190         break;
    191     case SDL_EGL_CLIENT_EXTENSION:
    192         /* EGL_EXT_client_extensions modifies eglQueryString to return client extensions
    193          * if EGL_NO_DISPLAY is passed. Implementations without it are required to return NULL.
    194          * This behavior is included in EGL 1.5.
    195          */
    196         egl_extstr = _this->egl_data->eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
    197         break;
    198     default:
    199         /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SDL_EGL_HasExtension: Invalid extension type"); */
    200         return SDL_FALSE;
    201     }
    202 
    203     if (egl_extstr != NULL) {
    204         ext_start = egl_extstr;
    205 
    206         while (*ext_start) {
    207             ext_start = SDL_strstr(ext_start, ext);
    208             if (ext_start == NULL) {
    209                 return SDL_FALSE;
    210             }
    211             /* Check if the match is not just a substring of one of the extensions */
    212             if (ext_start == egl_extstr || *(ext_start - 1) == ' ') {
    213                 if (ext_start[ext_len] == ' ' || ext_start[ext_len] == 0) {
    214                     return SDL_TRUE;
    215                 }
    216             }
    217             /* If the search stopped in the middle of an extension, skip to the end of it */
    218             ext_start += ext_len;
    219             while (*ext_start != ' ' && *ext_start != 0) {
    220                 ext_start++;
    221             }
    222         }
    223     }
    224 
    225     return SDL_FALSE;
    226 }
    227 
    228 void *
    229 SDL_EGL_GetProcAddress(_THIS, const char *proc)
    230 {
    231     const Uint32 eglver = (((Uint32) _this->egl_data->egl_version_major) << 16) | ((Uint32) _this->egl_data->egl_version_minor);
    232     const SDL_bool is_egl_15_or_later = eglver >= ((((Uint32) 1) << 16) | 5);
    233     void *retval = NULL;
    234 
    235     /* EGL 1.5 can use eglGetProcAddress() for any symbol. 1.4 and earlier can't use it for core entry points. */
    236     if (!retval && is_egl_15_or_later && _this->egl_data->eglGetProcAddress) {
    237         retval = _this->egl_data->eglGetProcAddress(proc);
    238     }
    239 
    240     #ifndef __EMSCRIPTEN__  /* LoadFunction isn't needed on Emscripten and will call dlsym(), causing other problems. */
    241     /* Try SDL_LoadFunction() first for EGL <= 1.4, or as a fallback for >= 1.5. */
    242     if (!retval) {
    243         static char procname[64];
    244         retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, proc);
    245         /* just in case you need an underscore prepended... */
    246         if (!retval && (SDL_strlen(proc) < (sizeof (procname) - 1))) {
    247             procname[0] = '_';
    248             SDL_strlcpy(procname + 1, proc, sizeof (procname) - 1);
    249             retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, procname);
    250         }
    251     }
    252     #endif
    253 
    254     /* Try eglGetProcAddress if we're on <= 1.4 and still searching... */
    255     if (!retval && !is_egl_15_or_later && _this->egl_data->eglGetProcAddress) {
    256         retval = _this->egl_data->eglGetProcAddress(proc);
    257         if (retval) {
    258             return retval;
    259         }
    260     }
    261 
    262     return retval;
    263 }
    264 
    265 void
    266 SDL_EGL_UnloadLibrary(_THIS)
    267 {
    268     if (_this->egl_data) {
    269         if (_this->egl_data->egl_display) {
    270             _this->egl_data->eglTerminate(_this->egl_data->egl_display);
    271             _this->egl_data->egl_display = NULL;
    272         }
    273 
    274         if (_this->egl_data->dll_handle) {
    275             SDL_UnloadObject(_this->egl_data->dll_handle);
    276             _this->egl_data->dll_handle = NULL;
    277         }
    278         if (_this->egl_data->egl_dll_handle) {
    279             SDL_UnloadObject(_this->egl_data->egl_dll_handle);
    280             _this->egl_data->egl_dll_handle = NULL;
    281         }
    282         
    283         SDL_free(_this->egl_data);
    284         _this->egl_data = NULL;
    285     }
    286 }
    287 
    288 int
    289 SDL_EGL_LoadLibraryOnly(_THIS, const char *egl_path)
    290 {
    291     void *dll_handle = NULL, *egl_dll_handle = NULL; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */
    292     const char *path = NULL;
    293 #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
    294     const char *d3dcompiler;
    295 #endif
    296 #if SDL_VIDEO_DRIVER_RPI
    297     SDL_bool vc4 = (0 == access("/sys/module/vc4/", F_OK));
    298 #endif
    299 
    300     if (_this->egl_data) {
    301         return SDL_SetError("EGL context already created");
    302     }
    303 
    304     _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData));
    305     if (!_this->egl_data) {
    306         return SDL_OutOfMemory();
    307     }
    308 
    309 #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
    310     d3dcompiler = SDL_GetHint(SDL_HINT_VIDEO_WIN_D3DCOMPILER);
    311     if (d3dcompiler) {
    312         if (SDL_strcasecmp(d3dcompiler, "none") != 0) {
    313             if (SDL_LoadObject(d3dcompiler) == NULL) {
    314                 SDL_ClearError();
    315             }
    316         }
    317     } else {
    318         if (WIN_IsWindowsVistaOrGreater()) {
    319             /* Try the newer d3d compilers first */
    320             const char *d3dcompiler_list[] = {
    321                 "d3dcompiler_47.dll", "d3dcompiler_46.dll",
    322             };
    323             int i;
    324 
    325             for (i = 0; i < SDL_arraysize(d3dcompiler_list); ++i) {
    326                 if (SDL_LoadObject(d3dcompiler_list[i]) != NULL) {
    327                     break;
    328                 }
    329                 SDL_ClearError();
    330             }
    331         } else {
    332             if (SDL_LoadObject("d3dcompiler_43.dll") == NULL) {
    333                 SDL_ClearError();
    334             }
    335         }
    336     }
    337 #endif
    338 
    339 #ifndef SDL_VIDEO_STATIC_ANGLE
    340     /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */
    341     path = SDL_getenv("SDL_VIDEO_GL_DRIVER");
    342     if (path != NULL) {
    343         egl_dll_handle = SDL_LoadObject(path);
    344     }
    345 
    346     if (egl_dll_handle == NULL) {
    347         if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
    348             if (_this->gl_config.major_version > 1) {
    349                 path = DEFAULT_OGL_ES2;
    350                 egl_dll_handle = SDL_LoadObject(path);
    351 #ifdef ALT_OGL_ES2
    352                 if (egl_dll_handle == NULL && !vc4) {
    353                     path = ALT_OGL_ES2;
    354                     egl_dll_handle = SDL_LoadObject(path);
    355                 }
    356 #endif
    357 
    358             } else {
    359                 path = DEFAULT_OGL_ES;
    360                 egl_dll_handle = SDL_LoadObject(path);
    361                 if (egl_dll_handle == NULL) {
    362                     path = DEFAULT_OGL_ES_PVR;
    363                     egl_dll_handle = SDL_LoadObject(path);
    364                 }
    365 #ifdef ALT_OGL_ES2
    366                 if (egl_dll_handle == NULL && !vc4) {
    367                     path = ALT_OGL_ES2;
    368                     egl_dll_handle = SDL_LoadObject(path);
    369                 }
    370 #endif
    371             }
    372         }
    373 #ifdef DEFAULT_OGL         
    374         else {
    375             path = DEFAULT_OGL;
    376             egl_dll_handle = SDL_LoadObject(path);
    377         }
    378 #endif        
    379     }
    380     _this->egl_data->egl_dll_handle = egl_dll_handle;
    381 
    382     if (egl_dll_handle == NULL) {
    383         return SDL_SetError("Could not initialize OpenGL / GLES library");
    384     }
    385 
    386     /* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */
    387     if (egl_path != NULL) {
    388         dll_handle = SDL_LoadObject(egl_path);
    389     }   
    390     /* Try loading a EGL symbol, if it does not work try the default library paths */
    391     if (dll_handle == NULL || SDL_LoadFunction(dll_handle, "eglChooseConfig") == NULL) {
    392         if (dll_handle != NULL) {
    393             SDL_UnloadObject(dll_handle);
    394         }
    395         path = SDL_getenv("SDL_VIDEO_EGL_DRIVER");
    396         if (path == NULL) {
    397             path = DEFAULT_EGL;
    398         }
    399         dll_handle = SDL_LoadObject(path);
    400 
    401 #ifdef ALT_EGL
    402         if (dll_handle == NULL && !vc4) {
    403             path = ALT_EGL;
    404             dll_handle = SDL_LoadObject(path);
    405         }
    406 #endif
    407 
    408         if (dll_handle == NULL || SDL_LoadFunction(dll_handle, "eglChooseConfig") == NULL) {
    409             if (dll_handle != NULL) {
    410                 SDL_UnloadObject(dll_handle);
    411             }
    412             return SDL_SetError("Could not load EGL library");
    413         }
    414         SDL_ClearError();
    415     }
    416 #endif
    417 
    418     _this->egl_data->dll_handle = dll_handle;
    419 
    420     /* Load new function pointers */
    421     LOAD_FUNC(eglGetDisplay);
    422     LOAD_FUNC(eglInitialize);
    423     LOAD_FUNC(eglTerminate);
    424     LOAD_FUNC(eglGetProcAddress);
    425     LOAD_FUNC(eglChooseConfig);
    426     LOAD_FUNC(eglGetConfigAttrib);
    427     LOAD_FUNC(eglCreateContext);
    428     LOAD_FUNC(eglDestroyContext);
    429     LOAD_FUNC(eglCreatePbufferSurface);
    430     LOAD_FUNC(eglCreateWindowSurface);
    431     LOAD_FUNC(eglDestroySurface);
    432     LOAD_FUNC(eglMakeCurrent);
    433     LOAD_FUNC(eglSwapBuffers);
    434     LOAD_FUNC(eglSwapInterval);
    435     LOAD_FUNC(eglWaitNative);
    436     LOAD_FUNC(eglWaitGL);
    437     LOAD_FUNC(eglBindAPI);
    438     LOAD_FUNC(eglQueryAPI);
    439     LOAD_FUNC(eglQueryString);
    440     LOAD_FUNC(eglGetError);
    441     LOAD_FUNC_EGLEXT(eglQueryDevicesEXT);
    442     LOAD_FUNC_EGLEXT(eglGetPlatformDisplayEXT);
    443     /* Atomic functions */
    444     LOAD_FUNC_EGLEXT(eglCreateSyncKHR);
    445     LOAD_FUNC_EGLEXT(eglDestroySyncKHR);
    446     LOAD_FUNC_EGLEXT(eglDupNativeFenceFDANDROID);
    447     LOAD_FUNC_EGLEXT(eglWaitSyncKHR);
    448     LOAD_FUNC_EGLEXT(eglClientWaitSyncKHR);
    449     /* Atomic functions end */
    450 
    451     if (path) {
    452         SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
    453     } else {
    454         *_this->gl_config.driver_path = '\0';
    455     }
    456 
    457     return 0;
    458 }
    459 
    460 static void
    461 SDL_EGL_GetVersion(_THIS) {
    462     if (_this->egl_data->eglQueryString) {
    463         const char *egl_version = _this->egl_data->eglQueryString(_this->egl_data->egl_display, EGL_VERSION);
    464         if (egl_version) {
    465             int major = 0, minor = 0;
    466             if (SDL_sscanf(egl_version, "%d.%d", &major, &minor) == 2) {
    467                 _this->egl_data->egl_version_major = major;
    468                 _this->egl_data->egl_version_minor = minor;
    469             } else {
    470                 SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not parse EGL version string: %s", egl_version);
    471             }
    472         }
    473     }
    474 }
    475 
    476 int
    477 SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display, EGLenum platform)
    478 {
    479     int egl_version_major, egl_version_minor;
    480     int library_load_retcode = SDL_EGL_LoadLibraryOnly(_this, egl_path);
    481     if (library_load_retcode != 0) {
    482         return library_load_retcode;
    483     }
    484 
    485     /* EGL 1.5 allows querying for client version with EGL_NO_DISPLAY */
    486     SDL_EGL_GetVersion(_this);
    487 
    488     egl_version_major = _this->egl_data->egl_version_major;
    489     egl_version_minor = _this->egl_data->egl_version_minor;
    490 
    491     if (egl_version_major == 1 && egl_version_minor == 5) {
    492         LOAD_FUNC(eglGetPlatformDisplay);
    493     }
    494 
    495     _this->egl_data->egl_display = EGL_NO_DISPLAY;
    496 #if !defined(__WINRT__)
    497     if (platform) {
    498         if (egl_version_major == 1 && egl_version_minor == 5) {
    499             _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(size_t)native_display, NULL);
    500         } else {
    501             if (SDL_EGL_HasExtension(_this, SDL_EGL_CLIENT_EXTENSION, "EGL_EXT_platform_base")) {
    502                 _this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddress(_this, "eglGetPlatformDisplayEXT");
    503                 if (_this->egl_data->eglGetPlatformDisplayEXT) {
    504                     _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(platform, (void *)(size_t)native_display, NULL);
    505                 }
    506             }
    507         }
    508     }
    509     /* Try the implementation-specific eglGetDisplay even if eglGetPlatformDisplay fails */
    510     if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
    511         _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
    512     }
    513     if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
    514         _this->gl_config.driver_loaded = 0;
    515         *_this->gl_config.driver_path = '\0';
    516         return SDL_SetError("Could not get EGL display");
    517     }
    518     
    519     if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
    520         _this->gl_config.driver_loaded = 0;
    521         *_this->gl_config.driver_path = '\0';
    522         return SDL_SetError("Could not initialize EGL");
    523     }
    524 #endif
    525 
    526     /* Get the EGL version with a valid egl_display, for EGL <= 1.4 */
    527     SDL_EGL_GetVersion(_this);
    528 
    529     _this->egl_data->is_offscreen = 0;
    530 
    531     return 0;
    532 }
    533 
    534 /**
    535    On multi GPU machines EGL device 0 is not always the first valid GPU.
    536    Container environments can restrict access to some GPUs that are still listed in the EGL
    537    device list. If the requested device is a restricted GPU and cannot be used
    538    (eglInitialize() will fail) then attempt to automatically and silently select the next
    539    valid available GPU for EGL to use.
    540 */
    541 
    542 int
    543 SDL_EGL_InitializeOffscreen(_THIS, int device)
    544 {
    545     void *egl_devices[SDL_EGL_MAX_DEVICES];
    546     EGLint num_egl_devices = 0;
    547     const char *egl_device_hint;
    548 
    549     if (_this->gl_config.driver_loaded != 1) {
    550         return SDL_SetError("SDL_EGL_LoadLibraryOnly() has not been called or has failed.");
    551     }
    552 
    553     /* Check for all extensions that are optional until used and fail if any is missing */
    554     if (_this->egl_data->eglQueryDevicesEXT == NULL) {
    555         return SDL_SetError("eglQueryDevicesEXT is missing (EXT_device_enumeration not supported by the drivers?)");
    556     }
    557 
    558     if (_this->egl_data->eglGetPlatformDisplayEXT == NULL) {
    559         return SDL_SetError("eglGetPlatformDisplayEXT is missing (EXT_platform_base not supported by the drivers?)");
    560     }
    561 
    562     if (_this->egl_data->eglQueryDevicesEXT(SDL_EGL_MAX_DEVICES, egl_devices, &num_egl_devices) != EGL_TRUE) {
    563         return SDL_SetError("eglQueryDevicesEXT() failed");
    564     }
    565 
    566     egl_device_hint = SDL_GetHint("SDL_HINT_EGL_DEVICE");
    567     if (egl_device_hint) {
    568         device = SDL_atoi(egl_device_hint);
    569 
    570         if (device >= num_egl_devices) {
    571             return SDL_SetError("Invalid EGL device is requested.");
    572         }
    573 
    574         _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, egl_devices[device], NULL);
    575 
    576         if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
    577             return SDL_SetError("eglGetPlatformDisplayEXT() failed.");
    578         }
    579 
    580         if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
    581             return SDL_SetError("Could not initialize EGL");
    582         }
    583     }
    584     else {
    585         int i;
    586         SDL_bool found = SDL_FALSE;
    587         EGLDisplay attempted_egl_display;
    588 
    589         /* If no hint is provided lets look for the first device/display that will allow us to eglInit */
    590         for (i = 0; i < num_egl_devices; i++) {
    591             attempted_egl_display = _this->egl_data->eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, egl_devices[i], NULL);
    592 
    593             if (attempted_egl_display == EGL_NO_DISPLAY) {
    594                 continue;
    595             }
    596 
    597             if (_this->egl_data->eglInitialize(attempted_egl_display, NULL, NULL) != EGL_TRUE) {
    598                 _this->egl_data->eglTerminate(attempted_egl_display);
    599                 continue;
    600             }
    601 
    602             /* We did not fail, we'll pick this one! */
    603             _this->egl_data->egl_display = attempted_egl_display;
    604             found = SDL_TRUE;
    605 
    606             break;
    607         }
    608 
    609         if (!found) {
    610             return SDL_SetError("Could not find a valid EGL device to initialize");
    611         }
    612     }
    613 
    614     /* Get the EGL version with a valid egl_display, for EGL <= 1.4 */
    615     SDL_EGL_GetVersion(_this);
    616 
    617     _this->egl_data->is_offscreen = 1;
    618 
    619     return 0;
    620 }
    621 
    622 void
    623 SDL_EGL_SetRequiredVisualId(_THIS, int visual_id) 
    624 {
    625     _this->egl_data->egl_required_visual_id=visual_id;
    626 }
    627 
    628 #ifdef DUMP_EGL_CONFIG
    629 
    630 #define ATTRIBUTE(_attr) { _attr, #_attr }
    631 
    632 typedef struct {
    633     EGLint attribute;
    634     char const* name;
    635 } Attribute;
    636 
    637 Attribute attributes[] = {
    638         ATTRIBUTE( EGL_BUFFER_SIZE ),
    639         ATTRIBUTE( EGL_ALPHA_SIZE ),
    640         ATTRIBUTE( EGL_BLUE_SIZE ),
    641         ATTRIBUTE( EGL_GREEN_SIZE ),
    642         ATTRIBUTE( EGL_RED_SIZE ),
    643         ATTRIBUTE( EGL_DEPTH_SIZE ),
    644         ATTRIBUTE( EGL_STENCIL_SIZE ),
    645         ATTRIBUTE( EGL_CONFIG_CAVEAT ),
    646         ATTRIBUTE( EGL_CONFIG_ID ),
    647         ATTRIBUTE( EGL_LEVEL ),
    648         ATTRIBUTE( EGL_MAX_PBUFFER_HEIGHT ),
    649         ATTRIBUTE( EGL_MAX_PBUFFER_WIDTH ),
    650         ATTRIBUTE( EGL_MAX_PBUFFER_PIXELS ),
    651         ATTRIBUTE( EGL_NATIVE_RENDERABLE ),
    652         ATTRIBUTE( EGL_NATIVE_VISUAL_ID ),
    653         ATTRIBUTE( EGL_NATIVE_VISUAL_TYPE ),
    654         ATTRIBUTE( EGL_SAMPLES ),
    655         ATTRIBUTE( EGL_SAMPLE_BUFFERS ),
    656         ATTRIBUTE( EGL_SURFACE_TYPE ),
    657         ATTRIBUTE( EGL_TRANSPARENT_TYPE ),
    658         ATTRIBUTE( EGL_TRANSPARENT_BLUE_VALUE ),
    659         ATTRIBUTE( EGL_TRANSPARENT_GREEN_VALUE ),
    660         ATTRIBUTE( EGL_TRANSPARENT_RED_VALUE ),
    661         ATTRIBUTE( EGL_BIND_TO_TEXTURE_RGB ),
    662         ATTRIBUTE( EGL_BIND_TO_TEXTURE_RGBA ),
    663         ATTRIBUTE( EGL_MIN_SWAP_INTERVAL ),
    664         ATTRIBUTE( EGL_MAX_SWAP_INTERVAL ),
    665         ATTRIBUTE( EGL_LUMINANCE_SIZE ),
    666         ATTRIBUTE( EGL_ALPHA_MASK_SIZE ),
    667         ATTRIBUTE( EGL_COLOR_BUFFER_TYPE ),
    668         ATTRIBUTE( EGL_RENDERABLE_TYPE ),
    669         ATTRIBUTE( EGL_MATCH_NATIVE_PIXMAP ),
    670         ATTRIBUTE( EGL_CONFORMANT ),
    671 };
    672 
    673 
    674 static void dumpconfig(_THIS, EGLConfig config)
    675 {
    676     int attr;
    677     for (attr = 0 ; attr<sizeof(attributes)/sizeof(Attribute) ; attr++) {
    678         EGLint value;
    679         _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, config, attributes[attr].attribute, &value);
    680         SDL_Log("\t%-32s: %10d (0x%08x)\n", attributes[attr].name, value, value);
    681     }
    682 }
    683 
    684 #endif /* DUMP_EGL_CONFIG */
    685 
    686 int
    687 SDL_EGL_ChooseConfig(_THIS) 
    688 {
    689 /* 64 seems nice. */
    690     EGLint attribs[64];
    691     EGLint found_configs = 0, value;
    692     /* 128 seems even nicer here */
    693     EGLConfig configs[128];
    694     SDL_bool has_matching_format = SDL_FALSE;
    695     int i, j, best_bitdiff = -1, bitdiff;
    696    
    697     if (!_this->egl_data) {
    698         /* The EGL library wasn't loaded, SDL_GetError() should have info */
    699         return -1;
    700     }
    701   
    702     /* Get a valid EGL configuration */
    703     i = 0;
    704     attribs[i++] = EGL_RED_SIZE;
    705     attribs[i++] = _this->gl_config.red_size;
    706     attribs[i++] = EGL_GREEN_SIZE;
    707     attribs[i++] = _this->gl_config.green_size;
    708     attribs[i++] = EGL_BLUE_SIZE;
    709     attribs[i++] = _this->gl_config.blue_size;
    710     
    711     if (_this->gl_config.alpha_size) {
    712         attribs[i++] = EGL_ALPHA_SIZE;
    713         attribs[i++] = _this->gl_config.alpha_size;
    714     }
    715     
    716     if (_this->gl_config.buffer_size) {
    717         attribs[i++] = EGL_BUFFER_SIZE;
    718         attribs[i++] = _this->gl_config.buffer_size;
    719     }
    720     
    721     attribs[i++] = EGL_DEPTH_SIZE;
    722     attribs[i++] = _this->gl_config.depth_size;
    723     
    724     if (_this->gl_config.stencil_size) {
    725         attribs[i++] = EGL_STENCIL_SIZE;
    726         attribs[i++] = _this->gl_config.stencil_size;
    727     }
    728     
    729     if (_this->gl_config.multisamplebuffers) {
    730         attribs[i++] = EGL_SAMPLE_BUFFERS;
    731         attribs[i++] = _this->gl_config.multisamplebuffers;
    732     }
    733     
    734     if (_this->gl_config.multisamplesamples) {
    735         attribs[i++] = EGL_SAMPLES;
    736         attribs[i++] = _this->gl_config.multisamplesamples;
    737     }
    738 
    739     if (_this->egl_data->is_offscreen) {
    740         attribs[i++] = EGL_SURFACE_TYPE;
    741         attribs[i++] = EGL_PBUFFER_BIT;
    742     }
    743 
    744     attribs[i++] = EGL_RENDERABLE_TYPE;
    745     if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
    746 #ifdef EGL_KHR_create_context
    747         if (_this->gl_config.major_version >= 3 &&
    748             SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_create_context")) {
    749             attribs[i++] = EGL_OPENGL_ES3_BIT_KHR;
    750         } else
    751 #endif
    752         if (_this->gl_config.major_version >= 2) {
    753             attribs[i++] = EGL_OPENGL_ES2_BIT;
    754         } else {
    755             attribs[i++] = EGL_OPENGL_ES_BIT;
    756         }
    757         _this->egl_data->eglBindAPI(EGL_OPENGL_ES_API);
    758     } else {
    759         attribs[i++] = EGL_OPENGL_BIT;
    760         _this->egl_data->eglBindAPI(EGL_OPENGL_API);
    761     }
    762 
    763     if (_this->egl_data->egl_surfacetype) {
    764         attribs[i++] = EGL_SURFACE_TYPE;
    765         attribs[i++] = _this->egl_data->egl_surfacetype;
    766     }
    767 
    768     attribs[i++] = EGL_NONE;
    769 
    770     if (_this->egl_data->eglChooseConfig(_this->egl_data->egl_display,
    771         attribs,
    772         configs, SDL_arraysize(configs),
    773         &found_configs) == EGL_FALSE ||
    774         found_configs == 0) {
    775         return SDL_EGL_SetError("Couldn't find matching EGL config", "eglChooseConfig");
    776     }
    777 
    778     /* first ensure that a found config has a matching format, or the function will fall through. */
    779     for (i = 0; i < found_configs; i++ ) {
    780         if (_this->egl_data->egl_required_visual_id)
    781         {
    782             EGLint format;
    783             _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display,
    784                                             configs[i],
    785                                             EGL_NATIVE_VISUAL_ID, &format);
    786             if (_this->egl_data->egl_required_visual_id == format)
    787                 has_matching_format = SDL_TRUE;
    788         }
    789     }
    790 
    791     /* eglChooseConfig returns a number of configurations that match or exceed the requested attribs. */
    792     /* From those, we select the one that matches our requirements more closely via a makeshift algorithm */
    793 
    794     for (i = 0; i < found_configs; i++ ) {
    795         if (has_matching_format && _this->egl_data->egl_required_visual_id)
    796         {
    797             EGLint format;
    798             _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display,
    799                                             configs[i], 
    800                                             EGL_NATIVE_VISUAL_ID, &format);
    801             if (_this->egl_data->egl_required_visual_id != format)
    802                 continue;
    803         }
    804 
    805         bitdiff = 0;
    806         for (j = 0; j < SDL_arraysize(attribs) - 1; j += 2) {
    807             if (attribs[j] == EGL_NONE) {
    808                break;
    809             }
    810             
    811             if ( attribs[j+1] != EGL_DONT_CARE && (
    812                 attribs[j] == EGL_RED_SIZE ||
    813                 attribs[j] == EGL_GREEN_SIZE ||
    814                 attribs[j] == EGL_BLUE_SIZE ||
    815                 attribs[j] == EGL_ALPHA_SIZE ||
    816                 attribs[j] == EGL_DEPTH_SIZE ||
    817                 attribs[j] == EGL_STENCIL_SIZE)) {
    818                 _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, configs[i], attribs[j], &value);
    819                 bitdiff += value - attribs[j + 1]; /* value is always >= attrib */
    820             }
    821         }
    822 
    823         if (bitdiff < best_bitdiff || best_bitdiff == -1) {
    824             _this->egl_data->egl_config = configs[i];
    825             
    826             best_bitdiff = bitdiff;
    827         }
    828 
    829         if (bitdiff == 0) {
    830             break; /* we found an exact match! */
    831         }
    832     }
    833 
    834 #ifdef DUMP_EGL_CONFIG
    835     dumpconfig(_this, _this->egl_data->egl_config);
    836 #endif
    837     
    838     return 0;
    839 }
    840 
    841 SDL_GLContext
    842 SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
    843 {
    844     /* max 14 values plus terminator. */
    845     EGLint attribs[15];
    846     int attr = 0;
    847 
    848     EGLContext egl_context, share_context = EGL_NO_CONTEXT;
    849     EGLint profile_mask = _this->gl_config.profile_mask;
    850     EGLint major_version = _this->gl_config.major_version;
    851     EGLint minor_version = _this->gl_config.minor_version;
    852     SDL_bool profile_es = (profile_mask == SDL_GL_CONTEXT_PROFILE_ES);
    853 
    854     if (!_this->egl_data) {
    855         /* The EGL library wasn't loaded, SDL_GetError() should have info */
    856         return NULL;
    857     }
    858 
    859     if (_this->gl_config.share_with_current_context) {
    860         share_context = (EGLContext)SDL_GL_GetCurrentContext();
    861     }
    862 
    863 #if SDL_VIDEO_DRIVER_ANDROID
    864     if ((_this->gl_config.flags & SDL_GL_CONTEXT_DEBUG_FLAG) != 0) {
    865         /* If SDL_GL_CONTEXT_DEBUG_FLAG is set but EGL_KHR_debug unsupported, unset.
    866          * This is required because some Android devices like to complain about it
    867          * by "silently" failing, logging a hint which could be easily overlooked:
    868          * E/libEGL  (26984): validate_display:255 error 3008 (EGL_BAD_DISPLAY)
    869          * The following explicitly checks for EGL_KHR_debug before EGL 1.5
    870          */
    871         int egl_version_major = _this->egl_data->egl_version_major;
    872         int egl_version_minor = _this->egl_data->egl_version_minor;
    873         if (((egl_version_major < 1) || (egl_version_major == 1 && egl_version_minor < 5)) &&
    874             !SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_debug")) {
    875             /* SDL profile bits match EGL profile bits. */
    876             _this->gl_config.flags &= ~SDL_GL_CONTEXT_DEBUG_FLAG;
    877         }
    878     }
    879 #endif
    880 
    881     /* Set the context version and other attributes. */
    882     if ((major_version < 3 || (minor_version == 0 && profile_es)) &&
    883         _this->gl_config.flags == 0 &&
    884         (profile_mask == 0 || profile_es)) {
    885         /* Create a context without using EGL_KHR_create_context attribs.
    886          * When creating a GLES context without EGL_KHR_create_context we can
    887          * only specify the major version. When creating a desktop GL context
    888          * we can't specify any version, so we only try in that case when the
    889          * version is less than 3.0 (matches SDL's GLX/WGL behavior.)
    890          */
    891         if (profile_es) {
    892             attribs[attr++] = EGL_CONTEXT_CLIENT_VERSION;
    893             attribs[attr++] = SDL_max(major_version, 1);
    894         }
    895     } else {
    896 #ifdef EGL_KHR_create_context
    897         /* The Major/minor version, context profiles, and context flags can
    898          * only be specified when this extension is available.
    899          */
    900         if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_create_context")) {
    901             attribs[attr++] = EGL_CONTEXT_MAJOR_VERSION_KHR;
    902             attribs[attr++] = major_version;
    903             attribs[attr++] = EGL_CONTEXT_MINOR_VERSION_KHR;
    904             attribs[attr++] = minor_version;
    905 
    906             /* SDL profile bits match EGL profile bits. */
    907             if (profile_mask != 0 && profile_mask != SDL_GL_CONTEXT_PROFILE_ES) {
    908                 attribs[attr++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
    909                 attribs[attr++] = profile_mask;
    910             }
    911 
    912             /* SDL flags match EGL flags. */
    913             if (_this->gl_config.flags != 0) {
    914                 attribs[attr++] = EGL_CONTEXT_FLAGS_KHR;
    915                 attribs[attr++] = _this->gl_config.flags;
    916             }
    917         } else
    918 #endif /* EGL_KHR_create_context */
    919         {
    920             SDL_SetError("Could not create EGL context (context attributes are not supported)");
    921             return NULL;
    922         }
    923     }
    924 
    925     if (_this->gl_config.no_error) {
    926 #ifdef EGL_KHR_create_context_no_error
    927         if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_create_context_no_error")) {
    928             attribs[attr++] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
    929             attribs[attr++] = _this->gl_config.no_error;
    930         } else
    931 #endif
    932         {
    933             SDL_SetError("EGL implementation does not support no_error contexts");
    934             return NULL;
    935         }
    936     }
    937 
    938     attribs[attr++] = EGL_NONE;
    939 
    940     /* Bind the API */
    941     if (profile_es) {
    942         _this->egl_data->eglBindAPI(EGL_OPENGL_ES_API);
    943     } else {
    944         _this->egl_data->eglBindAPI(EGL_OPENGL_API);
    945     }
    946 
    947     egl_context = _this->egl_data->eglCreateContext(_this->egl_data->egl_display,
    948                                       _this->egl_data->egl_config,
    949                                       share_context, attribs);
    950 
    951     if (egl_context == EGL_NO_CONTEXT) {
    952         SDL_EGL_SetError("Could not create EGL context", "eglCreateContext");
    953         return NULL;
    954     }
    955 
    956     _this->egl_data->egl_swapinterval = 0;
    957 
    958     if (SDL_EGL_MakeCurrent(_this, egl_surface, egl_context) < 0) {
    959         /* Save the SDL error set by SDL_EGL_MakeCurrent */
    960         char errorText[1024];
    961         SDL_strlcpy(errorText, SDL_GetError(), SDL_arraysize(errorText));
    962 
    963         /* Delete the context, which may alter the value returned by SDL_GetError() */
    964         SDL_EGL_DeleteContext(_this, egl_context);
    965 
    966         /* Restore the SDL error */
    967         SDL_SetError("%s", errorText);
    968 
    969         return NULL;
    970     }
    971 
    972     /* Check whether making contexts current without a surface is supported.
    973      * First condition: EGL must support it. That's the case for EGL 1.5
    974      * or later, or if the EGL_KHR_surfaceless_context extension is present. */
    975     if ((_this->egl_data->egl_version_major > 1) ||
    976         ((_this->egl_data->egl_version_major == 1) && (_this->egl_data->egl_version_minor >= 5)) ||
    977         SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_surfaceless_context"))
    978     {
    979         /* Secondary condition: The client API must support it. */
    980         if (profile_es) {
    981             /* On OpenGL ES, the GL_OES_surfaceless_context extension must be
    982              * present. */
    983             if (SDL_GL_ExtensionSupported("GL_OES_surfaceless_context")) {
    984                 _this->gl_allow_no_surface = SDL_TRUE;
    985             }
    986 #if SDL_VIDEO_OPENGL
    987         } else {
    988             /* Desktop OpenGL supports it by default from version 3.0 on. */
    989             void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
    990             glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv");
    991             if (glGetIntegervFunc) {
    992                 GLint v = 0;
    993                 glGetIntegervFunc(GL_MAJOR_VERSION, &v);
    994                 if (v >= 3) {
    995                     _this->gl_allow_no_surface = SDL_TRUE;
    996                 }
    997             }
    998 #endif
    999         }
   1000     }
   1001 
   1002     return (SDL_GLContext) egl_context;
   1003 }
   1004 
   1005 int
   1006 SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context)
   1007 {
   1008     EGLContext egl_context = (EGLContext) context;
   1009 
   1010     if (!_this->egl_data) {
   1011         return SDL_SetError("OpenGL not initialized");
   1012     }
   1013     
   1014     /* The android emulator crashes badly if you try to eglMakeCurrent 
   1015      * with a valid context and invalid surface, so we have to check for both here.
   1016      */
   1017     if (!egl_context || (!egl_surface && !_this->gl_allow_no_surface)) {
   1018          _this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
   1019     } else {
   1020         if (!_this->egl_data->eglMakeCurrent(_this->egl_data->egl_display,
   1021             egl_surface, egl_surface, egl_context)) {
   1022             return SDL_EGL_SetError("Unable to make EGL context current", "eglMakeCurrent");
   1023         }
   1024     }
   1025       
   1026     return 0;
   1027 }
   1028 
   1029 int
   1030 SDL_EGL_SetSwapInterval(_THIS, int interval)
   1031 {
   1032     EGLBoolean status;
   1033     
   1034     if (!_this->egl_data) {
   1035         return SDL_SetError("EGL not initialized");
   1036     }
   1037     
   1038     status = _this->egl_data->eglSwapInterval(_this->egl_data->egl_display, interval);
   1039     if (status == EGL_TRUE) {
   1040         _this->egl_data->egl_swapinterval = interval;
   1041         return 0;
   1042     }
   1043     
   1044     return SDL_EGL_SetError("Unable to set the EGL swap interval", "eglSwapInterval");
   1045 }
   1046 
   1047 int
   1048 SDL_EGL_GetSwapInterval(_THIS)
   1049 {
   1050     if (!_this->egl_data) {
   1051         SDL_SetError("EGL not initialized");
   1052         return 0;
   1053     }
   1054     
   1055     return _this->egl_data->egl_swapinterval;
   1056 }
   1057 
   1058 int
   1059 SDL_EGL_SwapBuffers(_THIS, EGLSurface egl_surface)
   1060 {
   1061     if (!_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, egl_surface)) {
   1062         return SDL_EGL_SetError("unable to show color buffer in an OS-native window", "eglSwapBuffers");
   1063     }
   1064     return 0;
   1065 }
   1066 
   1067 void
   1068 SDL_EGL_DeleteContext(_THIS, SDL_GLContext context)
   1069 {
   1070     EGLContext egl_context = (EGLContext) context;
   1071 
   1072     /* Clean up GLES and EGL */
   1073     if (!_this->egl_data) {
   1074         return;
   1075     }
   1076     
   1077     if (egl_context != NULL && egl_context != EGL_NO_CONTEXT) {
   1078         _this->egl_data->eglDestroyContext(_this->egl_data->egl_display, egl_context);
   1079     }
   1080         
   1081 }
   1082 
   1083 EGLSurface *
   1084 SDL_EGL_CreateSurface(_THIS, NativeWindowType nw) 
   1085 {
   1086     /* max 2 values plus terminator. */
   1087     EGLint attribs[3];
   1088     int attr = 0;
   1089 
   1090     EGLSurface * surface;
   1091 
   1092     if (SDL_EGL_ChooseConfig(_this) != 0) {
   1093         return EGL_NO_SURFACE;
   1094     }
   1095     
   1096 #if SDL_VIDEO_DRIVER_ANDROID
   1097     {
   1098         /* Android docs recommend doing this!
   1099          * Ref: http://developer.android.com/reference/android/app/NativeActivity.html 
   1100          */
   1101         EGLint format;
   1102         _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display,
   1103                                             _this->egl_data->egl_config, 
   1104                                             EGL_NATIVE_VISUAL_ID, &format);
   1105 
   1106         ANativeWindow_setBuffersGeometry(nw, 0, 0, format);
   1107 
   1108         /* Update SurfaceView holder format.
   1109          * May triggers a sequence surfaceDestroyed(), surfaceCreated(), surfaceChanged(). */
   1110         Android_JNI_SetSurfaceViewFormat(format);
   1111     }
   1112 #endif    
   1113     if (_this->gl_config.framebuffer_srgb_capable) {
   1114 #ifdef EGL_KHR_gl_colorspace
   1115         if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_gl_colorspace")) {
   1116             attribs[attr++] = EGL_GL_COLORSPACE_KHR;
   1117             attribs[attr++] = EGL_GL_COLORSPACE_SRGB_KHR;
   1118         } else
   1119 #endif
   1120         {
   1121             SDL_SetError("EGL implementation does not support sRGB system framebuffers");
   1122             return EGL_NO_SURFACE;
   1123         }
   1124     }
   1125 
   1126     attribs[attr++] = EGL_NONE;
   1127     
   1128     surface = _this->egl_data->eglCreateWindowSurface(
   1129             _this->egl_data->egl_display,
   1130             _this->egl_data->egl_config,
   1131             nw, &attribs[0]);
   1132     if (surface == EGL_NO_SURFACE) {
   1133         SDL_EGL_SetError("unable to create an EGL window surface", "eglCreateWindowSurface");
   1134     }
   1135     return surface;
   1136 }
   1137 
   1138 EGLSurface
   1139 SDL_EGL_CreateOffscreenSurface(_THIS, int width, int height)
   1140 {
   1141     EGLint attributes[] = {
   1142         EGL_WIDTH, width,
   1143         EGL_HEIGHT, height,
   1144         EGL_NONE
   1145     };
   1146 
   1147     if (SDL_EGL_ChooseConfig(_this) != 0) {
   1148         return EGL_NO_SURFACE;
   1149     }
   1150 
   1151     return _this->egl_data->eglCreatePbufferSurface(
   1152         _this->egl_data->egl_display,
   1153         _this->egl_data->egl_config,
   1154         attributes);
   1155 }
   1156 
   1157 void
   1158 SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface) 
   1159 {
   1160     if (!_this->egl_data) {
   1161         return;
   1162     }
   1163     
   1164     if (egl_surface != EGL_NO_SURFACE) {
   1165         _this->egl_data->eglDestroySurface(_this->egl_data->egl_display, egl_surface);
   1166     }
   1167 }
   1168 
   1169 #endif /* SDL_VIDEO_OPENGL_EGL */
   1170 
   1171 /* vi: set ts=4 sw=4 expandtab: */
   1172