From 475ce1988d2e3e29e8b521c06d9cceaf5666ed29 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Sat, 9 Apr 2016 22:07:12 +0100 Subject: [PATCH 01/14] Revert "Linux joystick: Look at entire axis namespace for controls (thanks, "spaz16"!)." This reverts commit 4cb7923f251543c1175c1702f8cf8b4201ce9054. see https://github.com/RetroPie/RetroPie-Setup/issues/1297 --- src/joystick/linux/SDL_sysjoystick.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index ad8309196..482f87474 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -609,7 +609,7 @@ ConfigJoystick(SDL_Joystick * joystick, int fd) ++joystick->nbuttons; } } - for (i = 0; i < ABS_MAX; ++i) { + for (i = 0; i < ABS_MISC; ++i) { /* Skip hats */ if (i == ABS_HAT0X) { i = ABS_HAT3Y; @@ -906,6 +906,10 @@ HandleInputEvents(SDL_Joystick * joystick) events[i].value); break; case EV_ABS: + if (code >= ABS_MISC) { + break; + } + switch (code) { case ABS_HAT0X: case ABS_HAT0Y: From 110c83c15fd5be3d1f326de1d4cc6b22409e092e Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Fri, 17 Feb 2017 17:16:05 +0000 Subject: [PATCH 02/14] packaging fixes - * updated debian/control to match debian/ubuntu package names * fix libudev dependency * rename libsdl2.install -> libsdl2-2.0-0.install --- debian/control | 12 ++++++------ debian/{libsdl2.install => libsdl2-2.0-0.install} | 0 2 files changed, 6 insertions(+), 6 deletions(-) rename debian/{libsdl2.install => libsdl2-2.0-0.install} (100%) diff --git a/debian/control b/debian/control index a3411335a..a6b9b5e32 100644 --- a/debian/control +++ b/debian/control @@ -30,16 +30,16 @@ Build-Depends: debhelper (>= 9), libxxf86vm-dev Homepage: http://www.libsdl.org/ -Package: libsdl2 +Package: libsdl2-2.0-0 Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} Depends: ${misc:Depends}, ${shlibs:Depends}, - libudev0 [linux-any], + libudev0 | libudev1 [linux-any], libdbus-1-3 [linux-any] -Conflicts: libsdl-1.3-0 -Replaces: libsdl-1.3-0 +Conflicts: libsdl-1.3-0, libsdl2 +Replaces: libsdl-1.3-0, libsdl2 Description: Simple DirectMedia Layer SDL is a library that allows programs portable low level access to a video framebuffer, audio output, mouse, and keyboard. @@ -51,7 +51,7 @@ Section: libdevel Architecture: any Multi-Arch: same Depends: ${misc:Depends}, - libsdl2 (= ${binary:Version}), + libsdl2-2.0-0 (= ${binary:Version}), libc6-dev, libgl1-mesa-dev Conflicts: libsdl-1.3-dev @@ -68,7 +68,7 @@ Section: debug Architecture: any Multi-Arch: same Depends: ${misc:Depends}, - libsdl2 (= ${binary:Version}), + libsdl2-2.0-0 (= ${binary:Version}), Description: Simple DirectMedia Layer debug files SDL is a library that allows programs portable low level access to a video framebuffer, audio output, mouse, and keyboard. diff --git a/debian/libsdl2.install b/debian/libsdl2-2.0-0.install similarity index 100% rename from debian/libsdl2.install rename to debian/libsdl2-2.0-0.install From 9ae0a812a13fd5bb6676351bf34ccfa518381fd1 Mon Sep 17 00:00:00 2001 From: Stefan Date: Wed, 6 Jul 2016 21:53:43 +0200 Subject: [PATCH 03/14] rpi video - Use dispmanx scaling (#1) * Use dispmanx scaling * There is the new SDL hint SDL_VIDEO_RPI_SCALE_MODE. There are three values. * The variable can be set to the following values: * "0" - Window resolution is desktop resolution. * This is the behaviour of SDL <= 2.0.4. (default) * "1" - Requested video resolution will be scaled to desktop resolution. * Aspect ratio of requested video resolution will be respected. * "2" - Requested video resolution will be scaled to desktop resolution * "3" - Integer scaling. dst_rect is an integral multiple of src_rect. Should prevent scaling artifacts. * Add aspect ratio hint --- include/SDL_hints.h | 27 +++++++++ src/video/raspberry/SDL_rpivideo.c | 89 ++++++++++++++++++++++++++---- 2 files changed, 106 insertions(+), 10 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 8fa0dd660..b2baeaf52 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -922,6 +922,33 @@ extern "C" { */ #define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS" +/** + * \brief Tell dispmanx to stretch the SDL window to fill the display. + * + * This hint only applies to the rpi video driver. + * + * The variable can be set to the following values: + * "0" - Window resolution is desktop resolution. + * This is the behaviour of SDL <= 2.0.4. (default) + * "1" - Requested video resolution will be scaled to desktop resolution. + * Aspect ratio of requested video resolution will be respected. + * "2" - Requested video resolution will be scaled to desktop resolution. + * "3" - Requested video resolution will be scaled to desktop resolution. + * Aspect ratio of requested video resolution will be respected. + * If possible output resolution will be integral multiple of video + * resolution. + */ +#define SDL_HINT_VIDEO_RPI_SCALE_MODE "SDL_VIDEO_RPI_SCALE_MODE" + +/** + * \brief Tell dispmanx to set a specific aspect ratio. + * + * This hint only applies to the rpi video driver. + * + * Must be set together with SDL_HINT_VIDEO_RPI_SCALE_MODE=1. + */ +#define SDL_HINT_VIDEO_RPI_RATIO "SDL_VIDEO_RPI_RATIO" + /** * \brief Tell SDL not to generate window-close events for Alt+F4 on Windows. * diff --git a/src/video/raspberry/SDL_rpivideo.c b/src/video/raspberry/SDL_rpivideo.c index 0f1ac00dc..4528191c0 100644 --- a/src/video/raspberry/SDL_rpivideo.c +++ b/src/video/raspberry/SDL_rpivideo.c @@ -31,6 +31,7 @@ */ /* SDL internals */ +#include "SDL_hints.h" #include "../SDL_sysvideo.h" #include "SDL_version.h" #include "SDL_syswm.h" @@ -260,6 +261,9 @@ RPI_vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *data) int RPI_CreateWindow(_THIS, SDL_Window * window) { + const char *hintScale = SDL_GetHint(SDL_HINT_VIDEO_RPI_SCALE_MODE); + const char *hintRatio = SDL_GetHint(SDL_HINT_VIDEO_RPI_RATIO); + char scalemode = '0'; SDL_WindowData *wdata; SDL_VideoDisplay *display; SDL_DisplayData *displaydata; @@ -269,6 +273,10 @@ RPI_CreateWindow(_THIS, SDL_Window * window) DISPMANX_UPDATE_HANDLE_T dispman_update; uint32_t layer = SDL_RPI_VIDEOLAYER; const char *env; + float srcAspect = 1; + float dstAspect = 1; + int factor_x = 0; + int factor_y = 0; /* Disable alpha, otherwise the app looks composed with whatever dispman is showing (X11, console,etc) */ dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; @@ -283,24 +291,85 @@ RPI_CreateWindow(_THIS, SDL_Window * window) display = SDL_GetDisplayForWindow(window); displaydata = (SDL_DisplayData *) display->driverdata; - /* Windows have one size for now */ - window->w = display->desktop_mode.w; - window->h = display->desktop_mode.h; - - /* OpenGL ES is the law here, buddy */ - window->flags |= SDL_WINDOW_OPENGL; + if (hintScale != NULL) + scalemode = *hintScale; /* Create a dispman element and associate a window to it */ - dst_rect.x = 0; - dst_rect.y = 0; - dst_rect.width = window->w; - dst_rect.height = window->h; + switch(scalemode) { + case '3': + /* Pixel perfect scaling mode. */ + factor_x = (display->desktop_mode.w / window->w); + factor_y = (display->desktop_mode.h / window->h); + if ((factor_x != 0) && (factor_y != 0)) { + if (factor_x >= factor_y) { + dst_rect.width = window->w * factor_y; + dst_rect.height = window->h * factor_y; + } + else { + dst_rect.width = window->w * factor_x; + dst_rect.height = window->h * factor_x; + } + /* Center window. */ + dst_rect.x = (display->desktop_mode.w - dst_rect.width) / 2; + dst_rect.y = (display->desktop_mode.h - dst_rect.height) / 2; + break; + } + /* If integer scale is not possible fallback to mode 1. */ + case '1': + /* Fullscreen mode. */ + /* Calculate source and destination aspect ratios. */ + if (hintRatio != NULL) + srcAspect = strtof(hintRatio, NULL); + else + srcAspect = (float)window->w / (float)window->h; + /* only allow sensible aspect ratios */ + if (srcAspect < 0.2f || srcAspect > 6.0f) + srcAspect = (float)window->w / (float)window->h; + dstAspect = (float)display->desktop_mode.w / (float)display->desktop_mode.h; + /* If source and destination aspect ratios are not equal correct destination width. */ + if (srcAspect < dstAspect) { + dst_rect.width = (unsigned)(display->desktop_mode.h * srcAspect); + dst_rect.height = display->desktop_mode.h; + } + else if (srcAspect > dstAspect) { + dst_rect.width = display->desktop_mode.w; + dst_rect.height = (unsigned)((float)display->desktop_mode.w / srcAspect); + } + else { + dst_rect.width = display->desktop_mode.w; + dst_rect.height = display->desktop_mode.h; + } + /* Center window. */ + dst_rect.x = (display->desktop_mode.w - dst_rect.width) / 2; + dst_rect.y = (display->desktop_mode.h - dst_rect.height) / 2; + break; + case '2': + /* Fullscreen streched mode. */ + dst_rect.x = 0; + dst_rect.y = 0; + dst_rect.width = display->desktop_mode.w; + dst_rect.height = display->desktop_mode.h; + break; + default: + /* Default mode. */ + window->w = display->desktop_mode.w; + window->h = display->desktop_mode.h; + + dst_rect.x = 0; + dst_rect.y = 0; + dst_rect.width = window->w; + dst_rect.height = window->h; + break; + } src_rect.x = 0; src_rect.y = 0; src_rect.width = window->w << 16; src_rect.height = window->h << 16; + /* OpenGL ES is the law here, buddy */ + window->flags |= SDL_WINDOW_OPENGL; + env = SDL_GetHint(SDL_HINT_RPI_VIDEO_LAYER); if (env) { layer = SDL_atoi(env); From 65b77e23ab80727a8ea1a5bf9513b40abb8f1259 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Sun, 3 Jan 2016 21:27:57 +0000 Subject: [PATCH 04/14] mali-fbdev support * mali-fbdev support from https://github.com/mihailescu2m/libsdl2-2.0.2-dfsg1 with changes for newer SDL --- CMakeLists.txt | 2 + cmake/sdlchecks.cmake | 23 ++ configure | 53 ++++ configure.ac | 30 +++ debian/control | 5 +- include/SDL_config.h.cmake | 1 + include/SDL_config.h.in | 1 + src/video/SDL_egl.c | 2 +- src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 3 + src/video/mali-fbdev/SDL_maliopengles.c | 43 ++++ src/video/mali-fbdev/SDL_maliopengles.h | 48 ++++ src/video/mali-fbdev/SDL_malivideo.c | 323 ++++++++++++++++++++++++ src/video/mali-fbdev/SDL_malivideo.h | 80 ++++++ 14 files changed, 611 insertions(+), 4 deletions(-) create mode 100644 src/video/mali-fbdev/SDL_maliopengles.c create mode 100644 src/video/mali-fbdev/SDL_maliopengles.h create mode 100644 src/video/mali-fbdev/SDL_malivideo.c create mode 100644 src/video/mali-fbdev/SDL_malivideo.h diff --git a/CMakeLists.txt b/CMakeLists.txt index bd59d89b2..3032c938d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -366,6 +366,7 @@ set_option(VIDEO_COCOA "Use Cocoa video driver" ${APPLE}) set_option(DIRECTX "Use DirectX for Windows audio/video" ${WINDOWS}) set_option(WASAPI "Use the Windows WASAPI audio driver" ${WINDOWS}) set_option(RENDER_D3D "Enable the Direct3D render driver" ${WINDOWS}) +set_option(VIDEO_MALI "Use Mali EGL video driver" ${UNIX_SYS}) set_option(VIDEO_VIVANTE "Use Vivante EGL video driver" ${UNIX_SYS}) dep_option(VIDEO_VULKAN "Enable Vulkan support" ON "ANDROID OR APPLE OR LINUX OR WINDOWS" OFF) set_option(VIDEO_KMSDRM "Use KMS DRM video driver" ${UNIX_SYS}) @@ -1046,6 +1047,7 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID) CheckWayland() CheckVivante() CheckKMSDRM() + CheckMali() endif() if(UNIX) diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index 5d4d2f936..c054a81fd 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -738,6 +738,29 @@ macro(CheckVivante) endif(VIDEO_VIVANTE) endmacro(CheckVivante) +# Requires: +# - n/a +macro(CheckMali) + if(VIDEO_MALI) + check_c_source_compiles(" + #define LINUX + #define EGL_API_FB + #include + int main(int argc, char** argv) {}" HAVE_VIDEO_MALI_EGL_FB) + if(HAVE_VIDEO_MALI_EGL_FB) + set(HAVE_VIDEO_MALI TRUE) + set(HAVE_SDL_VIDEO TRUE) + + file(GLOB MALI_SOURCES ${SDL2_SOURCE_DIR}/src/video/mali-fbdev/*.c) + set(SOURCE_FILES ${SOURCE_FILES} ${MALI_SOURCES}) + set(SDL_VIDEO_DRIVER_MALI 1) + set(SDL_CFLAGS "${SDL_CFLAGS} -DLINUX -DEGL_API_FB") + list(APPEND EXTRA_LIBS EGL) + endif(HAVE_VIDEO_MALI_EGL_MALI) + endif(VIDEO_MALI) +endmacro(CheckMali) + + # Requires: # - nada macro(CheckOpenGLX11) diff --git a/configure b/configure index ab7b65887..ca8be79fa 100755 --- a/configure +++ b/configure @@ -868,6 +868,7 @@ enable_video_x11_scrnsaver enable_video_x11_xshape enable_video_x11_vm enable_video_vivante +enable_video_mali enable_video_cocoa enable_render_metal enable_video_directfb @@ -1646,6 +1647,7 @@ Optional Features: enable X11 XShape support [[default=yes]] --enable-video-x11-vm use X11 VM extension for fullscreen [[default=yes]] --enable-video-vivante use Vivante EGL video driver [[default=yes]] + --enable-video-mali use Mali EGL video driver [[default=no]] --enable-video-cocoa use Cocoa video driver [[default=yes]] --enable-render-metal enable the Metal render driver [[default=yes]] --enable-video-directfb use DirectFB video driver [[default=no]] @@ -21467,6 +21469,56 @@ $as_echo "#define SDL_VIDEO_DRIVER_VIVANTE_VDK 1" >>confdefs.h fi } +CheckMaliVideo() +{ + # Check whether --enable-video-mali was given. +if test "${enable_video_mali+set}" = set; then : + enableval=$enable_video_mali; +else + enable_video_mali=no +fi + + if test x$enable_video = xyes -a x$enable_video_mali = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Mali FB API" >&5 +$as_echo_n "checking for Mali FB API... " >&6; } + have_mali_egl=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #define LINUX + #define EGL_API_FB + #include + +int +main () +{ + + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + have_mali_egl=yes + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_mali_egl" >&5 +$as_echo "$have_mali_egl" >&6; } + + if test x$have_mali_egl = xyes; then + +$as_echo "#define SDL_VIDEO_DRIVER_MALI 1" >>confdefs.h + + EXTRA_CFLAGS="$EXTRA_CFLAGS -DLINUX -DEGL_API_FB" + SOURCES="$SOURCES $srcdir/src/video/mali-fbdev/*.c" + SUMMARY_video="${SUMMARY_video} mali" + have_video=yes + fi + fi +} + CheckHaikuVideo() { if test x$enable_video = xyes; then @@ -24483,6 +24535,7 @@ case "$host" in CheckLinuxVersion CheckRPATH CheckVivanteVideo + CheckMaliVideo # Set up files for the audio library if test x$enable_audio = xyes; then diff --git a/configure.ac b/configure.ac index 9e782c653..513065f31 100644 --- a/configure.ac +++ b/configure.ac @@ -2006,6 +2006,35 @@ AS_HELP_STRING([--enable-video-vivante], [use Vivante EGL video driver [[default fi } +dnl Set up the Mali video driver if enabled +CheckMaliVideo() +{ + AC_ARG_ENABLE(video-mali, +AC_HELP_STRING([--enable-video-mali], [use Mali EGL video driver [[default=yes]]]), + , enable_video_mali=yes) + if test x$enable_video = xyes -a x$enable_video_mali = xyes; then + AC_MSG_CHECKING(for Mali FB API) + have_mali_egl=no + AC_TRY_COMPILE([ + #define LINUX + #define EGL_API_FB + #include + ],[ + ],[ + have_mali_egl=yes + ]) + AC_MSG_RESULT($have_mali_egl) + + if test x$have_mali_egl = xyes; then + AC_DEFINE(SDL_VIDEO_DRIVER_MALI, 1, [ ]) + EXTRA_CFLAGS="$EXTRA_CFLAGS -DLINUX -DEGL_API_FB" + SOURCES="$SOURCES $srcdir/src/video/mali-fbdev/*.c" + SUMMARY_video="${SUMMARY_video} mali" + have_video=yes + fi + fi +} + dnl Set up the Haiku video driver if enabled CheckHaikuVideo() { @@ -3400,6 +3429,7 @@ case "$host" in CheckLinuxVersion CheckRPATH CheckVivanteVideo + CheckMaliVideo # Set up files for the audio library if test x$enable_audio = xyes; then diff --git a/debian/control b/debian/control index a6b9b5e32..450aa2925 100644 --- a/debian/control +++ b/debian/control @@ -13,8 +13,6 @@ Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), fcitx-libs-dev [linux-any], libasound2-dev [linux-any], - libgl1-mesa-dev, - libpulse-dev, libudev-dev [linux-any], libdbus-1-dev [linux-any], libibus-1.0-dev[linux-any], @@ -53,7 +51,8 @@ Multi-Arch: same Depends: ${misc:Depends}, libsdl2-2.0-0 (= ${binary:Version}), libc6-dev, - libgl1-mesa-dev + libgl1-mesa-dev, + libx11-dev Conflicts: libsdl-1.3-dev Replaces: libsdl-1.3-dev Description: Simple DirectMedia Layer development files diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake index 5e9e5bcea..ef928eebd 100644 --- a/include/SDL_config.h.cmake +++ b/include/SDL_config.h.cmake @@ -330,6 +330,7 @@ #cmakedefine SDL_VIDEO_DRIVER_RPI @SDL_VIDEO_DRIVER_RPI@ #cmakedefine SDL_VIDEO_DRIVER_VIVANTE @SDL_VIDEO_DRIVER_VIVANTE@ #cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@ +#cmakedefine SDL_VIDEO_DRIVER_MALI @SDL_VIDEO_DRIVER_MALI@ #cmakedefine SDL_VIDEO_DRIVER_KMSDRM @SDL_VIDEO_DRIVER_KMSDRM@ #cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC@ diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index a5e9d1328..0b93b3614 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -335,6 +335,7 @@ #undef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM #undef SDL_VIDEO_DRIVER_ANDROID #undef SDL_VIDEO_DRIVER_EMSCRIPTEN +#undef SDL_VIDEO_DRIVER_MALI #undef SDL_VIDEO_DRIVER_X11_DYNAMIC #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT #undef SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index 778e555c3..4ed679af3 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -52,7 +52,7 @@ #define DEFAULT_OGL_ES_PVR ( vc4 ? "libGLES_CM.so.1" : "libbrcmGLESv2.so" ) #define DEFAULT_OGL_ES ( vc4 ? "libGLESv1_CM.so.1" : "libbrcmGLESv2.so" ) -#elif SDL_VIDEO_DRIVER_ANDROID || SDL_VIDEO_DRIVER_VIVANTE +#elif SDL_VIDEO_DRIVER_ANDROID || SDL_VIDEO_DRIVER_MALI || SDL_VIDEO_DRIVER_VIVANTE /* Android */ #define DEFAULT_EGL "libEGL.so" #define DEFAULT_OGL_ES2 "libGLESv2.so" diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index e88a8b60e..c991608f7 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -415,6 +415,7 @@ extern VideoBootStrap Android_bootstrap; extern VideoBootStrap PSP_bootstrap; extern VideoBootStrap RPI_bootstrap; extern VideoBootStrap KMSDRM_bootstrap; +extern VideoBootStrap MALI_bootstrap; extern VideoBootStrap DUMMY_bootstrap; extern VideoBootStrap Wayland_bootstrap; extern VideoBootStrap NACL_bootstrap; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index c63f74631..3301e9f8b 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -94,6 +94,9 @@ static VideoBootStrap *bootstrap[] = { #if SDL_VIDEO_DRIVER_PSP &PSP_bootstrap, #endif +#if SDL_VIDEO_DRIVER_MALI + &MALI_bootstrap, +#endif #if SDL_VIDEO_DRIVER_KMSDRM &KMSDRM_bootstrap, #endif diff --git a/src/video/mali-fbdev/SDL_maliopengles.c b/src/video/mali-fbdev/SDL_maliopengles.c new file mode 100644 index 000000000..0e4836d2e --- /dev/null +++ b/src/video/mali-fbdev/SDL_maliopengles.c @@ -0,0 +1,43 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2014 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_MALI && SDL_VIDEO_OPENGL_EGL + +#include "SDL_maliopengles.h" +#include "SDL_malivideo.h" + +/* EGL implementation of SDL OpenGL support */ + +int +MALI_GLES_LoadLibrary(_THIS, const char *path) +{ + return SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY, 0); +} + +SDL_EGL_CreateContext_impl(MALI) +SDL_EGL_SwapWindow_impl(MALI) +SDL_EGL_MakeCurrent_impl(MALI) + +#endif /* SDL_VIDEO_DRIVER_MALI && SDL_VIDEO_OPENGL_EGL */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/video/mali-fbdev/SDL_maliopengles.h b/src/video/mali-fbdev/SDL_maliopengles.h new file mode 100644 index 000000000..121af74f9 --- /dev/null +++ b/src/video/mali-fbdev/SDL_maliopengles.h @@ -0,0 +1,48 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2014 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef _SDL_maliopengles_h +#define _SDL_maliopengles_h + +#if SDL_VIDEO_DRIVER_MALI && SDL_VIDEO_OPENGL_EGL + +#include "../SDL_sysvideo.h" +#include "../SDL_egl_c.h" + +/* OpenGLES functions */ +#define MALI_GLES_GetAttribute SDL_EGL_GetAttribute +#define MALI_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define MALI_GLES_UnloadLibrary SDL_EGL_UnloadLibrary +#define MALI_GLES_SetSwapInterval SDL_EGL_SetSwapInterval +#define MALI_GLES_GetSwapInterval SDL_EGL_GetSwapInterval +#define MALI_GLES_DeleteContext SDL_EGL_DeleteContext + +extern int MALI_GLES_LoadLibrary(_THIS, const char *path); +extern SDL_GLContext MALI_GLES_CreateContext(_THIS, SDL_Window * window); +extern int MALI_GLES_SwapWindow(_THIS, SDL_Window * window); +extern int MALI_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); + +#endif /* SDL_VIDEO_DRIVER_MALI && SDL_VIDEO_OPENGL_EGL */ + +#endif /* _SDL_maliopengles_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/mali-fbdev/SDL_malivideo.c b/src/video/mali-fbdev/SDL_malivideo.c new file mode 100644 index 000000000..1d076a68d --- /dev/null +++ b/src/video/mali-fbdev/SDL_malivideo.c @@ -0,0 +1,323 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2014 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_MALI + +/* SDL internals */ +#include "../SDL_sysvideo.h" +#include "SDL_version.h" +#include "SDL_syswm.h" +#include "SDL_loadso.h" +#include "SDL_events.h" +#include "../../events/SDL_events_c.h" + +#ifdef SDL_INPUT_LINUXEV +#include "../../core/linux/SDL_evdev.h" +#endif + +#include "SDL_malivideo.h" +#include "SDL_maliopengles.h" + + +static int +MALI_Available(void) +{ + return 1; +} + +static void +MALI_Destroy(SDL_VideoDevice * device) +{ + if (device->driverdata != NULL) { + SDL_free(device->driverdata); + device->driverdata = NULL; + } +} + +static SDL_VideoDevice * +MALI_Create() +{ + SDL_VideoDevice *device; + + /* Initialize SDL_VideoDevice structure */ + device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); + if (device == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + device->driverdata = NULL; + + /* Setup amount of available displays and current display */ + device->num_displays = 0; + + /* Set device free function */ + device->free = MALI_Destroy; + + /* Setup all functions which we can handle */ + device->VideoInit = MALI_VideoInit; + device->VideoQuit = MALI_VideoQuit; + device->GetDisplayModes = MALI_GetDisplayModes; + device->SetDisplayMode = MALI_SetDisplayMode; + device->CreateSDLWindow = MALI_CreateWindow; + device->SetWindowTitle = MALI_SetWindowTitle; + device->SetWindowPosition = MALI_SetWindowPosition; + device->SetWindowSize = MALI_SetWindowSize; + device->ShowWindow = MALI_ShowWindow; + device->HideWindow = MALI_HideWindow; + device->DestroyWindow = MALI_DestroyWindow; + device->GetWindowWMInfo = MALI_GetWindowWMInfo; + + device->GL_LoadLibrary = MALI_GLES_LoadLibrary; + device->GL_GetProcAddress = MALI_GLES_GetProcAddress; + device->GL_UnloadLibrary = MALI_GLES_UnloadLibrary; + device->GL_CreateContext = MALI_GLES_CreateContext; + device->GL_MakeCurrent = MALI_GLES_MakeCurrent; + device->GL_SetSwapInterval = MALI_GLES_SetSwapInterval; + device->GL_GetSwapInterval = MALI_GLES_GetSwapInterval; + device->GL_SwapWindow = MALI_GLES_SwapWindow; + device->GL_DeleteContext = MALI_GLES_DeleteContext; + + device->PumpEvents = MALI_PumpEvents; + + return device; +} + +VideoBootStrap MALI_bootstrap = { + "mali", + "Mali EGL Video Driver", + MALI_Available, + MALI_Create +}; + +/*****************************************************************************/ +/* SDL Video and Display initialization/handling functions */ +/*****************************************************************************/ + +int +MALI_VideoInit(_THIS) +{ + SDL_VideoDisplay display; + SDL_DisplayMode current_mode; + SDL_DisplayData *data; + struct fb_var_screeninfo vinfo; + int fd; + + data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData)); + if (data == NULL) { + return SDL_OutOfMemory(); + } + + fd = open("/dev/fb0", O_RDWR, 0); + if (fd < 0) { + return SDL_SetError("mali-fbdev: Could not open framebuffer device"); + } + + if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) { + MALI_VideoQuit(_this); + return SDL_SetError("mali-fbdev: Could not get framebuffer information"); + } + /* Enable triple buffering */ + /* + vinfo.yres_virtual = vinfo.yres * 3; + if (ioctl(fd, FBIOPUT_VSCREENINFO, vinfo) == -1) { + printf("mali-fbdev: Error setting VSCREENINFO\n"); + } + */ + close(fd); + system("setterm -cursor off"); + + data->native_display.width = vinfo.xres; + data->native_display.height = vinfo.yres; + + SDL_zero(current_mode); + current_mode.w = vinfo.xres; + current_mode.h = vinfo.yres; + /* FIXME: Is there a way to tell the actual refresh rate? */ + current_mode.refresh_rate = 60; + /* 32 bpp for default */ + //current_mode.format = SDL_PIXELFORMAT_ABGR8888; + current_mode.format = SDL_PIXELFORMAT_RGBX8888; + + current_mode.driverdata = NULL; + + SDL_zero(display); + display.desktop_mode = current_mode; + display.current_mode = current_mode; + display.driverdata = data; + + SDL_AddVideoDisplay(&display); + +#ifdef SDL_INPUT_LINUXEV + if (SDL_EVDEV_Init() < 0) { + return -1; + } +#endif + + return 0; +} + +void +MALI_VideoQuit(_THIS) +{ + /* Clear the framebuffer and ser cursor on again */ + int fd = open("/dev/tty", O_RDWR); + ioctl(fd, VT_ACTIVATE, 5); + ioctl(fd, VT_ACTIVATE, 1); + close(fd); + system("setterm -cursor on"); + +#ifdef SDL_INPUT_LINUXEV + SDL_EVDEV_Quit(); +#endif + +} + +void +MALI_GetDisplayModes(_THIS, SDL_VideoDisplay * display) +{ + /* Only one display mode available, the current one */ + SDL_AddDisplayMode(display, &display->current_mode); +} + +int +MALI_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) +{ + return 0; +} + +int +MALI_CreateWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *windowdata; + SDL_DisplayData *displaydata; + + displaydata = SDL_GetDisplayDriverData(0); + + /* Allocate window internal data */ + windowdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData)); + if (windowdata == NULL) { + return SDL_OutOfMemory(); + } + + /* Windows have one size for now */ + window->w = displaydata->native_display.width; + window->h = displaydata->native_display.height; + + /* OpenGL ES is the law here */ + window->flags |= SDL_WINDOW_OPENGL; + + if (!_this->egl_data) { + if (SDL_GL_LoadLibrary(NULL) < 0) { + return -1; + } + } + windowdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) &displaydata->native_display); + + if (windowdata->egl_surface == EGL_NO_SURFACE) { + MALI_VideoQuit(_this); + return SDL_SetError("mali-fbdev: Can't create EGL window surface"); + } + + /* Setup driver data for this window */ + window->driverdata = windowdata; + + /* One window, it always has focus */ + SDL_SetMouseFocus(window); + SDL_SetKeyboardFocus(window); + + /* Window has been successfully created */ + return 0; +} + +void +MALI_DestroyWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *data; + + data = window->driverdata; + if (data) { + if (data->egl_surface != EGL_NO_SURFACE) { + SDL_EGL_DestroySurface(_this, data->egl_surface); + data->egl_surface = EGL_NO_SURFACE; + } + SDL_free(data); + } + window->driverdata = NULL; +} + +void +MALI_SetWindowTitle(_THIS, SDL_Window * window) +{ +} + +void +MALI_SetWindowPosition(_THIS, SDL_Window * window) +{ +} + +void +MALI_SetWindowSize(_THIS, SDL_Window * window) +{ +} + +void +MALI_ShowWindow(_THIS, SDL_Window * window) +{ +} + +void +MALI_HideWindow(_THIS, SDL_Window * window) +{ +} + +/*****************************************************************************/ +/* SDL Window Manager function */ +/*****************************************************************************/ +SDL_bool +MALI_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info) +{ + if (info->version.major <= SDL_MAJOR_VERSION) { + return SDL_TRUE; + } else { + SDL_SetError("application not compiled with SDL %d.%d\n", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + } + + /* Failed to get window manager information */ + return SDL_FALSE; +} + +/*****************************************************************************/ +/* SDL event functions */ +/*****************************************************************************/ +void MALI_PumpEvents(_THIS) +{ +#ifdef SDL_INPUT_LINUXEV + SDL_EVDEV_Poll(); +#endif +} + +#endif /* SDL_VIDEO_DRIVER_MALI */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/video/mali-fbdev/SDL_malivideo.h b/src/video/mali-fbdev/SDL_malivideo.h new file mode 100644 index 000000000..c14667fa8 --- /dev/null +++ b/src/video/mali-fbdev/SDL_malivideo.h @@ -0,0 +1,80 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2014 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _SDL_malivideo_h +#define _SDL_malivideo_h + +#include "../../SDL_internal.h" +#include "../SDL_sysvideo.h" + +#include "SDL_egl.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct SDL_DisplayData +{ + struct { + unsigned short width; + unsigned short height; + } native_display; +} SDL_DisplayData; + +typedef struct SDL_WindowData +{ + EGLSurface egl_surface; +} SDL_WindowData; + +/****************************************************************************/ +/* SDL_VideoDevice functions declaration */ +/****************************************************************************/ + +/* Display and window functions */ +int MALI_VideoInit(_THIS); +void MALI_VideoQuit(_THIS); +void MALI_GetDisplayModes(_THIS, SDL_VideoDisplay * display); +int MALI_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); +int MALI_CreateWindow(_THIS, SDL_Window * window); +void MALI_SetWindowTitle(_THIS, SDL_Window * window); +void MALI_SetWindowPosition(_THIS, SDL_Window * window); +void MALI_SetWindowSize(_THIS, SDL_Window * window); +void MALI_ShowWindow(_THIS, SDL_Window * window); +void MALI_HideWindow(_THIS, SDL_Window * window); +void MALI_DestroyWindow(_THIS, SDL_Window * window); + +/* Window manager function */ +SDL_bool MALI_GetWindowWMInfo(_THIS, SDL_Window * window, + struct SDL_SysWMinfo *info); + +/* Event functions */ +void MALI_PumpEvents(_THIS); + +#endif /* _SDL_malivideo_h */ + +/* vi: set ts=4 sw=4 expandtab: */ + From 57b95ddd3b16c2f9dd597fa55af40d559d1cc020 Mon Sep 17 00:00:00 2001 From: Nicolas Adenis-Lamarre Date: Wed, 7 Aug 2019 11:27:46 +0100 Subject: [PATCH 05/14] fix sdl2 joystick events after joystick closed See: https://bugzilla.libsdl.org/show_bug.cgi?id=4640 --- src/joystick/SDL_joystick.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index dcc1b7440..f8a8639f3 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -1047,7 +1047,7 @@ SDL_JoystickUpdate(void) if (joystick->delayed_guide_button) { SDL_GameControllerHandleDelayedGuideButton(joystick); } - } + if (joystick->force_recentering) { /* Tell the app that everything is centered/unpressed... */ @@ -1067,6 +1067,8 @@ SDL_JoystickUpdate(void) joystick->force_recentering = SDL_FALSE; } + + } } SDL_LockJoysticks(); From 2db72c15114a190d18ebac343aafd3f53c4d849a Mon Sep 17 00:00:00 2001 From: Conn O'Griofa Date: Wed, 7 Aug 2019 03:11:08 +0100 Subject: [PATCH 06/14] Improve kmsdrm + rpi driver coexistence * Ensure that DEFAULT_OGL is set correctly (fixes OpenGL) * Silence kmsdrm driver init error when using VideoCore. * Remove VideoCore cflags from SDL_CFLAGS; these flags are unnecessary and will cause conflicts when building SDL2 applications for VC4. --- configure | 2 +- configure.ac | 2 +- src/video/SDL_egl.c | 2 ++ src/video/kmsdrm/SDL_kmsdrmvideo.c | 6 ++++++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/configure b/configure index ca8be79fa..4e38f7a5b 100755 --- a/configure +++ b/configure @@ -19859,7 +19859,7 @@ $as_echo "$have_video_rpi" >&6; } if test x$have_video_rpi = xyes; then CFLAGS="$CFLAGS $RPI_CFLAGS" - SDL_CFLAGS="$SDL_CFLAGS $RPI_CFLAGS" + #SDL_CFLAGS="$SDL_CFLAGS $RPI_CFLAGS" EXTRA_CFLAGS="$EXTRA_CFLAGS $RPI_CFLAGS" EXTRA_LDFLAGS="$EXTRA_LDFLAGS $RPI_LIBS" SOURCES="$SOURCES $srcdir/src/video/raspberry/*.c" diff --git a/configure.ac b/configure.ac index 513065f31..d7f7e3009 100644 --- a/configure.ac +++ b/configure.ac @@ -1588,7 +1588,7 @@ AS_HELP_STRING([--enable-video-rpi], [use Raspberry Pi video driver [[default=ye if test x$have_video_rpi = xyes; then CFLAGS="$CFLAGS $RPI_CFLAGS" - SDL_CFLAGS="$SDL_CFLAGS $RPI_CFLAGS" + #SDL_CFLAGS="$SDL_CFLAGS $RPI_CFLAGS" EXTRA_CFLAGS="$EXTRA_CFLAGS $RPI_CFLAGS" EXTRA_LDFLAGS="$EXTRA_LDFLAGS $RPI_LIBS" SOURCES="$SOURCES $srcdir/src/video/raspberry/*.c" diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index 4ed679af3..1a40197d0 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -45,6 +45,8 @@ #if SDL_VIDEO_DRIVER_RPI /* Raspbian places the OpenGL ES/EGL binaries in a non standard path */ +#include +#define DEFAULT_OGL ( vc4 ? "libGL.so.1" : "" ) #define DEFAULT_EGL ( vc4 ? "libEGL.so.1" : "libbrcmEGL.so" ) #define DEFAULT_OGL_ES2 ( vc4 ? "libGLESv2.so.2" : "libbrcmGLESv2.so" ) #define ALT_EGL "libEGL.so" diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 54f623e29..3fe4dfbbc 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -87,6 +87,12 @@ static int get_dricount(void) if (!(stat(KMSDRM_DRI_PATH, &sb) == 0 && S_ISDIR(sb.st_mode))) { +#if SDL_VIDEO_DRIVER_RPI + // exit silently if VC4 driver is not active + SDL_bool vc4 = (0 == access("/sys/module/vc4/", F_OK)); + if (!vc4) + return 0; +#endif printf("The path %s cannot be opened or is not available\n", KMSDRM_DRI_PATH); return 0; From c7e1c332e3fb306b250df3dc7d7cb6f835c799ce Mon Sep 17 00:00:00 2001 From: Conn O'Griofa Date: Wed, 7 Aug 2019 07:14:35 +0100 Subject: [PATCH 07/14] SDL_EGL_ChooseConfig: don't fall through if no matching format exists On Raspberry Pi 3 via the VC4 driver in firmware KMS mode, none of the found configs match the desired format, causing the function to fall through without any config being selected. Fix by first iterating over the found configs, and if no match exists, don't exclude the non-matching configs. This should fix RPI3 and possibly other targets without breaking targets that have a matching native format (such as RPI4). --- src/video/SDL_egl.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index 1a40197d0..fd59a963e 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -538,6 +538,7 @@ SDL_EGL_ChooseConfig(_THIS) EGLint found_configs = 0, value; /* 128 seems even nicer here */ EGLConfig configs[128]; + SDL_bool has_matching_format = SDL_FALSE; int i, j, best_bitdiff = -1, bitdiff; if (!_this->egl_data) { @@ -616,11 +617,24 @@ SDL_EGL_ChooseConfig(_THIS) return SDL_EGL_SetError("Couldn't find matching EGL config", "eglChooseConfig"); } + /* first ensure that a found config has a matching format, or the function will fall through. */ + for (i = 0; i < found_configs; i++ ) { + if (_this->egl_data->egl_required_visual_id) + { + EGLint format; + _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, + configs[i], + EGL_NATIVE_VISUAL_ID, &format); + if (_this->egl_data->egl_required_visual_id == format) + has_matching_format = SDL_TRUE; + } + } + /* eglChooseConfig returns a number of configurations that match or exceed the requested attribs. */ /* From those, we select the one that matches our requirements more closely via a makeshift algorithm */ for (i = 0; i < found_configs; i++ ) { - if (_this->egl_data->egl_required_visual_id) + if (has_matching_format && _this->egl_data->egl_required_visual_id) { EGLint format; _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, From c9f99401db0a65e6a1dcb3f0381b7a6847c0cee8 Mon Sep 17 00:00:00 2001 From: Ozkan Sezer Date: Mon, 26 Aug 2019 18:41:40 +0300 Subject: [PATCH 08/14] RPI_FreeCursor: set global_cursor to NULL to prevent double-free (bug 4769) --- src/video/raspberry/SDL_rpimouse.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/video/raspberry/SDL_rpimouse.c b/src/video/raspberry/SDL_rpimouse.c index 0a51a40e6..134ebf6b7 100644 --- a/src/video/raspberry/SDL_rpimouse.c +++ b/src/video/raspberry/SDL_rpimouse.c @@ -226,6 +226,9 @@ RPI_FreeCursor(SDL_Cursor * cursor) SDL_free(cursor->driverdata); } SDL_free(cursor); + if (cursor == global_cursor) { + global_cursor = NULL; + } } } From 23b9113ec9d6b86c072163a7db6c47b23023f66b Mon Sep 17 00:00:00 2001 From: Conn O'Griofa Date: Thu, 5 Sep 2019 16:37:19 +0100 Subject: [PATCH 09/14] KMSDRM_GLES_SwapWindow: fix non-vsync case If KMSDRM_drmModeSetCrtc is called when the swap interval is set to 0, the driver behaves as though vertical sync is engaged by limiting framerate to the refresh rate, but performance is much worse than with vertical sync enabled. Resolve this issue by ensuring that the Crtc is only set up once, and KMSDRM_drmModePageFlip is called, albeit without any followup queueing or waiting for flips. --- src/video/kmsdrm/SDL_kmsdrmopengles.c | 38 +++++++++++---------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c index 9616c832f..212c2b5d7 100644 --- a/src/video/kmsdrm/SDL_kmsdrmopengles.c +++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c @@ -140,32 +140,24 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) { if (fb_info == NULL) { return 0; } - if (_this->egl_data->egl_swapinterval == 0) { - /* Swap buffers instantly, possible tearing */ - /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModeSetCrtc(%d, %u, %u, 0, 0, &%u, 1, &%ux%u@%u)", - vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, vdata->saved_conn_id, - displaydata->cur_mode.hdisplay, displaydata->cur_mode.vdisplay, displaydata->cur_mode.vrefresh); */ - ret = KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, - 0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode); - if(ret != 0) { - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not pageflip with drmModeSetCrtc: %d", ret); + + /* Have we already setup the CRTC to one of the GBM buffers? Do so if we have not, + or FlipPage won't work in some cases. */ + if (!wdata->crtc_ready) { + if(!KMSDRM_GLES_SetupCrtc(_this, window)) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC for doing pageflips"); + return 0; } - } else { + } + + /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip)", + vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */ + ret = KMSDRM_drmModePageFlip(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, + DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip); + + if (_this->egl_data->egl_swapinterval == 1) { /* Queue page flip at vsync */ - /* Have we already setup the CRTC to one of the GBM buffers? Do so if we have not, - or FlipPage won't work in some cases. */ - if (!wdata->crtc_ready) { - if(!KMSDRM_GLES_SetupCrtc(_this, window)) { - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC for doing vsync-ed pageflips"); - return 0; - } - } - - /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip)", - vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */ - ret = KMSDRM_drmModePageFlip(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, - DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip); if (ret == 0) { wdata->waiting_for_flip = SDL_TRUE; } else { From 1509ccac910948becb3406ad484a32118521a430 Mon Sep 17 00:00:00 2001 From: Sylvain Becker Date: Tue, 10 Sep 2019 17:12:34 +0200 Subject: [PATCH 10/14] Fixed bug 4798 - PNG w/transparency breaks in SDL 2.0.10 but works in SDL 2.0.9 --- src/video/SDL_surface.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 75dc2bb26..814e536e2 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -959,6 +959,8 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format, SDL_Color copy_color; SDL_Rect bounds; int ret; + int palette_ck_transform = 0; + int palette_ck_value = 0; if (!surface) { SDL_InvalidParamError("surface"); @@ -1019,8 +1021,23 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format, bounds.y = 0; bounds.w = surface->w; bounds.h = surface->h; + + /* Transform colorkey to alpha. for cases where source palette has duplicate values, and colorkey is one of them */ + if (copy_flags & SDL_COPY_COLORKEY) { + if (surface->format->palette && !format->palette) { + palette_ck_transform = 1; + palette_ck_value = surface->format->palette->colors[surface->map->info.colorkey].a; + surface->format->palette->colors[surface->map->info.colorkey].a = SDL_ALPHA_TRANSPARENT; + } + } + ret = SDL_LowerBlit(surface, &bounds, convert, &bounds); + /* Restore value */ + if (palette_ck_transform) { + surface->format->palette->colors[surface->map->info.colorkey].a = palette_ck_value; + } + /* Clean up the original surface, and update converted surface */ convert->map->info.r = copy_color.r; convert->map->info.g = copy_color.g; @@ -1055,7 +1072,9 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format, surface->format->palette->ncolors * sizeof(SDL_Color)) == 0)) { /* The palette is identical, just set the same colorkey */ SDL_SetColorKey(convert, 1, surface->map->info.colorkey); - } else if (format->Amask) { + } else if (!format->palette) { + /* Was done by 'palette_ck_transform' */ + }else if (format->Amask) { set_colorkey_by_color = SDL_TRUE; ignore_alpha = SDL_FALSE; } else { From 6113b056a22fce230eaf81ba8961daf83a7c0f49 Mon Sep 17 00:00:00 2001 From: cmitu <31816814+cmitu@users.noreply.github.com> Date: Sun, 17 Nov 2019 08:31:23 +0000 Subject: [PATCH 11/14] KMSDRM_VideoInit: add hints for overriding the default video mode --- src/video/kmsdrm/SDL_kmsdrmvideo.c | 74 ++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 3fe4dfbbc..888f573e1 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -145,6 +145,28 @@ KMSDRM_Available(void) return ret; } +static drmModeModeInfo * +connector_find_mode(drmModeConnector *connector, const char *mode_str, const unsigned int vrefresh) +{ + short i; + drmModeModeInfo *mode; + for (i = 0; i < connector->count_modes; i++) { + mode = &connector->modes[i]; + if (!strcmp(mode->name, mode_str)) { + /* If the vertical refresh frequency is not specified then return the + * first mode that match with the name. Else, return the mode that match + * the name and the specified vertical refresh frequency. + */ + if (vrefresh == 0) + return mode; + else if (mode->vrefresh == vrefresh) + return mode; + } + } + + return NULL; +} + static void KMSDRM_Destroy(SDL_VideoDevice * device) { @@ -350,12 +372,19 @@ KMSDRM_VideoInit(_THIS) SDL_bool found; int ret = 0; char *devname; + const char *crtc_override; + const char *mode_override; SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); drmModeRes *resources = NULL; drmModeConnector *connector = NULL; drmModeEncoder *encoder = NULL; SDL_DisplayMode current_mode; SDL_VideoDisplay display; + const char *mode_line_override; + char *hint_video_mode = NULL; + unsigned short hint_vrefresh=0; + char* p; + drmModeModeInfo *override_mode = NULL; /* Allocate display internal data */ SDL_DisplayData *data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData)); @@ -472,9 +501,48 @@ KMSDRM_VideoInit(_THIS) SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Saved crtc_id %u, fb_id %u, (%u,%u), %ux%u", vdata->saved_crtc->crtc_id, vdata->saved_crtc->buffer_id, vdata->saved_crtc->x, vdata->saved_crtc->y, vdata->saved_crtc->width, vdata->saved_crtc->height); - data->crtc_id = encoder->crtc_id; - data->cur_mode = vdata->saved_crtc->mode; - vdata->crtc_id = encoder->crtc_id; + + crtc_override = SDL_getenv("SDL_VIDEO_KMSDRM_CRTCID"); + if (crtc_override) + data->crtc_id = vdata->crtc_id = SDL_atoi(crtc_override); + else + data->crtc_id = vdata->crtc_id = encoder->crtc_id; + + mode_override = SDL_getenv("SDL_VIDEO_KMSDRM_MODEID"); + if (mode_override) + data->cur_mode = connector->modes[SDL_atoi(mode_override)]; + else + data->cur_mode = vdata->saved_crtc->mode; + + mode_line_override = SDL_getenv("SDL_VIDEO_KMSDRM_MODELINE"); + if (mode_line_override && !mode_override) { + /* Video mode override, formatted as WxH[@vRefresh] */ + SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO,"Override video mode received - %s", mode_line_override); + + p = strchr(mode_line_override, '@'); + if (p == NULL) { + hint_video_mode =strdup(mode_line_override); + } else { + hint_video_mode = strndup(mode_line_override, (unsigned int)(p - mode_line_override)); + hint_vrefresh = strtoul(p + 1, NULL, 10); + } + + override_mode = connector_find_mode(connector, hint_video_mode, hint_vrefresh); + if (override_mode) { + if ((*override_mode).hdisplay != data->cur_mode.hdisplay || + (*override_mode).vdisplay != data->cur_mode.vdisplay || + (*override_mode).vrefresh != data->cur_mode.vrefresh) { + SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "Changing video mode to %dx%d @ %d",(*override_mode).hdisplay, (*override_mode).vdisplay, (*override_mode).vrefresh); + current_mode.w = (*override_mode).hdisplay; + current_mode.h = (*override_mode).vdisplay; + current_mode.refresh_rate = (*override_mode).vrefresh; + data->cur_mode = (*override_mode); + } + } else { + SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Cannot find a suitable video mode on connector %d for mode %s, using default", + connector->connector_id, mode_line_override); + } + } // select default mode if this one is not valid if (vdata->saved_crtc->mode_valid == 0) { From 6b1e8ac6dd8c96a5533fc53cf912b485f6d48550 Mon Sep 17 00:00:00 2001 From: Conn O'Griofa Date: Tue, 19 Nov 2019 16:56:21 +0000 Subject: [PATCH 12/14] kmsdrm: enable aspect ratio support Enable the DRM_CLIENT_CAP_ASPECT_RATIO cap to communicate aspect ratio information via mode flags, making additional modes available. --- src/video/kmsdrm/SDL_kmsdrmsym.h | 2 +- src/video/kmsdrm/SDL_kmsdrmvideo.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h index e34642350..1b90de8cd 100644 --- a/src/video/kmsdrm/SDL_kmsdrmsym.h +++ b/src/video/kmsdrm/SDL_kmsdrmsym.h @@ -61,7 +61,7 @@ SDL_KMSDRM_SYM(drmModeConnectorPtr,drmModeGetConnector,(int fd, uint32_t connect SDL_KMSDRM_SYM(int,drmHandleEvent,(int fd,drmEventContextPtr evctx)) SDL_KMSDRM_SYM(int,drmModePageFlip,(int fd, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, void *user_data)) - +SDL_KMSDRM_SYM(int,drmSetClientCap,(int fd, uint64_t capability, uint64_t value)) SDL_KMSDRM_MODULE(GBM) SDL_KMSDRM_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm)) diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 888f573e1..57ff18bbc 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -417,6 +417,9 @@ KMSDRM_VideoInit(_THIS) goto cleanup; } + /* Expose aspect ratio flags to userspace */ + KMSDRM_drmSetClientCap(vdata->drm_fd, DRM_CLIENT_CAP_ASPECT_RATIO, 1); + /* Find the first available connector with modes */ resources = KMSDRM_drmModeGetResources(vdata->drm_fd); if (!resources) { From 63270f2df0c3d49c1020617b64d65c3f52d96694 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Wed, 1 Jan 2020 05:42:50 +0000 Subject: [PATCH 13/14] Revert "Modesetting support for KMSDRM driver" --- src/video/kmsdrm/SDL_kmsdrmsym.h | 2 +- src/video/kmsdrm/SDL_kmsdrmvideo.c | 77 ++---------------------------- 2 files changed, 4 insertions(+), 75 deletions(-) diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h index 1b90de8cd..e34642350 100644 --- a/src/video/kmsdrm/SDL_kmsdrmsym.h +++ b/src/video/kmsdrm/SDL_kmsdrmsym.h @@ -61,7 +61,7 @@ SDL_KMSDRM_SYM(drmModeConnectorPtr,drmModeGetConnector,(int fd, uint32_t connect SDL_KMSDRM_SYM(int,drmHandleEvent,(int fd,drmEventContextPtr evctx)) SDL_KMSDRM_SYM(int,drmModePageFlip,(int fd, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, void *user_data)) -SDL_KMSDRM_SYM(int,drmSetClientCap,(int fd, uint64_t capability, uint64_t value)) + SDL_KMSDRM_MODULE(GBM) SDL_KMSDRM_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm)) diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 57ff18bbc..3fe4dfbbc 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -145,28 +145,6 @@ KMSDRM_Available(void) return ret; } -static drmModeModeInfo * -connector_find_mode(drmModeConnector *connector, const char *mode_str, const unsigned int vrefresh) -{ - short i; - drmModeModeInfo *mode; - for (i = 0; i < connector->count_modes; i++) { - mode = &connector->modes[i]; - if (!strcmp(mode->name, mode_str)) { - /* If the vertical refresh frequency is not specified then return the - * first mode that match with the name. Else, return the mode that match - * the name and the specified vertical refresh frequency. - */ - if (vrefresh == 0) - return mode; - else if (mode->vrefresh == vrefresh) - return mode; - } - } - - return NULL; -} - static void KMSDRM_Destroy(SDL_VideoDevice * device) { @@ -372,19 +350,12 @@ KMSDRM_VideoInit(_THIS) SDL_bool found; int ret = 0; char *devname; - const char *crtc_override; - const char *mode_override; SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); drmModeRes *resources = NULL; drmModeConnector *connector = NULL; drmModeEncoder *encoder = NULL; SDL_DisplayMode current_mode; SDL_VideoDisplay display; - const char *mode_line_override; - char *hint_video_mode = NULL; - unsigned short hint_vrefresh=0; - char* p; - drmModeModeInfo *override_mode = NULL; /* Allocate display internal data */ SDL_DisplayData *data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData)); @@ -417,9 +388,6 @@ KMSDRM_VideoInit(_THIS) goto cleanup; } - /* Expose aspect ratio flags to userspace */ - KMSDRM_drmSetClientCap(vdata->drm_fd, DRM_CLIENT_CAP_ASPECT_RATIO, 1); - /* Find the first available connector with modes */ resources = KMSDRM_drmModeGetResources(vdata->drm_fd); if (!resources) { @@ -504,48 +472,9 @@ KMSDRM_VideoInit(_THIS) SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Saved crtc_id %u, fb_id %u, (%u,%u), %ux%u", vdata->saved_crtc->crtc_id, vdata->saved_crtc->buffer_id, vdata->saved_crtc->x, vdata->saved_crtc->y, vdata->saved_crtc->width, vdata->saved_crtc->height); - - crtc_override = SDL_getenv("SDL_VIDEO_KMSDRM_CRTCID"); - if (crtc_override) - data->crtc_id = vdata->crtc_id = SDL_atoi(crtc_override); - else - data->crtc_id = vdata->crtc_id = encoder->crtc_id; - - mode_override = SDL_getenv("SDL_VIDEO_KMSDRM_MODEID"); - if (mode_override) - data->cur_mode = connector->modes[SDL_atoi(mode_override)]; - else - data->cur_mode = vdata->saved_crtc->mode; - - mode_line_override = SDL_getenv("SDL_VIDEO_KMSDRM_MODELINE"); - if (mode_line_override && !mode_override) { - /* Video mode override, formatted as WxH[@vRefresh] */ - SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO,"Override video mode received - %s", mode_line_override); - - p = strchr(mode_line_override, '@'); - if (p == NULL) { - hint_video_mode =strdup(mode_line_override); - } else { - hint_video_mode = strndup(mode_line_override, (unsigned int)(p - mode_line_override)); - hint_vrefresh = strtoul(p + 1, NULL, 10); - } - - override_mode = connector_find_mode(connector, hint_video_mode, hint_vrefresh); - if (override_mode) { - if ((*override_mode).hdisplay != data->cur_mode.hdisplay || - (*override_mode).vdisplay != data->cur_mode.vdisplay || - (*override_mode).vrefresh != data->cur_mode.vrefresh) { - SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "Changing video mode to %dx%d @ %d",(*override_mode).hdisplay, (*override_mode).vdisplay, (*override_mode).vrefresh); - current_mode.w = (*override_mode).hdisplay; - current_mode.h = (*override_mode).vdisplay; - current_mode.refresh_rate = (*override_mode).vrefresh; - data->cur_mode = (*override_mode); - } - } else { - SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Cannot find a suitable video mode on connector %d for mode %s, using default", - connector->connector_id, mode_line_override); - } - } + data->crtc_id = encoder->crtc_id; + data->cur_mode = vdata->saved_crtc->mode; + vdata->crtc_id = encoder->crtc_id; // select default mode if this one is not valid if (vdata->saved_crtc->mode_valid == 0) { From 1ebd3293e917a72c3c258c35d82730927b08b0d5 Mon Sep 17 00:00:00 2001 From: Jools Wills Date: Fri, 3 Jan 2020 00:19:02 +0000 Subject: [PATCH 14/14] Revert "Revert "Modesetting support for KMSDRM driver"" --- src/video/kmsdrm/SDL_kmsdrmsym.h | 2 +- src/video/kmsdrm/SDL_kmsdrmvideo.c | 77 ++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h index e34642350..1b90de8cd 100644 --- a/src/video/kmsdrm/SDL_kmsdrmsym.h +++ b/src/video/kmsdrm/SDL_kmsdrmsym.h @@ -61,7 +61,7 @@ SDL_KMSDRM_SYM(drmModeConnectorPtr,drmModeGetConnector,(int fd, uint32_t connect SDL_KMSDRM_SYM(int,drmHandleEvent,(int fd,drmEventContextPtr evctx)) SDL_KMSDRM_SYM(int,drmModePageFlip,(int fd, uint32_t crtc_id, uint32_t fb_id, uint32_t flags, void *user_data)) - +SDL_KMSDRM_SYM(int,drmSetClientCap,(int fd, uint64_t capability, uint64_t value)) SDL_KMSDRM_MODULE(GBM) SDL_KMSDRM_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm)) diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c index 3fe4dfbbc..57ff18bbc 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -145,6 +145,28 @@ KMSDRM_Available(void) return ret; } +static drmModeModeInfo * +connector_find_mode(drmModeConnector *connector, const char *mode_str, const unsigned int vrefresh) +{ + short i; + drmModeModeInfo *mode; + for (i = 0; i < connector->count_modes; i++) { + mode = &connector->modes[i]; + if (!strcmp(mode->name, mode_str)) { + /* If the vertical refresh frequency is not specified then return the + * first mode that match with the name. Else, return the mode that match + * the name and the specified vertical refresh frequency. + */ + if (vrefresh == 0) + return mode; + else if (mode->vrefresh == vrefresh) + return mode; + } + } + + return NULL; +} + static void KMSDRM_Destroy(SDL_VideoDevice * device) { @@ -350,12 +372,19 @@ KMSDRM_VideoInit(_THIS) SDL_bool found; int ret = 0; char *devname; + const char *crtc_override; + const char *mode_override; SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); drmModeRes *resources = NULL; drmModeConnector *connector = NULL; drmModeEncoder *encoder = NULL; SDL_DisplayMode current_mode; SDL_VideoDisplay display; + const char *mode_line_override; + char *hint_video_mode = NULL; + unsigned short hint_vrefresh=0; + char* p; + drmModeModeInfo *override_mode = NULL; /* Allocate display internal data */ SDL_DisplayData *data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData)); @@ -388,6 +417,9 @@ KMSDRM_VideoInit(_THIS) goto cleanup; } + /* Expose aspect ratio flags to userspace */ + KMSDRM_drmSetClientCap(vdata->drm_fd, DRM_CLIENT_CAP_ASPECT_RATIO, 1); + /* Find the first available connector with modes */ resources = KMSDRM_drmModeGetResources(vdata->drm_fd); if (!resources) { @@ -472,9 +504,48 @@ KMSDRM_VideoInit(_THIS) SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Saved crtc_id %u, fb_id %u, (%u,%u), %ux%u", vdata->saved_crtc->crtc_id, vdata->saved_crtc->buffer_id, vdata->saved_crtc->x, vdata->saved_crtc->y, vdata->saved_crtc->width, vdata->saved_crtc->height); - data->crtc_id = encoder->crtc_id; - data->cur_mode = vdata->saved_crtc->mode; - vdata->crtc_id = encoder->crtc_id; + + crtc_override = SDL_getenv("SDL_VIDEO_KMSDRM_CRTCID"); + if (crtc_override) + data->crtc_id = vdata->crtc_id = SDL_atoi(crtc_override); + else + data->crtc_id = vdata->crtc_id = encoder->crtc_id; + + mode_override = SDL_getenv("SDL_VIDEO_KMSDRM_MODEID"); + if (mode_override) + data->cur_mode = connector->modes[SDL_atoi(mode_override)]; + else + data->cur_mode = vdata->saved_crtc->mode; + + mode_line_override = SDL_getenv("SDL_VIDEO_KMSDRM_MODELINE"); + if (mode_line_override && !mode_override) { + /* Video mode override, formatted as WxH[@vRefresh] */ + SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO,"Override video mode received - %s", mode_line_override); + + p = strchr(mode_line_override, '@'); + if (p == NULL) { + hint_video_mode =strdup(mode_line_override); + } else { + hint_video_mode = strndup(mode_line_override, (unsigned int)(p - mode_line_override)); + hint_vrefresh = strtoul(p + 1, NULL, 10); + } + + override_mode = connector_find_mode(connector, hint_video_mode, hint_vrefresh); + if (override_mode) { + if ((*override_mode).hdisplay != data->cur_mode.hdisplay || + (*override_mode).vdisplay != data->cur_mode.vdisplay || + (*override_mode).vrefresh != data->cur_mode.vrefresh) { + SDL_LogInfo(SDL_LOG_CATEGORY_VIDEO, "Changing video mode to %dx%d @ %d",(*override_mode).hdisplay, (*override_mode).vdisplay, (*override_mode).vrefresh); + current_mode.w = (*override_mode).hdisplay; + current_mode.h = (*override_mode).vdisplay; + current_mode.refresh_rate = (*override_mode).vrefresh; + data->cur_mode = (*override_mode); + } + } else { + SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Cannot find a suitable video mode on connector %d for mode %s, using default", + connector->connector_id, mode_line_override); + } + } // select default mode if this one is not valid if (vdata->saved_crtc->mode_valid == 0) {