diff --git a/CMakeLists.txt b/CMakeLists.txt index 4aec79f0e..572918693 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -314,6 +314,8 @@ set_option(VIDEO_COCOA "Use Cocoa video driver" ${APPLE}) set_option(DIRECTX "Use DirectX for Windows audio/video" ${WINDOWS}) set_option(RENDER_D3D "Enable the Direct3D render driver" ${WINDOWS}) set_option(VIDEO_VIVANTE "Use Vivante EGL video driver" ${UNIX_SYS}) +set_option(VIDEO_KMSDRM "Use KMS DRM video driver" ${UNIX_SYS}) +dep_option(KMSDRM_SHARED "Dynamically load KMS DRM support" ON "VIDEO_KMSDRM" OFF) # TODO: We should (should we?) respect cmake's ${BUILD_SHARED_LIBS} flag here # The options below are for compatibility to configure's default behaviour. @@ -917,6 +919,7 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID) CheckOpenGLESX11() CheckWayland() CheckVivante() + CheckKMSDRM() endif() if(LINUX) diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index 770378828..6f6a41f90 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -1149,3 +1149,46 @@ macro(CheckRPI) endif(SDL_VIDEO AND HAVE_VIDEO_RPI) endif(VIDEO_RPI) endmacro(CheckRPI) + +# Requires: +# - EGL +# - PkgCheckModules +# Optional: +# - KMSDRM_SHARED opt +# - HAVE_DLOPEN opt +macro(CheckKMSDRM) + if(VIDEO_KMSDRM) + pkg_check_modules(KMSDRM libdrm gbm egl) + if(KMSDRM_FOUND) + link_directories( + ${KMSDRM_LIBRARY_DIRS} + ) + include_directories( + ${KMSDRM_INCLUDE_DIRS} + ) + set(HAVE_VIDEO_KMSDRM TRUE) + set(HAVE_SDL_VIDEO TRUE) + + file(GLOB KMSDRM_SOURCES ${SDL2_SOURCE_DIR}/src/video/kmsdrm/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${KMSDRM_SOURCES}) + + list(APPEND EXTRA_CFLAGS ${KMSDRM_CLFLAGS}) + + set(SDL_VIDEO_DRIVER_KMSDRM 1) + + if(KMSDRM_SHARED) + if(NOT HAVE_DLOPEN) + message_warn("You must have SDL_LoadObject() support for dynamic KMS/DRM loading") + else() + FindLibraryAndSONAME(drm) + FindLibraryAndSONAME(gbm) + set(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC "\"${DRM_LIB_SONAME}\"") + set(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM "\"${GBM_LIB_SONAME}\"") + set(HAVE_KMSDRM_SHARED TRUE) + endif() + else() + set(EXTRA_LIBS ${KMSDRM_LIBRARIES} ${EXTRA_LIBS}) + endif() + endif() + endif() +endmacro() diff --git a/configure.in b/configure.in index 769ea81a5..0fa88c3e2 100644 --- a/configure.in +++ b/configure.in @@ -2084,6 +2084,81 @@ AC_MSG_WARN("directfb $directfb_lib") fi } +dnl Find KMSDRM +CheckKMSDRM() +{ + AC_ARG_ENABLE(video-kmsdrm, +AC_HELP_STRING([--enable-video-kmsdrm], [use KMSDRM video driver [[default=no]]]), + , enable_video_kmsdrm=no) + + if test x$enable_video = xyes -a x$enable_video_kmsdrm = xyes; then + video_kmsdrm=no + libdrm_avail=no + libgbm_avail=no + + LIBDRM_REQUIRED_VERSION=2.4.46 + LIBGBM_REQUIRED_VERSION=9.0.0 + + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + if test x$PKG_CONFIG != xno; then + if $PKG_CONFIG --atleast-pkgconfig-version 0.7; then + if $PKG_CONFIG --atleast-version $LIBDRM_REQUIRED_VERSION libdrm; then + LIBDRM_CFLAGS=`$PKG_CONFIG --cflags libdrm` + LIBDRM_LIBS=`$PKG_CONFIG --libs libdrm` + LIBDRM_PREFIX=`$PKG_CONFIG --variable=prefix libdrm` + libdrm_avail=yes + fi + if $PKG_CONFIG --atleast-version $LIBGBM_REQUIRED_VERSION gbm; then + LIBGBM_CFLAGS=`$PKG_CONFIG --cflags gbm` + LIBGBM_LIBS=`$PKG_CONFIG --libs gbm` + LIBGBM_PREFIX=`$PKG_CONFIG --variable=prefix gbm` + libgbm_avail=yes + fi + if test x$libdrm_avail = xyes -a x$libgbm_avail = xyes; then + video_kmsdrm=yes + fi + + AC_MSG_CHECKING(for libdrm $LIBDRM_REQUIRED_VERSION library for kmsdrm support) + AC_MSG_RESULT($libdrm_avail) + AC_MSG_CHECKING(for libgbm $LIBGBM_REQUIRED_VERSION library for kmsdrm support) + AC_MSG_RESULT($libgbm_avail) + + if test x$video_kmsdrm = xyes; then + AC_ARG_ENABLE(kmsdrm-shared, +AC_HELP_STRING([--enable-kmsdrm-shared], [dynamically load kmsdrm support [[default=yes]]]), + , enable_kmsdrm_shared=yes) + + AC_DEFINE(SDL_VIDEO_DRIVER_KMSDRM, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/video/kmsdrm/*.c" + EXTRA_CFLAGS="$EXTRA_CFLAGS $LIBDRM_CFLAGS $LIBGBM_CFLAGS" + + AC_MSG_CHECKING(for kmsdrm dynamic loading support) + kmsdrm_shared=no + drm_lib=[`find_lib "libdrm.so.*" "$DRM_LIBS"`] + gbm_lib=[`find_lib "libgbm.so.*" "$DRM_LIBS"`] + if test x$have_loadso != xyes && \ + test x$enable_kmsdrm_shared = xyes; then + AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic kmsdrm loading]) + fi + if test x$have_loadso = xyes && \ + test x$enable_kmsdrm_shared = xyes && test x$drm_lib != x && test x$gbm_lib != x; then + kmsdrm_shared=yes + AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC, "$drm_lib", [ ]) + AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM, "$gbm_lib", [ ]) + AC_DEFINE_UNQUOTED(HAVE_KMSDRM_SHARED, "TRUE", [ ]) + SUMMARY_video="${SUMMARY_video} kmsdrm(dynamic)" + else + EXTRA_LDFLAGS="$EXTRA_LDFLAGS $LIBDRM_LIBS $LIBGBM_LIBS" + SUMMARY_video="${SUMMARY_video} kmsdrm" + fi + AC_MSG_RESULT($kmsdrm_shared) + have_video=yes + fi + fi + fi + fi +} + dnl rcg04172001 Set up the Null video driver. CheckDummyVideo() { @@ -3148,6 +3223,7 @@ case "$host" in CheckLibSampleRate CheckX11 CheckDirectFB + CheckKMSDRM CheckOpenGLX11 CheckOpenGLESX11 CheckMir diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake index 2f236b945..3f6283a4d 100644 --- a/include/SDL_config.h.cmake +++ b/include/SDL_config.h.cmake @@ -291,6 +291,10 @@ #cmakedefine SDL_VIDEO_DRIVER_VIVANTE @SDL_VIDEO_DRIVER_VIVANTE@ #cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@ +#cmakedefine SDL_VIDEO_DRIVER_KMSDRM @SDL_VIDEO_DRIVER_KMSDRM@ +#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC@ +#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM@ + #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH @SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH@ #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC@ #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@ diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index 87a5b707a..8822a80e3 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -294,6 +294,9 @@ #undef SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON #undef SDL_VIDEO_DRIVER_X11 #undef SDL_VIDEO_DRIVER_RPI +#undef SDL_VIDEO_DRIVER_KMSDRM +#undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC +#undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM #undef SDL_VIDEO_DRIVER_ANDROID #undef SDL_VIDEO_DRIVER_EMSCRIPTEN #undef SDL_VIDEO_DRIVER_X11_DYNAMIC diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index c7f76e68b..832d52bfd 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -30,6 +30,7 @@ #endif #include "SDL_sysvideo.h" +#include "SDL_log.h" #include "SDL_egl_c.h" #include "SDL_loadso.h" #include "SDL_hints.h" @@ -114,38 +115,82 @@ int SDL_EGL_SetErrorEx(const char * message, const char * eglFunctionName, EGLin } /* EGL implementation of SDL OpenGL ES support */ -#ifdef EGL_KHR_create_context -static int SDL_EGL_HasExtension(_THIS, const char *ext) +typedef enum { + SDL_EGL_DISPLAY_EXTENSION, + SDL_EGL_CLIENT_EXTENSION +} SDL_EGL_ExtensionType; + +static SDL_bool SDL_EGL_HasExtension(_THIS, SDL_EGL_ExtensionType type, const char *ext) { - int i; - int len = 0; size_t ext_len; - const char *exts; - const char *ext_word; + const char *ext_override; + const char *egl_extstr; + const char *ext_start; + + /* Invalid extensions can be rejected early */ + if (ext == NULL || *ext == 0 || SDL_strchr(ext, ' ') != NULL) { + /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SDL_EGL_HasExtension: Invalid EGL extension"); */ + return SDL_FALSE; + } + + /* Extensions can be masked with an environment variable. + * Unlike the OpenGL override, this will use the set bits of an integer + * to disable the extension. + * Bit Action + * 0 If set, the display extension is masked and not present to SDL. + * 1 If set, the client extension is masked and not present to SDL. + */ + ext_override = SDL_getenv(ext); + if (ext_override != NULL) { + int disable_ext = SDL_atoi(ext_override); + if (disable_ext & 0x01 && type == SDL_EGL_DISPLAY_EXTENSION) { + return SDL_FALSE; + } else if (disable_ext & 0x02 && type == SDL_EGL_CLIENT_EXTENSION) { + return SDL_FALSE; + } + } ext_len = SDL_strlen(ext); - exts = _this->egl_data->eglQueryString(_this->egl_data->egl_display, EGL_EXTENSIONS); + switch (type) { + case SDL_EGL_DISPLAY_EXTENSION: + egl_extstr = _this->egl_data->eglQueryString(_this->egl_data->egl_display, EGL_EXTENSIONS); + break; + case SDL_EGL_CLIENT_EXTENSION: + /* EGL_EXT_client_extensions modifies eglQueryString to return client extensions + * if EGL_NO_DISPLAY is passed. Implementations without it are required to return NULL. + * This behavior is included in EGL 1.5. + */ + egl_extstr = _this->egl_data->eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); + break; + default: + /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SDL_EGL_HasExtension: Invalid extension type"); */ + return SDL_FALSE; + } - if (exts) { - ext_word = exts; + if (egl_extstr != NULL) { + ext_start = egl_extstr; - for (i = 0; exts[i] != 0; i++) { - if (exts[i] == ' ') { - if (ext_len == len && !SDL_strncmp(ext_word, ext, len)) { - return 1; + while (*ext_start) { + ext_start = SDL_strstr(ext_start, ext); + if (ext_start == NULL) { + return SDL_FALSE; + } + /* Check if the match is not just a substring of one of the extensions */ + if (ext_start == egl_extstr || *(ext_start - 1) == ' ') { + if (ext_start[ext_len] == ' ' || ext_start[ext_len] == 0) { + return SDL_TRUE; } - - len = 0; - ext_word = &exts[i + 1]; - } else { - len++; + } + /* If the search stopped in the middle of an extension, skip to the end of it */ + ext_start += ext_len; + while (*ext_start != ' ' && *ext_start != 0) { + ext_start++; } } } - return 0; + return SDL_FALSE; } -#endif /* EGL_KHR_create_context */ void * SDL_EGL_GetProcAddress(_THIS, const char *proc) @@ -196,10 +241,11 @@ SDL_EGL_UnloadLibrary(_THIS) } int -SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display) +SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display, EGLenum platform) { void *dll_handle = NULL, *egl_dll_handle = NULL; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */ const char *path = NULL; + int egl_version_major = 0, egl_version_minor = 0; #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT const char *d3dcompiler; #endif @@ -305,9 +351,41 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa LOAD_FUNC(eglQueryString); LOAD_FUNC(eglGetError); + if (_this->egl_data->eglQueryString) { + /* EGL 1.5 allows querying for client version */ + const char *egl_version = _this->egl_data->eglQueryString(EGL_NO_DISPLAY, EGL_VERSION); + if (egl_version != NULL) { + if (SDL_sscanf(egl_version, "%d.%d", &egl_version_major, &egl_version_minor) != 2) { + egl_version_major = 0; + egl_version_minor = 0; + SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not parse EGL version string: %s", egl_version); + } + } + } + + if (egl_version_major == 1 && egl_version_minor == 5) { + LOAD_FUNC(eglGetPlatformDisplay); + } + + _this->egl_data->egl_display = EGL_NO_DISPLAY; #if !defined(__WINRT__) - _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display); - if (!_this->egl_data->egl_display) { + if (platform) { + if (egl_version_major == 1 && egl_version_minor == 5) { + _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, native_display, NULL); + } else { + if (SDL_EGL_HasExtension(_this, SDL_EGL_CLIENT_EXTENSION, "EGL_EXT_platform_base")) { + _this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddress(_this, "eglGetPlatformDisplayEXT"); + if (_this->egl_data->eglGetPlatformDisplayEXT) { + _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(platform, native_display, NULL); + } + } + } + } + /* Try the implementation-specific eglGetDisplay even if eglGetPlatformDisplay fails */ + if (_this->egl_data->egl_display == EGL_NO_DISPLAY) { + _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display); + } + if (_this->egl_data->egl_display == EGL_NO_DISPLAY) { return SDL_SetError("Could not get EGL display"); } @@ -328,13 +406,19 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa int SDL_EGL_ChooseConfig(_THIS) { - /* 64 seems nice. */ +/* 64 seems nice. */ EGLint attribs[64]; EGLint found_configs = 0, value; +#ifdef SDL_VIDEO_DRIVER_KMSDRM + /* Intel EGL on KMS/DRM (al least) returns invalid configs that confuse the bitdiff search used */ + /* later in this function, so we simply use the first one when using the KMSDRM driver for now. */ + EGLConfig configs[1]; +#else /* 128 seems even nicer here */ EGLConfig configs[128]; +#endif int i, j, best_bitdiff = -1, bitdiff; - + if (!_this->egl_data) { /* The EGL library wasn't loaded, SDL_GetError() should have info */ return -1; @@ -379,7 +463,7 @@ SDL_EGL_ChooseConfig(_THIS) if (_this->gl_config.framebuffer_srgb_capable) { #ifdef EGL_KHR_gl_colorspace - if (SDL_EGL_HasExtension(_this, "EGL_KHR_gl_colorspace")) { + if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_gl_colorspace")) { attribs[i++] = EGL_GL_COLORSPACE_KHR; attribs[i++] = EGL_GL_COLORSPACE_SRGB_KHR; } else @@ -393,7 +477,7 @@ SDL_EGL_ChooseConfig(_THIS) if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { #ifdef EGL_KHR_create_context if (_this->gl_config.major_version >= 3 && - SDL_EGL_HasExtension(_this, "EGL_KHR_create_context")) { + SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_create_context")) { attribs[i++] = EGL_OPENGL_ES3_BIT_KHR; } else #endif @@ -495,7 +579,7 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface) /* The Major/minor version, context profiles, and context flags can * only be specified when this extension is available. */ - if (SDL_EGL_HasExtension(_this, "EGL_KHR_create_context")) { + if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_create_context")) { attribs[attr++] = EGL_CONTEXT_MAJOR_VERSION_KHR; attribs[attr++] = major_version; attribs[attr++] = EGL_CONTEXT_MINOR_VERSION_KHR; diff --git a/src/video/SDL_egl_c.h b/src/video/SDL_egl_c.h index 001742a7f..f727e6681 100644 --- a/src/video/SDL_egl_c.h +++ b/src/video/SDL_egl_c.h @@ -37,6 +37,12 @@ typedef struct SDL_EGL_VideoData int egl_swapinterval; EGLDisplay(EGLAPIENTRY *eglGetDisplay) (NativeDisplayType display); + EGLDisplay(EGLAPIENTRY *eglGetPlatformDisplay) (EGLenum platform, + void *native_display, + const EGLint *attrib_list); + EGLDisplay(EGLAPIENTRY *eglGetPlatformDisplayEXT) (EGLenum platform, + void *native_display, + const EGLint *attrib_list); EGLBoolean(EGLAPIENTRY *eglInitialize) (EGLDisplay dpy, EGLint * major, EGLint * minor); EGLBoolean(EGLAPIENTRY *eglTerminate) (EGLDisplay dpy); @@ -85,7 +91,10 @@ typedef struct SDL_EGL_VideoData /* OpenGLES functions */ extern int SDL_EGL_GetAttribute(_THIS, SDL_GLattr attrib, int *value); -extern int SDL_EGL_LoadLibrary(_THIS, const char *path, NativeDisplayType native_display); +/* SDL_EGL_LoadLibrary can get a display for a specific platform (EGL_PLATFORM_*) + * or, if 0 is passed, let the implementation decide. + */ +extern int SDL_EGL_LoadLibrary(_THIS, const char *path, NativeDisplayType native_display, EGLenum platform); extern void *SDL_EGL_GetProcAddress(_THIS, const char *proc); extern void SDL_EGL_UnloadLibrary(_THIS); extern int SDL_EGL_ChooseConfig(_THIS); diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index d1f5658c4..d2b8bf9ff 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -385,6 +385,7 @@ extern VideoBootStrap UIKIT_bootstrap; extern VideoBootStrap Android_bootstrap; extern VideoBootStrap PSP_bootstrap; extern VideoBootStrap RPI_bootstrap; +extern VideoBootStrap KMSDRM_bootstrap; extern VideoBootStrap DUMMY_bootstrap; extern VideoBootStrap Wayland_bootstrap; extern VideoBootStrap NACL_bootstrap; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index af2ac2697..89524defe 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -105,6 +105,9 @@ static VideoBootStrap *bootstrap[] = { #if SDL_VIDEO_DRIVER_RPI &RPI_bootstrap, #endif +#if SDL_VIDEO_DRIVER_KMSDRM + &KMSDRM_bootstrap, +#endif #if SDL_VIDEO_DRIVER_NACL &NACL_bootstrap, #endif @@ -2892,7 +2895,7 @@ SDL_GL_ExtensionSupported(const char *extension) break; terminator = where + SDL_strlen(extension); - if (where == start || *(where - 1) == ' ') + if (where == extensions || *(where - 1) == ' ') if (*terminator == ' ' || *terminator == '\0') return SDL_TRUE; diff --git a/src/video/android/SDL_androidgl.c b/src/video/android/SDL_androidgl.c index f16da3658..783fa2a38 100644 --- a/src/video/android/SDL_androidgl.c +++ b/src/video/android/SDL_androidgl.c @@ -54,7 +54,7 @@ Android_GLES_SwapWindow(_THIS, SDL_Window * window) int Android_GLES_LoadLibrary(_THIS, const char *path) { - return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) 0); + return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) 0, 0); } #endif /* SDL_VIDEO_DRIVER_ANDROID */ diff --git a/src/video/kmsdrm/SDL_kmsdrmdyn.c b/src/video/kmsdrm/SDL_kmsdrmdyn.c new file mode 100644 index 000000000..ba4141fd6 --- /dev/null +++ b/src/video/kmsdrm/SDL_kmsdrmdyn.c @@ -0,0 +1,170 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_KMSDRM + +#define DEBUG_DYNAMIC_KMSDRM 0 + +#include "SDL_kmsdrmdyn.h" + +#if DEBUG_DYNAMIC_KMSDRM +#include "SDL_log.h" +#endif + +#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC + +#include "SDL_name.h" +#include "SDL_loadso.h" + +typedef struct +{ + void *lib; + const char *libname; +} kmsdrmdynlib; + +#ifndef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC +#define SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC NULL +#endif +#ifndef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM +#define SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM NULL +#endif + +static kmsdrmdynlib kmsdrmlibs[] = { + {NULL, SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC}, + {NULL, SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM} +}; + +static void * +KMSDRM_GetSym(const char *fnname, int *pHasModule) +{ + int i; + void *fn = NULL; + for (i = 0; i < SDL_TABLESIZE(kmsdrmlibs); i++) { + if (kmsdrmlibs[i].lib != NULL) { + fn = SDL_LoadFunction(kmsdrmlibs[i].lib, fnname); + if (fn != NULL) + break; + } + } + +#if DEBUG_DYNAMIC_KMSDRM + if (fn != NULL) + SDL_Log("KMSDRM: Found '%s' in %s (%p)\n", fnname, kmsdrmlibs[i].libname, fn); + else + SDL_Log("KMSDRM: Symbol '%s' NOT FOUND!\n", fnname); +#endif + + if (fn == NULL) + *pHasModule = 0; /* kill this module. */ + + return fn; +} + +#endif /* SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC */ + +/* Define all the function pointers and wrappers... */ +#define SDL_KMSDRM_MODULE(modname) int SDL_KMSDRM_HAVE_##modname = 0; +#define SDL_KMSDRM_SYM(rc,fn,params) SDL_DYNKMSDRMFN_##fn KMSDRM_##fn = NULL; +#define SDL_KMSDRM_SYM_CONST(type,name) SDL_DYNKMSDRMCONST_##name KMSDRM_##name = NULL; +#include "SDL_kmsdrmsym.h" + +static int kmsdrm_load_refcount = 0; + +void +SDL_KMSDRM_UnloadSymbols(void) +{ + /* Don't actually unload if more than one module is using the libs... */ + if (kmsdrm_load_refcount > 0) { + if (--kmsdrm_load_refcount == 0) { +#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC + int i; +#endif + + /* set all the function pointers to NULL. */ +#define SDL_KMSDRM_MODULE(modname) SDL_KMSDRM_HAVE_##modname = 0; +#define SDL_KMSDRM_SYM(rc,fn,params) KMSDRM_##fn = NULL; +#define SDL_KMSDRM_SYM_CONST(type,name) KMSDRM_##name = NULL; +#include "SDL_kmsdrmsym.h" + + +#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC + for (i = 0; i < SDL_TABLESIZE(kmsdrmlibs); i++) { + if (kmsdrmlibs[i].lib != NULL) { + SDL_UnloadObject(kmsdrmlibs[i].lib); + kmsdrmlibs[i].lib = NULL; + } + } +#endif + } + } +} + +/* returns non-zero if all needed symbols were loaded. */ +int +SDL_KMSDRM_LoadSymbols(void) +{ + int rc = 1; /* always succeed if not using Dynamic KMSDRM stuff. */ + + /* deal with multiple modules needing these symbols... */ + if (kmsdrm_load_refcount++ == 0) { +#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC + int i; + int *thismod = NULL; + for (i = 0; i < SDL_TABLESIZE(kmsdrmlibs); i++) { + if (kmsdrmlibs[i].libname != NULL) { + kmsdrmlibs[i].lib = SDL_LoadObject(kmsdrmlibs[i].libname); + } + } + +#define SDL_KMSDRM_MODULE(modname) SDL_KMSDRM_HAVE_##modname = 1; /* default yes */ +#include "SDL_kmsdrmsym.h" + +#define SDL_KMSDRM_MODULE(modname) thismod = &SDL_KMSDRM_HAVE_##modname; +#define SDL_KMSDRM_SYM(rc,fn,params) KMSDRM_##fn = (SDL_DYNKMSDRMFN_##fn) KMSDRM_GetSym(#fn,thismod); +#define SDL_KMSDRM_SYM_CONST(type,name) KMSDRM_##name = *(SDL_DYNKMSDRMCONST_##name*) KMSDRM_GetSym(#name,thismod); +#include "SDL_kmsdrmsym.h" + + if ((SDL_KMSDRM_HAVE_LIBDRM) && (SDL_KMSDRM_HAVE_GBM)) { + /* all required symbols loaded. */ + SDL_ClearError(); + } else { + /* in case something got loaded... */ + SDL_KMSDRM_UnloadSymbols(); + rc = 0; + } + +#else /* no dynamic KMSDRM */ + +#define SDL_KMSDRM_MODULE(modname) SDL_KMSDRM_HAVE_##modname = 1; /* default yes */ +#define SDL_KMSDRM_SYM(rc,fn,params) KMSDRM_##fn = fn; +#define SDL_KMSDRM_SYM_CONST(type,name) KMSDRM_##name = name; +#include "SDL_kmsdrmsym.h" + +#endif + } + + return rc; +} + +#endif /* SDL_VIDEO_DRIVER_KMSDRM */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/kmsdrm/SDL_kmsdrmdyn.h b/src/video/kmsdrm/SDL_kmsdrmdyn.h new file mode 100644 index 000000000..653afbccc --- /dev/null +++ b/src/video/kmsdrm/SDL_kmsdrmdyn.h @@ -0,0 +1,54 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _SDL_kmsdrmdyn_h +#define _SDL_kmsdrmdyn_h + +#include "../../SDL_internal.h" + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int SDL_KMSDRM_LoadSymbols(void); +void SDL_KMSDRM_UnloadSymbols(void); + +/* Declare all the function pointers and wrappers... */ +#define SDL_KMSDRM_SYM(rc,fn,params) \ + typedef rc (*SDL_DYNKMSDRMFN_##fn) params; \ + extern SDL_DYNKMSDRMFN_##fn KMSDRM_##fn; +#define SDL_KMSDRM_SYM_CONST(type, name) \ + typedef type SDL_DYNKMSDRMCONST_##name; \ + extern SDL_DYNKMSDRMCONST_##name KMSDRM_##name; +#include "SDL_kmsdrmsym.h" + +#ifdef __cplusplus +} +#endif + +#endif /* !defined _SDL_kmsdrmdyn_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/kmsdrm/SDL_kmsdrmevents.c b/src/video/kmsdrm/SDL_kmsdrmevents.c new file mode 100644 index 000000000..959a30183 --- /dev/null +++ b/src/video/kmsdrm/SDL_kmsdrmevents.c @@ -0,0 +1,45 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_KMSDRM + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "../../events/SDL_keyboard_c.h" +#include "SDL_kmsdrmvideo.h" +#include "SDL_kmsdrmevents_c.h" + +#ifdef SDL_INPUT_LINUXEV +#include "../../core/linux/SDL_evdev.h" +#endif + +void KMSDRM_PumpEvents(_THIS) +{ +#ifdef SDL_INPUT_LINUXEV + SDL_EVDEV_Poll(); +#endif + +} + +#endif /* SDL_VIDEO_DRIVER_KMSDRM */ + diff --git a/src/video/kmsdrm/SDL_kmsdrmevents_c.h b/src/video/kmsdrm/SDL_kmsdrmevents_c.h new file mode 100644 index 000000000..9534988df --- /dev/null +++ b/src/video/kmsdrm/SDL_kmsdrmevents_c.h @@ -0,0 +1,31 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _SDL_kmsdrmevents_c_h +#define _SDL_kmsdrmevents_c_h + +#include "SDL_kmsdrmvideo.h" + +void KMSDRM_PumpEvents(_THIS); +void KMSDRM_EventInit(_THIS); +void KMSDRM_EventQuit(_THIS); + +#endif /* _SDL_kmsdrmevents_c_h */ diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c new file mode 100644 index 000000000..f8d642233 --- /dev/null +++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c @@ -0,0 +1,426 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_KMSDRM + +#include "SDL_assert.h" +#include "SDL_surface.h" + +#include "SDL_kmsdrmvideo.h" +#include "SDL_kmsdrmmouse.h" +#include "SDL_kmsdrmdyn.h" + +#include "../SDL_sysvideo.h" +#include "../../events/SDL_mouse_c.h" +#include "../../events/default_cursor.h" + + +static SDL_Cursor *KMSDRM_CreateDefaultCursor(void); +static SDL_Cursor *KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y); +static int KMSDRM_ShowCursor(SDL_Cursor * cursor); +static void KMSDRM_MoveCursor(SDL_Cursor * cursor); +static void KMSDRM_FreeCursor(SDL_Cursor * cursor); +static void KMSDRM_WarpMouse(SDL_Window * window, int x, int y); +static int KMSDRM_WarpMouseGlobal(int x, int y); + +static SDL_Cursor * +KMSDRM_CreateDefaultCursor(void) +{ + return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY); +} + +/* Create a cursor from a surface */ +static SDL_Cursor * +KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y) +{ + SDL_VideoDevice *dev = SDL_GetVideoDevice(); + SDL_VideoData *vdata = ((SDL_VideoData *)dev->driverdata); + SDL_PixelFormat *pixlfmt = surface->format; + KMSDRM_CursorData *curdata; + SDL_Cursor *cursor; + int i, ret; + uint32_t bo_format, bo_stride; + char *buffer = NULL; + size_t bufsize; + + switch(pixlfmt->format) { + case SDL_PIXELFORMAT_RGB332: + bo_format = GBM_FORMAT_RGB332; + break; + case SDL_PIXELFORMAT_ARGB4444: + bo_format = GBM_FORMAT_ARGB4444; + break; + case SDL_PIXELFORMAT_RGBA4444: + bo_format = GBM_FORMAT_RGBA4444; + break; + case SDL_PIXELFORMAT_ABGR4444: + bo_format = GBM_FORMAT_ABGR4444; + break; + case SDL_PIXELFORMAT_BGRA4444: + bo_format = GBM_FORMAT_BGRA4444; + break; + case SDL_PIXELFORMAT_ARGB1555: + bo_format = GBM_FORMAT_ARGB1555; + break; + case SDL_PIXELFORMAT_RGBA5551: + bo_format = GBM_FORMAT_RGBA5551; + break; + case SDL_PIXELFORMAT_ABGR1555: + bo_format = GBM_FORMAT_ABGR1555; + break; + case SDL_PIXELFORMAT_BGRA5551: + bo_format = GBM_FORMAT_BGRA5551; + break; + case SDL_PIXELFORMAT_RGB565: + bo_format = GBM_FORMAT_RGB565; + break; + case SDL_PIXELFORMAT_BGR565: + bo_format = GBM_FORMAT_BGR565; + break; + case SDL_PIXELFORMAT_RGB888: + case SDL_PIXELFORMAT_RGB24: + bo_format = GBM_FORMAT_RGB888; + break; + case SDL_PIXELFORMAT_BGR888: + case SDL_PIXELFORMAT_BGR24: + bo_format = GBM_FORMAT_BGR888; + break; + case SDL_PIXELFORMAT_RGBX8888: + bo_format = GBM_FORMAT_RGBX8888; + break; + case SDL_PIXELFORMAT_BGRX8888: + bo_format = GBM_FORMAT_BGRX8888; + break; + case SDL_PIXELFORMAT_ARGB8888: + bo_format = GBM_FORMAT_ARGB8888; + break; + case SDL_PIXELFORMAT_RGBA8888: + bo_format = GBM_FORMAT_RGBA8888; + break; + case SDL_PIXELFORMAT_ABGR8888: + bo_format = GBM_FORMAT_ABGR8888; + break; + case SDL_PIXELFORMAT_BGRA8888: + bo_format = GBM_FORMAT_BGRA8888; + break; + case SDL_PIXELFORMAT_ARGB2101010: + bo_format = GBM_FORMAT_ARGB2101010; + break; + default: + SDL_SetError("Unsupported pixel format for cursor"); + return NULL; + } + + if (!KMSDRM_gbm_device_is_format_supported(vdata->gbm, bo_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)) { + SDL_SetError("Unsupported pixel format for cursor"); + return NULL; + } + + cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor)); + if (cursor == NULL) { + SDL_OutOfMemory(); + return NULL; + } + curdata = (KMSDRM_CursorData *) SDL_calloc(1, sizeof(*curdata)); + if (curdata == NULL) { + SDL_OutOfMemory(); + SDL_free(cursor); + return NULL; + } + + curdata->hot_x = hot_x; + curdata->hot_y = hot_y; + curdata->w = surface->w; + curdata->h = surface->h; + + curdata->bo = KMSDRM_gbm_bo_create(vdata->gbm, surface->w, surface->h, bo_format, + GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); + if (curdata->bo == NULL) { + SDL_SetError("Could not create GBM cursor BO"); + goto cleanup; + } + + bo_stride = KMSDRM_gbm_bo_get_stride(curdata->bo); + bufsize = bo_stride * surface->h; + + if (surface->pitch != bo_stride) { + /* pitch doesn't match stride, must be copied to temp buffer */ + buffer = SDL_malloc(bufsize); + if (buffer == NULL) { + SDL_OutOfMemory(); + goto cleanup; + } + + if (SDL_MUSTLOCK(surface)) { + if (SDL_LockSurface(surface) < 0) { + /* Could not lock surface */ + goto cleanup; + } + } + + /* Copy to temporary buffer */ + for (i = 0; i < surface->h; i++) { + SDL_memcpy(buffer + (i * bo_stride), + ((char *)surface->pixels) + (i * surface->pitch), + surface->w * pixlfmt->BytesPerPixel); + } + + if (SDL_MUSTLOCK(surface)) { + SDL_UnlockSurface(surface); + } + + if (KMSDRM_gbm_bo_write(curdata->bo, buffer, bufsize)) { + SDL_SetError("Could not write to GBM cursor BO"); + goto cleanup; + } + + /* Free temporary buffer */ + SDL_free(buffer); + buffer = NULL; + } else { + /* surface matches BO format */ + if (SDL_MUSTLOCK(surface)) { + if (SDL_LockSurface(surface) < 0) { + /* Could not lock surface */ + goto cleanup; + } + } + + ret = KMSDRM_gbm_bo_write(curdata->bo, surface->pixels, bufsize); + + if (SDL_MUSTLOCK(surface)) { + SDL_UnlockSurface(surface); + } + + if (ret) { + SDL_SetError("Could not write to GBM cursor BO"); + goto cleanup; + } + } + + cursor->driverdata = curdata; + + return cursor; + +cleanup: + if (buffer != NULL) { + SDL_free(buffer); + } + if (cursor != NULL) { + SDL_free(cursor); + } + if (curdata != NULL) { + if (curdata->bo != NULL) { + KMSDRM_gbm_bo_destroy(curdata->bo); + } + SDL_free(curdata); + } + return NULL; +} + +/* Show the specified cursor, or hide if cursor is NULL */ +static int +KMSDRM_ShowCursor(SDL_Cursor * cursor) +{ + SDL_VideoDevice *dev = SDL_GetVideoDevice(); + SDL_VideoData *vdata = ((SDL_VideoData *)dev->driverdata); + SDL_Mouse *mouse; + KMSDRM_CursorData *curdata; + SDL_VideoDisplay *display = NULL; + SDL_DisplayData *ddata = NULL; + int ret; + uint32_t bo_handle; + + mouse = SDL_GetMouse(); + if (mouse == NULL) { + return SDL_SetError("No mouse."); + } + + if (mouse->focus != NULL) { + display = SDL_GetDisplayForWindow(mouse->focus); + if (display != NULL) { + ddata = (SDL_DisplayData*) display->driverdata; + } + } + + if (cursor == NULL) { + /* Hide current cursor */ + if ( mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) { + curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata; + + if (curdata->crtc_id != 0) { + ret = KMSDRM_drmModeSetCursor(vdata->drm_fd, curdata->crtc_id, 0, 0, 0); + if (ret) { + SDL_SetError("Could not hide current cursor with drmModeSetCursor()."); + return ret; + } + /* Mark previous cursor as not-displayed */ + curdata->crtc_id = 0; + + return 0; + } + } + /* otherwise if possible, hide global cursor */ + if (ddata != NULL && ddata->crtc_id != 0) { + ret = KMSDRM_drmModeSetCursor(vdata->drm_fd, ddata->crtc_id, 0, 0, 0); + if (ret) { + SDL_SetError("Could not hide display's cursor with drmModeSetCursor()."); + return ret; + } + return 0; + } + + return SDL_SetError("Couldn't find cursor to hide."); + } + /* If cursor != NULL, show new cursor on display */ + if (display == NULL) { + return SDL_SetError("Could not get display for mouse."); + } + if (ddata == NULL) { + return SDL_SetError("Could not get display driverdata."); + } + + curdata = (KMSDRM_CursorData *) cursor->driverdata; + if (curdata == NULL || curdata->bo == NULL) { + return SDL_SetError("Cursor not initialized properly."); + } + + bo_handle = KMSDRM_gbm_bo_get_handle(curdata->bo).u32; + if (curdata->hot_x == 0 && curdata->hot_y == 0) { + ret = KMSDRM_drmModeSetCursor(vdata->drm_fd, ddata->crtc_id, bo_handle, + curdata->w, curdata->h); + } else { + ret = KMSDRM_drmModeSetCursor2(vdata->drm_fd, ddata->crtc_id, bo_handle, + curdata->w, curdata->h, + curdata->hot_x, curdata->hot_y); + } + if (ret) { + SDL_SetError("drmModeSetCursor failed."); + return ret; + } + + curdata->crtc_id = ddata->crtc_id; + + return 0; +} + +/* Free a window manager cursor */ +static void +KMSDRM_FreeCursor(SDL_Cursor * cursor) +{ + KMSDRM_CursorData *curdata; + int drm_fd; + + if (cursor != NULL) { + curdata = (KMSDRM_CursorData *) cursor->driverdata; + + if (curdata != NULL) { + if (curdata->bo != NULL) { + if (curdata->crtc_id != 0) { + drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(curdata->bo)); + /* Hide the cursor if previously shown on a CRTC */ + KMSDRM_drmModeSetCursor(drm_fd, curdata->crtc_id, 0, 0, 0); + curdata->crtc_id = 0; + } + KMSDRM_gbm_bo_destroy(curdata->bo); + curdata->bo = NULL; + } + SDL_free(cursor->driverdata); + } + SDL_free(cursor); + } +} + +/* Warp the mouse to (x,y) */ +static void +KMSDRM_WarpMouse(SDL_Window * window, int x, int y) +{ + /* Only one global/fullscreen window is supported */ + KMSDRM_WarpMouseGlobal(x, y); +} + +/* Warp the mouse to (x,y) */ +static int +KMSDRM_WarpMouseGlobal(int x, int y) +{ + KMSDRM_CursorData *curdata; + SDL_Mouse *mouse = SDL_GetMouse(); + + if (mouse != NULL && mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) { + curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata; + if (curdata->bo != NULL) { + if (curdata->crtc_id != 0) { + int ret, drm_fd; + drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(curdata->bo)); + ret = KMSDRM_drmModeMoveCursor(drm_fd, curdata->crtc_id, x, y); + + if (ret) { + SDL_SetError("drmModeMoveCursor() failed."); + } + + return ret; + } else { + return SDL_SetError("Cursor is not currently shown."); + } + } else { + return SDL_SetError("Cursor not initialized properly."); + } + } else { + return SDL_SetError("No mouse or current cursor."); + } +} + +void +KMSDRM_InitMouse(_THIS) +{ + /* FIXME: Using UDEV it should be possible to scan all mice + * but there's no point in doing so as there's no multimice support...yet! + */ + SDL_Mouse *mouse = SDL_GetMouse(); + + mouse->CreateCursor = KMSDRM_CreateCursor; + mouse->ShowCursor = KMSDRM_ShowCursor; + mouse->MoveCursor = KMSDRM_MoveCursor; + mouse->FreeCursor = KMSDRM_FreeCursor; + mouse->WarpMouse = KMSDRM_WarpMouse; + mouse->WarpMouseGlobal = KMSDRM_WarpMouseGlobal; + + SDL_SetDefaultCursor(KMSDRM_CreateDefaultCursor()); +} + +void +KMSDRM_QuitMouse(_THIS) +{ + /* TODO: ? */ +} + +/* This is called when a mouse motion event occurs */ +static void +KMSDRM_MoveCursor(SDL_Cursor * cursor) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + KMSDRM_WarpMouse(mouse->focus, mouse->x, mouse->y); +} + +#endif /* SDL_VIDEO_DRIVER_KMSDRM */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.h b/src/video/kmsdrm/SDL_kmsdrmmouse.h new file mode 100644 index 000000000..2fda1cc86 --- /dev/null +++ b/src/video/kmsdrm/SDL_kmsdrmmouse.h @@ -0,0 +1,42 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _SDL_KMSDRM_mouse_h +#define _SDL_KMSDRM_mouse_h + +#include + +#include "../SDL_sysvideo.h" + +typedef struct _KMSDRM_CursorData +{ + struct gbm_bo *bo; + uint32_t crtc_id; + int hot_x, hot_y; + int w, h; +} KMSDRM_CursorData; + +extern void KMSDRM_InitMouse(_THIS); +extern void KMSDRM_QuitMouse(_THIS); + +#endif /* _SDL_KMSDRM_mouse_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c new file mode 100644 index 000000000..fb0c248c6 --- /dev/null +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c @@ -0,0 +1,126 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL + +#include "SDL_log.h" + +#include "SDL_kmsdrmvideo.h" +#include "SDL_kmsdrmopengles.h" +#include "SDL_kmsdrmdyn.h" + +#ifndef EGL_PLATFORM_GBM_MESA +#define EGL_PLATFORM_GBM_MESA 0x31D7 +#endif + +/* EGL implementation of SDL OpenGL support */ + +int +KMSDRM_GLES_LoadLibrary(_THIS, const char *path) { + return SDL_EGL_LoadLibrary(_this, path, ((SDL_VideoData *)_this->driverdata)->gbm, EGL_PLATFORM_GBM_MESA); +} + +SDL_EGL_CreateContext_impl(KMSDRM) + +int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) { + if (!_this->egl_data) { + return SDL_SetError("EGL not initialized"); + } + + if (interval == 0 || interval == 1) { + _this->egl_data->egl_swapinterval = interval; + } else { + return SDL_SetError("Only swap intervals of 0 or 1 are supported"); + } + + return 0; +} + +int +KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) { + SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata); + SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata; + SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); + KMSDRM_FBInfo *fb_info; + int ret; + + /* Do we still need to wait for a flip? */ + int timeout = 0; + if (_this->egl_data->egl_swapinterval == 1) { + timeout = -1; + } + if (!KMSDRM_WaitPageFlip(_this, wdata, timeout)) { + return 0; + } + + /* Release previously displayed buffer (which is now the backbuffer) and lock a new one */ + if (wdata->locked_bo != NULL) { + KMSDRM_gbm_surface_release_buffer(wdata->gs, wdata->locked_bo); + /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Released GBM surface %p", (void *)wdata->locked_bo); */ + wdata->locked_bo = NULL; + } + + if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed."); + return 0; + } + + wdata->locked_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs); + if (wdata->locked_bo == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer"); + return 0; + /* } else { + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Locked GBM surface %p", (void *)wdata->locked_bo); */ + } + + fb_info = KMSDRM_FBFromBO(_this, wdata->locked_bo); + if (_this->egl_data->egl_swapinterval == 0) { + /* Swap buffers instantly, possible tearing */ + /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModeSetCrtc(%d, %u, %u, 0, 0, &%u, 1, &%ux%u@%u)", + vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, vdata->saved_conn_id, + displaydata->cur_mode.hdisplay, displaydata->cur_mode.vdisplay, displaydata->cur_mode.vrefresh); */ + ret = KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, + 0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode); + if(ret != 0) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not pageflip with drmModeSetCrtc: %d", ret); + } + } else { + /* Queue page flip at vsync */ + /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip)", + vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */ + ret = KMSDRM_drmModePageFlip(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, + DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip); + if (ret == 0) { + wdata->waiting_for_flip = SDL_TRUE; + } else { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret); + } + } + + return 0; +} + +SDL_EGL_MakeCurrent_impl(KMSDRM) + +#endif /* SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.h b/src/video/kmsdrm/SDL_kmsdrmopengles.h new file mode 100644 index 000000000..f3a61faa9 --- /dev/null +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.h @@ -0,0 +1,48 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_kmsdrmopengles_h +#define _SDL_kmsdrmopengles_h + +#if SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL + +#include "../SDL_sysvideo.h" +#include "../SDL_egl_c.h" + +/* OpenGLES functions */ +#define KMSDRM_GLES_GetAttribute SDL_EGL_GetAttribute +#define KMSDRM_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define KMSDRM_GLES_UnloadLibrary SDL_EGL_UnloadLibrary +#define KMSDRM_GLES_DeleteContext SDL_EGL_DeleteContext +#define KMSDRM_GLES_GetSwapInterval SDL_EGL_GetSwapInterval + +extern int KMSDRM_GLES_SetSwapInterval(_THIS, int interval); +extern int KMSDRM_GLES_LoadLibrary(_THIS, const char *path); +extern SDL_GLContext KMSDRM_GLES_CreateContext(_THIS, SDL_Window * window); +extern int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window); +extern int KMSDRM_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); + +#endif /* SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL */ + +#endif /* _SDL_kmsdrmopengles_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h new file mode 100644 index 000000000..72c07a95f --- /dev/null +++ b/src/video/kmsdrm/SDL_kmsdrmsym.h @@ -0,0 +1,99 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* *INDENT-OFF* */ + +#ifndef SDL_KMSDRM_MODULE +#define SDL_KMSDRM_MODULE(modname) +#endif + +#ifndef SDL_KMSDRM_SYM +#define SDL_KMSDRM_SYM(rc,fn,params) +#endif + +#ifndef SDL_KMSDRM_SYM_CONST +#define SDL_KMSDRM_SYM_CONST(type, name) +#endif + + +SDL_KMSDRM_MODULE(LIBDRM) +SDL_KMSDRM_SYM(void,drmModeFreeResources,(drmModeResPtr ptr)) +SDL_KMSDRM_SYM(void,drmModeFreeFB,(drmModeFBPtr ptr)) +SDL_KMSDRM_SYM(void,drmModeFreeCrtc,(drmModeCrtcPtr ptr)) +SDL_KMSDRM_SYM(void,drmModeFreeConnector,(drmModeConnectorPtr ptr)) +SDL_KMSDRM_SYM(void,drmModeFreeEncoder,(drmModeEncoderPtr ptr)) +SDL_KMSDRM_SYM(drmModeResPtr,drmModeGetResources,(int fd)) +SDL_KMSDRM_SYM(int,drmModeAddFB,(int fd, uint32_t width, uint32_t height, uint8_t depth, + uint8_t bpp, uint32_t pitch, uint32_t bo_handle, + uint32_t *buf_id)) +SDL_KMSDRM_SYM(int,drmModeRmFB,(int fd, uint32_t bufferId)) +SDL_KMSDRM_SYM(drmModeFBPtr,drmModeGetFB,(int fd, uint32_t buf)) +SDL_KMSDRM_SYM(drmModeCrtcPtr,drmModeGetCrtc,(int fd, uint32_t crtcId)) +SDL_KMSDRM_SYM(int,drmModeSetCrtc,(int fd, uint32_t crtcId, uint32_t bufferId, + uint32_t x, uint32_t y, uint32_t *connectors, int count, + drmModeModeInfoPtr mode)) +SDL_KMSDRM_SYM(int,drmModeSetCursor,(int fd, uint32_t crtcId, uint32_t bo_handle, + uint32_t width, uint32_t height)) +SDL_KMSDRM_SYM(int,drmModeSetCursor2,(int fd, uint32_t crtcId, uint32_t bo_handle, + uint32_t width, uint32_t height, + int32_t hot_x, int32_t hot_y)) +SDL_KMSDRM_SYM(int,drmModeMoveCursor,(int fd, uint32_t crtcId, int x, int y)) +SDL_KMSDRM_SYM(drmModeEncoderPtr,drmModeGetEncoder,(int fd, uint32_t encoder_id)) +SDL_KMSDRM_SYM(drmModeConnectorPtr,drmModeGetConnector,(int fd, uint32_t connector_id)) +SDL_KMSDRM_SYM(int,drmHandleEvent,(int fd,drmEventContextPtr evctx)) +SDL_KMSDRM_SYM(int,drmModePageFlip,(int fd, uint32_t crtc_id, uint32_t fb_id, + uint32_t flags, void *user_data)) + + +SDL_KMSDRM_MODULE(GBM) +SDL_KMSDRM_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm)) +SDL_KMSDRM_SYM(int,gbm_device_is_format_supported,(struct gbm_device *gbm, + uint32_t format, uint32_t usage)) +SDL_KMSDRM_SYM(void,gbm_device_destroy,(struct gbm_device *gbm)) +SDL_KMSDRM_SYM(struct gbm_device *,gbm_create_device,(int fd)) +SDL_KMSDRM_SYM(unsigned int,gbm_bo_get_width,(struct gbm_bo *bo)) +SDL_KMSDRM_SYM(unsigned int,gbm_bo_get_height,(struct gbm_bo *bo)) +SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_stride,(struct gbm_bo *bo)) +SDL_KMSDRM_SYM(union gbm_bo_handle,gbm_bo_get_handle,(struct gbm_bo *bo)) +SDL_KMSDRM_SYM(int,gbm_bo_write,(struct gbm_bo *bo, const void *buf, size_t count)) +SDL_KMSDRM_SYM(struct gbm_device *,gbm_bo_get_device,(struct gbm_bo *bo)) +SDL_KMSDRM_SYM(void,gbm_bo_set_user_data,(struct gbm_bo *bo, void *data, + void (*destroy_user_data)(struct gbm_bo *, void *))) +SDL_KMSDRM_SYM(void *,gbm_bo_get_user_data,(struct gbm_bo *bo)) +SDL_KMSDRM_SYM(void,gbm_bo_destroy,(struct gbm_bo *bo)) +SDL_KMSDRM_SYM(struct gbm_bo *,gbm_bo_create,(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, uint32_t usage)) +SDL_KMSDRM_SYM(struct gbm_surface *,gbm_surface_create,(struct gbm_device *gbm, + uint32_t width, uint32_t height, + uint32_t format, uint32_t flags)) +SDL_KMSDRM_SYM(void,gbm_surface_destroy,(struct gbm_surface *surf)) +SDL_KMSDRM_SYM(struct gbm_bo *,gbm_surface_lock_front_buffer,(struct gbm_surface *surf)) +SDL_KMSDRM_SYM(void,gbm_surface_release_buffer,(struct gbm_surface *surf, struct gbm_bo *bo)) + + +#undef SDL_KMSDRM_MODULE +#undef SDL_KMSDRM_SYM +#undef SDL_KMSDRM_SYM_CONST + +/* *INDENT-ON* */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c new file mode 100644 index 000000000..bdd359722 --- /dev/null +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -0,0 +1,634 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_KMSDRM + +/* SDL internals */ +#include "../SDL_sysvideo.h" +#include "SDL_version.h" +#include "SDL_syswm.h" +#include "SDL_loadso.h" +#include "SDL_events.h" +#include "SDL_log.h" +#include "../../events/SDL_mouse_c.h" +#include "../../events/SDL_keyboard_c.h" + +#ifdef SDL_INPUT_LINUXEV +#include "../../core/linux/SDL_evdev.h" +#endif + +/* KMS/DRM declarations */ +#include "SDL_kmsdrmvideo.h" +#include "SDL_kmsdrmevents_c.h" +#include "SDL_kmsdrmopengles.h" +#include "SDL_kmsdrmmouse.h" +#include "SDL_kmsdrmdyn.h" + +#define KMSDRM_DRI_CARD_0 "/dev/dri/card0" + +static int +KMSDRM_Available(void) +{ + int available = 0; + + int drm_fd = open(KMSDRM_DRI_CARD_0, O_RDWR | O_CLOEXEC); + if (drm_fd >= 0) { + if (SDL_KMSDRM_LoadSymbols()) { + drmModeRes *resources = KMSDRM_drmModeGetResources(drm_fd); + if (resources != NULL) { + available = 1; + KMSDRM_drmModeFreeResources(resources); + } + SDL_KMSDRM_UnloadSymbols(); + } + close(drm_fd); + } + + return available; +} + +static void +KMSDRM_Destroy(SDL_VideoDevice * device) +{ + if (device->driverdata != NULL) { + SDL_free(device->driverdata); + device->driverdata = NULL; + } + SDL_KMSDRM_UnloadSymbols(); +} + +static SDL_VideoDevice * +KMSDRM_Create(int devindex) +{ + SDL_VideoDevice *device; + SDL_VideoData *vdata; + + if (devindex < 0 || devindex > 99) { + SDL_SetError("devindex (%d) must be between 0 and 99.\n", devindex); + return NULL; + } + + if (!SDL_KMSDRM_LoadSymbols()) { + return NULL; + } + + /* Initialize SDL_VideoDevice structure */ + device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); + if (device == NULL) { + SDL_OutOfMemory(); + goto cleanup; + } + + /* Initialize internal data */ + vdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData)); + if (vdata == NULL) { + SDL_OutOfMemory(); + goto cleanup; + } + vdata->devindex = devindex; + vdata->drm_fd = -1; + + device->driverdata = vdata; + + /* Setup amount of available displays and current display */ + device->num_displays = 0; + + /* Set device free function */ + device->free = KMSDRM_Destroy; + + /* Setup all functions which we can handle */ + device->VideoInit = KMSDRM_VideoInit; + device->VideoQuit = KMSDRM_VideoQuit; + device->GetDisplayModes = KMSDRM_GetDisplayModes; + device->SetDisplayMode = KMSDRM_SetDisplayMode; + device->CreateWindow = KMSDRM_CreateWindow; + device->CreateWindowFrom = KMSDRM_CreateWindowFrom; + device->SetWindowTitle = KMSDRM_SetWindowTitle; + device->SetWindowIcon = KMSDRM_SetWindowIcon; + device->SetWindowPosition = KMSDRM_SetWindowPosition; + device->SetWindowSize = KMSDRM_SetWindowSize; + device->ShowWindow = KMSDRM_ShowWindow; + device->HideWindow = KMSDRM_HideWindow; + device->RaiseWindow = KMSDRM_RaiseWindow; + device->MaximizeWindow = KMSDRM_MaximizeWindow; + device->MinimizeWindow = KMSDRM_MinimizeWindow; + device->RestoreWindow = KMSDRM_RestoreWindow; + device->SetWindowGrab = KMSDRM_SetWindowGrab; + device->DestroyWindow = KMSDRM_DestroyWindow; + device->GetWindowWMInfo = KMSDRM_GetWindowWMInfo; + device->GL_LoadLibrary = KMSDRM_GLES_LoadLibrary; + device->GL_GetProcAddress = KMSDRM_GLES_GetProcAddress; + device->GL_UnloadLibrary = KMSDRM_GLES_UnloadLibrary; + device->GL_CreateContext = KMSDRM_GLES_CreateContext; + device->GL_MakeCurrent = KMSDRM_GLES_MakeCurrent; + device->GL_SetSwapInterval = KMSDRM_GLES_SetSwapInterval; + device->GL_GetSwapInterval = KMSDRM_GLES_GetSwapInterval; + device->GL_SwapWindow = KMSDRM_GLES_SwapWindow; + device->GL_DeleteContext = KMSDRM_GLES_DeleteContext; + + device->PumpEvents = KMSDRM_PumpEvents; + + return device; + +cleanup: + if (device != NULL) + SDL_free(device); + if (vdata != NULL) + SDL_free(vdata); + return NULL; +} + +VideoBootStrap KMSDRM_bootstrap = { + "KMSDRM", + "KMS/DRM Video Driver", + KMSDRM_Available, + KMSDRM_Create +}; + + +static void +KMSDRM_FBDestroyCallback(struct gbm_bo *bo, void *data) +{ + KMSDRM_FBInfo *fb_info = (KMSDRM_FBInfo *)data; + + if (fb_info && fb_info->drm_fd > 0 && fb_info->fb_id != 0) { + KMSDRM_drmModeRmFB(fb_info->drm_fd, fb_info->fb_id); + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Delete DRM FB %u", fb_info->fb_id); + } + + free(fb_info); +} + +KMSDRM_FBInfo * +KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo) +{ + uint32_t w, h, stride, handle; + int ret; + SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); + KMSDRM_FBInfo *fb_info; + + fb_info = (KMSDRM_FBInfo *)KMSDRM_gbm_bo_get_user_data(bo); + if (fb_info != NULL) { + /* Have a previously used framebuffer, return it */ + return fb_info; + } + + /* Here a new DRM FB must be created */ + fb_info = (KMSDRM_FBInfo *)SDL_calloc(1, sizeof(KMSDRM_FBInfo)); + fb_info->drm_fd = vdata->drm_fd; + + w = KMSDRM_gbm_bo_get_width(bo); + h = KMSDRM_gbm_bo_get_height(bo); + stride = KMSDRM_gbm_bo_get_stride(bo); + handle = KMSDRM_gbm_bo_get_handle(bo).u32; + + ret = KMSDRM_drmModeAddFB(vdata->drm_fd, w, h, 24, 32, stride, handle, &fb_info->fb_id); + if (ret < 0) { + free(fb_info); + return NULL; + } + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "New DRM FB (%u): %ux%u, stride %u from BO %p", fb_info->fb_id, w, h, stride, (void *)bo); + + /* Associate our DRM framebuffer with this buffer object */ + KMSDRM_gbm_bo_set_user_data(bo, fb_info, KMSDRM_FBDestroyCallback); + return fb_info; +} + +SDL_bool +KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *wdata, int timeout) { + SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); + + while (wdata->waiting_for_flip) { + vdata->drm_pollfd.revents = 0; + if (poll(&vdata->drm_pollfd, 1, timeout) < 0) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll error"); + return SDL_FALSE; + } + + if (vdata->drm_pollfd.revents & (POLLHUP | POLLERR)) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll hup or error"); + return SDL_FALSE; + } + + if (vdata->drm_pollfd.revents & POLLIN) { + /* Page flip? If so, drmHandleEvent will unset wdata->waiting_for_flip */ + KMSDRM_drmHandleEvent(vdata->drm_fd, &vdata->drm_evctx); + } else { + /* Timed out and page flip didn't happen */ + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Dropping frame while waiting_for_flip"); + return SDL_FALSE; + } + } + return SDL_TRUE; +} + +static void +KMSDRM_FlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data) +{ + *((SDL_bool *) data) = SDL_FALSE; +} + + +/*****************************************************************************/ +/* SDL Video and Display initialization/handling functions */ +/* _this is a SDL_VideoDevice * */ +/*****************************************************************************/ +int +KMSDRM_VideoInit(_THIS) +{ + int i; + int ret = 0; + char *devname; + SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); + drmModeRes *resources = NULL; + drmModeConnector *connector = NULL; + drmModeEncoder *encoder = NULL; + SDL_DisplayMode current_mode; + SDL_VideoDisplay display; + + /* Allocate display internal data */ + SDL_DisplayData *data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData)); + if (data == NULL) { + return SDL_OutOfMemory(); + } + + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoInit()"); + + /* Open /dev/dri/cardNN */ + devname = (char *) SDL_calloc(1, 16); + SDL_snprintf(devname, 16, "/dev/dri/card%d", vdata->devindex); + vdata->drm_fd = open(devname, O_RDWR | O_CLOEXEC); + SDL_free(devname); + + if (vdata->drm_fd < 0) { + ret = SDL_SetError("Could not open /dev/dri/card%d.", vdata->devindex); + goto cleanup; + } + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Opened DRM FD (%d)", vdata->drm_fd); + + vdata->gbm = KMSDRM_gbm_create_device(vdata->drm_fd); + if (vdata->gbm == NULL) { + ret = SDL_SetError("Couldn't create gbm device."); + goto cleanup; + } + + /* Find the first available connector with modes */ + resources = KMSDRM_drmModeGetResources(vdata->drm_fd); + if (!resources) { + ret = SDL_SetError("drmModeGetResources(%d) failed", vdata->drm_fd); + goto cleanup; + } + + for (i = 0; i < resources->count_connectors; i++) { + connector = KMSDRM_drmModeGetConnector(vdata->drm_fd, resources->connectors[i]); + if (connector == NULL) + continue; + + if (connector->connection == DRM_MODE_CONNECTED && + connector->count_modes > 0) { + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Found connector %d with %d modes.", + connector->connector_id, connector->count_modes); + vdata->saved_conn_id = connector->connector_id; + break; + } + + KMSDRM_drmModeFreeConnector(connector); + } + + if (i == resources->count_connectors) { + ret = SDL_SetError("No currently active connector found."); + goto cleanup; + } + + for (i = 0; i < resources->count_encoders; i++) { + encoder = KMSDRM_drmModeGetEncoder(vdata->drm_fd, resources->encoders[i]); + + if (encoder == NULL) + continue; + + if (encoder->encoder_id == connector->encoder_id) { + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Found encoder %d.", encoder->encoder_id); + data->encoder_id = encoder->encoder_id; + break; + } + + KMSDRM_drmModeFreeEncoder(encoder); + } + + if (i == resources->count_encoders) { + ret = SDL_SetError("No connected encoder found."); + goto cleanup; + } + + vdata->saved_crtc = KMSDRM_drmModeGetCrtc(vdata->drm_fd, encoder->crtc_id); + if (vdata->saved_crtc == NULL) { + ret = SDL_SetError("No CRTC found."); + goto cleanup; + } + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Saved crtc_id %u, fb_id %u, (%u,%u), %ux%u", + vdata->saved_crtc->crtc_id, vdata->saved_crtc->buffer_id, vdata->saved_crtc->x, + vdata->saved_crtc->y, vdata->saved_crtc->width, vdata->saved_crtc->height); + data->crtc_id = encoder->crtc_id; + data->cur_mode = vdata->saved_crtc->mode; + + SDL_zero(current_mode); + + current_mode.w = vdata->saved_crtc->mode.hdisplay; + current_mode.h = vdata->saved_crtc->mode.vdisplay; + current_mode.refresh_rate = vdata->saved_crtc->mode.vrefresh; + + /* FIXME ? + drmModeFB *fb = drmModeGetFB(vdata->drm_fd, vdata->saved_crtc->buffer_id); + current_mode.format = drmToSDLPixelFormat(fb->bpp, fb->depth); + drmModeFreeFB(fb); + */ + current_mode.format = SDL_PIXELFORMAT_ARGB8888; + + current_mode.driverdata = NULL; + + SDL_zero(display); + display.desktop_mode = current_mode; + display.current_mode = current_mode; + + display.driverdata = data; + /* SDL_VideoQuit will later SDL_free(display.driverdata) */ + SDL_AddVideoDisplay(&display); + + /* Setup page flip handler */ + vdata->drm_pollfd.fd = vdata->drm_fd; + vdata->drm_pollfd.events = POLLIN; + vdata->drm_evctx.version = DRM_EVENT_CONTEXT_VERSION; + vdata->drm_evctx.page_flip_handler = KMSDRM_FlipHandler; + +#ifdef SDL_INPUT_LINUXEV + SDL_EVDEV_Init(); +#endif + + KMSDRM_InitMouse(_this); + +cleanup: + if (encoder != NULL) + KMSDRM_drmModeFreeEncoder(encoder); + if (connector != NULL) + KMSDRM_drmModeFreeConnector(connector); + if (resources != NULL) + KMSDRM_drmModeFreeResources(resources); + + if (ret != 0) { + /* Error (complete) cleanup */ + SDL_free(data); + if(vdata->saved_crtc != NULL) { + KMSDRM_drmModeFreeCrtc(vdata->saved_crtc); + vdata->saved_crtc = NULL; + } + if (vdata->gbm != NULL) { + KMSDRM_gbm_device_destroy(vdata->gbm); + vdata->gbm = NULL; + } + if (vdata->drm_fd >= 0) { + close(vdata->drm_fd); + vdata->drm_fd = -1; + } + } + return ret; +} + +void +KMSDRM_VideoQuit(_THIS) +{ + SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); + + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoQuit()"); + + if (_this->gl_config.driver_loaded) { + SDL_GL_UnloadLibrary(); + } + + if(vdata->saved_crtc != NULL) { + if(vdata->drm_fd > 0 && vdata->saved_conn_id > 0) { + /* Restore saved CRTC settings */ + drmModeCrtc *crtc = vdata->saved_crtc; + if(KMSDRM_drmModeSetCrtc(vdata->drm_fd, crtc->crtc_id, crtc->buffer_id, + crtc->x, crtc->y, &vdata->saved_conn_id, 1, + &crtc->mode) != 0) { + SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not restore original CRTC mode"); + } + } + KMSDRM_drmModeFreeCrtc(vdata->saved_crtc); + vdata->saved_crtc = NULL; + } + if (vdata->gbm != NULL) { + KMSDRM_gbm_device_destroy(vdata->gbm); + vdata->gbm = NULL; + } + if (vdata->drm_fd >= 0) { + close(vdata->drm_fd); + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Closed DRM FD %d", vdata->drm_fd); + vdata->drm_fd = -1; + } +#ifdef SDL_INPUT_LINUXEV + SDL_EVDEV_Quit(); +#endif +} + +void +KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay * display) +{ + /* Only one display mode available, the current one */ + SDL_AddDisplayMode(display, &display->current_mode); +} + +int +KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) +{ + return 0; +} + +int +KMSDRM_CreateWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *wdata; + SDL_VideoDisplay *display; + SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); + Uint32 surface_fmt, surface_flags; + + /* Allocate window internal data */ + wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData)); + if (wdata == NULL) { + return SDL_OutOfMemory(); + } + + wdata->waiting_for_flip = SDL_FALSE; + display = SDL_GetDisplayForWindow(window); + + /* Windows have one size for now */ + window->w = display->desktop_mode.w; + window->h = display->desktop_mode.h; + + /* Maybe you didn't ask for a fullscreen OpenGL window, but that's what you get */ + window->flags |= (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL); + + surface_fmt = GBM_BO_FORMAT_XRGB8888; + surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; + + if (!KMSDRM_gbm_device_is_format_supported(vdata->gbm, surface_fmt, surface_flags)) { + SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "GBM surface format not supported. Trying anyway."); + } + wdata->gs = KMSDRM_gbm_surface_create(vdata->gbm, window->w, window->h, surface_fmt, surface_flags); + +#if SDL_VIDEO_OPENGL_EGL + if (!_this->egl_data) { + if (SDL_GL_LoadLibrary(NULL) < 0) { + goto error; + } + } + wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wdata->gs); + + if (wdata->egl_surface == EGL_NO_SURFACE) { + SDL_SetError("Could not create EGL window surface"); + goto error; + } +#endif /* SDL_VIDEO_OPENGL_EGL */ + + /* Setup driver data for this window */ + window->driverdata = wdata; + + /* One window, it always has focus */ + SDL_SetMouseFocus(window); + SDL_SetKeyboardFocus(window); + + /* Window has been successfully created */ + return 0; + +error: + if (wdata != NULL) { +#if SDL_VIDEO_OPENGL_EGL + if (wdata->egl_surface != EGL_NO_SURFACE) + SDL_EGL_DestroySurface(_this, wdata->egl_surface); +#endif /* SDL_VIDEO_OPENGL_EGL */ + if (wdata->gs != NULL) + KMSDRM_gbm_surface_destroy(wdata->gs); + SDL_free(wdata); + } + return -1; +} + +void +KMSDRM_DestroyWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + if(data) { + /* Wait for any pending page flips and unlock buffer */ + KMSDRM_WaitPageFlip(_this, data, -1); + if (data->locked_bo != NULL) { + KMSDRM_gbm_surface_release_buffer(data->gs, data->locked_bo); + data->locked_bo = NULL; + } +#if SDL_VIDEO_OPENGL_EGL + SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (data->egl_surface != EGL_NO_SURFACE) { + SDL_EGL_DestroySurface(_this, data->egl_surface); + } +#endif /* SDL_VIDEO_OPENGL_EGL */ + if (data->gs != NULL) { + KMSDRM_gbm_surface_destroy(data->gs); + data->gs = NULL; + } + SDL_free(data); + window->driverdata = NULL; + } +} + +int +KMSDRM_CreateWindowFrom(_THIS, SDL_Window * window, const void *data) +{ + return -1; +} + +void +KMSDRM_SetWindowTitle(_THIS, SDL_Window * window) +{ +} +void +KMSDRM_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon) +{ +} +void +KMSDRM_SetWindowPosition(_THIS, SDL_Window * window) +{ +} +void +KMSDRM_SetWindowSize(_THIS, SDL_Window * window) +{ +} +void +KMSDRM_ShowWindow(_THIS, SDL_Window * window) +{ +} +void +KMSDRM_HideWindow(_THIS, SDL_Window * window) +{ +} +void +KMSDRM_RaiseWindow(_THIS, SDL_Window * window) +{ +} +void +KMSDRM_MaximizeWindow(_THIS, SDL_Window * window) +{ +} +void +KMSDRM_MinimizeWindow(_THIS, SDL_Window * window) +{ +} +void +KMSDRM_RestoreWindow(_THIS, SDL_Window * window) +{ +} +void +KMSDRM_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed) +{ + +} + +/*****************************************************************************/ +/* SDL Window Manager function */ +/*****************************************************************************/ +SDL_bool +KMSDRM_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info) +{ + if (info->version.major <= SDL_MAJOR_VERSION) { + return SDL_TRUE; + } else { + SDL_SetError("application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return SDL_FALSE; + } + + /* Failed to get window manager information */ + return SDL_FALSE; +} + +#endif /* SDL_VIDEO_DRIVER_KMSDRM */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h new file mode 100644 index 000000000..bc44e1ab3 --- /dev/null +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h @@ -0,0 +1,119 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2016 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef __SDL_KMSDRMVIDEO_H__ +#define __SDL_KMSDRMVIDEO_H__ + +#include "../../SDL_internal.h" +#include "../SDL_sysvideo.h" + +#include +#include +#include +#include +#include +#include +#if SDL_VIDEO_OPENGL_EGL +#include +#endif + +typedef struct SDL_VideoData +{ + int devindex; /* device index that was passed on creation */ + int drm_fd; /* DRM file desc */ + struct gbm_device *gbm; + drmEventContext drm_evctx; /* DRM event context */ + struct pollfd drm_pollfd; /* pollfd containing DRM file desc */ + drmModeCrtc *saved_crtc; /* Saved CRTC to restore on quit */ + uint32_t saved_conn_id; /* Saved DRM connector ID */ +} SDL_VideoData; + + +typedef struct SDL_DisplayData +{ + uint32_t encoder_id; + uint32_t crtc_id; + drmModeModeInfo cur_mode; +} SDL_DisplayData; + + +typedef struct SDL_WindowData +{ + struct gbm_surface *gs; + struct gbm_bo *locked_bo; + SDL_bool waiting_for_flip; +#if SDL_VIDEO_OPENGL_EGL + EGLSurface egl_surface; +#endif +} SDL_WindowData; + +typedef struct KMSDRM_FBInfo +{ + int drm_fd; /* DRM file desc */ + uint32_t fb_id; /* DRM framebuffer ID */ +} KMSDRM_FBInfo; + +/* Helper functions */ +KMSDRM_FBInfo *KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo); +SDL_bool KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *wdata, int timeout); + +/****************************************************************************/ +/* SDL_VideoDevice functions declaration */ +/****************************************************************************/ + +/* Display and window functions */ +int KMSDRM_VideoInit(_THIS); +void KMSDRM_VideoQuit(_THIS); +void KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay * display); +int KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); +int KMSDRM_CreateWindow(_THIS, SDL_Window * window); +int KMSDRM_CreateWindowFrom(_THIS, SDL_Window * window, const void *data); +void KMSDRM_SetWindowTitle(_THIS, SDL_Window * window); +void KMSDRM_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon); +void KMSDRM_SetWindowPosition(_THIS, SDL_Window * window); +void KMSDRM_SetWindowSize(_THIS, SDL_Window * window); +void KMSDRM_ShowWindow(_THIS, SDL_Window * window); +void KMSDRM_HideWindow(_THIS, SDL_Window * window); +void KMSDRM_RaiseWindow(_THIS, SDL_Window * window); +void KMSDRM_MaximizeWindow(_THIS, SDL_Window * window); +void KMSDRM_MinimizeWindow(_THIS, SDL_Window * window); +void KMSDRM_RestoreWindow(_THIS, SDL_Window * window); +void KMSDRM_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed); +void KMSDRM_DestroyWindow(_THIS, SDL_Window * window); + +/* Window manager function */ +SDL_bool KMSDRM_GetWindowWMInfo(_THIS, SDL_Window * window, + struct SDL_SysWMinfo *info); + +/* OpenGL/OpenGL ES functions */ +int KMSDRM_GLES_LoadLibrary(_THIS, const char *path); +void *KMSDRM_GLES_GetProcAddress(_THIS, const char *proc); +void KMSDRM_GLES_UnloadLibrary(_THIS); +SDL_GLContext KMSDRM_GLES_CreateContext(_THIS, SDL_Window * window); +int KMSDRM_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); +int KMSDRM_GLES_SetSwapInterval(_THIS, int interval); +int KMSDRM_GLES_GetSwapInterval(_THIS); +int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window); +void KMSDRM_GLES_DeleteContext(_THIS, SDL_GLContext context); + +#endif /* __SDL_KMSDRMVIDEO_H__ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/mir/SDL_miropengl.c b/src/video/mir/SDL_miropengl.c index 1f10f6360..64b17a8ee 100644 --- a/src/video/mir/SDL_miropengl.c +++ b/src/video/mir/SDL_miropengl.c @@ -66,7 +66,7 @@ MIR_GL_LoadLibrary(_THIS, const char* path) { MIR_Data* mir_data = _this->driverdata; - SDL_EGL_LoadLibrary(_this, path, MIR_mir_connection_get_egl_native_display(mir_data->connection)); + SDL_EGL_LoadLibrary(_this, path, MIR_mir_connection_get_egl_native_display(mir_data->connection), 0); SDL_EGL_ChooseConfig(_this); diff --git a/src/video/raspberry/SDL_rpiopengles.c b/src/video/raspberry/SDL_rpiopengles.c index d3605487a..44188e688 100644 --- a/src/video/raspberry/SDL_rpiopengles.c +++ b/src/video/raspberry/SDL_rpiopengles.c @@ -29,7 +29,7 @@ int RPI_GLES_LoadLibrary(_THIS, const char *path) { - return SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY); + return SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY, 0); } SDL_EGL_CreateContext_impl(RPI) diff --git a/src/video/vivante/SDL_vivanteopengles.c b/src/video/vivante/SDL_vivanteopengles.c index 9c3275347..7341a4841 100644 --- a/src/video/vivante/SDL_vivanteopengles.c +++ b/src/video/vivante/SDL_vivanteopengles.c @@ -34,7 +34,7 @@ VIVANTE_GLES_LoadLibrary(_THIS, const char *path) displaydata = SDL_GetDisplayDriverData(0); - return SDL_EGL_LoadLibrary(_this, path, displaydata->native_display); + return SDL_EGL_LoadLibrary(_this, path, displaydata->native_display, 0); } SDL_EGL_CreateContext_impl(VIVANTE) diff --git a/src/video/wayland/SDL_waylandopengles.c b/src/video/wayland/SDL_waylandopengles.c index 549ab535b..e44aa2133 100644 --- a/src/video/wayland/SDL_waylandopengles.c +++ b/src/video/wayland/SDL_waylandopengles.c @@ -35,7 +35,7 @@ Wayland_GLES_LoadLibrary(_THIS, const char *path) { int ret; SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; - ret = SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display); + ret = SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display, 0); Wayland_PumpEvents(_this); WAYLAND_wl_display_flush(data->display); diff --git a/src/video/windows/SDL_windowsopengles.c b/src/video/windows/SDL_windowsopengles.c index 90d0a7b8d..e2ef5f8da 100644 --- a/src/video/windows/SDL_windowsopengles.c +++ b/src/video/windows/SDL_windowsopengles.c @@ -52,7 +52,7 @@ WIN_GLES_LoadLibrary(_THIS, const char *path) { } if (_this->egl_data == NULL) { - return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY); + return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0); } return 0; @@ -110,7 +110,7 @@ WIN_GLES_SetupWindow(_THIS, SDL_Window * window) if (_this->egl_data == NULL) { - if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY) < 0) { + if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0) < 0) { SDL_EGL_UnloadLibrary(_this); return -1; } diff --git a/src/video/winrt/SDL_winrtopengles.cpp b/src/video/winrt/SDL_winrtopengles.cpp index 567d46890..4edb566a2 100644 --- a/src/video/winrt/SDL_winrtopengles.cpp +++ b/src/video/winrt/SDL_winrtopengles.cpp @@ -58,7 +58,7 @@ WINRT_GLES_LoadLibrary(_THIS, const char *path) { SDL_VideoData *video_data = (SDL_VideoData *)_this->driverdata; - if (SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY) != 0) { + if (SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY, 0) != 0) { return -1; } diff --git a/src/video/x11/SDL_x11opengles.c b/src/video/x11/SDL_x11opengles.c index c5af50dd1..8f62abfd8 100644 --- a/src/video/x11/SDL_x11opengles.c +++ b/src/video/x11/SDL_x11opengles.c @@ -52,7 +52,7 @@ X11_GLES_LoadLibrary(_THIS, const char *path) #endif } - return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display); + return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display, 0); } XVisualInfo *