Fixed bug 3690 - SDL2 KMS/DRM render context support
authorSam Lantinga <slouken@libsdl.org>
Wed, 02 Aug 2017 10:22:48 -0700
changeset 11175cbc6a8a5b701
parent 11174 3767cdd2d64b
child 11176 9397a2d41d6b
Fixed bug 3690 - SDL2 KMS/DRM render context support

Manuel

The attached patch adds support for KMS/DRM context graphics.

It builds with no problem on X86_64 GNU/Linux systems, provided the needed libraries are present, and on ARM GNU/Linux systems that have KMS/DRM support and a GLES2 implementation.
Tested on Raspberry Pi: KMS/DRM is what the Raspberry Pi will use as default in the near future, once the propietary DispmanX API by Broadcom is overtaken by open graphics stack, it's possible to boot current Raspbian system in KMS mode by adding "dtoverlay=vc4-kms-v3d" to config.txt on Raspbian's boot partition.
X86 systems use KMS right away in every current GNU/Linux system.

Simple build instructions:

$./autogen.sh
$./configure --enable-video-kmsdrm
$make
CMakeLists.txt
cmake/sdlchecks.cmake
configure.in
include/SDL_config.h.cmake
include/SDL_config.h.in
src/video/SDL_egl.c
src/video/SDL_egl_c.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/android/SDL_androidgl.c
src/video/kmsdrm/SDL_kmsdrmdyn.c
src/video/kmsdrm/SDL_kmsdrmdyn.h
src/video/kmsdrm/SDL_kmsdrmevents.c
src/video/kmsdrm/SDL_kmsdrmevents_c.h
src/video/kmsdrm/SDL_kmsdrmmouse.c
src/video/kmsdrm/SDL_kmsdrmmouse.h
src/video/kmsdrm/SDL_kmsdrmopengles.c
src/video/kmsdrm/SDL_kmsdrmopengles.h
src/video/kmsdrm/SDL_kmsdrmsym.h
src/video/kmsdrm/SDL_kmsdrmvideo.c
src/video/kmsdrm/SDL_kmsdrmvideo.h
src/video/mir/SDL_miropengl.c
src/video/raspberry/SDL_rpiopengles.c
src/video/vivante/SDL_vivanteopengles.c
src/video/wayland/SDL_waylandopengles.c
src/video/windows/SDL_windowsopengles.c
src/video/winrt/SDL_winrtopengles.cpp
src/video/x11/SDL_x11opengles.c
     1.1 --- a/CMakeLists.txt	Mon Jul 31 13:49:22 2017 -0400
     1.2 +++ b/CMakeLists.txt	Wed Aug 02 10:22:48 2017 -0700
     1.3 @@ -314,6 +314,8 @@
     1.4  set_option(DIRECTX             "Use DirectX for Windows audio/video" ${WINDOWS})
     1.5  set_option(RENDER_D3D          "Enable the Direct3D render driver" ${WINDOWS})
     1.6  set_option(VIDEO_VIVANTE       "Use Vivante EGL video driver" ${UNIX_SYS})
     1.7 +set_option(VIDEO_KMSDRM        "Use KMS DRM video driver" ${UNIX_SYS})
     1.8 +dep_option(KMSDRM_SHARED       "Dynamically load KMS DRM support" ON "VIDEO_KMSDRM" OFF)
     1.9  
    1.10  # TODO: We should (should we?) respect cmake's ${BUILD_SHARED_LIBS} flag here
    1.11  # The options below are for compatibility to configure's default behaviour.
    1.12 @@ -917,6 +919,7 @@
    1.13      CheckOpenGLESX11()
    1.14      CheckWayland()
    1.15      CheckVivante()
    1.16 +    CheckKMSDRM()
    1.17    endif()
    1.18  
    1.19    if(LINUX)
     2.1 --- a/cmake/sdlchecks.cmake	Mon Jul 31 13:49:22 2017 -0400
     2.2 +++ b/cmake/sdlchecks.cmake	Wed Aug 02 10:22:48 2017 -0700
     2.3 @@ -1149,3 +1149,46 @@
     2.4      endif(SDL_VIDEO AND HAVE_VIDEO_RPI)
     2.5    endif(VIDEO_RPI)
     2.6  endmacro(CheckRPI)
     2.7 +
     2.8 +# Requires:
     2.9 +# - EGL
    2.10 +# - PkgCheckModules
    2.11 +# Optional:
    2.12 +# - KMSDRM_SHARED opt
    2.13 +# - HAVE_DLOPEN opt
    2.14 +macro(CheckKMSDRM)
    2.15 +  if(VIDEO_KMSDRM)
    2.16 +    pkg_check_modules(KMSDRM libdrm gbm egl)
    2.17 +    if(KMSDRM_FOUND)
    2.18 +      link_directories(
    2.19 +        ${KMSDRM_LIBRARY_DIRS}
    2.20 +      )
    2.21 +      include_directories(
    2.22 +        ${KMSDRM_INCLUDE_DIRS}
    2.23 +      )
    2.24 +      set(HAVE_VIDEO_KMSDRM TRUE)
    2.25 +      set(HAVE_SDL_VIDEO TRUE)
    2.26 +
    2.27 +      file(GLOB KMSDRM_SOURCES ${SDL2_SOURCE_DIR}/src/video/kmsdrm/*.c)
    2.28 +      set(SOURCE_FILES ${SOURCE_FILES} ${KMSDRM_SOURCES})
    2.29 +
    2.30 +      list(APPEND EXTRA_CFLAGS ${KMSDRM_CLFLAGS})
    2.31 +
    2.32 +      set(SDL_VIDEO_DRIVER_KMSDRM 1)
    2.33 +
    2.34 +      if(KMSDRM_SHARED)
    2.35 +        if(NOT HAVE_DLOPEN)
    2.36 +          message_warn("You must have SDL_LoadObject() support for dynamic KMS/DRM loading")
    2.37 +        else()
    2.38 +          FindLibraryAndSONAME(drm)
    2.39 +          FindLibraryAndSONAME(gbm)
    2.40 +          set(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC "\"${DRM_LIB_SONAME}\"")
    2.41 +          set(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM "\"${GBM_LIB_SONAME}\"")
    2.42 +          set(HAVE_KMSDRM_SHARED TRUE)
    2.43 +        endif()
    2.44 +      else()
    2.45 +        set(EXTRA_LIBS ${KMSDRM_LIBRARIES} ${EXTRA_LIBS})
    2.46 +      endif()
    2.47 +    endif()
    2.48 +  endif()
    2.49 +endmacro()
     3.1 --- a/configure.in	Mon Jul 31 13:49:22 2017 -0400
     3.2 +++ b/configure.in	Wed Aug 02 10:22:48 2017 -0700
     3.3 @@ -2084,6 +2084,81 @@
     3.4      fi
     3.5  }
     3.6  
     3.7 +dnl Find KMSDRM
     3.8 +CheckKMSDRM()
     3.9 +{
    3.10 +    AC_ARG_ENABLE(video-kmsdrm,
    3.11 +AC_HELP_STRING([--enable-video-kmsdrm], [use KMSDRM video driver [[default=no]]]),
    3.12 +                  , enable_video_kmsdrm=no)
    3.13 +
    3.14 +    if test x$enable_video = xyes -a x$enable_video_kmsdrm = xyes; then
    3.15 +        video_kmsdrm=no
    3.16 +        libdrm_avail=no
    3.17 +        libgbm_avail=no
    3.18 +
    3.19 +        LIBDRM_REQUIRED_VERSION=2.4.46
    3.20 +        LIBGBM_REQUIRED_VERSION=9.0.0
    3.21 +
    3.22 +        AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
    3.23 +        if test x$PKG_CONFIG != xno; then
    3.24 +            if $PKG_CONFIG --atleast-pkgconfig-version 0.7; then
    3.25 +                if $PKG_CONFIG --atleast-version $LIBDRM_REQUIRED_VERSION libdrm; then
    3.26 +                    LIBDRM_CFLAGS=`$PKG_CONFIG --cflags libdrm`
    3.27 +                    LIBDRM_LIBS=`$PKG_CONFIG --libs libdrm`
    3.28 +                    LIBDRM_PREFIX=`$PKG_CONFIG --variable=prefix libdrm`
    3.29 +                    libdrm_avail=yes
    3.30 +                fi
    3.31 +                if $PKG_CONFIG --atleast-version $LIBGBM_REQUIRED_VERSION gbm; then
    3.32 +                    LIBGBM_CFLAGS=`$PKG_CONFIG --cflags gbm`
    3.33 +                    LIBGBM_LIBS=`$PKG_CONFIG --libs gbm`
    3.34 +                    LIBGBM_PREFIX=`$PKG_CONFIG --variable=prefix gbm`
    3.35 +                    libgbm_avail=yes
    3.36 +                fi
    3.37 +                if test x$libdrm_avail = xyes -a x$libgbm_avail = xyes; then
    3.38 +                    video_kmsdrm=yes
    3.39 +                fi
    3.40 + 
    3.41 +                AC_MSG_CHECKING(for libdrm $LIBDRM_REQUIRED_VERSION library for kmsdrm support)
    3.42 +                AC_MSG_RESULT($libdrm_avail)
    3.43 +                AC_MSG_CHECKING(for libgbm $LIBGBM_REQUIRED_VERSION library for kmsdrm support)
    3.44 +                AC_MSG_RESULT($libgbm_avail)
    3.45 +
    3.46 +                if test x$video_kmsdrm = xyes; then
    3.47 +                    AC_ARG_ENABLE(kmsdrm-shared,
    3.48 +AC_HELP_STRING([--enable-kmsdrm-shared], [dynamically load kmsdrm support [[default=yes]]]),
    3.49 +                              , enable_kmsdrm_shared=yes)
    3.50 +
    3.51 +                    AC_DEFINE(SDL_VIDEO_DRIVER_KMSDRM, 1, [ ])
    3.52 +                    SOURCES="$SOURCES $srcdir/src/video/kmsdrm/*.c"
    3.53 +                    EXTRA_CFLAGS="$EXTRA_CFLAGS $LIBDRM_CFLAGS $LIBGBM_CFLAGS"
    3.54 +
    3.55 +                    AC_MSG_CHECKING(for kmsdrm dynamic loading support)
    3.56 +                    kmsdrm_shared=no
    3.57 +                    drm_lib=[`find_lib "libdrm.so.*" "$DRM_LIBS"`]
    3.58 +                    gbm_lib=[`find_lib "libgbm.so.*" "$DRM_LIBS"`]
    3.59 +                    if test x$have_loadso != xyes && \
    3.60 +                       test x$enable_kmsdrm_shared = xyes; then
    3.61 +                        AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic kmsdrm loading])
    3.62 +                    fi
    3.63 +                    if test x$have_loadso = xyes && \
    3.64 +                       test x$enable_kmsdrm_shared = xyes && test x$drm_lib != x && test x$gbm_lib != x; then
    3.65 +                        kmsdrm_shared=yes
    3.66 +                        AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC, "$drm_lib", [ ])
    3.67 +                        AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM, "$gbm_lib", [ ])
    3.68 +                        AC_DEFINE_UNQUOTED(HAVE_KMSDRM_SHARED, "TRUE", [ ])
    3.69 +                        SUMMARY_video="${SUMMARY_video} kmsdrm(dynamic)"
    3.70 +                    else
    3.71 +                        EXTRA_LDFLAGS="$EXTRA_LDFLAGS $LIBDRM_LIBS $LIBGBM_LIBS"
    3.72 +                        SUMMARY_video="${SUMMARY_video} kmsdrm"
    3.73 +                    fi
    3.74 +                    AC_MSG_RESULT($kmsdrm_shared)
    3.75 +                    have_video=yes
    3.76 +                fi
    3.77 +            fi
    3.78 +        fi
    3.79 +    fi
    3.80 +}
    3.81 +
    3.82  dnl rcg04172001 Set up the Null video driver.
    3.83  CheckDummyVideo()
    3.84  {
    3.85 @@ -3148,6 +3223,7 @@
    3.86          CheckLibSampleRate
    3.87          CheckX11
    3.88          CheckDirectFB
    3.89 +        CheckKMSDRM
    3.90          CheckOpenGLX11
    3.91          CheckOpenGLESX11
    3.92          CheckMir
     4.1 --- a/include/SDL_config.h.cmake	Mon Jul 31 13:49:22 2017 -0400
     4.2 +++ b/include/SDL_config.h.cmake	Wed Aug 02 10:22:48 2017 -0700
     4.3 @@ -291,6 +291,10 @@
     4.4  #cmakedefine SDL_VIDEO_DRIVER_VIVANTE @SDL_VIDEO_DRIVER_VIVANTE@
     4.5  #cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@
     4.6  
     4.7 +#cmakedefine SDL_VIDEO_DRIVER_KMSDRM @SDL_VIDEO_DRIVER_KMSDRM@
     4.8 +#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC@
     4.9 +#cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM@
    4.10 +
    4.11  #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH @SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH@
    4.12  #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC@
    4.13  #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@
     5.1 --- a/include/SDL_config.h.in	Mon Jul 31 13:49:22 2017 -0400
     5.2 +++ b/include/SDL_config.h.in	Wed Aug 02 10:22:48 2017 -0700
     5.3 @@ -294,6 +294,9 @@
     5.4  #undef SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON
     5.5  #undef SDL_VIDEO_DRIVER_X11
     5.6  #undef SDL_VIDEO_DRIVER_RPI
     5.7 +#undef SDL_VIDEO_DRIVER_KMSDRM
     5.8 +#undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC
     5.9 +#undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM
    5.10  #undef SDL_VIDEO_DRIVER_ANDROID
    5.11  #undef SDL_VIDEO_DRIVER_EMSCRIPTEN
    5.12  #undef SDL_VIDEO_DRIVER_X11_DYNAMIC
     6.1 --- a/src/video/SDL_egl.c	Mon Jul 31 13:49:22 2017 -0400
     6.2 +++ b/src/video/SDL_egl.c	Wed Aug 02 10:22:48 2017 -0700
     6.3 @@ -30,6 +30,7 @@
     6.4  #endif
     6.5  
     6.6  #include "SDL_sysvideo.h"
     6.7 +#include "SDL_log.h"
     6.8  #include "SDL_egl_c.h"
     6.9  #include "SDL_loadso.h"
    6.10  #include "SDL_hints.h"
    6.11 @@ -114,38 +115,82 @@
    6.12  }
    6.13  
    6.14  /* EGL implementation of SDL OpenGL ES support */
    6.15 -#ifdef EGL_KHR_create_context        
    6.16 -static int SDL_EGL_HasExtension(_THIS, const char *ext)
    6.17 +typedef enum {
    6.18 +    SDL_EGL_DISPLAY_EXTENSION,
    6.19 +    SDL_EGL_CLIENT_EXTENSION
    6.20 +} SDL_EGL_ExtensionType;
    6.21 +
    6.22 +static SDL_bool SDL_EGL_HasExtension(_THIS, SDL_EGL_ExtensionType type, const char *ext)
    6.23  {
    6.24 -    int i;
    6.25 -    int len = 0;
    6.26      size_t ext_len;
    6.27 -    const char *exts;
    6.28 -    const char *ext_word;
    6.29 +    const char *ext_override;
    6.30 +    const char *egl_extstr;
    6.31 +    const char *ext_start;
    6.32 +
    6.33 +    /* Invalid extensions can be rejected early */
    6.34 +    if (ext == NULL || *ext == 0 || SDL_strchr(ext, ' ') != NULL) {
    6.35 +        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SDL_EGL_HasExtension: Invalid EGL extension"); */
    6.36 +        return SDL_FALSE;
    6.37 +    }
    6.38 +
    6.39 +    /* Extensions can be masked with an environment variable.
    6.40 +     * Unlike the OpenGL override, this will use the set bits of an integer
    6.41 +     * to disable the extension.
    6.42 +     *  Bit   Action
    6.43 +     *  0     If set, the display extension is masked and not present to SDL.
    6.44 +     *  1     If set, the client extension is masked and not present to SDL.
    6.45 +     */
    6.46 +    ext_override = SDL_getenv(ext);
    6.47 +    if (ext_override != NULL) {
    6.48 +        int disable_ext = SDL_atoi(ext_override);
    6.49 +        if (disable_ext & 0x01 && type == SDL_EGL_DISPLAY_EXTENSION) {
    6.50 +            return SDL_FALSE;
    6.51 +        } else if (disable_ext & 0x02 && type == SDL_EGL_CLIENT_EXTENSION) {
    6.52 +            return SDL_FALSE;
    6.53 +        }
    6.54 +    }
    6.55  
    6.56      ext_len = SDL_strlen(ext);
    6.57 -    exts = _this->egl_data->eglQueryString(_this->egl_data->egl_display, EGL_EXTENSIONS);
    6.58 +    switch (type) {
    6.59 +    case SDL_EGL_DISPLAY_EXTENSION:
    6.60 +        egl_extstr = _this->egl_data->eglQueryString(_this->egl_data->egl_display, EGL_EXTENSIONS);
    6.61 +        break;
    6.62 +    case SDL_EGL_CLIENT_EXTENSION:
    6.63 +        /* EGL_EXT_client_extensions modifies eglQueryString to return client extensions
    6.64 +         * if EGL_NO_DISPLAY is passed. Implementations without it are required to return NULL.
    6.65 +         * This behavior is included in EGL 1.5.
    6.66 +         */
    6.67 +        egl_extstr = _this->egl_data->eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
    6.68 +        break;
    6.69 +    default:
    6.70 +        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "SDL_EGL_HasExtension: Invalid extension type"); */
    6.71 +        return SDL_FALSE;
    6.72 +    }
    6.73  
    6.74 -    if (exts) {
    6.75 -        ext_word = exts;
    6.76 +    if (egl_extstr != NULL) {
    6.77 +        ext_start = egl_extstr;
    6.78  
    6.79 -        for (i = 0; exts[i] != 0; i++) {
    6.80 -            if (exts[i] == ' ') {
    6.81 -                if (ext_len == len && !SDL_strncmp(ext_word, ext, len)) {
    6.82 -                    return 1;
    6.83 +        while (*ext_start) {
    6.84 +            ext_start = SDL_strstr(ext_start, ext);
    6.85 +            if (ext_start == NULL) {
    6.86 +                return SDL_FALSE;
    6.87 +            }
    6.88 +            /* Check if the match is not just a substring of one of the extensions */
    6.89 +            if (ext_start == egl_extstr || *(ext_start - 1) == ' ') {
    6.90 +                if (ext_start[ext_len] == ' ' || ext_start[ext_len] == 0) {
    6.91 +                    return SDL_TRUE;
    6.92                  }
    6.93 -
    6.94 -                len = 0;
    6.95 -                ext_word = &exts[i + 1];
    6.96 -            } else {
    6.97 -                len++;
    6.98 +            }
    6.99 +            /* If the search stopped in the middle of an extension, skip to the end of it */
   6.100 +            ext_start += ext_len;
   6.101 +            while (*ext_start != ' ' && *ext_start != 0) {
   6.102 +                ext_start++;
   6.103              }
   6.104          }
   6.105      }
   6.106  
   6.107 -    return 0;
   6.108 +    return SDL_FALSE;
   6.109  }
   6.110 -#endif /* EGL_KHR_create_context */
   6.111  
   6.112  void *
   6.113  SDL_EGL_GetProcAddress(_THIS, const char *proc)
   6.114 @@ -196,10 +241,11 @@
   6.115  }
   6.116  
   6.117  int
   6.118 -SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display)
   6.119 +SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display, EGLenum platform)
   6.120  {
   6.121      void *dll_handle = NULL, *egl_dll_handle = NULL; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */
   6.122      const char *path = NULL;
   6.123 +    int egl_version_major = 0, egl_version_minor = 0;
   6.124  #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
   6.125      const char *d3dcompiler;
   6.126  #endif
   6.127 @@ -305,9 +351,41 @@
   6.128      LOAD_FUNC(eglQueryString);
   6.129      LOAD_FUNC(eglGetError);
   6.130  
   6.131 +    if (_this->egl_data->eglQueryString) {
   6.132 +        /* EGL 1.5 allows querying for client version */
   6.133 +        const char *egl_version = _this->egl_data->eglQueryString(EGL_NO_DISPLAY, EGL_VERSION);
   6.134 +        if (egl_version != NULL) {
   6.135 +            if (SDL_sscanf(egl_version, "%d.%d", &egl_version_major, &egl_version_minor) != 2) {
   6.136 +                egl_version_major = 0;
   6.137 +                egl_version_minor = 0;
   6.138 +                SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not parse EGL version string: %s", egl_version);
   6.139 +            }
   6.140 +        }
   6.141 +    }
   6.142 +
   6.143 +    if (egl_version_major == 1 && egl_version_minor == 5) {
   6.144 +        LOAD_FUNC(eglGetPlatformDisplay);
   6.145 +    }
   6.146 +
   6.147 +    _this->egl_data->egl_display = EGL_NO_DISPLAY;
   6.148  #if !defined(__WINRT__)
   6.149 -    _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
   6.150 -    if (!_this->egl_data->egl_display) {
   6.151 +    if (platform) {
   6.152 +        if (egl_version_major == 1 && egl_version_minor == 5) {
   6.153 +            _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, native_display, NULL);
   6.154 +        } else {
   6.155 +            if (SDL_EGL_HasExtension(_this, SDL_EGL_CLIENT_EXTENSION, "EGL_EXT_platform_base")) {
   6.156 +                _this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddress(_this, "eglGetPlatformDisplayEXT");
   6.157 +                if (_this->egl_data->eglGetPlatformDisplayEXT) {
   6.158 +                    _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(platform, native_display, NULL);
   6.159 +                }
   6.160 +            }
   6.161 +        }
   6.162 +    }
   6.163 +    /* Try the implementation-specific eglGetDisplay even if eglGetPlatformDisplay fails */
   6.164 +    if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
   6.165 +        _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
   6.166 +    }
   6.167 +    if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
   6.168          return SDL_SetError("Could not get EGL display");
   6.169      }
   6.170      
   6.171 @@ -328,13 +406,19 @@
   6.172  int
   6.173  SDL_EGL_ChooseConfig(_THIS) 
   6.174  {
   6.175 -    /* 64 seems nice. */
   6.176 +/* 64 seems nice. */
   6.177      EGLint attribs[64];
   6.178      EGLint found_configs = 0, value;
   6.179 +#ifdef SDL_VIDEO_DRIVER_KMSDRM
   6.180 +    /* Intel EGL on KMS/DRM (al least) returns invalid configs that confuse the bitdiff search used */
   6.181 +    /* later in this function, so we simply use the first one when using the KMSDRM driver for now. */
   6.182 +    EGLConfig configs[1];
   6.183 +#else
   6.184      /* 128 seems even nicer here */
   6.185      EGLConfig configs[128];
   6.186 +#endif
   6.187      int i, j, best_bitdiff = -1, bitdiff;
   6.188 -    
   6.189 +   
   6.190      if (!_this->egl_data) {
   6.191          /* The EGL library wasn't loaded, SDL_GetError() should have info */
   6.192          return -1;
   6.193 @@ -379,7 +463,7 @@
   6.194  
   6.195      if (_this->gl_config.framebuffer_srgb_capable) {
   6.196  #ifdef EGL_KHR_gl_colorspace
   6.197 -        if (SDL_EGL_HasExtension(_this, "EGL_KHR_gl_colorspace")) {
   6.198 +        if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_gl_colorspace")) {
   6.199              attribs[i++] = EGL_GL_COLORSPACE_KHR;
   6.200              attribs[i++] = EGL_GL_COLORSPACE_SRGB_KHR;
   6.201          } else
   6.202 @@ -393,7 +477,7 @@
   6.203      if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
   6.204  #ifdef EGL_KHR_create_context
   6.205          if (_this->gl_config.major_version >= 3 &&
   6.206 -            SDL_EGL_HasExtension(_this, "EGL_KHR_create_context")) {
   6.207 +            SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_create_context")) {
   6.208              attribs[i++] = EGL_OPENGL_ES3_BIT_KHR;
   6.209          } else
   6.210  #endif
   6.211 @@ -495,7 +579,7 @@
   6.212          /* The Major/minor version, context profiles, and context flags can
   6.213           * only be specified when this extension is available.
   6.214           */
   6.215 -        if (SDL_EGL_HasExtension(_this, "EGL_KHR_create_context")) {
   6.216 +        if (SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_create_context")) {
   6.217              attribs[attr++] = EGL_CONTEXT_MAJOR_VERSION_KHR;
   6.218              attribs[attr++] = major_version;
   6.219              attribs[attr++] = EGL_CONTEXT_MINOR_VERSION_KHR;
     7.1 --- a/src/video/SDL_egl_c.h	Mon Jul 31 13:49:22 2017 -0400
     7.2 +++ b/src/video/SDL_egl_c.h	Wed Aug 02 10:22:48 2017 -0700
     7.3 @@ -37,6 +37,12 @@
     7.4      int egl_swapinterval;
     7.5      
     7.6      EGLDisplay(EGLAPIENTRY *eglGetDisplay) (NativeDisplayType display);
     7.7 +    EGLDisplay(EGLAPIENTRY *eglGetPlatformDisplay) (EGLenum platform,
     7.8 +                                void *native_display,
     7.9 +                                const EGLint *attrib_list);
    7.10 +    EGLDisplay(EGLAPIENTRY *eglGetPlatformDisplayEXT) (EGLenum platform,
    7.11 +                                void *native_display,
    7.12 +                                const EGLint *attrib_list);
    7.13      EGLBoolean(EGLAPIENTRY *eglInitialize) (EGLDisplay dpy, EGLint * major,
    7.14                                  EGLint * minor);
    7.15      EGLBoolean(EGLAPIENTRY  *eglTerminate) (EGLDisplay dpy);
    7.16 @@ -85,7 +91,10 @@
    7.17  
    7.18  /* OpenGLES functions */
    7.19  extern int SDL_EGL_GetAttribute(_THIS, SDL_GLattr attrib, int *value);
    7.20 -extern int SDL_EGL_LoadLibrary(_THIS, const char *path, NativeDisplayType native_display);
    7.21 +/* SDL_EGL_LoadLibrary can get a display for a specific platform (EGL_PLATFORM_*)
    7.22 + * or, if 0 is passed, let the implementation decide.
    7.23 + */
    7.24 +extern int SDL_EGL_LoadLibrary(_THIS, const char *path, NativeDisplayType native_display, EGLenum platform);
    7.25  extern void *SDL_EGL_GetProcAddress(_THIS, const char *proc);
    7.26  extern void SDL_EGL_UnloadLibrary(_THIS);
    7.27  extern int SDL_EGL_ChooseConfig(_THIS);
     8.1 --- a/src/video/SDL_sysvideo.h	Mon Jul 31 13:49:22 2017 -0400
     8.2 +++ b/src/video/SDL_sysvideo.h	Wed Aug 02 10:22:48 2017 -0700
     8.3 @@ -385,6 +385,7 @@
     8.4  extern VideoBootStrap Android_bootstrap;
     8.5  extern VideoBootStrap PSP_bootstrap;
     8.6  extern VideoBootStrap RPI_bootstrap;
     8.7 +extern VideoBootStrap KMSDRM_bootstrap;
     8.8  extern VideoBootStrap DUMMY_bootstrap;
     8.9  extern VideoBootStrap Wayland_bootstrap;
    8.10  extern VideoBootStrap NACL_bootstrap;
     9.1 --- a/src/video/SDL_video.c	Mon Jul 31 13:49:22 2017 -0400
     9.2 +++ b/src/video/SDL_video.c	Wed Aug 02 10:22:48 2017 -0700
     9.3 @@ -105,6 +105,9 @@
     9.4  #if SDL_VIDEO_DRIVER_RPI
     9.5      &RPI_bootstrap,
     9.6  #endif 
     9.7 +#if SDL_VIDEO_DRIVER_KMSDRM
     9.8 +    &KMSDRM_bootstrap,
     9.9 +#endif
    9.10  #if SDL_VIDEO_DRIVER_NACL
    9.11      &NACL_bootstrap,
    9.12  #endif
    9.13 @@ -2892,7 +2895,7 @@
    9.14              break;
    9.15  
    9.16          terminator = where + SDL_strlen(extension);
    9.17 -        if (where == start || *(where - 1) == ' ')
    9.18 +        if (where == extensions || *(where - 1) == ' ')
    9.19              if (*terminator == ' ' || *terminator == '\0')
    9.20                  return SDL_TRUE;
    9.21  
    10.1 --- a/src/video/android/SDL_androidgl.c	Mon Jul 31 13:49:22 2017 -0400
    10.2 +++ b/src/video/android/SDL_androidgl.c	Wed Aug 02 10:22:48 2017 -0700
    10.3 @@ -54,7 +54,7 @@
    10.4  
    10.5  int
    10.6  Android_GLES_LoadLibrary(_THIS, const char *path) {
    10.7 -    return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) 0);
    10.8 +    return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) 0, 0);
    10.9  }
   10.10  
   10.11  #endif /* SDL_VIDEO_DRIVER_ANDROID */
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/video/kmsdrm/SDL_kmsdrmdyn.c	Wed Aug 02 10:22:48 2017 -0700
    11.3 @@ -0,0 +1,170 @@
    11.4 +/*
    11.5 +  Simple DirectMedia Layer
    11.6 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
    11.7 +
    11.8 +  This software is provided 'as-is', without any express or implied
    11.9 +  warranty.  In no event will the authors be held liable for any damages
   11.10 +  arising from the use of this software.
   11.11 +
   11.12 +  Permission is granted to anyone to use this software for any purpose,
   11.13 +  including commercial applications, and to alter it and redistribute it
   11.14 +  freely, subject to the following restrictions:
   11.15 +
   11.16 +  1. The origin of this software must not be misrepresented; you must not
   11.17 +     claim that you wrote the original software. If you use this software
   11.18 +     in a product, an acknowledgment in the product documentation would be
   11.19 +     appreciated but is not required.
   11.20 +  2. Altered source versions must be plainly marked as such, and must not be
   11.21 +     misrepresented as being the original software.
   11.22 +  3. This notice may not be removed or altered from any source distribution.
   11.23 +*/
   11.24 +#include "../../SDL_internal.h"
   11.25 +
   11.26 +#if SDL_VIDEO_DRIVER_KMSDRM
   11.27 +
   11.28 +#define DEBUG_DYNAMIC_KMSDRM 0
   11.29 +
   11.30 +#include "SDL_kmsdrmdyn.h"
   11.31 +
   11.32 +#if DEBUG_DYNAMIC_KMSDRM
   11.33 +#include "SDL_log.h"
   11.34 +#endif
   11.35 +
   11.36 +#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC
   11.37 +
   11.38 +#include "SDL_name.h"
   11.39 +#include "SDL_loadso.h"
   11.40 +
   11.41 +typedef struct
   11.42 +{
   11.43 +    void *lib;
   11.44 +    const char *libname;
   11.45 +} kmsdrmdynlib;
   11.46 +
   11.47 +#ifndef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC
   11.48 +#define SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC NULL
   11.49 +#endif
   11.50 +#ifndef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM
   11.51 +#define SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM NULL
   11.52 +#endif
   11.53 +
   11.54 +static kmsdrmdynlib kmsdrmlibs[] = {
   11.55 +    {NULL, SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC},
   11.56 +    {NULL, SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM}
   11.57 +};
   11.58 +
   11.59 +static void *
   11.60 +KMSDRM_GetSym(const char *fnname, int *pHasModule)
   11.61 +{
   11.62 +    int i;
   11.63 +    void *fn = NULL;
   11.64 +    for (i = 0; i < SDL_TABLESIZE(kmsdrmlibs); i++) {
   11.65 +        if (kmsdrmlibs[i].lib != NULL) {
   11.66 +            fn = SDL_LoadFunction(kmsdrmlibs[i].lib, fnname);
   11.67 +            if (fn != NULL)
   11.68 +                break;
   11.69 +        }
   11.70 +    }
   11.71 +
   11.72 +#if DEBUG_DYNAMIC_KMSDRM
   11.73 +    if (fn != NULL)
   11.74 +        SDL_Log("KMSDRM: Found '%s' in %s (%p)\n", fnname, kmsdrmlibs[i].libname, fn);
   11.75 +    else
   11.76 +        SDL_Log("KMSDRM: Symbol '%s' NOT FOUND!\n", fnname);
   11.77 +#endif
   11.78 +
   11.79 +    if (fn == NULL)
   11.80 +        *pHasModule = 0;  /* kill this module. */
   11.81 +
   11.82 +    return fn;
   11.83 +}
   11.84 +
   11.85 +#endif /* SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC */
   11.86 +
   11.87 +/* Define all the function pointers and wrappers... */
   11.88 +#define SDL_KMSDRM_MODULE(modname) int SDL_KMSDRM_HAVE_##modname = 0;
   11.89 +#define SDL_KMSDRM_SYM(rc,fn,params) SDL_DYNKMSDRMFN_##fn KMSDRM_##fn = NULL;
   11.90 +#define SDL_KMSDRM_SYM_CONST(type,name) SDL_DYNKMSDRMCONST_##name KMSDRM_##name = NULL;
   11.91 +#include "SDL_kmsdrmsym.h"
   11.92 +
   11.93 +static int kmsdrm_load_refcount = 0;
   11.94 +
   11.95 +void
   11.96 +SDL_KMSDRM_UnloadSymbols(void)
   11.97 +{
   11.98 +    /* Don't actually unload if more than one module is using the libs... */
   11.99 +    if (kmsdrm_load_refcount > 0) {
  11.100 +        if (--kmsdrm_load_refcount == 0) {
  11.101 +#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC
  11.102 +            int i;
  11.103 +#endif
  11.104 +
  11.105 +            /* set all the function pointers to NULL. */
  11.106 +#define SDL_KMSDRM_MODULE(modname) SDL_KMSDRM_HAVE_##modname = 0;
  11.107 +#define SDL_KMSDRM_SYM(rc,fn,params) KMSDRM_##fn = NULL;
  11.108 +#define SDL_KMSDRM_SYM_CONST(type,name) KMSDRM_##name = NULL;
  11.109 +#include "SDL_kmsdrmsym.h"
  11.110 +
  11.111 +
  11.112 +#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC
  11.113 +            for (i = 0; i < SDL_TABLESIZE(kmsdrmlibs); i++) {
  11.114 +                if (kmsdrmlibs[i].lib != NULL) {
  11.115 +                    SDL_UnloadObject(kmsdrmlibs[i].lib);
  11.116 +                    kmsdrmlibs[i].lib = NULL;
  11.117 +                }
  11.118 +            }
  11.119 +#endif
  11.120 +        }
  11.121 +    }
  11.122 +}
  11.123 +
  11.124 +/* returns non-zero if all needed symbols were loaded. */
  11.125 +int
  11.126 +SDL_KMSDRM_LoadSymbols(void)
  11.127 +{
  11.128 +    int rc = 1;                 /* always succeed if not using Dynamic KMSDRM stuff. */
  11.129 +
  11.130 +    /* deal with multiple modules needing these symbols... */
  11.131 +    if (kmsdrm_load_refcount++ == 0) {
  11.132 +#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC
  11.133 +        int i;
  11.134 +        int *thismod = NULL;
  11.135 +        for (i = 0; i < SDL_TABLESIZE(kmsdrmlibs); i++) {
  11.136 +            if (kmsdrmlibs[i].libname != NULL) {
  11.137 +                kmsdrmlibs[i].lib = SDL_LoadObject(kmsdrmlibs[i].libname);
  11.138 +            }
  11.139 +        }
  11.140 +
  11.141 +#define SDL_KMSDRM_MODULE(modname) SDL_KMSDRM_HAVE_##modname = 1; /* default yes */
  11.142 +#include "SDL_kmsdrmsym.h"
  11.143 +
  11.144 +#define SDL_KMSDRM_MODULE(modname) thismod = &SDL_KMSDRM_HAVE_##modname;
  11.145 +#define SDL_KMSDRM_SYM(rc,fn,params) KMSDRM_##fn = (SDL_DYNKMSDRMFN_##fn) KMSDRM_GetSym(#fn,thismod);
  11.146 +#define SDL_KMSDRM_SYM_CONST(type,name) KMSDRM_##name = *(SDL_DYNKMSDRMCONST_##name*) KMSDRM_GetSym(#name,thismod);
  11.147 +#include "SDL_kmsdrmsym.h"
  11.148 +
  11.149 +        if ((SDL_KMSDRM_HAVE_LIBDRM) && (SDL_KMSDRM_HAVE_GBM)) {
  11.150 +            /* all required symbols loaded. */
  11.151 +            SDL_ClearError();
  11.152 +        } else {
  11.153 +            /* in case something got loaded... */
  11.154 +            SDL_KMSDRM_UnloadSymbols();
  11.155 +            rc = 0;
  11.156 +        }
  11.157 +
  11.158 +#else  /* no dynamic KMSDRM */
  11.159 +
  11.160 +#define SDL_KMSDRM_MODULE(modname) SDL_KMSDRM_HAVE_##modname = 1; /* default yes */
  11.161 +#define SDL_KMSDRM_SYM(rc,fn,params) KMSDRM_##fn = fn;
  11.162 +#define SDL_KMSDRM_SYM_CONST(type,name) KMSDRM_##name = name;
  11.163 +#include "SDL_kmsdrmsym.h"
  11.164 +
  11.165 +#endif
  11.166 +    }
  11.167 +
  11.168 +    return rc;
  11.169 +}
  11.170 +
  11.171 +#endif /* SDL_VIDEO_DRIVER_KMSDRM */
  11.172 +
  11.173 +/* vi: set ts=4 sw=4 expandtab: */
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/video/kmsdrm/SDL_kmsdrmdyn.h	Wed Aug 02 10:22:48 2017 -0700
    12.3 @@ -0,0 +1,54 @@
    12.4 +/*
    12.5 +  Simple DirectMedia Layer
    12.6 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
    12.7 +
    12.8 +  This software is provided 'as-is', without any express or implied
    12.9 +  warranty.  In no event will the authors be held liable for any damages
   12.10 +  arising from the use of this software.
   12.11 +
   12.12 +  Permission is granted to anyone to use this software for any purpose,
   12.13 +  including commercial applications, and to alter it and redistribute it
   12.14 +  freely, subject to the following restrictions:
   12.15 +
   12.16 +  1. The origin of this software must not be misrepresented; you must not
   12.17 +     claim that you wrote the original software. If you use this software
   12.18 +     in a product, an acknowledgment in the product documentation would be
   12.19 +     appreciated but is not required.
   12.20 +  2. Altered source versions must be plainly marked as such, and must not be
   12.21 +     misrepresented as being the original software.
   12.22 +  3. This notice may not be removed or altered from any source distribution.
   12.23 +*/
   12.24 +
   12.25 +#ifndef _SDL_kmsdrmdyn_h
   12.26 +#define _SDL_kmsdrmdyn_h
   12.27 +
   12.28 +#include "../../SDL_internal.h"
   12.29 +
   12.30 +#include <xf86drm.h>
   12.31 +#include <xf86drmMode.h>
   12.32 +#include <gbm.h>
   12.33 +#include <EGL/egl.h>
   12.34 +
   12.35 +#ifdef __cplusplus
   12.36 +extern "C" {
   12.37 +#endif
   12.38 +
   12.39 +int SDL_KMSDRM_LoadSymbols(void);
   12.40 +void SDL_KMSDRM_UnloadSymbols(void);
   12.41 +
   12.42 +/* Declare all the function pointers and wrappers... */
   12.43 +#define SDL_KMSDRM_SYM(rc,fn,params) \
   12.44 +    typedef rc (*SDL_DYNKMSDRMFN_##fn) params; \
   12.45 +    extern SDL_DYNKMSDRMFN_##fn KMSDRM_##fn;
   12.46 +#define SDL_KMSDRM_SYM_CONST(type, name) \
   12.47 +    typedef type SDL_DYNKMSDRMCONST_##name; \
   12.48 +    extern SDL_DYNKMSDRMCONST_##name KMSDRM_##name;
   12.49 +#include "SDL_kmsdrmsym.h"
   12.50 +
   12.51 +#ifdef __cplusplus
   12.52 +}
   12.53 +#endif
   12.54 +
   12.55 +#endif /* !defined _SDL_kmsdrmdyn_h */
   12.56 +
   12.57 +/* vi: set ts=4 sw=4 expandtab: */
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/video/kmsdrm/SDL_kmsdrmevents.c	Wed Aug 02 10:22:48 2017 -0700
    13.3 @@ -0,0 +1,45 @@
    13.4 +/*
    13.5 +  Simple DirectMedia Layer
    13.6 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
    13.7 +
    13.8 +  This software is provided 'as-is', without any express or implied
    13.9 +  warranty.  In no event will the authors be held liable for any damages
   13.10 +  arising from the use of this software.
   13.11 +
   13.12 +  Permission is granted to anyone to use this software for any purpose,
   13.13 +  including commercial applications, and to alter it and redistribute it
   13.14 +  freely, subject to the following restrictions:
   13.15 +
   13.16 +  1. The origin of this software must not be misrepresented; you must not
   13.17 +     claim that you wrote the original software. If you use this software
   13.18 +     in a product, an acknowledgment in the product documentation would be
   13.19 +     appreciated but is not required.
   13.20 +  2. Altered source versions must be plainly marked as such, and must not be
   13.21 +     misrepresented as being the original software.
   13.22 +  3. This notice may not be removed or altered from any source distribution.
   13.23 +*/
   13.24 +
   13.25 +#include "../../SDL_internal.h"
   13.26 +
   13.27 +#if SDL_VIDEO_DRIVER_KMSDRM
   13.28 +
   13.29 +#include "../../events/SDL_sysevents.h"
   13.30 +#include "../../events/SDL_events_c.h"
   13.31 +#include "../../events/SDL_keyboard_c.h"
   13.32 +#include "SDL_kmsdrmvideo.h"
   13.33 +#include "SDL_kmsdrmevents_c.h"
   13.34 +
   13.35 +#ifdef SDL_INPUT_LINUXEV
   13.36 +#include "../../core/linux/SDL_evdev.h"
   13.37 +#endif
   13.38 +
   13.39 +void KMSDRM_PumpEvents(_THIS)
   13.40 +{
   13.41 +#ifdef SDL_INPUT_LINUXEV
   13.42 +    SDL_EVDEV_Poll();
   13.43 +#endif
   13.44 +
   13.45 +}
   13.46 +
   13.47 +#endif /* SDL_VIDEO_DRIVER_KMSDRM */
   13.48 +
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/src/video/kmsdrm/SDL_kmsdrmevents_c.h	Wed Aug 02 10:22:48 2017 -0700
    14.3 @@ -0,0 +1,31 @@
    14.4 +/*
    14.5 +  Simple DirectMedia Layer
    14.6 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
    14.7 +
    14.8 +  This software is provided 'as-is', without any express or implied
    14.9 +  warranty.  In no event will the authors be held liable for any damages
   14.10 +  arising from the use of this software.
   14.11 +
   14.12 +  Permission is granted to anyone to use this software for any purpose,
   14.13 +  including commercial applications, and to alter it and redistribute it
   14.14 +  freely, subject to the following restrictions:
   14.15 +
   14.16 +  1. The origin of this software must not be misrepresented; you must not
   14.17 +     claim that you wrote the original software. If you use this software
   14.18 +     in a product, an acknowledgment in the product documentation would be
   14.19 +     appreciated but is not required.
   14.20 +  2. Altered source versions must be plainly marked as such, and must not be
   14.21 +     misrepresented as being the original software.
   14.22 +  3. This notice may not be removed or altered from any source distribution.
   14.23 +*/
   14.24 +
   14.25 +#ifndef _SDL_kmsdrmevents_c_h
   14.26 +#define _SDL_kmsdrmevents_c_h
   14.27 +
   14.28 +#include "SDL_kmsdrmvideo.h"
   14.29 +
   14.30 +void KMSDRM_PumpEvents(_THIS);
   14.31 +void KMSDRM_EventInit(_THIS);
   14.32 +void KMSDRM_EventQuit(_THIS);
   14.33 +
   14.34 +#endif /* _SDL_kmsdrmevents_c_h */
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c	Wed Aug 02 10:22:48 2017 -0700
    15.3 @@ -0,0 +1,426 @@
    15.4 +/*
    15.5 +  Simple DirectMedia Layer
    15.6 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
    15.7 +
    15.8 +  This software is provided 'as-is', without any express or implied
    15.9 +  warranty.  In no event will the authors be held liable for any damages
   15.10 +  arising from the use of this software.
   15.11 +
   15.12 +  Permission is granted to anyone to use this software for any purpose,
   15.13 +  including commercial applications, and to alter it and redistribute it
   15.14 +  freely, subject to the following restrictions:
   15.15 +
   15.16 +  1. The origin of this software must not be misrepresented; you must not
   15.17 +     claim that you wrote the original software. If you use this software
   15.18 +     in a product, an acknowledgment in the product documentation would be
   15.19 +     appreciated but is not required.
   15.20 +  2. Altered source versions must be plainly marked as such, and must not be
   15.21 +     misrepresented as being the original software.
   15.22 +  3. This notice may not be removed or altered from any source distribution.
   15.23 +*/
   15.24 +#include "../../SDL_internal.h"
   15.25 +
   15.26 +#if SDL_VIDEO_DRIVER_KMSDRM
   15.27 +
   15.28 +#include "SDL_assert.h"
   15.29 +#include "SDL_surface.h"
   15.30 +
   15.31 +#include "SDL_kmsdrmvideo.h"
   15.32 +#include "SDL_kmsdrmmouse.h"
   15.33 +#include "SDL_kmsdrmdyn.h"
   15.34 +
   15.35 +#include "../SDL_sysvideo.h"
   15.36 +#include "../../events/SDL_mouse_c.h"
   15.37 +#include "../../events/default_cursor.h"
   15.38 +
   15.39 +
   15.40 +static SDL_Cursor *KMSDRM_CreateDefaultCursor(void);
   15.41 +static SDL_Cursor *KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y);
   15.42 +static int KMSDRM_ShowCursor(SDL_Cursor * cursor);
   15.43 +static void KMSDRM_MoveCursor(SDL_Cursor * cursor);
   15.44 +static void KMSDRM_FreeCursor(SDL_Cursor * cursor);
   15.45 +static void KMSDRM_WarpMouse(SDL_Window * window, int x, int y);
   15.46 +static int KMSDRM_WarpMouseGlobal(int x, int y);
   15.47 +
   15.48 +static SDL_Cursor *
   15.49 +KMSDRM_CreateDefaultCursor(void)
   15.50 +{
   15.51 +    return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
   15.52 +}
   15.53 +
   15.54 +/* Create a cursor from a surface */
   15.55 +static SDL_Cursor *
   15.56 +KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
   15.57 +{
   15.58 +    SDL_VideoDevice *dev = SDL_GetVideoDevice();
   15.59 +    SDL_VideoData *vdata = ((SDL_VideoData *)dev->driverdata);
   15.60 +    SDL_PixelFormat *pixlfmt = surface->format;
   15.61 +    KMSDRM_CursorData *curdata;
   15.62 +    SDL_Cursor *cursor;
   15.63 +    int i, ret;
   15.64 +    uint32_t bo_format, bo_stride;
   15.65 +    char *buffer = NULL;
   15.66 +    size_t bufsize;
   15.67 +
   15.68 +    switch(pixlfmt->format) {
   15.69 +    case SDL_PIXELFORMAT_RGB332:
   15.70 +        bo_format = GBM_FORMAT_RGB332;
   15.71 +        break;
   15.72 +    case SDL_PIXELFORMAT_ARGB4444:
   15.73 +        bo_format = GBM_FORMAT_ARGB4444;
   15.74 +        break;
   15.75 +    case SDL_PIXELFORMAT_RGBA4444:
   15.76 +        bo_format = GBM_FORMAT_RGBA4444;
   15.77 +        break;
   15.78 +    case SDL_PIXELFORMAT_ABGR4444:
   15.79 +        bo_format = GBM_FORMAT_ABGR4444;
   15.80 +        break;
   15.81 +    case SDL_PIXELFORMAT_BGRA4444:
   15.82 +        bo_format = GBM_FORMAT_BGRA4444;
   15.83 +        break;
   15.84 +    case SDL_PIXELFORMAT_ARGB1555:
   15.85 +        bo_format = GBM_FORMAT_ARGB1555;
   15.86 +        break;
   15.87 +    case SDL_PIXELFORMAT_RGBA5551:
   15.88 +        bo_format = GBM_FORMAT_RGBA5551;
   15.89 +        break;
   15.90 +    case SDL_PIXELFORMAT_ABGR1555:
   15.91 +        bo_format = GBM_FORMAT_ABGR1555;
   15.92 +        break;
   15.93 +    case SDL_PIXELFORMAT_BGRA5551:
   15.94 +        bo_format = GBM_FORMAT_BGRA5551;
   15.95 +        break;
   15.96 +    case SDL_PIXELFORMAT_RGB565:
   15.97 +        bo_format = GBM_FORMAT_RGB565;
   15.98 +        break;
   15.99 +    case SDL_PIXELFORMAT_BGR565:
  15.100 +        bo_format = GBM_FORMAT_BGR565;
  15.101 +        break;
  15.102 +    case SDL_PIXELFORMAT_RGB888:
  15.103 +    case SDL_PIXELFORMAT_RGB24:
  15.104 +        bo_format = GBM_FORMAT_RGB888;
  15.105 +        break;
  15.106 +    case SDL_PIXELFORMAT_BGR888:
  15.107 +    case SDL_PIXELFORMAT_BGR24:
  15.108 +        bo_format = GBM_FORMAT_BGR888;
  15.109 +        break;
  15.110 +    case SDL_PIXELFORMAT_RGBX8888:
  15.111 +        bo_format = GBM_FORMAT_RGBX8888;
  15.112 +        break;
  15.113 +    case SDL_PIXELFORMAT_BGRX8888:
  15.114 +        bo_format = GBM_FORMAT_BGRX8888;
  15.115 +        break;
  15.116 +    case SDL_PIXELFORMAT_ARGB8888:
  15.117 +        bo_format = GBM_FORMAT_ARGB8888;
  15.118 +        break;
  15.119 +    case SDL_PIXELFORMAT_RGBA8888:
  15.120 +        bo_format = GBM_FORMAT_RGBA8888;
  15.121 +        break;
  15.122 +    case SDL_PIXELFORMAT_ABGR8888:
  15.123 +        bo_format = GBM_FORMAT_ABGR8888;
  15.124 +        break;
  15.125 +    case SDL_PIXELFORMAT_BGRA8888:
  15.126 +        bo_format = GBM_FORMAT_BGRA8888;
  15.127 +        break;
  15.128 +    case SDL_PIXELFORMAT_ARGB2101010:
  15.129 +        bo_format = GBM_FORMAT_ARGB2101010;
  15.130 +        break;
  15.131 +    default:
  15.132 +        SDL_SetError("Unsupported pixel format for cursor");
  15.133 +        return NULL;
  15.134 +    }
  15.135 +
  15.136 +    if (!KMSDRM_gbm_device_is_format_supported(vdata->gbm, bo_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)) {
  15.137 +        SDL_SetError("Unsupported pixel format for cursor");
  15.138 +        return NULL;
  15.139 +    }
  15.140 +
  15.141 +    cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor));
  15.142 +    if (cursor == NULL) {
  15.143 +        SDL_OutOfMemory();
  15.144 +        return NULL;
  15.145 +    }
  15.146 +    curdata = (KMSDRM_CursorData *) SDL_calloc(1, sizeof(*curdata));
  15.147 +    if (curdata == NULL) {
  15.148 +        SDL_OutOfMemory();
  15.149 +        SDL_free(cursor);
  15.150 +        return NULL;
  15.151 +    }
  15.152 +
  15.153 +    curdata->hot_x = hot_x;
  15.154 +    curdata->hot_y = hot_y;
  15.155 +    curdata->w = surface->w;
  15.156 +    curdata->h = surface->h;
  15.157 +
  15.158 +    curdata->bo = KMSDRM_gbm_bo_create(vdata->gbm, surface->w, surface->h, bo_format,
  15.159 +                                       GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
  15.160 +    if (curdata->bo == NULL) {
  15.161 +        SDL_SetError("Could not create GBM cursor BO");
  15.162 +        goto cleanup;
  15.163 +    }
  15.164 +
  15.165 +    bo_stride = KMSDRM_gbm_bo_get_stride(curdata->bo);
  15.166 +    bufsize = bo_stride * surface->h;
  15.167 +
  15.168 +    if (surface->pitch != bo_stride) {
  15.169 +        /* pitch doesn't match stride, must be copied to temp buffer  */
  15.170 +        buffer = SDL_malloc(bufsize);
  15.171 +        if (buffer == NULL) {
  15.172 +            SDL_OutOfMemory();
  15.173 +            goto cleanup;
  15.174 +        }
  15.175 +
  15.176 +        if (SDL_MUSTLOCK(surface)) {
  15.177 +            if (SDL_LockSurface(surface) < 0) {
  15.178 +                /* Could not lock surface */
  15.179 +                goto cleanup;
  15.180 +            }
  15.181 +        }
  15.182 +
  15.183 +        /* Copy to temporary buffer */
  15.184 +        for (i = 0; i < surface->h; i++) {
  15.185 +            SDL_memcpy(buffer + (i * bo_stride),
  15.186 +                       ((char *)surface->pixels) + (i * surface->pitch),
  15.187 +                       surface->w * pixlfmt->BytesPerPixel);
  15.188 +        }
  15.189 +
  15.190 +        if (SDL_MUSTLOCK(surface)) {
  15.191 +            SDL_UnlockSurface(surface);
  15.192 +        }
  15.193 +
  15.194 +        if (KMSDRM_gbm_bo_write(curdata->bo, buffer, bufsize)) {
  15.195 +            SDL_SetError("Could not write to GBM cursor BO");
  15.196 +            goto cleanup;
  15.197 +        }
  15.198 +
  15.199 +        /* Free temporary buffer */
  15.200 +        SDL_free(buffer);
  15.201 +        buffer = NULL;
  15.202 +    } else {
  15.203 +        /* surface matches BO format */
  15.204 +        if (SDL_MUSTLOCK(surface)) {
  15.205 +            if (SDL_LockSurface(surface) < 0) {
  15.206 +                /* Could not lock surface */
  15.207 +                goto cleanup;
  15.208 +            }
  15.209 +        }
  15.210 +
  15.211 +        ret = KMSDRM_gbm_bo_write(curdata->bo, surface->pixels, bufsize);
  15.212 +
  15.213 +        if (SDL_MUSTLOCK(surface)) {
  15.214 +            SDL_UnlockSurface(surface);
  15.215 +        }
  15.216 +
  15.217 +        if (ret) {
  15.218 +            SDL_SetError("Could not write to GBM cursor BO");
  15.219 +            goto cleanup;
  15.220 +        }
  15.221 +    }
  15.222 +
  15.223 +    cursor->driverdata = curdata;
  15.224 +
  15.225 +    return cursor;
  15.226 +
  15.227 +cleanup:
  15.228 +    if (buffer != NULL) {
  15.229 +        SDL_free(buffer);
  15.230 +    }
  15.231 +    if (cursor != NULL) {
  15.232 +        SDL_free(cursor);
  15.233 +    }
  15.234 +    if (curdata != NULL) {
  15.235 +        if (curdata->bo != NULL) {
  15.236 +            KMSDRM_gbm_bo_destroy(curdata->bo);
  15.237 +        }
  15.238 +        SDL_free(curdata);
  15.239 +    }
  15.240 +    return NULL;
  15.241 +}
  15.242 +
  15.243 +/* Show the specified cursor, or hide if cursor is NULL */
  15.244 +static int
  15.245 +KMSDRM_ShowCursor(SDL_Cursor * cursor)
  15.246 +{
  15.247 +    SDL_VideoDevice *dev = SDL_GetVideoDevice();
  15.248 +    SDL_VideoData *vdata = ((SDL_VideoData *)dev->driverdata);
  15.249 +    SDL_Mouse *mouse;
  15.250 +    KMSDRM_CursorData *curdata;
  15.251 +    SDL_VideoDisplay *display = NULL;
  15.252 +    SDL_DisplayData *ddata = NULL;
  15.253 +    int ret;
  15.254 +    uint32_t bo_handle;
  15.255 +
  15.256 +    mouse = SDL_GetMouse();
  15.257 +    if (mouse == NULL) {
  15.258 +        return SDL_SetError("No mouse.");
  15.259 +    }
  15.260 +
  15.261 +    if (mouse->focus != NULL) {
  15.262 +        display = SDL_GetDisplayForWindow(mouse->focus);
  15.263 +        if (display != NULL) {
  15.264 +            ddata = (SDL_DisplayData*) display->driverdata;
  15.265 +        }
  15.266 +    }
  15.267 +
  15.268 +    if (cursor == NULL) {
  15.269 +        /* Hide current cursor */
  15.270 +        if ( mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) {
  15.271 +            curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata;
  15.272 +
  15.273 +            if (curdata->crtc_id != 0) {
  15.274 +                ret = KMSDRM_drmModeSetCursor(vdata->drm_fd, curdata->crtc_id, 0, 0, 0);
  15.275 +                if (ret) {
  15.276 +                    SDL_SetError("Could not hide current cursor with drmModeSetCursor().");
  15.277 +                    return ret;
  15.278 +                }
  15.279 +                /* Mark previous cursor as not-displayed */
  15.280 +                curdata->crtc_id = 0;
  15.281 +
  15.282 +                return 0;
  15.283 +            }
  15.284 +        }
  15.285 +        /* otherwise if possible, hide global cursor */
  15.286 +        if (ddata != NULL && ddata->crtc_id != 0) {
  15.287 +            ret = KMSDRM_drmModeSetCursor(vdata->drm_fd, ddata->crtc_id, 0, 0, 0);
  15.288 +            if (ret) {
  15.289 +                SDL_SetError("Could not hide display's cursor with drmModeSetCursor().");
  15.290 +                return ret;
  15.291 +            }
  15.292 +            return 0;
  15.293 +        }
  15.294 +
  15.295 +        return SDL_SetError("Couldn't find cursor to hide.");
  15.296 +    }
  15.297 +    /* If cursor != NULL, show new cursor on display */
  15.298 +    if (display == NULL) {
  15.299 +        return SDL_SetError("Could not get display for mouse.");
  15.300 +    }
  15.301 +    if (ddata == NULL) {
  15.302 +        return SDL_SetError("Could not get display driverdata.");
  15.303 +    }
  15.304 +
  15.305 +    curdata = (KMSDRM_CursorData *) cursor->driverdata;
  15.306 +    if (curdata == NULL || curdata->bo == NULL) {
  15.307 +        return SDL_SetError("Cursor not initialized properly.");
  15.308 +    }
  15.309 +
  15.310 +    bo_handle = KMSDRM_gbm_bo_get_handle(curdata->bo).u32;
  15.311 +    if (curdata->hot_x == 0 && curdata->hot_y == 0) {
  15.312 +        ret = KMSDRM_drmModeSetCursor(vdata->drm_fd, ddata->crtc_id, bo_handle,
  15.313 +                                      curdata->w, curdata->h);
  15.314 +    } else {
  15.315 +        ret = KMSDRM_drmModeSetCursor2(vdata->drm_fd, ddata->crtc_id, bo_handle,
  15.316 +                                       curdata->w, curdata->h,
  15.317 +                                       curdata->hot_x, curdata->hot_y);
  15.318 +    }
  15.319 +    if (ret) {
  15.320 +        SDL_SetError("drmModeSetCursor failed.");
  15.321 +        return ret;
  15.322 +    }
  15.323 +
  15.324 +    curdata->crtc_id = ddata->crtc_id;
  15.325 +
  15.326 +    return 0;
  15.327 +}
  15.328 +
  15.329 +/* Free a window manager cursor */
  15.330 +static void
  15.331 +KMSDRM_FreeCursor(SDL_Cursor * cursor)
  15.332 +{
  15.333 +    KMSDRM_CursorData *curdata;
  15.334 +    int drm_fd;
  15.335 +
  15.336 +    if (cursor != NULL) {
  15.337 +        curdata = (KMSDRM_CursorData *) cursor->driverdata;
  15.338 +
  15.339 +        if (curdata != NULL) {
  15.340 +            if (curdata->bo != NULL) {
  15.341 +                if (curdata->crtc_id != 0) {
  15.342 +                    drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(curdata->bo));
  15.343 +                    /* Hide the cursor if previously shown on a CRTC */
  15.344 +                    KMSDRM_drmModeSetCursor(drm_fd, curdata->crtc_id, 0, 0, 0);
  15.345 +                    curdata->crtc_id = 0;
  15.346 +                }
  15.347 +                KMSDRM_gbm_bo_destroy(curdata->bo);
  15.348 +                curdata->bo = NULL;
  15.349 +            }
  15.350 +            SDL_free(cursor->driverdata);
  15.351 +        }
  15.352 +        SDL_free(cursor);
  15.353 +    }
  15.354 +}
  15.355 +
  15.356 +/* Warp the mouse to (x,y) */
  15.357 +static void
  15.358 +KMSDRM_WarpMouse(SDL_Window * window, int x, int y)
  15.359 +{
  15.360 +    /* Only one global/fullscreen window is supported */
  15.361 +    KMSDRM_WarpMouseGlobal(x, y);
  15.362 +}
  15.363 +
  15.364 +/* Warp the mouse to (x,y) */
  15.365 +static int
  15.366 +KMSDRM_WarpMouseGlobal(int x, int y)
  15.367 +{
  15.368 +    KMSDRM_CursorData *curdata;
  15.369 +    SDL_Mouse *mouse = SDL_GetMouse();
  15.370 +
  15.371 +    if (mouse != NULL && mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) {
  15.372 +        curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata;
  15.373 +        if (curdata->bo != NULL) {
  15.374 +            if (curdata->crtc_id != 0) {
  15.375 +                int ret, drm_fd;
  15.376 +                drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(curdata->bo));
  15.377 +                ret = KMSDRM_drmModeMoveCursor(drm_fd, curdata->crtc_id, x, y);
  15.378 +
  15.379 +                if (ret) {
  15.380 +                    SDL_SetError("drmModeMoveCursor() failed.");
  15.381 +                }
  15.382 +
  15.383 +                return ret;
  15.384 +            } else {
  15.385 +                return SDL_SetError("Cursor is not currently shown.");
  15.386 +            }
  15.387 +        } else {
  15.388 +            return SDL_SetError("Cursor not initialized properly.");
  15.389 +        }
  15.390 +    } else {
  15.391 +        return SDL_SetError("No mouse or current cursor.");
  15.392 +    }
  15.393 +}
  15.394 +
  15.395 +void
  15.396 +KMSDRM_InitMouse(_THIS)
  15.397 +{
  15.398 +    /* FIXME: Using UDEV it should be possible to scan all mice
  15.399 +     * but there's no point in doing so as there's no multimice support...yet!
  15.400 +     */
  15.401 +    SDL_Mouse *mouse = SDL_GetMouse();
  15.402 +
  15.403 +    mouse->CreateCursor = KMSDRM_CreateCursor;
  15.404 +    mouse->ShowCursor = KMSDRM_ShowCursor;
  15.405 +    mouse->MoveCursor = KMSDRM_MoveCursor;
  15.406 +    mouse->FreeCursor = KMSDRM_FreeCursor;
  15.407 +    mouse->WarpMouse = KMSDRM_WarpMouse;
  15.408 +    mouse->WarpMouseGlobal = KMSDRM_WarpMouseGlobal;
  15.409 +
  15.410 +    SDL_SetDefaultCursor(KMSDRM_CreateDefaultCursor());
  15.411 +}
  15.412 +
  15.413 +void
  15.414 +KMSDRM_QuitMouse(_THIS)
  15.415 +{
  15.416 +    /* TODO: ? */
  15.417 +}
  15.418 +
  15.419 +/* This is called when a mouse motion event occurs */
  15.420 +static void
  15.421 +KMSDRM_MoveCursor(SDL_Cursor * cursor)
  15.422 +{
  15.423 +    SDL_Mouse *mouse = SDL_GetMouse();
  15.424 +    KMSDRM_WarpMouse(mouse->focus, mouse->x, mouse->y);
  15.425 +}
  15.426 +
  15.427 +#endif /* SDL_VIDEO_DRIVER_KMSDRM */
  15.428 +
  15.429 +/* vi: set ts=4 sw=4 expandtab: */
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/src/video/kmsdrm/SDL_kmsdrmmouse.h	Wed Aug 02 10:22:48 2017 -0700
    16.3 @@ -0,0 +1,42 @@
    16.4 +/*
    16.5 +  Simple DirectMedia Layer
    16.6 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
    16.7 +
    16.8 +  This software is provided 'as-is', without any express or implied
    16.9 +  warranty.  In no event will the authors be held liable for any damages
   16.10 +  arising from the use of this software.
   16.11 +
   16.12 +  Permission is granted to anyone to use this software for any purpose,
   16.13 +  including commercial applications, and to alter it and redistribute it
   16.14 +  freely, subject to the following restrictions:
   16.15 +
   16.16 +  1. The origin of this software must not be misrepresented; you must not
   16.17 +     claim that you wrote the original software. If you use this software
   16.18 +     in a product, an acknowledgment in the product documentation would be
   16.19 +     appreciated but is not required.
   16.20 +  2. Altered source versions must be plainly marked as such, and must not be
   16.21 +     misrepresented as being the original software.
   16.22 +  3. This notice may not be removed or altered from any source distribution.
   16.23 +*/
   16.24 +
   16.25 +#ifndef _SDL_KMSDRM_mouse_h
   16.26 +#define _SDL_KMSDRM_mouse_h
   16.27 +
   16.28 +#include <gbm.h>
   16.29 +
   16.30 +#include "../SDL_sysvideo.h"
   16.31 +
   16.32 +typedef struct _KMSDRM_CursorData
   16.33 +{
   16.34 +    struct gbm_bo *bo;
   16.35 +    uint32_t       crtc_id;
   16.36 +    int            hot_x, hot_y;
   16.37 +    int            w, h;
   16.38 +} KMSDRM_CursorData;
   16.39 +
   16.40 +extern void KMSDRM_InitMouse(_THIS);
   16.41 +extern void KMSDRM_QuitMouse(_THIS);
   16.42 +
   16.43 +#endif /* _SDL_KMSDRM_mouse_h */
   16.44 +
   16.45 +/* vi: set ts=4 sw=4 expandtab: */
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c	Wed Aug 02 10:22:48 2017 -0700
    17.3 @@ -0,0 +1,126 @@
    17.4 +/*
    17.5 +  Simple DirectMedia Layer
    17.6 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
    17.7 +
    17.8 +  This software is provided 'as-is', without any express or implied
    17.9 +  warranty.  In no event will the authors be held liable for any damages
   17.10 +  arising from the use of this software.
   17.11 +
   17.12 +  Permission is granted to anyone to use this software for any purpose,
   17.13 +  including commercial applications, and to alter it and redistribute it
   17.14 +  freely, subject to the following restrictions:
   17.15 +
   17.16 +  1. The origin of this software must not be misrepresented; you must not
   17.17 +     claim that you wrote the original software. If you use this software
   17.18 +     in a product, an acknowledgment in the product documentation would be
   17.19 +     appreciated but is not required.
   17.20 +  2. Altered source versions must be plainly marked as such, and must not be
   17.21 +     misrepresented as being the original software.
   17.22 +  3. This notice may not be removed or altered from any source distribution.
   17.23 +*/
   17.24 +#include "../../SDL_internal.h"
   17.25 +
   17.26 +#if SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL
   17.27 +
   17.28 +#include "SDL_log.h"
   17.29 +
   17.30 +#include "SDL_kmsdrmvideo.h"
   17.31 +#include "SDL_kmsdrmopengles.h"
   17.32 +#include "SDL_kmsdrmdyn.h"
   17.33 +
   17.34 +#ifndef EGL_PLATFORM_GBM_MESA
   17.35 +#define EGL_PLATFORM_GBM_MESA 0x31D7
   17.36 +#endif
   17.37 +
   17.38 +/* EGL implementation of SDL OpenGL support */
   17.39 +
   17.40 +int
   17.41 +KMSDRM_GLES_LoadLibrary(_THIS, const char *path) {
   17.42 +    return SDL_EGL_LoadLibrary(_this, path, ((SDL_VideoData *)_this->driverdata)->gbm, EGL_PLATFORM_GBM_MESA);
   17.43 +}
   17.44 +
   17.45 +SDL_EGL_CreateContext_impl(KMSDRM)
   17.46 +
   17.47 +int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) {
   17.48 +    if (!_this->egl_data) {
   17.49 +        return SDL_SetError("EGL not initialized");
   17.50 +    }
   17.51 +
   17.52 +    if (interval == 0 || interval == 1) {
   17.53 +        _this->egl_data->egl_swapinterval = interval;
   17.54 +    } else {
   17.55 +        return SDL_SetError("Only swap intervals of 0 or 1 are supported");
   17.56 +    }
   17.57 +
   17.58 +    return 0;
   17.59 +}
   17.60 +
   17.61 +int
   17.62 +KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
   17.63 +    SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata);
   17.64 +    SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
   17.65 +    SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
   17.66 +    KMSDRM_FBInfo *fb_info;
   17.67 +    int ret;
   17.68 +
   17.69 +    /* Do we still need to wait for a flip? */
   17.70 +    int timeout = 0;
   17.71 +    if (_this->egl_data->egl_swapinterval == 1) {
   17.72 +        timeout = -1;
   17.73 +    }
   17.74 +    if (!KMSDRM_WaitPageFlip(_this, wdata, timeout)) {
   17.75 +        return 0;
   17.76 +    }
   17.77 +
   17.78 +    /* Release previously displayed buffer (which is now the backbuffer) and lock a new one */
   17.79 +    if (wdata->locked_bo != NULL) {
   17.80 +        KMSDRM_gbm_surface_release_buffer(wdata->gs, wdata->locked_bo);
   17.81 +        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Released GBM surface %p", (void *)wdata->locked_bo); */
   17.82 +        wdata->locked_bo = NULL;
   17.83 +    }
   17.84 +
   17.85 +    if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) {
   17.86 +        SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed.");
   17.87 +        return 0;
   17.88 +    }
   17.89 +
   17.90 +    wdata->locked_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
   17.91 +    if (wdata->locked_bo == NULL) {
   17.92 +        SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer");
   17.93 +        return 0;
   17.94 +    /* } else {
   17.95 +        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Locked GBM surface %p", (void *)wdata->locked_bo); */
   17.96 +    }
   17.97 +
   17.98 +    fb_info = KMSDRM_FBFromBO(_this, wdata->locked_bo);
   17.99 +    if (_this->egl_data->egl_swapinterval == 0) {
  17.100 +        /* Swap buffers instantly, possible tearing */
  17.101 +        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModeSetCrtc(%d, %u, %u, 0, 0, &%u, 1, &%ux%u@%u)",
  17.102 +            vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, vdata->saved_conn_id,
  17.103 +            displaydata->cur_mode.hdisplay, displaydata->cur_mode.vdisplay, displaydata->cur_mode.vrefresh); */
  17.104 +        ret = KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
  17.105 +                                    0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode);
  17.106 +        if(ret != 0) {
  17.107 +            SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not pageflip with drmModeSetCrtc: %d", ret);
  17.108 +        }
  17.109 +    } else {
  17.110 +        /* Queue page flip at vsync */
  17.111 +        /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip)",
  17.112 +            vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */
  17.113 +        ret = KMSDRM_drmModePageFlip(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
  17.114 +                                     DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip);
  17.115 +        if (ret == 0) {
  17.116 +            wdata->waiting_for_flip = SDL_TRUE;
  17.117 +        } else {
  17.118 +            SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
  17.119 +        }
  17.120 +    }
  17.121 +
  17.122 +    return 0;
  17.123 +}
  17.124 +
  17.125 +SDL_EGL_MakeCurrent_impl(KMSDRM)
  17.126 +
  17.127 +#endif /* SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL */
  17.128 +
  17.129 +/* vi: set ts=4 sw=4 expandtab: */
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.h	Wed Aug 02 10:22:48 2017 -0700
    18.3 @@ -0,0 +1,48 @@
    18.4 +/*
    18.5 +  Simple DirectMedia Layer
    18.6 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
    18.7 +
    18.8 +  This software is provided 'as-is', without any express or implied
    18.9 +  warranty.  In no event will the authors be held liable for any damages
   18.10 +  arising from the use of this software.
   18.11 +
   18.12 +  Permission is granted to anyone to use this software for any purpose,
   18.13 +  including commercial applications, and to alter it and redistribute it
   18.14 +  freely, subject to the following restrictions:
   18.15 +
   18.16 +  1. The origin of this software must not be misrepresented; you must not
   18.17 +     claim that you wrote the original software. If you use this software
   18.18 +     in a product, an acknowledgment in the product documentation would be
   18.19 +     appreciated but is not required.
   18.20 +  2. Altered source versions must be plainly marked as such, and must not be
   18.21 +     misrepresented as being the original software.
   18.22 +  3. This notice may not be removed or altered from any source distribution.
   18.23 +*/
   18.24 +#include "../../SDL_internal.h"
   18.25 +
   18.26 +#ifndef _SDL_kmsdrmopengles_h
   18.27 +#define _SDL_kmsdrmopengles_h
   18.28 +
   18.29 +#if SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL
   18.30 +
   18.31 +#include "../SDL_sysvideo.h"
   18.32 +#include "../SDL_egl_c.h"
   18.33 +
   18.34 +/* OpenGLES functions */
   18.35 +#define KMSDRM_GLES_GetAttribute SDL_EGL_GetAttribute
   18.36 +#define KMSDRM_GLES_GetProcAddress SDL_EGL_GetProcAddress
   18.37 +#define KMSDRM_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
   18.38 +#define KMSDRM_GLES_DeleteContext SDL_EGL_DeleteContext
   18.39 +#define KMSDRM_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
   18.40 +
   18.41 +extern int KMSDRM_GLES_SetSwapInterval(_THIS, int interval);
   18.42 +extern int KMSDRM_GLES_LoadLibrary(_THIS, const char *path);
   18.43 +extern SDL_GLContext KMSDRM_GLES_CreateContext(_THIS, SDL_Window * window);
   18.44 +extern int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window);
   18.45 +extern int KMSDRM_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
   18.46 +
   18.47 +#endif /* SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL */
   18.48 +
   18.49 +#endif /* _SDL_kmsdrmopengles_h */
   18.50 +
   18.51 +/* vi: set ts=4 sw=4 expandtab: */
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/src/video/kmsdrm/SDL_kmsdrmsym.h	Wed Aug 02 10:22:48 2017 -0700
    19.3 @@ -0,0 +1,99 @@
    19.4 +/*
    19.5 +  Simple DirectMedia Layer
    19.6 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
    19.7 +
    19.8 +  This software is provided 'as-is', without any express or implied
    19.9 +  warranty.  In no event will the authors be held liable for any damages
   19.10 +  arising from the use of this software.
   19.11 +
   19.12 +  Permission is granted to anyone to use this software for any purpose,
   19.13 +  including commercial applications, and to alter it and redistribute it
   19.14 +  freely, subject to the following restrictions:
   19.15 +
   19.16 +  1. The origin of this software must not be misrepresented; you must not
   19.17 +     claim that you wrote the original software. If you use this software
   19.18 +     in a product, an acknowledgment in the product documentation would be
   19.19 +     appreciated but is not required.
   19.20 +  2. Altered source versions must be plainly marked as such, and must not be
   19.21 +     misrepresented as being the original software.
   19.22 +  3. This notice may not be removed or altered from any source distribution.
   19.23 +*/
   19.24 +
   19.25 +/* *INDENT-OFF* */
   19.26 +
   19.27 +#ifndef SDL_KMSDRM_MODULE
   19.28 +#define SDL_KMSDRM_MODULE(modname)
   19.29 +#endif
   19.30 +
   19.31 +#ifndef SDL_KMSDRM_SYM
   19.32 +#define SDL_KMSDRM_SYM(rc,fn,params)
   19.33 +#endif
   19.34 +
   19.35 +#ifndef SDL_KMSDRM_SYM_CONST
   19.36 +#define SDL_KMSDRM_SYM_CONST(type, name)
   19.37 +#endif
   19.38 +
   19.39 +
   19.40 +SDL_KMSDRM_MODULE(LIBDRM)
   19.41 +SDL_KMSDRM_SYM(void,drmModeFreeResources,(drmModeResPtr ptr))
   19.42 +SDL_KMSDRM_SYM(void,drmModeFreeFB,(drmModeFBPtr ptr))
   19.43 +SDL_KMSDRM_SYM(void,drmModeFreeCrtc,(drmModeCrtcPtr ptr))
   19.44 +SDL_KMSDRM_SYM(void,drmModeFreeConnector,(drmModeConnectorPtr ptr))
   19.45 +SDL_KMSDRM_SYM(void,drmModeFreeEncoder,(drmModeEncoderPtr ptr))
   19.46 +SDL_KMSDRM_SYM(drmModeResPtr,drmModeGetResources,(int fd))
   19.47 +SDL_KMSDRM_SYM(int,drmModeAddFB,(int fd, uint32_t width, uint32_t height, uint8_t depth,
   19.48 +                                 uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
   19.49 +                                 uint32_t *buf_id))
   19.50 +SDL_KMSDRM_SYM(int,drmModeRmFB,(int fd, uint32_t bufferId))
   19.51 +SDL_KMSDRM_SYM(drmModeFBPtr,drmModeGetFB,(int fd, uint32_t buf))
   19.52 +SDL_KMSDRM_SYM(drmModeCrtcPtr,drmModeGetCrtc,(int fd, uint32_t crtcId))
   19.53 +SDL_KMSDRM_SYM(int,drmModeSetCrtc,(int fd, uint32_t crtcId, uint32_t bufferId,
   19.54 +                                   uint32_t x, uint32_t y, uint32_t *connectors, int count,
   19.55 +                                   drmModeModeInfoPtr mode))
   19.56 +SDL_KMSDRM_SYM(int,drmModeSetCursor,(int fd, uint32_t crtcId, uint32_t bo_handle,
   19.57 +                                     uint32_t width, uint32_t height))
   19.58 +SDL_KMSDRM_SYM(int,drmModeSetCursor2,(int fd, uint32_t crtcId, uint32_t bo_handle,
   19.59 +                                      uint32_t width, uint32_t height,
   19.60 +                                      int32_t hot_x, int32_t hot_y))
   19.61 +SDL_KMSDRM_SYM(int,drmModeMoveCursor,(int fd, uint32_t crtcId, int x, int y))
   19.62 +SDL_KMSDRM_SYM(drmModeEncoderPtr,drmModeGetEncoder,(int fd, uint32_t encoder_id))
   19.63 +SDL_KMSDRM_SYM(drmModeConnectorPtr,drmModeGetConnector,(int fd, uint32_t connector_id))
   19.64 +SDL_KMSDRM_SYM(int,drmHandleEvent,(int fd,drmEventContextPtr evctx))
   19.65 +SDL_KMSDRM_SYM(int,drmModePageFlip,(int fd, uint32_t crtc_id, uint32_t fb_id,
   19.66 +                                    uint32_t flags, void *user_data))
   19.67 +
   19.68 +
   19.69 +SDL_KMSDRM_MODULE(GBM)
   19.70 +SDL_KMSDRM_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm))
   19.71 +SDL_KMSDRM_SYM(int,gbm_device_is_format_supported,(struct gbm_device *gbm,
   19.72 +                                                   uint32_t format, uint32_t usage))
   19.73 +SDL_KMSDRM_SYM(void,gbm_device_destroy,(struct gbm_device *gbm))
   19.74 +SDL_KMSDRM_SYM(struct gbm_device *,gbm_create_device,(int fd))
   19.75 +SDL_KMSDRM_SYM(unsigned int,gbm_bo_get_width,(struct gbm_bo *bo))
   19.76 +SDL_KMSDRM_SYM(unsigned int,gbm_bo_get_height,(struct gbm_bo *bo))
   19.77 +SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_stride,(struct gbm_bo *bo))
   19.78 +SDL_KMSDRM_SYM(union gbm_bo_handle,gbm_bo_get_handle,(struct gbm_bo *bo))
   19.79 +SDL_KMSDRM_SYM(int,gbm_bo_write,(struct gbm_bo *bo, const void *buf, size_t count))
   19.80 +SDL_KMSDRM_SYM(struct gbm_device *,gbm_bo_get_device,(struct gbm_bo *bo))
   19.81 +SDL_KMSDRM_SYM(void,gbm_bo_set_user_data,(struct gbm_bo *bo, void *data,
   19.82 +                                          void (*destroy_user_data)(struct gbm_bo *, void *)))
   19.83 +SDL_KMSDRM_SYM(void *,gbm_bo_get_user_data,(struct gbm_bo *bo))
   19.84 +SDL_KMSDRM_SYM(void,gbm_bo_destroy,(struct gbm_bo *bo))
   19.85 +SDL_KMSDRM_SYM(struct gbm_bo *,gbm_bo_create,(struct gbm_device *gbm,
   19.86 +                                              uint32_t width, uint32_t height,
   19.87 +                                              uint32_t format, uint32_t usage))
   19.88 +SDL_KMSDRM_SYM(struct gbm_surface *,gbm_surface_create,(struct gbm_device *gbm,
   19.89 +                                                        uint32_t width, uint32_t height,
   19.90 +                                                        uint32_t format, uint32_t flags))
   19.91 +SDL_KMSDRM_SYM(void,gbm_surface_destroy,(struct gbm_surface *surf))
   19.92 +SDL_KMSDRM_SYM(struct gbm_bo *,gbm_surface_lock_front_buffer,(struct gbm_surface *surf))
   19.93 +SDL_KMSDRM_SYM(void,gbm_surface_release_buffer,(struct gbm_surface *surf, struct gbm_bo *bo))
   19.94 +
   19.95 +
   19.96 +#undef SDL_KMSDRM_MODULE
   19.97 +#undef SDL_KMSDRM_SYM
   19.98 +#undef SDL_KMSDRM_SYM_CONST
   19.99 +
  19.100 +/* *INDENT-ON* */
  19.101 +
  19.102 +/* vi: set ts=4 sw=4 expandtab: */
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c	Wed Aug 02 10:22:48 2017 -0700
    20.3 @@ -0,0 +1,634 @@
    20.4 +/*
    20.5 +  Simple DirectMedia Layer
    20.6 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
    20.7 +
    20.8 +  This software is provided 'as-is', without any express or implied
    20.9 +  warranty.  In no event will the authors be held liable for any damages
   20.10 +  arising from the use of this software.
   20.11 +
   20.12 +  Permission is granted to anyone to use this software for any purpose,
   20.13 +  including commercial applications, and to alter it and redistribute it
   20.14 +  freely, subject to the following restrictions:
   20.15 +
   20.16 +  1. The origin of this software must not be misrepresented; you must not
   20.17 +     claim that you wrote the original software. If you use this software
   20.18 +     in a product, an acknowledgment in the product documentation would be
   20.19 +     appreciated but is not required.
   20.20 +  2. Altered source versions must be plainly marked as such, and must not be
   20.21 +     misrepresented as being the original software.
   20.22 +  3. This notice may not be removed or altered from any source distribution.
   20.23 +*/
   20.24 +
   20.25 +#include "../../SDL_internal.h"
   20.26 +
   20.27 +#if SDL_VIDEO_DRIVER_KMSDRM
   20.28 +
   20.29 +/* SDL internals */
   20.30 +#include "../SDL_sysvideo.h"
   20.31 +#include "SDL_version.h"
   20.32 +#include "SDL_syswm.h"
   20.33 +#include "SDL_loadso.h"
   20.34 +#include "SDL_events.h"
   20.35 +#include "SDL_log.h"
   20.36 +#include "../../events/SDL_mouse_c.h"
   20.37 +#include "../../events/SDL_keyboard_c.h"
   20.38 +
   20.39 +#ifdef SDL_INPUT_LINUXEV
   20.40 +#include "../../core/linux/SDL_evdev.h"
   20.41 +#endif
   20.42 +
   20.43 +/* KMS/DRM declarations */
   20.44 +#include "SDL_kmsdrmvideo.h"
   20.45 +#include "SDL_kmsdrmevents_c.h"
   20.46 +#include "SDL_kmsdrmopengles.h"
   20.47 +#include "SDL_kmsdrmmouse.h"
   20.48 +#include "SDL_kmsdrmdyn.h"
   20.49 +
   20.50 +#define KMSDRM_DRI_CARD_0 "/dev/dri/card0"
   20.51 +
   20.52 +static int
   20.53 +KMSDRM_Available(void)
   20.54 +{
   20.55 +    int available = 0;
   20.56 +
   20.57 +    int drm_fd = open(KMSDRM_DRI_CARD_0, O_RDWR | O_CLOEXEC);
   20.58 +    if (drm_fd >= 0) {
   20.59 +        if (SDL_KMSDRM_LoadSymbols()) {
   20.60 +            drmModeRes *resources = KMSDRM_drmModeGetResources(drm_fd);
   20.61 +            if (resources != NULL) {
   20.62 +                available = 1;
   20.63 +                KMSDRM_drmModeFreeResources(resources);
   20.64 +            }
   20.65 +            SDL_KMSDRM_UnloadSymbols();
   20.66 +        }
   20.67 +        close(drm_fd);
   20.68 +    }
   20.69 +
   20.70 +    return available;
   20.71 +}
   20.72 +
   20.73 +static void
   20.74 +KMSDRM_Destroy(SDL_VideoDevice * device)
   20.75 +{
   20.76 +    if (device->driverdata != NULL) {
   20.77 +        SDL_free(device->driverdata);
   20.78 +        device->driverdata = NULL;
   20.79 +    }
   20.80 +    SDL_KMSDRM_UnloadSymbols();
   20.81 +}
   20.82 +
   20.83 +static SDL_VideoDevice *
   20.84 +KMSDRM_Create(int devindex)
   20.85 +{
   20.86 +    SDL_VideoDevice *device;
   20.87 +    SDL_VideoData *vdata;
   20.88 +
   20.89 +    if (devindex < 0 || devindex > 99) {
   20.90 +        SDL_SetError("devindex (%d) must be between 0 and 99.\n", devindex);
   20.91 +        return NULL;
   20.92 +    }
   20.93 +
   20.94 +    if (!SDL_KMSDRM_LoadSymbols()) {
   20.95 +        return NULL;
   20.96 +    }
   20.97 +
   20.98 +    /* Initialize SDL_VideoDevice structure */
   20.99 +    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
  20.100 +    if (device == NULL) {
  20.101 +        SDL_OutOfMemory();
  20.102 +        goto cleanup;
  20.103 +    }
  20.104 +
  20.105 +    /* Initialize internal data */
  20.106 +    vdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
  20.107 +    if (vdata == NULL) {
  20.108 +        SDL_OutOfMemory();
  20.109 +        goto cleanup;
  20.110 +    }
  20.111 +    vdata->devindex = devindex;
  20.112 +    vdata->drm_fd = -1;
  20.113 +
  20.114 +    device->driverdata = vdata;
  20.115 +
  20.116 +    /* Setup amount of available displays and current display */
  20.117 +    device->num_displays = 0;
  20.118 +
  20.119 +    /* Set device free function */
  20.120 +    device->free = KMSDRM_Destroy;
  20.121 +
  20.122 +    /* Setup all functions which we can handle */
  20.123 +    device->VideoInit = KMSDRM_VideoInit;
  20.124 +    device->VideoQuit = KMSDRM_VideoQuit;
  20.125 +    device->GetDisplayModes = KMSDRM_GetDisplayModes;
  20.126 +    device->SetDisplayMode = KMSDRM_SetDisplayMode;
  20.127 +    device->CreateWindow = KMSDRM_CreateWindow;
  20.128 +    device->CreateWindowFrom = KMSDRM_CreateWindowFrom;
  20.129 +    device->SetWindowTitle = KMSDRM_SetWindowTitle;
  20.130 +    device->SetWindowIcon = KMSDRM_SetWindowIcon;
  20.131 +    device->SetWindowPosition = KMSDRM_SetWindowPosition;
  20.132 +    device->SetWindowSize = KMSDRM_SetWindowSize;
  20.133 +    device->ShowWindow = KMSDRM_ShowWindow;
  20.134 +    device->HideWindow = KMSDRM_HideWindow;
  20.135 +    device->RaiseWindow = KMSDRM_RaiseWindow;
  20.136 +    device->MaximizeWindow = KMSDRM_MaximizeWindow;
  20.137 +    device->MinimizeWindow = KMSDRM_MinimizeWindow;
  20.138 +    device->RestoreWindow = KMSDRM_RestoreWindow;
  20.139 +    device->SetWindowGrab = KMSDRM_SetWindowGrab;
  20.140 +    device->DestroyWindow = KMSDRM_DestroyWindow;
  20.141 +    device->GetWindowWMInfo = KMSDRM_GetWindowWMInfo;
  20.142 +    device->GL_LoadLibrary = KMSDRM_GLES_LoadLibrary;
  20.143 +    device->GL_GetProcAddress = KMSDRM_GLES_GetProcAddress;
  20.144 +    device->GL_UnloadLibrary = KMSDRM_GLES_UnloadLibrary;
  20.145 +    device->GL_CreateContext = KMSDRM_GLES_CreateContext;
  20.146 +    device->GL_MakeCurrent = KMSDRM_GLES_MakeCurrent;
  20.147 +    device->GL_SetSwapInterval = KMSDRM_GLES_SetSwapInterval;
  20.148 +    device->GL_GetSwapInterval = KMSDRM_GLES_GetSwapInterval;
  20.149 +    device->GL_SwapWindow = KMSDRM_GLES_SwapWindow;
  20.150 +    device->GL_DeleteContext = KMSDRM_GLES_DeleteContext;
  20.151 +
  20.152 +    device->PumpEvents = KMSDRM_PumpEvents;
  20.153 +
  20.154 +    return device;
  20.155 +
  20.156 +cleanup:
  20.157 +    if (device != NULL)
  20.158 +        SDL_free(device);
  20.159 +    if (vdata != NULL)
  20.160 +        SDL_free(vdata);
  20.161 +    return NULL;
  20.162 +}
  20.163 +
  20.164 +VideoBootStrap KMSDRM_bootstrap = {
  20.165 +    "KMSDRM",
  20.166 +    "KMS/DRM Video Driver",
  20.167 +    KMSDRM_Available,
  20.168 +    KMSDRM_Create
  20.169 +};
  20.170 +
  20.171 +
  20.172 +static void
  20.173 +KMSDRM_FBDestroyCallback(struct gbm_bo *bo, void *data)
  20.174 +{
  20.175 +    KMSDRM_FBInfo *fb_info = (KMSDRM_FBInfo *)data;
  20.176 +
  20.177 +    if (fb_info && fb_info->drm_fd > 0 && fb_info->fb_id != 0) {
  20.178 +        KMSDRM_drmModeRmFB(fb_info->drm_fd, fb_info->fb_id);
  20.179 +        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Delete DRM FB %u", fb_info->fb_id);
  20.180 +    }
  20.181 +
  20.182 +    free(fb_info);
  20.183 +}
  20.184 +
  20.185 +KMSDRM_FBInfo *
  20.186 +KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo)
  20.187 +{
  20.188 +    uint32_t w, h, stride, handle;
  20.189 +    int ret;
  20.190 +    SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
  20.191 +    KMSDRM_FBInfo *fb_info;
  20.192 +
  20.193 +    fb_info = (KMSDRM_FBInfo *)KMSDRM_gbm_bo_get_user_data(bo);
  20.194 +    if (fb_info != NULL) {
  20.195 +        /* Have a previously used framebuffer, return it */
  20.196 +        return fb_info;
  20.197 +    }
  20.198 +
  20.199 +    /* Here a new DRM FB must be created */
  20.200 +    fb_info = (KMSDRM_FBInfo *)SDL_calloc(1, sizeof(KMSDRM_FBInfo));
  20.201 +    fb_info->drm_fd = vdata->drm_fd;
  20.202 +
  20.203 +    w  = KMSDRM_gbm_bo_get_width(bo);
  20.204 +    h = KMSDRM_gbm_bo_get_height(bo);
  20.205 +    stride = KMSDRM_gbm_bo_get_stride(bo);
  20.206 +    handle = KMSDRM_gbm_bo_get_handle(bo).u32;
  20.207 +
  20.208 +    ret = KMSDRM_drmModeAddFB(vdata->drm_fd, w, h, 24, 32, stride, handle, &fb_info->fb_id);
  20.209 +    if (ret < 0) {
  20.210 +       free(fb_info);
  20.211 +       return NULL;
  20.212 +    }
  20.213 +    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);
  20.214 +
  20.215 +    /* Associate our DRM framebuffer with this buffer object */
  20.216 +    KMSDRM_gbm_bo_set_user_data(bo, fb_info, KMSDRM_FBDestroyCallback);
  20.217 +    return fb_info;
  20.218 +}
  20.219 +
  20.220 +SDL_bool
  20.221 +KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *wdata, int timeout) {
  20.222 +    SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
  20.223 +
  20.224 +    while (wdata->waiting_for_flip) {
  20.225 +        vdata->drm_pollfd.revents = 0;
  20.226 +        if (poll(&vdata->drm_pollfd, 1, timeout) < 0) {
  20.227 +            SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll error");
  20.228 +            return SDL_FALSE;
  20.229 +        }
  20.230 +
  20.231 +        if (vdata->drm_pollfd.revents & (POLLHUP | POLLERR)) {
  20.232 +            SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll hup or error");
  20.233 +            return SDL_FALSE;
  20.234 +        }
  20.235 +
  20.236 +        if (vdata->drm_pollfd.revents & POLLIN) {
  20.237 +            /* Page flip? If so, drmHandleEvent will unset wdata->waiting_for_flip */
  20.238 +            KMSDRM_drmHandleEvent(vdata->drm_fd, &vdata->drm_evctx);
  20.239 +        } else {
  20.240 +            /* Timed out and page flip didn't happen */
  20.241 +            SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Dropping frame while waiting_for_flip");
  20.242 +            return SDL_FALSE;
  20.243 +        }
  20.244 +    }
  20.245 +    return SDL_TRUE;
  20.246 +}
  20.247 +
  20.248 +static void
  20.249 +KMSDRM_FlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
  20.250 +{
  20.251 +    *((SDL_bool *) data) = SDL_FALSE;
  20.252 +}
  20.253 +
  20.254 +
  20.255 +/*****************************************************************************/
  20.256 +/* SDL Video and Display initialization/handling functions                   */
  20.257 +/* _this is a SDL_VideoDevice *                                              */
  20.258 +/*****************************************************************************/
  20.259 +int
  20.260 +KMSDRM_VideoInit(_THIS)
  20.261 +{
  20.262 +    int i;
  20.263 +    int ret = 0;
  20.264 +    char *devname;
  20.265 +    SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
  20.266 +    drmModeRes *resources = NULL;
  20.267 +    drmModeConnector *connector = NULL;
  20.268 +    drmModeEncoder *encoder = NULL;
  20.269 +    SDL_DisplayMode current_mode;
  20.270 +    SDL_VideoDisplay display;
  20.271 +
  20.272 +    /* Allocate display internal data */
  20.273 +    SDL_DisplayData *data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData));
  20.274 +    if (data == NULL) {
  20.275 +        return SDL_OutOfMemory();
  20.276 +    }
  20.277 +
  20.278 +    SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoInit()");
  20.279 +
  20.280 +    /* Open /dev/dri/cardNN */
  20.281 +    devname = (char *) SDL_calloc(1, 16);
  20.282 +    SDL_snprintf(devname, 16, "/dev/dri/card%d", vdata->devindex);
  20.283 +    vdata->drm_fd = open(devname, O_RDWR | O_CLOEXEC);
  20.284 +    SDL_free(devname);
  20.285 +
  20.286 +    if (vdata->drm_fd < 0) {
  20.287 +        ret = SDL_SetError("Could not open /dev/dri/card%d.", vdata->devindex);
  20.288 +        goto cleanup;
  20.289 +    }
  20.290 +    SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Opened DRM FD (%d)", vdata->drm_fd);
  20.291 +
  20.292 +    vdata->gbm = KMSDRM_gbm_create_device(vdata->drm_fd);
  20.293 +    if (vdata->gbm == NULL) {
  20.294 +        ret = SDL_SetError("Couldn't create gbm device.");
  20.295 +        goto cleanup;
  20.296 +    }
  20.297 +
  20.298 +    /* Find the first available connector with modes */
  20.299 +    resources = KMSDRM_drmModeGetResources(vdata->drm_fd);
  20.300 +    if (!resources) {
  20.301 +        ret = SDL_SetError("drmModeGetResources(%d) failed", vdata->drm_fd);
  20.302 +        goto cleanup;
  20.303 +    }
  20.304 +
  20.305 +    for (i = 0; i < resources->count_connectors; i++) {
  20.306 +        connector = KMSDRM_drmModeGetConnector(vdata->drm_fd, resources->connectors[i]);
  20.307 +        if (connector == NULL)
  20.308 +            continue;
  20.309 +
  20.310 +        if (connector->connection == DRM_MODE_CONNECTED &&
  20.311 +            connector->count_modes > 0) {
  20.312 +            SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Found connector %d with %d modes.",
  20.313 +                         connector->connector_id, connector->count_modes);
  20.314 +            vdata->saved_conn_id = connector->connector_id;
  20.315 +            break;
  20.316 +        }
  20.317 +
  20.318 +        KMSDRM_drmModeFreeConnector(connector);
  20.319 +    }
  20.320 +
  20.321 +    if (i == resources->count_connectors) {
  20.322 +        ret = SDL_SetError("No currently active connector found.");
  20.323 +        goto cleanup;
  20.324 +    }
  20.325 +
  20.326 +    for (i = 0; i < resources->count_encoders; i++) {
  20.327 +        encoder = KMSDRM_drmModeGetEncoder(vdata->drm_fd, resources->encoders[i]);
  20.328 +
  20.329 +        if (encoder == NULL)
  20.330 +            continue;
  20.331 +
  20.332 +        if (encoder->encoder_id == connector->encoder_id) {
  20.333 +            SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Found encoder %d.", encoder->encoder_id);
  20.334 +            data->encoder_id = encoder->encoder_id;
  20.335 +            break;
  20.336 +        }
  20.337 +
  20.338 +        KMSDRM_drmModeFreeEncoder(encoder);
  20.339 +    }
  20.340 +
  20.341 +    if (i == resources->count_encoders) {
  20.342 +        ret = SDL_SetError("No connected encoder found.");
  20.343 +        goto cleanup;
  20.344 +    }
  20.345 +
  20.346 +    vdata->saved_crtc = KMSDRM_drmModeGetCrtc(vdata->drm_fd, encoder->crtc_id);
  20.347 +    if (vdata->saved_crtc == NULL) {
  20.348 +        ret = SDL_SetError("No CRTC found.");
  20.349 +        goto cleanup;
  20.350 +    }
  20.351 +    SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Saved crtc_id %u, fb_id %u, (%u,%u), %ux%u",
  20.352 +                 vdata->saved_crtc->crtc_id, vdata->saved_crtc->buffer_id, vdata->saved_crtc->x,
  20.353 +                 vdata->saved_crtc->y, vdata->saved_crtc->width, vdata->saved_crtc->height);
  20.354 +    data->crtc_id = encoder->crtc_id;
  20.355 +    data->cur_mode = vdata->saved_crtc->mode;
  20.356 +
  20.357 +    SDL_zero(current_mode);
  20.358 +
  20.359 +    current_mode.w = vdata->saved_crtc->mode.hdisplay;
  20.360 +    current_mode.h = vdata->saved_crtc->mode.vdisplay;
  20.361 +    current_mode.refresh_rate = vdata->saved_crtc->mode.vrefresh;
  20.362 +
  20.363 +    /* FIXME ?
  20.364 +    drmModeFB *fb = drmModeGetFB(vdata->drm_fd, vdata->saved_crtc->buffer_id);
  20.365 +    current_mode.format = drmToSDLPixelFormat(fb->bpp, fb->depth);
  20.366 +    drmModeFreeFB(fb);
  20.367 +    */
  20.368 +    current_mode.format = SDL_PIXELFORMAT_ARGB8888;
  20.369 +
  20.370 +    current_mode.driverdata = NULL;
  20.371 +
  20.372 +    SDL_zero(display);
  20.373 +    display.desktop_mode = current_mode;
  20.374 +    display.current_mode = current_mode;
  20.375 +
  20.376 +    display.driverdata = data;
  20.377 +    /* SDL_VideoQuit will later SDL_free(display.driverdata) */
  20.378 +    SDL_AddVideoDisplay(&display);
  20.379 +
  20.380 +    /* Setup page flip handler */
  20.381 +    vdata->drm_pollfd.fd = vdata->drm_fd;
  20.382 +    vdata->drm_pollfd.events = POLLIN;
  20.383 +    vdata->drm_evctx.version = DRM_EVENT_CONTEXT_VERSION;
  20.384 +    vdata->drm_evctx.page_flip_handler = KMSDRM_FlipHandler;
  20.385 +
  20.386 +#ifdef SDL_INPUT_LINUXEV
  20.387 +    SDL_EVDEV_Init();
  20.388 +#endif
  20.389 +
  20.390 +    KMSDRM_InitMouse(_this);
  20.391 +
  20.392 +cleanup:
  20.393 +    if (encoder != NULL)
  20.394 +        KMSDRM_drmModeFreeEncoder(encoder);
  20.395 +    if (connector != NULL)
  20.396 +        KMSDRM_drmModeFreeConnector(connector);
  20.397 +    if (resources != NULL)
  20.398 +        KMSDRM_drmModeFreeResources(resources);
  20.399 +
  20.400 +    if (ret != 0) {
  20.401 +        /* Error (complete) cleanup */
  20.402 +        SDL_free(data);
  20.403 +        if(vdata->saved_crtc != NULL) {
  20.404 +            KMSDRM_drmModeFreeCrtc(vdata->saved_crtc);
  20.405 +            vdata->saved_crtc = NULL;
  20.406 +        }
  20.407 +        if (vdata->gbm != NULL) {
  20.408 +            KMSDRM_gbm_device_destroy(vdata->gbm);
  20.409 +            vdata->gbm = NULL;
  20.410 +        }
  20.411 +        if (vdata->drm_fd >= 0) {
  20.412 +            close(vdata->drm_fd);
  20.413 +            vdata->drm_fd = -1;
  20.414 +        }
  20.415 +    }
  20.416 +    return ret;
  20.417 +}
  20.418 +
  20.419 +void
  20.420 +KMSDRM_VideoQuit(_THIS)
  20.421 +{
  20.422 +    SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
  20.423 +
  20.424 +    SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoQuit()");
  20.425 +
  20.426 +    if (_this->gl_config.driver_loaded) {
  20.427 +        SDL_GL_UnloadLibrary();
  20.428 +    }
  20.429 +
  20.430 +    if(vdata->saved_crtc != NULL) {
  20.431 +        if(vdata->drm_fd > 0 && vdata->saved_conn_id > 0) {
  20.432 +            /* Restore saved CRTC settings */
  20.433 +            drmModeCrtc *crtc = vdata->saved_crtc;
  20.434 +            if(KMSDRM_drmModeSetCrtc(vdata->drm_fd, crtc->crtc_id, crtc->buffer_id,
  20.435 +                                     crtc->x, crtc->y, &vdata->saved_conn_id, 1,
  20.436 +                                     &crtc->mode) != 0) {
  20.437 +                SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not restore original CRTC mode");
  20.438 +            }
  20.439 +        }
  20.440 +        KMSDRM_drmModeFreeCrtc(vdata->saved_crtc);
  20.441 +        vdata->saved_crtc = NULL;
  20.442 +    }
  20.443 +    if (vdata->gbm != NULL) {
  20.444 +        KMSDRM_gbm_device_destroy(vdata->gbm);
  20.445 +        vdata->gbm = NULL;
  20.446 +    }
  20.447 +    if (vdata->drm_fd >= 0) {
  20.448 +        close(vdata->drm_fd);
  20.449 +        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Closed DRM FD %d", vdata->drm_fd);
  20.450 +        vdata->drm_fd = -1;
  20.451 +    }
  20.452 +#ifdef SDL_INPUT_LINUXEV
  20.453 +    SDL_EVDEV_Quit();
  20.454 +#endif
  20.455 +}
  20.456 +
  20.457 +void
  20.458 +KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
  20.459 +{
  20.460 +    /* Only one display mode available, the current one */
  20.461 +    SDL_AddDisplayMode(display, &display->current_mode);
  20.462 +}
  20.463 +
  20.464 +int
  20.465 +KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
  20.466 +{
  20.467 +    return 0;
  20.468 +}
  20.469 +
  20.470 +int
  20.471 +KMSDRM_CreateWindow(_THIS, SDL_Window * window)
  20.472 +{
  20.473 +    SDL_WindowData *wdata;
  20.474 +    SDL_VideoDisplay *display;
  20.475 +    SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata);
  20.476 +    Uint32 surface_fmt, surface_flags;
  20.477 +
  20.478 +    /* Allocate window internal data */
  20.479 +    wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
  20.480 +    if (wdata == NULL) {
  20.481 +        return SDL_OutOfMemory();
  20.482 +    }
  20.483 +
  20.484 +    wdata->waiting_for_flip = SDL_FALSE;
  20.485 +    display = SDL_GetDisplayForWindow(window);
  20.486 +
  20.487 +    /* Windows have one size for now */
  20.488 +    window->w = display->desktop_mode.w;
  20.489 +    window->h = display->desktop_mode.h;
  20.490 +
  20.491 +    /* Maybe you didn't ask for a fullscreen OpenGL window, but that's what you get */
  20.492 +    window->flags |= (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL);
  20.493 +
  20.494 +    surface_fmt = GBM_BO_FORMAT_XRGB8888;
  20.495 +    surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
  20.496 +
  20.497 +    if (!KMSDRM_gbm_device_is_format_supported(vdata->gbm, surface_fmt, surface_flags)) {
  20.498 +        SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "GBM surface format not supported. Trying anyway.");
  20.499 +    }
  20.500 +    wdata->gs = KMSDRM_gbm_surface_create(vdata->gbm, window->w, window->h, surface_fmt, surface_flags);
  20.501 +
  20.502 +#if SDL_VIDEO_OPENGL_EGL
  20.503 +    if (!_this->egl_data) {
  20.504 +        if (SDL_GL_LoadLibrary(NULL) < 0) {
  20.505 +            goto error;
  20.506 +        }
  20.507 +    }
  20.508 +    wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wdata->gs);
  20.509 +
  20.510 +    if (wdata->egl_surface == EGL_NO_SURFACE) {
  20.511 +        SDL_SetError("Could not create EGL window surface");
  20.512 +        goto error;
  20.513 +    }
  20.514 +#endif /* SDL_VIDEO_OPENGL_EGL */
  20.515 +
  20.516 +    /* Setup driver data for this window */
  20.517 +    window->driverdata = wdata;
  20.518 +
  20.519 +    /* One window, it always has focus */
  20.520 +    SDL_SetMouseFocus(window);
  20.521 +    SDL_SetKeyboardFocus(window);
  20.522 +
  20.523 +    /* Window has been successfully created */
  20.524 +    return 0;
  20.525 +
  20.526 +error:
  20.527 +    if (wdata != NULL) {
  20.528 +#if SDL_VIDEO_OPENGL_EGL
  20.529 +        if (wdata->egl_surface != EGL_NO_SURFACE)
  20.530 +            SDL_EGL_DestroySurface(_this, wdata->egl_surface);
  20.531 +#endif /* SDL_VIDEO_OPENGL_EGL */
  20.532 +        if (wdata->gs != NULL)
  20.533 +            KMSDRM_gbm_surface_destroy(wdata->gs);
  20.534 +        SDL_free(wdata);
  20.535 +    }
  20.536 +    return -1;
  20.537 +}
  20.538 +
  20.539 +void
  20.540 +KMSDRM_DestroyWindow(_THIS, SDL_Window * window)
  20.541 +{
  20.542 +    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  20.543 +    if(data) {
  20.544 +        /* Wait for any pending page flips and unlock buffer */
  20.545 +        KMSDRM_WaitPageFlip(_this, data, -1);
  20.546 +        if (data->locked_bo != NULL) {
  20.547 +            KMSDRM_gbm_surface_release_buffer(data->gs, data->locked_bo);
  20.548 +            data->locked_bo = NULL;
  20.549 +        }
  20.550 +#if SDL_VIDEO_OPENGL_EGL
  20.551 +        SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  20.552 +        if (data->egl_surface != EGL_NO_SURFACE) {
  20.553 +            SDL_EGL_DestroySurface(_this, data->egl_surface);
  20.554 +        }
  20.555 +#endif /* SDL_VIDEO_OPENGL_EGL */
  20.556 +        if (data->gs != NULL) {
  20.557 +            KMSDRM_gbm_surface_destroy(data->gs);
  20.558 +            data->gs = NULL;
  20.559 +        }
  20.560 +        SDL_free(data);
  20.561 +        window->driverdata = NULL;
  20.562 +    }
  20.563 +}
  20.564 +
  20.565 +int
  20.566 +KMSDRM_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
  20.567 +{
  20.568 +    return -1;
  20.569 +}
  20.570 +
  20.571 +void
  20.572 +KMSDRM_SetWindowTitle(_THIS, SDL_Window * window)
  20.573 +{
  20.574 +}
  20.575 +void
  20.576 +KMSDRM_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
  20.577 +{
  20.578 +}
  20.579 +void
  20.580 +KMSDRM_SetWindowPosition(_THIS, SDL_Window * window)
  20.581 +{
  20.582 +}
  20.583 +void
  20.584 +KMSDRM_SetWindowSize(_THIS, SDL_Window * window)
  20.585 +{
  20.586 +}
  20.587 +void
  20.588 +KMSDRM_ShowWindow(_THIS, SDL_Window * window)
  20.589 +{
  20.590 +}
  20.591 +void
  20.592 +KMSDRM_HideWindow(_THIS, SDL_Window * window)
  20.593 +{
  20.594 +}
  20.595 +void
  20.596 +KMSDRM_RaiseWindow(_THIS, SDL_Window * window)
  20.597 +{
  20.598 +}
  20.599 +void
  20.600 +KMSDRM_MaximizeWindow(_THIS, SDL_Window * window)
  20.601 +{
  20.602 +}
  20.603 +void
  20.604 +KMSDRM_MinimizeWindow(_THIS, SDL_Window * window)
  20.605 +{
  20.606 +}
  20.607 +void
  20.608 +KMSDRM_RestoreWindow(_THIS, SDL_Window * window)
  20.609 +{
  20.610 +}
  20.611 +void
  20.612 +KMSDRM_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
  20.613 +{
  20.614 +
  20.615 +}
  20.616 +
  20.617 +/*****************************************************************************/
  20.618 +/* SDL Window Manager function                                               */
  20.619 +/*****************************************************************************/
  20.620 +SDL_bool
  20.621 +KMSDRM_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
  20.622 +{
  20.623 +    if (info->version.major <= SDL_MAJOR_VERSION) {
  20.624 +        return SDL_TRUE;
  20.625 +    } else {
  20.626 +        SDL_SetError("application not compiled with SDL %d.%d\n",
  20.627 +                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
  20.628 +        return SDL_FALSE;
  20.629 +    }
  20.630 +
  20.631 +    /* Failed to get window manager information */
  20.632 +    return SDL_FALSE;
  20.633 +}
  20.634 +
  20.635 +#endif /* SDL_VIDEO_DRIVER_KMSDRM */
  20.636 +
  20.637 +/* vi: set ts=4 sw=4 expandtab: */
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h	Wed Aug 02 10:22:48 2017 -0700
    21.3 @@ -0,0 +1,119 @@
    21.4 +/*
    21.5 +  Simple DirectMedia Layer
    21.6 +  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
    21.7 +
    21.8 +  This software is provided 'as-is', without any express or implied
    21.9 +  warranty.  In no event will the authors be held liable for any damages
   21.10 +  arising from the use of this software.
   21.11 +
   21.12 +  Permission is granted to anyone to use this software for any purpose,
   21.13 +  including commercial applications, and to alter it and redistribute it
   21.14 +  freely, subject to the following restrictions:
   21.15 +
   21.16 +  1. The origin of this software must not be misrepresented; you must not
   21.17 +     claim that you wrote the original software. If you use this software
   21.18 +     in a product, an acknowledgment in the product documentation would be
   21.19 +     appreciated but is not required.
   21.20 +  2. Altered source versions must be plainly marked as such, and must not be
   21.21 +     misrepresented as being the original software.
   21.22 +  3. This notice may not be removed or altered from any source distribution.
   21.23 +*/
   21.24 +
   21.25 +#ifndef __SDL_KMSDRMVIDEO_H__
   21.26 +#define __SDL_KMSDRMVIDEO_H__
   21.27 +
   21.28 +#include "../../SDL_internal.h"
   21.29 +#include "../SDL_sysvideo.h"
   21.30 +
   21.31 +#include <fcntl.h>
   21.32 +#include <unistd.h>
   21.33 +#include <poll.h>
   21.34 +#include <xf86drm.h>
   21.35 +#include <xf86drmMode.h>
   21.36 +#include <gbm.h>
   21.37 +#if SDL_VIDEO_OPENGL_EGL
   21.38 +#include <EGL/egl.h>
   21.39 +#endif
   21.40 +
   21.41 +typedef struct SDL_VideoData
   21.42 +{
   21.43 +    int devindex;               /* device index that was passed on creation */
   21.44 +    int drm_fd;                 /* DRM file desc */
   21.45 +    struct gbm_device *gbm;
   21.46 +    drmEventContext drm_evctx;  /* DRM event context */
   21.47 +    struct pollfd drm_pollfd;   /* pollfd containing DRM file desc */
   21.48 +    drmModeCrtc *saved_crtc;    /* Saved CRTC to restore on quit */
   21.49 +    uint32_t saved_conn_id;     /* Saved DRM connector ID */
   21.50 +} SDL_VideoData;
   21.51 +
   21.52 +
   21.53 +typedef struct SDL_DisplayData
   21.54 +{
   21.55 +    uint32_t encoder_id;
   21.56 +    uint32_t crtc_id;
   21.57 +    drmModeModeInfo cur_mode;
   21.58 +} SDL_DisplayData;
   21.59 +
   21.60 +
   21.61 +typedef struct SDL_WindowData
   21.62 +{
   21.63 +    struct gbm_surface *gs;
   21.64 +    struct gbm_bo *locked_bo;
   21.65 +    SDL_bool waiting_for_flip;
   21.66 +#if SDL_VIDEO_OPENGL_EGL
   21.67 +    EGLSurface egl_surface;
   21.68 +#endif
   21.69 +} SDL_WindowData;
   21.70 +
   21.71 +typedef struct KMSDRM_FBInfo
   21.72 +{
   21.73 +    int drm_fd;         /* DRM file desc */
   21.74 +    uint32_t fb_id;     /* DRM framebuffer ID */
   21.75 +} KMSDRM_FBInfo;
   21.76 +
   21.77 +/* Helper functions */
   21.78 +KMSDRM_FBInfo *KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo);
   21.79 +SDL_bool KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *wdata, int timeout);
   21.80 +
   21.81 +/****************************************************************************/
   21.82 +/* SDL_VideoDevice functions declaration                                    */
   21.83 +/****************************************************************************/
   21.84 +
   21.85 +/* Display and window functions */
   21.86 +int KMSDRM_VideoInit(_THIS);
   21.87 +void KMSDRM_VideoQuit(_THIS);
   21.88 +void KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
   21.89 +int KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
   21.90 +int KMSDRM_CreateWindow(_THIS, SDL_Window * window);
   21.91 +int KMSDRM_CreateWindowFrom(_THIS, SDL_Window * window, const void *data);
   21.92 +void KMSDRM_SetWindowTitle(_THIS, SDL_Window * window);
   21.93 +void KMSDRM_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
   21.94 +void KMSDRM_SetWindowPosition(_THIS, SDL_Window * window);
   21.95 +void KMSDRM_SetWindowSize(_THIS, SDL_Window * window);
   21.96 +void KMSDRM_ShowWindow(_THIS, SDL_Window * window);
   21.97 +void KMSDRM_HideWindow(_THIS, SDL_Window * window);
   21.98 +void KMSDRM_RaiseWindow(_THIS, SDL_Window * window);
   21.99 +void KMSDRM_MaximizeWindow(_THIS, SDL_Window * window);
  21.100 +void KMSDRM_MinimizeWindow(_THIS, SDL_Window * window);
  21.101 +void KMSDRM_RestoreWindow(_THIS, SDL_Window * window);
  21.102 +void KMSDRM_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
  21.103 +void KMSDRM_DestroyWindow(_THIS, SDL_Window * window);
  21.104 +
  21.105 +/* Window manager function */
  21.106 +SDL_bool KMSDRM_GetWindowWMInfo(_THIS, SDL_Window * window,
  21.107 +                             struct SDL_SysWMinfo *info);
  21.108 +
  21.109 +/* OpenGL/OpenGL ES functions */
  21.110 +int KMSDRM_GLES_LoadLibrary(_THIS, const char *path);
  21.111 +void *KMSDRM_GLES_GetProcAddress(_THIS, const char *proc);
  21.112 +void KMSDRM_GLES_UnloadLibrary(_THIS);
  21.113 +SDL_GLContext KMSDRM_GLES_CreateContext(_THIS, SDL_Window * window);
  21.114 +int KMSDRM_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
  21.115 +int KMSDRM_GLES_SetSwapInterval(_THIS, int interval);
  21.116 +int KMSDRM_GLES_GetSwapInterval(_THIS);
  21.117 +int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window);
  21.118 +void KMSDRM_GLES_DeleteContext(_THIS, SDL_GLContext context);
  21.119 +
  21.120 +#endif /* __SDL_KMSDRMVIDEO_H__ */
  21.121 +
  21.122 +/* vi: set ts=4 sw=4 expandtab: */
    22.1 --- a/src/video/mir/SDL_miropengl.c	Mon Jul 31 13:49:22 2017 -0400
    22.2 +++ b/src/video/mir/SDL_miropengl.c	Wed Aug 02 10:22:48 2017 -0700
    22.3 @@ -66,7 +66,7 @@
    22.4  {
    22.5      MIR_Data* mir_data = _this->driverdata;
    22.6  
    22.7 -    SDL_EGL_LoadLibrary(_this, path, MIR_mir_connection_get_egl_native_display(mir_data->connection));
    22.8 +    SDL_EGL_LoadLibrary(_this, path, MIR_mir_connection_get_egl_native_display(mir_data->connection), 0);
    22.9  
   22.10      SDL_EGL_ChooseConfig(_this);
   22.11  
    23.1 --- a/src/video/raspberry/SDL_rpiopengles.c	Mon Jul 31 13:49:22 2017 -0400
    23.2 +++ b/src/video/raspberry/SDL_rpiopengles.c	Wed Aug 02 10:22:48 2017 -0700
    23.3 @@ -29,7 +29,7 @@
    23.4  
    23.5  int
    23.6  RPI_GLES_LoadLibrary(_THIS, const char *path) {
    23.7 -    return SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY);
    23.8 +    return SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY, 0);
    23.9  }
   23.10  
   23.11  SDL_EGL_CreateContext_impl(RPI)
    24.1 --- a/src/video/vivante/SDL_vivanteopengles.c	Mon Jul 31 13:49:22 2017 -0400
    24.2 +++ b/src/video/vivante/SDL_vivanteopengles.c	Wed Aug 02 10:22:48 2017 -0700
    24.3 @@ -34,7 +34,7 @@
    24.4  
    24.5      displaydata = SDL_GetDisplayDriverData(0);
    24.6  
    24.7 -    return SDL_EGL_LoadLibrary(_this, path, displaydata->native_display);
    24.8 +    return SDL_EGL_LoadLibrary(_this, path, displaydata->native_display, 0);
    24.9  }
   24.10  
   24.11  SDL_EGL_CreateContext_impl(VIVANTE)
    25.1 --- a/src/video/wayland/SDL_waylandopengles.c	Mon Jul 31 13:49:22 2017 -0400
    25.2 +++ b/src/video/wayland/SDL_waylandopengles.c	Wed Aug 02 10:22:48 2017 -0700
    25.3 @@ -35,7 +35,7 @@
    25.4      int ret;
    25.5      SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    25.6      
    25.7 -    ret = SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display);
    25.8 +    ret = SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display, 0);
    25.9  
   25.10      Wayland_PumpEvents(_this);
   25.11      WAYLAND_wl_display_flush(data->display);
    26.1 --- a/src/video/windows/SDL_windowsopengles.c	Mon Jul 31 13:49:22 2017 -0400
    26.2 +++ b/src/video/windows/SDL_windowsopengles.c	Wed Aug 02 10:22:48 2017 -0700
    26.3 @@ -52,7 +52,7 @@
    26.4      }
    26.5      
    26.6      if (_this->egl_data == NULL) {
    26.7 -        return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY);
    26.8 +        return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0);
    26.9      }
   26.10  
   26.11      return 0;
   26.12 @@ -110,7 +110,7 @@
   26.13  
   26.14  
   26.15      if (_this->egl_data == NULL) {
   26.16 -        if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY) < 0) {
   26.17 +        if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0) < 0) {
   26.18              SDL_EGL_UnloadLibrary(_this);
   26.19              return -1;
   26.20          }
    27.1 --- a/src/video/winrt/SDL_winrtopengles.cpp	Mon Jul 31 13:49:22 2017 -0400
    27.2 +++ b/src/video/winrt/SDL_winrtopengles.cpp	Wed Aug 02 10:22:48 2017 -0700
    27.3 @@ -58,7 +58,7 @@
    27.4  {
    27.5      SDL_VideoData *video_data = (SDL_VideoData *)_this->driverdata;
    27.6  
    27.7 -    if (SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY) != 0) {
    27.8 +    if (SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY, 0) != 0) {
    27.9          return -1;
   27.10      }
   27.11  
    28.1 --- a/src/video/x11/SDL_x11opengles.c	Mon Jul 31 13:49:22 2017 -0400
    28.2 +++ b/src/video/x11/SDL_x11opengles.c	Wed Aug 02 10:22:48 2017 -0700
    28.3 @@ -52,7 +52,7 @@
    28.4          #endif
    28.5      }
    28.6      
    28.7 -    return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display);
    28.8 +    return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display, 0);
    28.9  }
   28.10  
   28.11  XVisualInfo *