diff --git a/Engine/lib/sdl/CMakeLists.txt b/Engine/lib/sdl/CMakeLists.txt
index 59bacf0f5..644715aae 100644
--- a/Engine/lib/sdl/CMakeLists.txt
+++ b/Engine/lib/sdl/CMakeLists.txt
@@ -66,12 +66,12 @@ include(${SDL2_SOURCE_DIR}/cmake/sdlchecks.cmake)
# set SDL_BINARY_AGE and SDL_INTERFACE_AGE to 0.
set(SDL_MAJOR_VERSION 2)
set(SDL_MINOR_VERSION 0)
-set(SDL_MICRO_VERSION 21)
-set(SDL_INTERFACE_AGE 3)
-set(SDL_BINARY_AGE 21)
+set(SDL_MICRO_VERSION 22)
+set(SDL_INTERFACE_AGE 0)
+set(SDL_BINARY_AGE 22)
set(SDL_VERSION "${SDL_MAJOR_VERSION}.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}")
# the following should match the versions in Xcode project file:
-set(DYLIB_CURRENT_VERSION 19.3.0)
+set(DYLIB_CURRENT_VERSION 23.0.0)
set(DYLIB_COMPATIBILITY_VERSION 1.0.0)
# Set defaults preventing destination file conflicts
@@ -372,6 +372,7 @@ endforeach()
# Allow some projects to be built conditionally.
set_option(SDL2_DISABLE_SDL2MAIN "Disable building/installation of SDL2main" OFF)
+set_option(SDL2_DISABLE_INSTALL "Disable installation of SDL2" OFF)
set_option(SDL2_DISABLE_UNINSTALL "Disable uninstallation of SDL2" OFF)
option_string(SDL_ASSERTIONS "Enable internal sanity checks (auto/disabled/release/enabled/paranoid)" "auto")
@@ -1600,6 +1601,7 @@ elseif(WINDOWS)
# headers needed elsewhere
check_include_file(tpcshrd.h HAVE_TPCSHRD_H)
+ check_include_file(roapi.h HAVE_ROAPI_H)
check_include_file(mmdeviceapi.h HAVE_MMDEVICEAPI_H)
check_include_file(audioclient.h HAVE_AUDIOCLIENT_H)
check_include_file(sensorsapi.h HAVE_SENSORSAPI_H)
@@ -2279,6 +2281,11 @@ elseif(VITA)
${SDL2_SOURCE_DIR}/src/thread/generic/SDL_systls.c)
set(HAVE_SDL_THREADS TRUE)
endif()
+ if(SDL_LOCALE)
+ file(GLOB LOCALE_SOURCES ${SDL2_SOURCE_DIR}/src/locale/vita/*.c)
+ set(SOURCE_FILES ${SOURCE_FILES} ${LOCALE_SOURCES})
+ set(HAVE_SDL_LOCALE TRUE)
+ endif()
if(SDL_TIMERS)
set(SDL_TIMER_VITA 1)
file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/vita/*.c)
@@ -2305,10 +2312,10 @@ elseif(VITA)
list(APPEND EXTRA_LIBS
pib
)
- set(HAVE_VITA_PIB ON)
+ set(HAVE_VIDEO_VITA_PIB ON)
set(SDL_VIDEO_VITA_PIB 1)
else()
- set(HAVE_VITA_PIB OFF)
+ set(HAVE_VIDEO_VITA_PIB OFF)
endif()
endif()
@@ -2316,6 +2323,7 @@ elseif(VITA)
check_include_file(gpu_es4/psp2_pvr_hint.h HAVE_PVR_H)
if(HAVE_PVR_H)
target_compile_definitions(sdl-build-options INTERFACE "-D__psp2__")
+ check_include_file(gl4esinit.h HAVE_GL4ES_H)
set(SDL_VIDEO_OPENGL_EGL 1)
set(HAVE_OPENGLES TRUE)
set(SDL_VIDEO_OPENGL_ES 1)
@@ -2327,10 +2335,20 @@ elseif(VITA)
libgpu_es4_ext_stub_weak
libIMGEGL_stub_weak
)
- set(HAVE_VITA_PVR ON)
+
+ set(HAVE_VIDEO_VITA_PVR ON)
set(SDL_VIDEO_VITA_PVR 1)
+
+ if(HAVE_GL4ES_H)
+ set(HAVE_OPENGL TRUE)
+ set(SDL_VIDEO_OPENGL 1)
+ set(SDL_VIDEO_RENDER_OGL 1)
+ list(APPEND EXTRA_LIBS libGL_stub)
+ set(SDL_VIDEO_VITA_PVR_OGL 1)
+ endif()
+
else()
- set(HAVE_VITA_PVR OFF)
+ set(HAVE_VIDEO_VITA_PVR OFF)
endif()
endif()
@@ -2342,6 +2360,7 @@ elseif(VITA)
SceCtrl_stub
SceAppMgr_stub
SceAudio_stub
+ SceAudioIn_stub
SceSysmodule_stub
SceDisplay_stub
SceCtrl_stub
@@ -2950,122 +2969,125 @@ if(SDL_TEST)
endif()
##### Installation targets #####
-if(SDL_SHARED)
- install(TARGETS SDL2 EXPORT SDL2Targets
- LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
- ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
- RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
-endif()
-
-if(NOT WINDOWS_STORE AND NOT SDL2_DISABLE_SDL2MAIN)
- install(TARGETS SDL2main EXPORT SDL2mainTargets
- LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
- ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
- RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
-endif()
-
-if(SDL_STATIC)
- install(TARGETS SDL2-static EXPORT SDL2staticTargets
- LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
- ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
- RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
-endif()
-
-##### Export files #####
-if (WINDOWS AND NOT MINGW)
- set(PKG_PREFIX "cmake")
-else ()
- set(PKG_PREFIX "${CMAKE_INSTALL_LIBDIR}/cmake/SDL2")
-endif ()
-
-include(CMakePackageConfigHelpers)
-write_basic_package_version_file("${CMAKE_BINARY_DIR}/SDL2ConfigVersion.cmake"
- VERSION ${SDL_VERSION}
- COMPATIBILITY AnyNewerVersion
-)
-
-if(SDL_SHARED)
- install(EXPORT SDL2Targets
- FILE SDL2Targets.cmake
- NAMESPACE SDL2::
- DESTINATION ${PKG_PREFIX}
- )
-endif()
-
-if(NOT WINDOWS_STORE AND NOT SDL2_DISABLE_SDL2MAIN)
- install(EXPORT SDL2mainTargets
- FILE SDL2mainTargets.cmake
- NAMESPACE SDL2::
- DESTINATION ${PKG_PREFIX}
- )
-endif()
-
-if(SDL_STATIC)
- install(EXPORT SDL2staticTargets
- FILE SDL2staticTargets.cmake
- NAMESPACE SDL2::
- DESTINATION ${PKG_PREFIX}
- )
-endif()
-
-install(
- FILES
- ${CMAKE_CURRENT_SOURCE_DIR}/SDL2Config.cmake
- ${CMAKE_BINARY_DIR}/SDL2ConfigVersion.cmake
- DESTINATION ${PKG_PREFIX}
- COMPONENT Devel
-)
-
-file(GLOB INCLUDE_FILES ${SDL2_SOURCE_DIR}/include/*.h)
-file(GLOB BIN_INCLUDE_FILES ${SDL2_BINARY_DIR}/include/*.h)
-foreach(_FNAME ${BIN_INCLUDE_FILES})
- get_filename_component(_INCNAME ${_FNAME} NAME)
- list(REMOVE_ITEM INCLUDE_FILES ${SDL2_SOURCE_DIR}/include/${_INCNAME})
-endforeach()
-list(APPEND INCLUDE_FILES ${BIN_INCLUDE_FILES})
-install(FILES ${INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/SDL2)
-
-string(TOUPPER "${CMAKE_BUILD_TYPE}" UPPER_BUILD_TYPE)
-if (UPPER_BUILD_TYPE MATCHES DEBUG)
- set(SOPOSTFIX "${SDL_CMAKE_DEBUG_POSTFIX}")
-else()
- set(SOPOSTFIX "")
-endif()
-
-if(NOT (WINDOWS OR CYGWIN) OR MINGW)
+if(NOT SDL2_DISABLE_INSTALL)
if(SDL_SHARED)
- set(SOEXT ${CMAKE_SHARED_LIBRARY_SUFFIX}) # ".so", ".dylib", etc.
- get_target_property(SONAME SDL2 OUTPUT_NAME)
- if(NOT ANDROID AND NOT MINGW AND NOT OS2)
- install(CODE "
- execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
- \"lib${SONAME}${SOPOSTFIX}${SOEXT}\" \"libSDL2${SOPOSTFIX}${SOEXT}\"
- WORKING_DIRECTORY \"${SDL2_BINARY_DIR}\")")
- install(FILES ${SDL2_BINARY_DIR}/libSDL2${SOPOSTFIX}${SOEXT} DESTINATION "${CMAKE_INSTALL_LIBDIR}")
- endif()
+ install(TARGETS SDL2 EXPORT SDL2Targets
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
endif()
- if(FREEBSD)
- # FreeBSD uses ${PREFIX}/libdata/pkgconfig
- install(FILES ${SDL2_BINARY_DIR}/sdl2.pc DESTINATION "libdata/pkgconfig")
+
+ if(NOT WINDOWS_STORE AND NOT SDL2_DISABLE_SDL2MAIN)
+ install(TARGETS SDL2main EXPORT SDL2mainTargets
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
+ endif()
+
+ if(SDL_STATIC)
+ install(TARGETS SDL2-static EXPORT SDL2staticTargets
+ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
+ RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
+ endif()
+
+ ##### Export files #####
+ if (WINDOWS AND NOT MINGW)
+ set(PKG_PREFIX "cmake")
+ else ()
+ set(PKG_PREFIX "${CMAKE_INSTALL_LIBDIR}/cmake/SDL2")
+ endif ()
+
+ include(CMakePackageConfigHelpers)
+ write_basic_package_version_file("${CMAKE_BINARY_DIR}/SDL2ConfigVersion.cmake"
+ VERSION ${SDL_VERSION}
+ COMPATIBILITY AnyNewerVersion
+ )
+
+ if(SDL_SHARED)
+ install(EXPORT SDL2Targets
+ FILE SDL2Targets.cmake
+ NAMESPACE SDL2::
+ DESTINATION ${PKG_PREFIX}
+ )
+ endif()
+
+ if(NOT WINDOWS_STORE AND NOT SDL2_DISABLE_SDL2MAIN)
+ install(EXPORT SDL2mainTargets
+ FILE SDL2mainTargets.cmake
+ NAMESPACE SDL2::
+ DESTINATION ${PKG_PREFIX}
+ )
+ endif()
+
+ if(SDL_STATIC)
+ install(EXPORT SDL2staticTargets
+ FILE SDL2staticTargets.cmake
+ NAMESPACE SDL2::
+ DESTINATION ${PKG_PREFIX}
+ )
+ endif()
+
+ install(
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/SDL2Config.cmake
+ ${CMAKE_BINARY_DIR}/SDL2ConfigVersion.cmake
+ DESTINATION ${PKG_PREFIX}
+ COMPONENT Devel
+ )
+
+ file(GLOB INCLUDE_FILES ${SDL2_SOURCE_DIR}/include/*.h)
+ file(GLOB BIN_INCLUDE_FILES ${SDL2_BINARY_DIR}/include/*.h)
+ foreach(_FNAME ${BIN_INCLUDE_FILES})
+ get_filename_component(_INCNAME ${_FNAME} NAME)
+ list(REMOVE_ITEM INCLUDE_FILES ${SDL2_SOURCE_DIR}/include/${_INCNAME})
+ endforeach()
+ list(APPEND INCLUDE_FILES ${BIN_INCLUDE_FILES})
+ install(FILES ${INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/SDL2)
+
+ string(TOUPPER "${CMAKE_BUILD_TYPE}" UPPER_BUILD_TYPE)
+ if (UPPER_BUILD_TYPE MATCHES DEBUG)
+ set(SOPOSTFIX "${SDL_CMAKE_DEBUG_POSTFIX}")
else()
- install(FILES ${SDL2_BINARY_DIR}/sdl2.pc
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+ set(SOPOSTFIX "")
+ endif()
+
+ if(NOT (WINDOWS OR CYGWIN) OR MINGW)
+ if(SDL_SHARED)
+ set(SOEXT ${CMAKE_SHARED_LIBRARY_SUFFIX}) # ".so", ".dylib", etc.
+ get_target_property(SONAME SDL2 OUTPUT_NAME)
+ if(NOT ANDROID AND NOT MINGW AND NOT OS2)
+ install(CODE "
+ execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
+ \"lib${SONAME}${SOPOSTFIX}${SOEXT}\" \"libSDL2${SOPOSTFIX}${SOEXT}\"
+ WORKING_DIRECTORY \"${SDL2_BINARY_DIR}\")")
+ install(FILES ${SDL2_BINARY_DIR}/libSDL2${SOPOSTFIX}${SOEXT} DESTINATION "${CMAKE_INSTALL_LIBDIR}")
+ endif()
+ endif()
+ if(FREEBSD)
+ # FreeBSD uses ${PREFIX}/libdata/pkgconfig
+ install(FILES ${SDL2_BINARY_DIR}/sdl2.pc DESTINATION "libdata/pkgconfig")
+ else()
+ install(FILES ${SDL2_BINARY_DIR}/sdl2.pc
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+ endif()
+ install(PROGRAMS ${SDL2_BINARY_DIR}/sdl2-config DESTINATION "${CMAKE_INSTALL_BINDIR}")
+ # TODO: what about the .spec file? Is it only needed for RPM creation?
+ install(FILES "${SDL2_SOURCE_DIR}/sdl2.m4" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/aclocal")
endif()
- install(PROGRAMS ${SDL2_BINARY_DIR}/sdl2-config DESTINATION "${CMAKE_INSTALL_BINDIR}")
- # TODO: what about the .spec file? Is it only needed for RPM creation?
- install(FILES "${SDL2_SOURCE_DIR}/sdl2.m4" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/aclocal")
endif()
##### Uninstall target #####
if(NOT SDL2_DISABLE_UNINSTALL)
-if(NOT TARGET uninstall)
- configure_file(
- "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
- "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
- IMMEDIATE @ONLY)
+ if(NOT TARGET uninstall)
+ configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+ IMMEDIATE @ONLY)
- add_custom_target(uninstall
- COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
+ add_custom_target(uninstall
+ COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
+ endif()
endif()
-endif(NOT SDL2_DISABLE_UNINSTALL)
+
diff --git a/Engine/lib/sdl/Makefile.in b/Engine/lib/sdl/Makefile.in
index 81c56fd3a..69f5cb1e2 100644
--- a/Engine/lib/sdl/Makefile.in
+++ b/Engine/lib/sdl/Makefile.in
@@ -19,6 +19,7 @@ distfile = $(distdir).tar.gz
@SET_MAKE@
SHELL = @SHELL@
CC = @CC@
+CXX = @CXX@
INCLUDE = @INCLUDE@
CFLAGS = @BUILD_CFLAGS@
EXTRA_CFLAGS = @EXTRA_CFLAGS@
diff --git a/Engine/lib/sdl/Makefile.os2 b/Engine/lib/sdl/Makefile.os2
index eb34494c5..cfd0d6562 100644
--- a/Engine/lib/sdl/Makefile.os2
+++ b/Engine/lib/sdl/Makefile.os2
@@ -11,7 +11,7 @@
# wmake -f Makefile.os2 HIDAPI=1
LIBNAME = SDL2
-VERSION = 2.0.21
+VERSION = 2.0.22
DESCRIPTION = Simple DirectMedia Layer 2
LIBICONV=0
@@ -60,7 +60,7 @@ CFLAGS_DLL+= -DHAVE_LIBUSB_H=1
# building SDL itself (for DECLSPEC):
CFLAGS_DLL+= -DBUILD_SDL
-SRCS = SDL.c SDL_assert.c SDL_error.c SDL_log.c SDL_dataqueue.c SDL_hints.c
+SRCS = SDL.c SDL_assert.c SDL_error.c SDL_log.c SDL_dataqueue.c SDL_hints.c SDL_list.c
SRCS+= SDL_getenv.c SDL_iconv.c SDL_malloc.c SDL_qsort.c SDL_stdlib.c SDL_string.c SDL_strtokr.c SDL_crc32.c
SRCS+= SDL_cpuinfo.c SDL_atomic.c SDL_spinlock.c SDL_thread.c SDL_timer.c
SRCS+= SDL_rwops.c SDL_power.c
@@ -140,9 +140,11 @@ SDL_blendpoint.obj: SDL_blendpoint.c
wcc386 $(CFLAGS_DLL) -wcd=200 -fo=$^@ $<
SDL_RLEaccel.obj: SDL_RLEaccel.c
wcc386 $(CFLAGS_DLL) -wcd=201 -fo=$^@ $<
+!ifeq HIDAPI 1
# c99 mode needed because of structs with flexible array members in libusb.h
SDL_hidapi.obj: SDL_hidapi.c
wcc386 $(CFLAGS_DLL) -za99 -fo=$^@ $<
+!endif
$(LIBICONV_LIB): "src/core/os2/iconv2.lbc"
@echo * Creating: $@
diff --git a/Engine/lib/sdl/WhatsNew.txt b/Engine/lib/sdl/WhatsNew.txt
index 33382ecea..fa6cbe11a 100644
--- a/Engine/lib/sdl/WhatsNew.txt
+++ b/Engine/lib/sdl/WhatsNew.txt
@@ -6,8 +6,38 @@ This is a list of major changes in SDL's version history.
---------------------------------------------------------------------------
General:
+* Added SDL_RenderGetWindow() to get the window associated with a renderer
+* Added floating point rectangle functions:
+ * SDL_PointInFRect()
+ * SDL_FRectEmpty()
+ * SDL_FRectEquals()
+ * SDL_FRectEqualsEpsilon()
+ * SDL_HasIntersectionF()
+ * SDL_IntersectFRect()
+ * SDL_UnionFRect()
+ * SDL_EncloseFPoints()
+ * SDL_IntersectFRectAndLine()
+* Added SDL_IsTextInputShown() which returns whether the IME window is currently shown
+* Added SDL_ClearComposition() to dismiss the composition window without disabling IME input
+* Added SDL_TEXTEDITING_EXT event for handling long composition text, and a hint SDL_HINT_IME_SUPPORT_EXTENDED_TEXT to enable it
+* Added the hint SDL_HINT_MOUSE_RELATIVE_MODE_CENTER to control whether the mouse should be constrained to the whole window or the center of the window when relative mode is enabled
+* The mouse is now automatically captured when mouse buttons are pressed, and the hint SDL_HINT_MOUSE_AUTO_CAPTURE allows you to control this behavior
+* Added the hint SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL to let SDL know that a foreign window will be used with OpenGL
+* Added the hint SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN to let SDL know that a foreign window will be used with Vulkan
+* Added the hint SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE to specify whether an SDL_QUIT event will be delivered when the last application window is closed
* Added the hint SDL_HINT_JOYSTICK_ROG_CHAKRAM to control whether ROG Chakram mice show up as joysticks
+Windows:
+* Added support for SDL_BLENDOPERATION_MINIMUM and SDL_BLENDOPERATION_MAXIMUM to the D3D9 renderer
+
+Linux:
+* Compiling with Wayland support requires libwayland-client version 1.18.0 or later
+* Added the hint SDL_HINT_X11_WINDOW_TYPE to specify the _NET_WM_WINDOW_TYPE of SDL windows
+* Added the hint SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR to allow using libdecor with compositors that support xdg-decoration
+
+Android:
+* Added SDL_AndroidSendMessage() to send a custom command to the SDL java activity
+
---------------------------------------------------------------------------
2.0.20:
diff --git a/Engine/lib/sdl/Xcode/SDL/Info-Framework.plist b/Engine/lib/sdl/Xcode/SDL/Info-Framework.plist
index 19049bd46..49a711322 100644
--- a/Engine/lib/sdl/Xcode/SDL/Info-Framework.plist
+++ b/Engine/lib/sdl/Xcode/SDL/Info-Framework.plist
@@ -19,10 +19,10 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 2.0.21
+ 2.0.22
CFBundleSignature
SDLX
CFBundleVersion
- 2.0.21
+ 2.0.22
diff --git a/Engine/lib/sdl/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Engine/lib/sdl/Xcode/SDL/SDL.xcodeproj/project.pbxproj
index cd8affb60..8858cfdd9 100644
--- a/Engine/lib/sdl/Xcode/SDL/SDL.xcodeproj/project.pbxproj
+++ b/Engine/lib/sdl/Xcode/SDL/SDL.xcodeproj/project.pbxproj
@@ -111,6 +111,24 @@
A1626A582617008D003F1973 /* SDL_triangle.h in Headers */ = {isa = PBXBuildFile; fileRef = A1626A512617008C003F1973 /* SDL_triangle.h */; };
A1626A592617008D003F1973 /* SDL_triangle.h in Headers */ = {isa = PBXBuildFile; fileRef = A1626A512617008C003F1973 /* SDL_triangle.h */; };
A1626A5A2617008D003F1973 /* SDL_triangle.h in Headers */ = {isa = PBXBuildFile; fileRef = A1626A512617008C003F1973 /* SDL_triangle.h */; };
+ A1BB8B6327F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
+ A1BB8B6427F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
+ A1BB8B6527F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
+ A1BB8B6627F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
+ A1BB8B6727F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
+ A1BB8B6827F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
+ A1BB8B6927F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
+ A1BB8B6A27F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
+ A1BB8B6B27F6CF330057CFA8 /* SDL_list.c in Sources */ = {isa = PBXBuildFile; fileRef = A1BB8B6127F6CF320057CFA8 /* SDL_list.c */; };
+ A1BB8B6C27F6CF330057CFA8 /* SDL_list.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB8B6227F6CF330057CFA8 /* SDL_list.h */; };
+ A1BB8B6D27F6CF330057CFA8 /* SDL_list.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB8B6227F6CF330057CFA8 /* SDL_list.h */; };
+ A1BB8B6E27F6CF330057CFA8 /* SDL_list.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB8B6227F6CF330057CFA8 /* SDL_list.h */; };
+ A1BB8B6F27F6CF330057CFA8 /* SDL_list.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB8B6227F6CF330057CFA8 /* SDL_list.h */; };
+ A1BB8B7027F6CF330057CFA8 /* SDL_list.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB8B6227F6CF330057CFA8 /* SDL_list.h */; };
+ A1BB8B7127F6CF330057CFA8 /* SDL_list.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB8B6227F6CF330057CFA8 /* SDL_list.h */; };
+ A1BB8B7227F6CF330057CFA8 /* SDL_list.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB8B6227F6CF330057CFA8 /* SDL_list.h */; };
+ A1BB8B7327F6CF330057CFA8 /* SDL_list.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB8B6227F6CF330057CFA8 /* SDL_list.h */; };
+ A1BB8B7427F6CF330057CFA8 /* SDL_list.h in Headers */ = {isa = PBXBuildFile; fileRef = A1BB8B6227F6CF330057CFA8 /* SDL_list.h */; };
A7381E961D8B69D600B177DD /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E951D8B69D600B177DD /* CoreAudio.framework */; };
A7381E971D8B6A0300B177DD /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E931D8B69C300B177DD /* AudioToolbox.framework */; };
A75FCCFD23E25AB700529352 /* SDL_shaders_metal_tvos.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A8E323E2514000DCD162 /* SDL_shaders_metal_tvos.h */; };
@@ -3574,6 +3592,8 @@
75E09159241EA924004729E1 /* SDL_virtualjoystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_virtualjoystick_c.h; sourceTree = ""; };
A1626A3D2617006A003F1973 /* SDL_triangle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_triangle.c; sourceTree = ""; };
A1626A512617008C003F1973 /* SDL_triangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_triangle.h; sourceTree = ""; };
+ A1BB8B6127F6CF320057CFA8 /* SDL_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_list.c; sourceTree = ""; };
+ A1BB8B6227F6CF330057CFA8 /* SDL_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_list.h; sourceTree = ""; };
A7381E931D8B69C300B177DD /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
A7381E951D8B69D600B177DD /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
A75FCEB323E25AB700529352 /* libSDL2.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libSDL2.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -4304,6 +4324,8 @@
A7D8A5AB23E2513D00DCD162 /* SDL_hints.c */,
A7D8A58323E2513D00DCD162 /* SDL_internal.h */,
A7D8A5DD23E2513D00DCD162 /* SDL_log.c */,
+ A1BB8B6127F6CF320057CFA8 /* SDL_list.c */,
+ A1BB8B6227F6CF330057CFA8 /* SDL_list.h */,
A7D8A57123E2513D00DCD162 /* SDL.c */,
);
name = "Library Source";
@@ -5284,6 +5306,7 @@
A75FCD4523E25AB700529352 /* SDL_gesture_c.h in Headers */,
A75FCD4623E25AB700529352 /* SDL_shaders_gl.h in Headers */,
A75FCD4723E25AB700529352 /* SDL_systhread_c.h in Headers */,
+ A1BB8B7327F6CF330057CFA8 /* SDL_list.h in Headers */,
A75FCD4823E25AB700529352 /* SDL_keycode.h in Headers */,
5616CA63252BB35F005D5928 /* SDL_sysurl.h in Headers */,
A75FCD4A23E25AB700529352 /* SDL_cocoakeyboard.h in Headers */,
@@ -5509,6 +5532,7 @@
A75FCEFE23E25AC700529352 /* SDL_gesture_c.h in Headers */,
A75FCEFF23E25AC700529352 /* SDL_shaders_gl.h in Headers */,
A75FCF0023E25AC700529352 /* SDL_systhread_c.h in Headers */,
+ A1BB8B7427F6CF330057CFA8 /* SDL_list.h in Headers */,
A75FCF0123E25AC700529352 /* SDL_keycode.h in Headers */,
5616CA66252BB361005D5928 /* SDL_sysurl.h in Headers */,
A75FCF0323E25AC700529352 /* SDL_cocoakeyboard.h in Headers */,
@@ -5707,6 +5731,7 @@
A769B0C623E259AE00872273 /* SDL_windowevents_c.h in Headers */,
A769B0C823E259AE00872273 /* SDL_cocoavideo.h in Headers */,
5605721C2473688D00B46B66 /* SDL_syslocale.h in Headers */,
+ A1BB8B7127F6CF330057CFA8 /* SDL_list.h in Headers */,
A769B0CA23E259AE00872273 /* SDL_uikitevents.h in Headers */,
A769B0CB23E259AE00872273 /* SDL_gesture_c.h in Headers */,
A769B0CC23E259AE00872273 /* SDL_shaders_gl.h in Headers */,
@@ -5955,6 +5980,7 @@
A7D8A98E23E2514000DCD162 /* SDL_sensor_c.h in Headers */,
A7D8BA7423E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
A7D8BA5023E2514400DCD162 /* SDL_shaders_gles2.h in Headers */,
+ A1BB8B6D27F6CF330057CFA8 /* SDL_list.h in Headers */,
A7D8B98D23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */,
A7D8B99C23E2514400DCD162 /* SDL_shaders_metal_osx.h in Headers */,
A7D8B9A223E2514400DCD162 /* SDL_shaders_metal_tvos.h in Headers */,
@@ -6185,6 +6211,7 @@
A7D8A98F23E2514000DCD162 /* SDL_sensor_c.h in Headers */,
A7D8BA7523E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
A7D8BA5123E2514400DCD162 /* SDL_shaders_gles2.h in Headers */,
+ A1BB8B6E27F6CF330057CFA8 /* SDL_list.h in Headers */,
A7D8B98E23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */,
A7D8B99D23E2514400DCD162 /* SDL_shaders_metal_osx.h in Headers */,
A7D8B9A323E2514400DCD162 /* SDL_shaders_metal_tvos.h in Headers */,
@@ -6332,6 +6359,7 @@
A7D8BBAF23E2514500DCD162 /* SDL_windowevents_c.h in Headers */,
A7D8AF0423E2514100DCD162 /* SDL_cocoavideo.h in Headers */,
5605721A2473688C00B46B66 /* SDL_syslocale.h in Headers */,
+ A1BB8B7027F6CF330057CFA8 /* SDL_list.h in Headers */,
A7D8ACC123E2514100DCD162 /* SDL_uikitevents.h in Headers */,
A7D8BB3D23E2514500DCD162 /* SDL_gesture_c.h in Headers */,
A7D8BA7723E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
@@ -6580,6 +6608,7 @@
A7D8A98D23E2514000DCD162 /* SDL_sensor_c.h in Headers */,
A7D8BA7323E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
A7D8BA4F23E2514400DCD162 /* SDL_shaders_gles2.h in Headers */,
+ A1BB8B6C27F6CF330057CFA8 /* SDL_list.h in Headers */,
A7D8B98C23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */,
A7D8B99B23E2514400DCD162 /* SDL_shaders_metal_osx.h in Headers */,
A7D8B9A123E2514400DCD162 /* SDL_shaders_metal_tvos.h in Headers */,
@@ -6796,6 +6825,7 @@
A7D8B29F23E2514200DCD162 /* vulkan_xlib.h in Headers */,
A7D8B25D23E2514200DCD162 /* vulkan_vi.h in Headers */,
A7D8B29923E2514200DCD162 /* vulkan_mir.h in Headers */,
+ A1BB8B6F27F6CF330057CFA8 /* SDL_list.h in Headers */,
A7D8BB4E23E2514500DCD162 /* default_cursor.h in Headers */,
A7D8B9FE23E2514400DCD162 /* SDL_render_sw_c.h in Headers */,
A7D8BBED23E2574800DCD162 /* SDL_uikitappdelegate.h in Headers */,
@@ -6918,6 +6948,7 @@
A7D8BB3E23E2514500DCD162 /* SDL_gesture_c.h in Headers */,
A7D8BA7823E2514400DCD162 /* SDL_shaders_gl.h in Headers */,
A7D8B42D23E2514300DCD162 /* SDL_systhread_c.h in Headers */,
+ A1BB8B7227F6CF330057CFA8 /* SDL_list.h in Headers */,
DB313FDB17554B71006C0E22 /* SDL_keycode.h in Headers */,
A7D8AE9323E2514100DCD162 /* SDL_cocoakeyboard.h in Headers */,
A7D8ACE623E2514100DCD162 /* SDL_uikitvulkan.h in Headers */,
@@ -7554,6 +7585,7 @@
A75FCE8423E25AB700529352 /* e_exp.c in Sources */,
A75FCE8523E25AB700529352 /* SDL_quit.c in Sources */,
A75FCE8623E25AB700529352 /* SDL_cocoawindow.m in Sources */,
+ A1BB8B6A27F6CF330057CFA8 /* SDL_list.c in Sources */,
A75FCE8723E25AB700529352 /* SDL_sysmutex.c in Sources */,
A75FCE8823E25AB700529352 /* SDL_syshaptic.c in Sources */,
F3F07D61269640160074468B /* SDL_hidapi_luna.c in Sources */,
@@ -7741,6 +7773,7 @@
A75FD03D23E25AC700529352 /* e_exp.c in Sources */,
A75FD03E23E25AC700529352 /* SDL_quit.c in Sources */,
A75FD03F23E25AC700529352 /* SDL_cocoawindow.m in Sources */,
+ A1BB8B6B27F6CF330057CFA8 /* SDL_list.c in Sources */,
A75FD04023E25AC700529352 /* SDL_sysmutex.c in Sources */,
A75FD04123E25AC700529352 /* SDL_syshaptic.c in Sources */,
F3F07D62269640160074468B /* SDL_hidapi_luna.c in Sources */,
@@ -7927,6 +7960,7 @@
A769B20F23E259AE00872273 /* SDL_syshaptic.c in Sources */,
A769B21023E259AE00872273 /* e_exp.c in Sources */,
F395C1A12569C68F00942BFF /* SDL_iokitjoystick.c in Sources */,
+ A1BB8B6827F6CF330057CFA8 /* SDL_list.c in Sources */,
A769B21123E259AE00872273 /* SDL_quit.c in Sources */,
A769B21223E259AE00872273 /* SDL_cocoawindow.m in Sources */,
A769B21323E259AE00872273 /* SDL_sysmutex.c in Sources */,
@@ -8116,6 +8150,7 @@
A7D8B43B23E2514300DCD162 /* SDL_sysmutex.c in Sources */,
A7D8AAB123E2514100DCD162 /* SDL_syshaptic.c in Sources */,
A7D8B5CA23E2514300DCD162 /* SDL_rwopsbundlesupport.m in Sources */,
+ A1BB8B6427F6CF330057CFA8 /* SDL_list.c in Sources */,
A7D8AC1023E2514100DCD162 /* SDL_video.c in Sources */,
560572062473687700B46B66 /* SDL_syslocale.m in Sources */,
F3F07D5B269640160074468B /* SDL_hidapi_luna.c in Sources */,
@@ -8303,6 +8338,7 @@
A7D8B43C23E2514300DCD162 /* SDL_sysmutex.c in Sources */,
A7D8AAB223E2514100DCD162 /* SDL_syshaptic.c in Sources */,
A7D8B5CB23E2514300DCD162 /* SDL_rwopsbundlesupport.m in Sources */,
+ A1BB8B6527F6CF330057CFA8 /* SDL_list.c in Sources */,
A7D8AC1123E2514100DCD162 /* SDL_video.c in Sources */,
560572072473687800B46B66 /* SDL_syslocale.m in Sources */,
F3F07D5C269640160074468B /* SDL_hidapi_luna.c in Sources */,
@@ -8489,6 +8525,7 @@
A7D8AADE23E2514100DCD162 /* SDL_syshaptic.c in Sources */,
A7D8BAE923E2514500DCD162 /* e_exp.c in Sources */,
F395C1A02569C68F00942BFF /* SDL_iokitjoystick.c in Sources */,
+ A1BB8B6727F6CF330057CFA8 /* SDL_list.c in Sources */,
A7D8BB8523E2514500DCD162 /* SDL_quit.c in Sources */,
A7D8AEAA23E2514100DCD162 /* SDL_cocoawindow.m in Sources */,
A7D8B43E23E2514300DCD162 /* SDL_sysmutex.c in Sources */,
@@ -8665,6 +8702,7 @@
A7D8B55123E2514300DCD162 /* SDL_hidapi_switch.c in Sources */,
A7D8B96223E2514400DCD162 /* SDL_strtokr.c in Sources */,
A7D8BB7523E2514500DCD162 /* SDL_clipboardevents.c in Sources */,
+ A1BB8B6327F6CF330057CFA8 /* SDL_list.c in Sources */,
A7D8BAB523E2514400DCD162 /* k_cos.c in Sources */,
A7D8B54523E2514300DCD162 /* SDL_hidapijoystick.c in Sources */,
A7D8B97423E2514400DCD162 /* SDL_malloc.c in Sources */,
@@ -8850,6 +8888,7 @@
A7D8B96523E2514400DCD162 /* SDL_strtokr.c in Sources */,
A7D8BB7823E2514500DCD162 /* SDL_clipboardevents.c in Sources */,
A7D8BAB823E2514400DCD162 /* k_cos.c in Sources */,
+ A1BB8B6627F6CF330057CFA8 /* SDL_list.c in Sources */,
A7D8B54823E2514300DCD162 /* SDL_hidapijoystick.c in Sources */,
A7D8B97723E2514400DCD162 /* SDL_malloc.c in Sources */,
A7D8BBF023E2574800DCD162 /* SDL_uikitclipboard.m in Sources */,
@@ -9035,6 +9074,7 @@
A7D8B96723E2514400DCD162 /* SDL_strtokr.c in Sources */,
A7D8BB7A23E2514500DCD162 /* SDL_clipboardevents.c in Sources */,
A7D8BABA23E2514400DCD162 /* k_cos.c in Sources */,
+ A1BB8B6927F6CF330057CFA8 /* SDL_list.c in Sources */,
A7D8B54A23E2514300DCD162 /* SDL_hidapijoystick.c in Sources */,
A7D8B97923E2514400DCD162 /* SDL_malloc.c in Sources */,
A7D8B8CB23E2514400DCD162 /* SDL_audio.c in Sources */,
@@ -9111,7 +9151,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEPLOYMENT_POSTPROCESSING = YES;
DYLIB_COMPATIBILITY_VERSION = 1.0.0;
- DYLIB_CURRENT_VERSION = 19.3.0;
+ DYLIB_CURRENT_VERSION = 23.0.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_ALTIVEC_EXTENSIONS = YES;
@@ -9195,7 +9235,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 1.0.0;
- DYLIB_CURRENT_VERSION = 19.3.0;
+ DYLIB_CURRENT_VERSION = 23.0.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -9387,6 +9427,7 @@
buildSettings = {
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_LINK_OBJC_RUNTIME = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = GLES_SILENCE_DEPRECATION;
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
@@ -9398,6 +9439,7 @@
buildSettings = {
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_LINK_OBJC_RUNTIME = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = GLES_SILENCE_DEPRECATION;
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
diff --git a/Engine/lib/sdl/build-scripts/os2-buildbot.sh b/Engine/lib/sdl/build-scripts/os2-buildbot.sh
deleted file mode 100644
index abe0350d0..000000000
--- a/Engine/lib/sdl/build-scripts/os2-buildbot.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-
-# This is the script buildbot.libsdl.org uses to cross-compile SDL2 from
-# x86 Linux to OS/2, using OpenWatcom.
-
-# The final zipfile can be unpacked on any machine that supports OpenWatcom
-# (Windows, Linux, OS/2, etc). Point the compiler at the include directory
-# and link against the SDL2.lib file. Ship the SDL2.dll with your app.
-
-if [ -z "$WATCOM" ]; then
- echo "This script expects \$WATCOM to be set to the OpenWatcom install dir." 1>&2
- echo "This is often something like '/usr/local/share/watcom'" 1>&2
- exit 1
-fi
-export PATH="$WATCOM/binl64:$PATH"
-
-ZIPFILE="$1"
-if [ -z $1 ]; then
- ZIPFILE=sdl-os2.zip
-fi
-ZIPDIR=buildbot/SDL
-
-set -e
-set -x
-
-cd `dirname "$0"`
-cd ..
-
-rm -f $ZIPFILE
-wmake -f Makefile.os2
-rm -rf $ZIPDIR
-mkdir -p $ZIPDIR
-chmod 644 SDL2.dll SDL2.lib SDL2test.lib
-mv SDL2.dll SDL2.lib SDL2test.lib $ZIPDIR/
-cp -R include $ZIPDIR/
-zip -9r "buildbot/$ZIPFILE" $ZIPDIR
-
-wmake -f Makefile.os2 distclean
-
-set +x
-echo "All done. Final installable is in $ZIPFILE ...";
diff --git a/Engine/lib/sdl/build-scripts/winrtbuild.ps1 b/Engine/lib/sdl/build-scripts/winrtbuild.ps1
index 1da76abb1..892658014 100644
--- a/Engine/lib/sdl/build-scripts/winrtbuild.ps1
+++ b/Engine/lib/sdl/build-scripts/winrtbuild.ps1
@@ -39,7 +39,7 @@
#
# Base version of SDL, used for packaging purposes
-$SDLVersion = "2.0.21"
+$SDLVersion = "2.0.22"
# Gets the .bat file that sets up an MSBuild environment, given one of
# Visual Studio's, "PlatformToolset"s.
diff --git a/Engine/lib/sdl/cmake/sdlchecks.cmake b/Engine/lib/sdl/cmake/sdlchecks.cmake
index c9feffb69..8dcb39265 100644
--- a/Engine/lib/sdl/cmake/sdlchecks.cmake
+++ b/Engine/lib/sdl/cmake/sdlchecks.cmake
@@ -632,7 +632,7 @@ endmacro()
# - HAVE_SDL_LOADSO opt
macro(CheckWayland)
if(SDL_WAYLAND)
- pkg_check_modules(WAYLAND wayland-client wayland-egl wayland-cursor egl "xkbcommon>=0.5.0")
+ pkg_check_modules(WAYLAND "wayland-client>=1.18" wayland-egl wayland-cursor egl "xkbcommon>=0.5.0")
if(WAYLAND_FOUND)
find_program(WAYLAND_SCANNER NAMES wayland-scanner REQUIRED)
@@ -792,7 +792,9 @@ macro(CheckVivante)
set(SDL_VIDEO_DRIVER_VIVANTE 1)
if(HAVE_VIVANTE_VDK)
set(SDL_VIDEO_DRIVER_VIVANTE_VDK 1)
- list(APPEND EXTRA_LIBS VDK VIVANTE)
+ find_library(VIVANTE_LIBRARY REQUIRED NAMES VIVANTE vivante drm_vivante)
+ find_library(VIVANTE_VDK_LIBRARY VDK REQUIRED)
+ list(APPEND EXTRA_LIBS ${VIVANTE_LIBRARY} ${VIVANTE_VDK_LIBRARY})
else()
set(SDL_CFLAGS "${SDL_CFLAGS} -DLINUX -DEGL_API_FB")
list(APPEND EXTRA_LIBS EGL)
diff --git a/Engine/lib/sdl/configure b/Engine/lib/sdl/configure
index df73ab0cb..f3ea813eb 100755
--- a/Engine/lib/sdl/configure
+++ b/Engine/lib/sdl/configure
@@ -673,6 +673,8 @@ X_CFLAGS
XMKMF
RPI_LIBS
RPI_CFLAGS
+DECOR_LIBS
+DECOR_CFLAGS
FUSIONSOUND_LIBS
FUSIONSOUND_CFLAGS
ARTSCONFIG
@@ -944,6 +946,8 @@ PULSEAUDIO_CFLAGS
PULSEAUDIO_LIBS
FUSIONSOUND_CFLAGS
FUSIONSOUND_LIBS
+DECOR_CFLAGS
+DECOR_LIBS
RPI_CFLAGS
RPI_LIBS
XMKMF
@@ -1779,6 +1783,9 @@ Some influential environment variables:
C compiler flags for FUSIONSOUND, overriding pkg-config
FUSIONSOUND_LIBS
linker flags for FUSIONSOUND, overriding pkg-config
+ DECOR_CFLAGS
+ C compiler flags for DECOR, overriding pkg-config
+ DECOR_LIBS linker flags for DECOR, overriding pkg-config
RPI_CFLAGS C compiler flags for RPI, overriding pkg-config
RPI_LIBS linker flags for RPI, overriding pkg-config
XMKMF Path to xmkmf, Makefile generator for X Window System
@@ -2859,9 +2866,9 @@ orig_CFLAGS="$CFLAGS"
#
SDL_MAJOR_VERSION=2
SDL_MINOR_VERSION=0
-SDL_MICRO_VERSION=21
-SDL_INTERFACE_AGE=3
-SDL_BINARY_AGE=21
+SDL_MICRO_VERSION=22
+SDL_INTERFACE_AGE=0
+SDL_BINARY_AGE=22
SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
@@ -20572,7 +20579,7 @@ $as_echo_n "checking for Wayland support... " >&6; }
video_wayland=no
if test x$video_opengl_egl = xyes && \
test x$video_opengles_v2 = xyes; then
- if $PKG_CONFIG --exists wayland-client wayland-scanner wayland-egl wayland-cursor egl 'xkbcommon >= 0.5.0'; then
+ if $PKG_CONFIG --exists 'wayland-client >= 1.18' wayland-scanner wayland-egl wayland-cursor egl 'xkbcommon >= 0.5.0'; then
WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon`
WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor xkbcommon`
WAYLAND_SCANNER=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`
@@ -20676,17 +20683,79 @@ else
fi
if test x$enable_libdecor = xyes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libdecor support" >&5
-$as_echo_n "checking for libdecor support... " >&6; }
- if $PKG_CONFIG --exists libdecor-0; then :
- video_libdecor=yes
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libdecor-0" >&5
+$as_echo_n "checking for libdecor-0... " >&6; }
+
+if test -n "$DECOR_CFLAGS"; then
+ pkg_cv_DECOR_CFLAGS="$DECOR_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdecor-0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libdecor-0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_DECOR_CFLAGS=`$PKG_CONFIG --cflags "libdecor-0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
else
- video_libdecor=no
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$DECOR_LIBS"; then
+ pkg_cv_DECOR_LIBS="$DECOR_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdecor-0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libdecor-0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_DECOR_LIBS=`$PKG_CONFIG --libs "libdecor-0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ DECOR_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libdecor-0" 2>&1`
+ else
+ DECOR_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libdecor-0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$DECOR_PKG_ERRORS" >&5
+
+ video_libdecor=no
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ video_libdecor=no
+else
+ DECOR_CFLAGS=$pkg_cv_DECOR_CFLAGS
+ DECOR_LIBS=$pkg_cv_DECOR_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ video_libdecor=yes
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_libdecor" >&5
-$as_echo "$video_libdecor" >&6; }
if test x$video_libdecor = xyes; then
- EXTRA_CFLAGS="$EXTRA_CFLAGS `$PKG_CONFIG --cflags libdecor-0`"
+ EXTRA_CFLAGS="$EXTRA_CFLAGS $DECOR_CFLAGS"
$as_echo "#define HAVE_LIBDECOR_H 1" >>confdefs.h
@@ -20699,18 +20768,16 @@ else
fi
+ decor_lib=`find_lib "libdecor-0.so.*" "$DECOR_LIBS" | sed 's/.*\/\(.*\)/\1/; q'`
+
if test x$enable_wayland_shared != xyes; then
enable_libdecor_shared=no
fi
-
- decor_lib=`find_lib "libdecor-0.so.*" "" | sed 's/.*\/\(.*\)/\1/; q'`
-
if test x$have_loadso != xyes && \
test x$enable_libdecor_shared = xyes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You must have SDL_LoadObject() support for dynamic libdecor loading" >&5
$as_echo "$as_me: WARNING: You must have SDL_LoadObject() support for dynamic libdecor loading" >&2;}
fi
-
if test x$have_loadso = xyes && \
test x$enable_libdecor_shared = xyes && test x$decor_lib != x; then
echo "-- dynamic libdecor -> $decor_lib"
@@ -20720,7 +20787,7 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
else
- EXTRA_LDFLAGS="$EXTRA_LDFLAGS `$PKG_CONFIG --libs libdecor-0`"
+ EXTRA_LDFLAGS="$EXTRA_LDFLAGS $DECOR_LIBS"
fi
fi
fi
@@ -24712,6 +24779,30 @@ $as_echo "$have_wince" >&6; }
# This fixes Windows stack alignment with newer GCC
CheckStackBoundary
+
+ # headers needed elsewhere
+ ac_fn_c_check_header_mongrel "$LINENO" "tpcshrd.h" "ac_cv_header_tpcshrd_h" "$ac_includes_default"
+if test "x$ac_cv_header_tpcshrd_h" = xyes; then :
+ have_tpcshrd_h=yes
+fi
+
+
+ if test x$have_tpcshrd_h = xyes; then
+
+$as_echo "#define HAVE_TPCSHRD_H 1" >>confdefs.h
+
+ fi
+ ac_fn_c_check_header_mongrel "$LINENO" "roapi.h" "ac_cv_header_roapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_roapi_h" = xyes; then :
+ have_roapi_h=yes
+fi
+
+
+ if test x$have_roapi_h = xyes; then
+
+$as_echo "#define HAVE_ROAPI_H 1" >>confdefs.h
+
+ fi
}
CheckOS2()
@@ -26188,17 +26279,6 @@ $as_echo "#define SDL_HAPTIC_DINPUT 1" >>confdefs.h
have_haptic=yes
fi
fi
- ac_fn_c_check_header_mongrel "$LINENO" "tpcshrd.h" "ac_cv_header_tpcshrd_h" "$ac_includes_default"
-if test "x$ac_cv_header_tpcshrd_h" = xyes; then :
- have_tpcshrd_h=yes
-fi
-
-
- if test x$have_tpcshrd_h = xyes; then
-
-$as_echo "#define HAVE_TPCSHRD_H 1" >>confdefs.h
-
- fi
# Set up files for the sensor library
ac_fn_c_check_header_mongrel "$LINENO" "sensorsapi.h" "ac_cv_header_sensorsapi_h" "$ac_includes_default"
if test "x$ac_cv_header_sensorsapi_h" = xyes; then :
diff --git a/Engine/lib/sdl/configure.ac b/Engine/lib/sdl/configure.ac
index 28d620d94..2209c04d7 100644
--- a/Engine/lib/sdl/configure.ac
+++ b/Engine/lib/sdl/configure.ac
@@ -22,9 +22,9 @@ dnl Set various version strings - taken gratefully from the GTk sources
#
SDL_MAJOR_VERSION=2
SDL_MINOR_VERSION=0
-SDL_MICRO_VERSION=21
-SDL_INTERFACE_AGE=3
-SDL_BINARY_AGE=21
+SDL_MICRO_VERSION=22
+SDL_INTERFACE_AGE=0
+SDL_BINARY_AGE=22
SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
AC_SUBST(SDL_MAJOR_VERSION)
@@ -1555,7 +1555,7 @@ CheckWayland()
video_wayland=no
if test x$video_opengl_egl = xyes && \
test x$video_opengles_v2 = xyes; then
- if $PKG_CONFIG --exists wayland-client wayland-scanner wayland-egl wayland-cursor egl 'xkbcommon >= 0.5.0'; then
+ if $PKG_CONFIG --exists 'wayland-client >= 1.18' wayland-scanner wayland-egl wayland-cursor egl 'xkbcommon >= 0.5.0'; then
WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon`
WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor xkbcommon`
WAYLAND_SCANNER=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`
@@ -1626,39 +1626,31 @@ dnl FIXME: Do BSD and OS X need special cases?
dnl See if libdecor is available
AC_ARG_ENABLE(libdecor,
-[AS_HELP_STRING([--enable-libdecor], [use libdecor for Wayland client-side decorations [default=yes]])],
- , enable_libdecor=yes)
+[AS_HELP_STRING([--enable-libdecor], [use libdecor for Wayland client-side decorations [default=yes]])],, enable_libdecor=yes)
if test x$enable_libdecor = xyes; then
- AC_MSG_CHECKING(for libdecor support)
- AS_IF([$PKG_CONFIG --exists libdecor-0],
- [video_libdecor=yes],
- [video_libdecor=no])
- AC_MSG_RESULT($video_libdecor)
+ PKG_CHECK_MODULES([DECOR], [libdecor-0], video_libdecor=yes, video_libdecor=no)
if test x$video_libdecor = xyes; then
- EXTRA_CFLAGS="$EXTRA_CFLAGS `$PKG_CONFIG --cflags libdecor-0`"
+ EXTRA_CFLAGS="$EXTRA_CFLAGS $DECOR_CFLAGS"
AC_DEFINE(HAVE_LIBDECOR_H, 1, [ ])
AC_ARG_ENABLE(libdecor-shared,
-[AS_HELP_STRING([--enable-libdecor-shared], [dynamically load libdecor [default=yes]])],
- , enable_libdecor_shared=yes)
+[AS_HELP_STRING([--enable-libdecor-shared], [dynamically load libdecor [default=yes]])],, enable_libdecor_shared=yes)
+
+ decor_lib=[`find_lib "libdecor-0.so.*" "$DECOR_LIBS" | sed 's/.*\/\(.*\)/\1/; q'`]
if test x$enable_wayland_shared != xyes; then
enable_libdecor_shared=no
fi
-
- decor_lib=[`find_lib "libdecor-0.so.*" "" | sed 's/.*\/\(.*\)/\1/; q'`]
-
if test x$have_loadso != xyes && \
test x$enable_libdecor_shared = xyes; then
AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic libdecor loading])
fi
-
if test x$have_loadso = xyes && \
test x$enable_libdecor_shared = xyes && test x$decor_lib != x; then
echo "-- dynamic libdecor -> $decor_lib"
AC_DEFINE_UNQUOTED(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR, "$decor_lib", [ ])
else
- EXTRA_LDFLAGS="$EXTRA_LDFLAGS `$PKG_CONFIG --libs libdecor-0`"
+ EXTRA_LDFLAGS="$EXTRA_LDFLAGS $DECOR_LIBS"
fi
fi
fi
@@ -3206,6 +3198,16 @@ CheckWINDOWS()
# This fixes Windows stack alignment with newer GCC
CheckStackBoundary
+
+ # headers needed elsewhere
+ AC_CHECK_HEADER(tpcshrd.h,have_tpcshrd_h=yes)
+ if test x$have_tpcshrd_h = xyes; then
+ AC_DEFINE(HAVE_TPCSHRD_H, 1, [ ])
+ fi
+ AC_CHECK_HEADER(roapi.h,have_roapi_h=yes)
+ if test x$have_roapi_h = xyes; then
+ AC_DEFINE(HAVE_ROAPI_H, 1, [ ])
+ fi
}
dnl Determine whether the compiler can produce OS/2 executables
@@ -4007,10 +4009,6 @@ case "$host" in
have_haptic=yes
fi
fi
- AC_CHECK_HEADER(tpcshrd.h,have_tpcshrd_h=yes)
- if test x$have_tpcshrd_h = xyes; then
- AC_DEFINE(HAVE_TPCSHRD_H, 1, [ ])
- fi
# Set up files for the sensor library
AC_CHECK_HEADER(sensorsapi.h,have_winsensors=yes,have_winsensors=no)
if test x$have_winsensors = xyes; then
diff --git a/Engine/lib/sdl/docs/README-directfb.md b/Engine/lib/sdl/docs/README-directfb.md
index 67b64fb61..6672fa40e 100644
--- a/Engine/lib/sdl/docs/README-directfb.md
+++ b/Engine/lib/sdl/docs/README-directfb.md
@@ -15,29 +15,34 @@ What you need:
* Kernel-Framebuffer support: required: vesafb, radeonfb ....
* Mesa 7.0.x - optional for OpenGL
-/etc/directfbrc
-
-This file should contain the following lines to make
+The `/etc/directfbrc` file should contain the following lines to make
your joystick work and avoid crashes:
-------------------------
+
+```
disable-module=joystick
disable-module=cle266
disable-module=cyber5k
no-linux-input-grab
-------------------------
+```
To disable to use x11 backend when DISPLAY variable is found use
+```
export SDL_DIRECTFB_X11_CHECK=0
+```
To disable the use of linux input devices, i.e. multimice/multikeyboard support,
use
+```
export SDL_DIRECTFB_LINUX_INPUT=0
+```
To use hardware accelerated YUV-overlays for YUV-textures, use:
+```
export SDL_DIRECTFB_YUV_DIRECT=1
+```
This is disabled by default. It will only support one
YUV texture, namely the first. Every other YUV texture will be
@@ -45,7 +50,9 @@ rendered in software.
In addition, you may use (directfb-1.2.x)
+```
export SDL_DIRECTFB_YUV_UNDERLAY=1
+```
to make the YUV texture an underlay. This will make the cursor to
be shown.
@@ -54,14 +61,18 @@ Simple Window Manager
=====================
The driver has support for a very, very basic window manager you may
-want to use when running with "wm=default". Use
+want to use when running with `wm=default`. Use
+```
export SDL_DIRECTFB_WM=1
+```
to enable basic window borders. In order to have the window title rendered,
you need to have the following font installed:
+```
/usr/share/fonts/truetype/freefont/FreeSans.ttf
+```
OpenGL Support
==============
@@ -71,21 +82,25 @@ works at least on all directfb supported platforms.
As of this writing 20100802 you need to pull Mesa from git and do the following:
-------------------------
+```
git clone git://anongit.freedesktop.org/git/mesa/mesa
cd mesa
git checkout 2c9fdaf7292423c157fc79b5ce43f0f199dd753a
-------------------------
+```
-Edit configs/linux-directfb so that the Directories-section looks like
-------------------------
+Edit `configs/linux-directfb` so that the Directories-section looks like this:
+
+```
# Directories
SRC_DIRS = mesa glu
GLU_DIRS = sgi
DRIVER_DIRS = directfb
PROGRAM_DIRS =
-------------------------
+```
+Then do the following:
+
+```
make linux-directfb
make
@@ -95,13 +110,14 @@ sudo make install INSTALL_DIR=/usr/local/dfb_GL
cd src/mesa/drivers/directfb
make
sudo make install INSTALL_DIR=/usr/local/dfb_GL
-------------------------
+```
To run the SDL - testprograms:
+```
export SDL_VIDEODRIVER=directfb
export LD_LIBRARY_PATH=/usr/local/dfb_GL/lib
export LD_PRELOAD=/usr/local/dfb_GL/libGL.so.7
./testgl
-
+```
diff --git a/Engine/lib/sdl/docs/README-visualc.md b/Engine/lib/sdl/docs/README-visualc.md
index ea2bc1852..759752a56 100644
--- a/Engine/lib/sdl/docs/README-visualc.md
+++ b/Engine/lib/sdl/docs/README-visualc.md
@@ -1,7 +1,7 @@
Using SDL with Microsoft Visual C++
===================================
-### by [Lion Kimbro](mailto:snowlion@sprynet.com) with additions by [James Turk](mailto:james@conceptofzero.net)
+### by Lion Kimbro with additions by James Turk
You can either use the precompiled libraries from the [SDL](https://www.libsdl.org/download.php) web site, or you can build SDL
yourself.
diff --git a/Engine/lib/sdl/docs/README-vita.md b/Engine/lib/sdl/docs/README-vita.md
index 535b4034c..503fef7d5 100644
--- a/Engine/lib/sdl/docs/README-vita.md
+++ b/Engine/lib/sdl/docs/README-vita.md
@@ -22,6 +22,9 @@ Notes
* gles1/gles2 support and renderers are disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PVR=ON`
These renderers support 720p and 1080i resolutions. These can be specified with:
`SDL_setenv("VITA_RESOLUTION", "720", 1);` and `SDL_setenv("VITA_RESOLUTION", "1080", 1);`
+* Desktop GL 1.X and 2.X support and renderers are also disabled by default and also can be enabled with `-DVIDEO_VITA_PVR=ON` as long as gl4es4vita is present in your SDK.
+ They support the same resolutions as the gles1/gles2 backends and require specifying `SDL_setenv("VITA_PVR_OGL", "1", 1);`
+ anytime before video subsystem initialization.
* gles2 support via PIB is disabled by default and can be enabled by configuring with `-DVIDEO_VITA_PIB=ON`
* By default SDL emits mouse events for touch events on every touchscreen.
Vita has two touchscreens, so it's recommended to use `SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");` and handle touch events instead.
diff --git a/Engine/lib/sdl/docs/README-windows.md b/Engine/lib/sdl/docs/README-windows.md
index 71f968eeb..ed0c93e2c 100644
--- a/Engine/lib/sdl/docs/README-windows.md
+++ b/Engine/lib/sdl/docs/README-windows.md
@@ -1,45 +1,58 @@
-Windows
-================================================================================
+# Windows
-================================================================================
-OpenGL ES 2.x support
-================================================================================
+## LLVM and Intel C++ compiler support
-SDL has support for OpenGL ES 2.x under Windows via two alternative
-implementations.
-The most straightforward method consists in running your app in a system with
-a graphic card paired with a relatively recent (as of November of 2013) driver
-which supports the WGL_EXT_create_context_es2_profile extension. Vendors known
+SDL will build with the Visual Studio project files with LLVM-based compilers, such as the Intel oneAPI C++
+compiler, but you'll have to manually add the "-msse3" command line option
+to at least the SDL_audiocvt.c source file, and possibly others. This may
+not be necessary if you build SDL with CMake instead of the included Visual
+Studio solution.
+
+Details are here: https://github.com/libsdl-org/SDL/issues/5186
+
+
+## OpenGL ES 2.x support
+
+SDL has support for OpenGL ES 2.x under Windows via two alternative
+implementations.
+
+The most straightforward method consists in running your app in a system with
+a graphic card paired with a relatively recent (as of November of 2013) driver
+which supports the WGL_EXT_create_context_es2_profile extension. Vendors known
to ship said extension on Windows currently include nVidia and Intel.
-The other method involves using the ANGLE library (https://code.google.com/p/angleproject/)
-If an OpenGL ES 2.x context is requested and no WGL_EXT_create_context_es2_profile
-extension is found, SDL will try to load the libEGL.dll library provided by
-ANGLE.
+The other method involves using the
+[ANGLE library](https://code.google.com/p/angleproject/). If an OpenGL ES 2.x
+context is requested and no WGL_EXT_create_context_es2_profile extension is
+found, SDL will try to load the libEGL.dll library provided by ANGLE.
+
To obtain the ANGLE binaries, you can either compile from source from
-https://chromium.googlesource.com/angle/angle or copy the relevant binaries from
-a recent Chrome/Chromium install for Windows. The files you need are:
-
- * libEGL.dll
- * libGLESv2.dll
- * d3dcompiler_46.dll (supports Windows Vista or later, better shader compiler)
- or...
- * d3dcompiler_43.dll (supports Windows XP or later)
+https://chromium.googlesource.com/angle/angle or copy the relevant binaries
+from a recent Chrome/Chromium install for Windows. The files you need are:
+
+- libEGL.dll
+- libGLESv2.dll
+- d3dcompiler_46.dll (supports Windows Vista or later, better shader
+ compiler) *or* d3dcompiler_43.dll (supports Windows XP or later)
If you compile ANGLE from source, you can configure it so it does not need the
-d3dcompiler_* DLL at all (for details on this, see their documentation).
+d3dcompiler_* DLL at all (for details on this, see their documentation).
However, by default SDL will try to preload the d3dcompiler_46.dll to
-comply with ANGLE's requirements. If you wish SDL to preload d3dcompiler_43.dll (to
-support Windows XP) or to skip this step at all, you can use the
-SDL_HINT_VIDEO_WIN_D3DCOMPILER hint (see SDL_hints.h for more details).
+comply with ANGLE's requirements. If you wish SDL to preload
+d3dcompiler_43.dll (to support Windows XP) or to skip this step at all, you
+can use the SDL_HINT_VIDEO_WIN_D3DCOMPILER hint (see SDL_hints.h for more
+details).
Known Bugs:
-
- * SDL_GL_SetSwapInterval is currently a no op when using ANGLE. It appears
- that there's a bug in the library which prevents the window contents from
- refreshing if this is set to anything other than the default value.
-
-Vulkan Surface Support
-==============
-Support for creating Vulkan surfaces is configured on by default. To disable it change the value of `SDL_VIDEO_VULKAN` to 0 in `SDL_config_windows.h`. You must install the [Vulkan SDK](https://www.lunarg.com/vulkan-sdk/) in order to use Vulkan graphics in your application.
+- SDL_GL_SetSwapInterval is currently a no op when using ANGLE. It appears
+ that there's a bug in the library which prevents the window contents from
+ refreshing if this is set to anything other than the default value.
+
+## Vulkan Surface Support
+
+Support for creating Vulkan surfaces is configured on by default. To disable
+it change the value of `SDL_VIDEO_VULKAN` to 0 in `SDL_config_windows.h`. You
+must install the [Vulkan SDK](https://www.lunarg.com/vulkan-sdk/) in order to
+use Vulkan graphics in your application.
+
diff --git a/Engine/lib/sdl/include/SDL_blendmode.h b/Engine/lib/sdl/include/SDL_blendmode.h
index b6d140dbb..08c9f9dd6 100644
--- a/Engine/lib/sdl/include/SDL_blendmode.h
+++ b/Engine/lib/sdl/include/SDL_blendmode.h
@@ -67,9 +67,8 @@ typedef enum
SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */
SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
- SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D11 */
- SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D11 */
-
+ SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D9, D3D11 */
+ SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D9, D3D11 */
} SDL_BlendOperation;
/**
@@ -87,7 +86,6 @@ typedef enum
SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = 0x8, /**< 1-dstR, 1-dstG, 1-dstB, 1-dstA */
SDL_BLENDFACTOR_DST_ALPHA = 0x9, /**< dstA, dstA, dstA, dstA */
SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = 0xA /**< 1-dstA, 1-dstA, 1-dstA, 1-dstA */
-
} SDL_BlendFactor;
/**
@@ -135,10 +133,10 @@ typedef enum
* SDL 2.0.6. All renderers support the four blend modes listed in the
* SDL_BlendMode enumeration.
*
- * - **direct3d**: Supports `SDL_BLENDOPERATION_ADD` with all factors.
- * - **direct3d11**: Supports all operations with all factors. However, some
+ * - **direct3d**: Supports all operations with all factors. However, some
* factors produce unexpected results with `SDL_BLENDOPERATION_MINIMUM` and
* `SDL_BLENDOPERATION_MAXIMUM`.
+ * - **direct3d11**: Same as Direct3D 9.
* - **opengl**: Supports the `SDL_BLENDOPERATION_ADD` operation with all
* factors. OpenGL versions 1.1, 1.2, and 1.3 do not work correctly with SDL
* 2.0.6.
diff --git a/Engine/lib/sdl/include/SDL_config.h.cmake b/Engine/lib/sdl/include/SDL_config.h.cmake
index 9a1bf6758..fcd18e57d 100644
--- a/Engine/lib/sdl/include/SDL_config.h.cmake
+++ b/Engine/lib/sdl/include/SDL_config.h.cmake
@@ -253,6 +253,7 @@
#cmakedefine HAVE_AUDIOCLIENT_H @HAVE_AUDIOCLIENT_H@
#cmakedefine HAVE_TPCSHRD_H @HAVE_TPCSHRD_H@
#cmakedefine HAVE_SENSORSAPI_H @HAVE_SENSORSAPI_H@
+#cmakedefine HAVE_ROAPI_H @HAVE_ROAPI_H@
#cmakedefine HAVE_XINPUT_GAMEPAD_EX @HAVE_XINPUT_GAMEPAD_EX@
#cmakedefine HAVE_XINPUT_STATE_EX @HAVE_XINPUT_STATE_EX@
@@ -520,6 +521,7 @@
#cmakedefine SDL_VIDEO_VITA_PIB @SDL_VIDEO_VITA_PIB@
#cmakedefine SDL_VIDEO_VITA_PVR @SDL_VIDEO_VITA_PVR@
+#cmakedefine SDL_VIDEO_VITA_PVR_OGL @SDL_VIDEO_VITA_PVR_OGL@
#if !defined(__WIN32__) && !defined(__WINRT__)
# if !defined(_STDINT_H_) && !defined(_STDINT_H) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H)
diff --git a/Engine/lib/sdl/include/SDL_config.h.in b/Engine/lib/sdl/include/SDL_config.h.in
index 195b9887e..f912e4112 100644
--- a/Engine/lib/sdl/include/SDL_config.h.in
+++ b/Engine/lib/sdl/include/SDL_config.h.in
@@ -242,6 +242,7 @@
#undef HAVE_AUDIOCLIENT_H
#undef HAVE_TPCSHRD_H
#undef HAVE_SENSORSAPI_H
+#undef HAVE_ROAPI_H
/* SDL internal assertion support */
#undef SDL_DEFAULT_ASSERT_LEVEL
diff --git a/Engine/lib/sdl/include/SDL_config_emscripten.h b/Engine/lib/sdl/include/SDL_config_emscripten.h
index 7efe32373..028777df1 100644
--- a/Engine/lib/sdl/include/SDL_config_emscripten.h
+++ b/Engine/lib/sdl/include/SDL_config_emscripten.h
@@ -185,6 +185,7 @@
/* Enable various threading systems */
#ifdef __EMSCRIPTEN_PTHREADS__
#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
#endif
/* Enable various timer systems */
diff --git a/Engine/lib/sdl/include/SDL_config_windows.h b/Engine/lib/sdl/include/SDL_config_windows.h
index efb246da9..770b19039 100644
--- a/Engine/lib/sdl/include/SDL_config_windows.h
+++ b/Engine/lib/sdl/include/SDL_config_windows.h
@@ -104,6 +104,7 @@ typedef unsigned int uintptr_t;
#endif
#if defined(_WIN32_MAXVER) && _WIN32_MAXVER >= 0x0602 /* Windows 8 SDK */
#define HAVE_D3D11_H 1
+#define HAVE_ROAPI_H 1
#endif
#define HAVE_MMDEVICEAPI_H 1
#define HAVE_AUDIOCLIENT_H 1
diff --git a/Engine/lib/sdl/include/SDL_config_winrt.h b/Engine/lib/sdl/include/SDL_config_winrt.h
index c548fd695..f3901a597 100644
--- a/Engine/lib/sdl/include/SDL_config_winrt.h
+++ b/Engine/lib/sdl/include/SDL_config_winrt.h
@@ -195,6 +195,8 @@ typedef unsigned int uintptr_t;
#define HAVE_TRUNCF 1
#define HAVE__FSEEKI64 1
+#define HAVE_ROAPI_H 1
+
/* Enable various audio drivers */
#define SDL_AUDIO_DRIVER_WASAPI 1
#define SDL_AUDIO_DRIVER_DISK 1
diff --git a/Engine/lib/sdl/include/SDL_hints.h b/Engine/lib/sdl/include/SDL_hints.h
index 133f68769..ea819c85d 100644
--- a/Engine/lib/sdl/include/SDL_hints.h
+++ b/Engine/lib/sdl/include/SDL_hints.h
@@ -1354,6 +1354,18 @@ extern "C" {
*/
#define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS"
+/**
+ * \brief A variable controlling which touchpad should generate synthetic mouse events
+ *
+ * This variable can be set to the following values:
+ * "0" - Only front touchpad should generate mouse events. Default
+ * "1" - Only back touchpad should generate mouse events.
+ * "2" - Both touchpads should generate mouse events.
+ *
+ * By default SDL will generate mouse events for all touch devices
+ */
+#define SDL_HINT_VITA_TOUCH_MOUSE_DEVICE "SDL_HINT_VITA_TOUCH_MOUSE_DEVICE"
+
/**
* \brief A variable controlling whether the Android / tvOS remotes
* should be listed as joystick devices, instead of sending keyboard events.
@@ -1463,6 +1475,20 @@ extern "C" {
*/
#define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR"
+/**
+ * \brief A variable controlling whether the libdecor Wayland backend is preferred over native decrations.
+ *
+ * When this hint is set, libdecor will be used to provide window decorations, even if xdg-decoration is
+ * available. (Note that, by default, libdecor will use xdg-decoration itself if available).
+ *
+ * This variable can be set to the following values:
+ * "0" - libdecor is enabled only if server-side decorations are unavailable.
+ * "1" - libdecor is always enabled if available.
+ *
+ * libdecor is used over xdg-shell when xdg-decoration protocol is unavailable.
+ */
+#define SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR "SDL_VIDEO_WAYLAND_PREFER_LIBDECOR"
+
/**
* \brief A variable that is the address of another SDL_Window* (as a hex string formatted with "%p").
*
@@ -1938,8 +1964,7 @@ extern "C" {
* If not set or set to "", this hint is ignored. This hint must be set
* before the SDL_CreateWindow() call that it is intended to affect.
*
- * This hint is available since SDL 2.0.22. Before then, virtual devices are
- * always ignored.
+ * This hint is available since SDL 2.0.22.
*/
#define SDL_HINT_X11_WINDOW_TYPE "SDL_X11_WINDOW_TYPE"
@@ -1968,6 +1993,53 @@ extern "C" {
#define SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE "SDL_QUIT_ON_LAST_WINDOW_CLOSE"
+/**
+ * \brief A variable that decides what video backend to use.
+ *
+ * By default, SDL will try all available video backends in a reasonable
+ * order until it finds one that can work, but this hint allows the app
+ * or user to force a specific target, such as "x11" if, say, you are
+ * on Wayland but want to try talking to the X server instead.
+ *
+ * This functionality has existed since SDL 2.0.0 (indeed, before that)
+ * but before 2.0.22 this was an environment variable only. In 2.0.22,
+ * it was upgraded to a full SDL hint, so you can set the environment
+ * variable as usual or programatically set the hint with SDL_SetHint,
+ * which won't propagate to child processes.
+ *
+ * The default value is unset, in which case SDL will try to figure out
+ * the best video backend on your behalf. This hint needs to be set
+ * before SDL_Init() is called to be useful.
+ *
+ * This hint is available since SDL 2.0.22. Before then, you could set
+ * the environment variable to get the same effect.
+ */
+#define SDL_HINT_VIDEODRIVER "SDL_VIDEODRIVER"
+
+/**
+ * \brief A variable that decides what audio backend to use.
+ *
+ * By default, SDL will try all available audio backends in a reasonable
+ * order until it finds one that can work, but this hint allows the app
+ * or user to force a specific target, such as "alsa" if, say, you are
+ * on PulseAudio but want to try talking to the lower level instead.
+ *
+ * This functionality has existed since SDL 2.0.0 (indeed, before that)
+ * but before 2.0.22 this was an environment variable only. In 2.0.22,
+ * it was upgraded to a full SDL hint, so you can set the environment
+ * variable as usual or programatically set the hint with SDL_SetHint,
+ * which won't propagate to child processes.
+ *
+ * The default value is unset, in which case SDL will try to figure out
+ * the best audio backend on your behalf. This hint needs to be set
+ * before SDL_Init() is called to be useful.
+ *
+ * This hint is available since SDL 2.0.22. Before then, you could set
+ * the environment variable to get the same effect.
+ */
+#define SDL_HINT_AUDIODRIVER "SDL_AUDIODRIVER"
+
+
/**
* \brief An enumeration of hint priorities
*/
diff --git a/Engine/lib/sdl/include/SDL_metal.h b/Engine/lib/sdl/include/SDL_metal.h
index 9ecaa8151..eb3082879 100644
--- a/Engine/lib/sdl/include/SDL_metal.h
+++ b/Engine/lib/sdl/include/SDL_metal.h
@@ -92,6 +92,7 @@ extern DECLSPEC void *SDLCALL SDL_Metal_GetLayer(SDL_MetalView view);
*
* \param window SDL_Window from which the drawable size should be queried
* \param w Pointer to variable for storing the width in pixels, may be NULL
+ * \param h Pointer to variable for storing the height in pixels, may be NULL
*
* \since This function is available since SDL 2.0.14.
*
diff --git a/Engine/lib/sdl/include/SDL_rect.h b/Engine/lib/sdl/include/SDL_rect.h
index 55a6473f2..b678c7a34 100644
--- a/Engine/lib/sdl/include/SDL_rect.h
+++ b/Engine/lib/sdl/include/SDL_rect.h
@@ -54,11 +54,6 @@ typedef struct SDL_Point
/**
* The structure that defines a point (floating point)
*
- * \sa SDL_FRectEmpty
- * \sa SDL_FRectEquals
- * \sa SDL_HasIntersectionF
- * \sa SDL_IntersectFRect
- * \sa SDL_UnionFRect
* \sa SDL_EncloseFPoints
* \sa SDL_PointInFRect
*/
@@ -76,6 +71,7 @@ typedef struct SDL_FPoint
* \sa SDL_RectEquals
* \sa SDL_HasIntersection
* \sa SDL_IntersectRect
+ * \sa SDL_IntersectRectAndLine
* \sa SDL_UnionRect
* \sa SDL_EnclosePoints
*/
@@ -88,6 +84,16 @@ typedef struct SDL_Rect
/**
* A rectangle, with the origin at the upper left (floating point).
+ *
+ * \sa SDL_FRectEmpty
+ * \sa SDL_FRectEquals
+ * \sa SDL_FRectEqualsEpsilon
+ * \sa SDL_HasIntersectionF
+ * \sa SDL_IntersectFRect
+ * \sa SDL_IntersectFRectAndLine
+ * \sa SDL_UnionFRect
+ * \sa SDL_EncloseFPoints
+ * \sa SDL_PointInFRect
*/
typedef struct SDL_FRect
{
@@ -239,12 +245,28 @@ SDL_FORCE_INLINE SDL_bool SDL_FRectEmpty(const SDL_FRect *r)
}
/**
- * Returns true if the two rectangles are equal.
+ * Returns true if the two rectangles are equal, within some given epsilon.
+ *
+ * \since This function is available since SDL 2.0.22.
+ */
+SDL_FORCE_INLINE SDL_bool SDL_FRectEqualsEpsilon(const SDL_FRect *a, const SDL_FRect *b, const float epsilon)
+{
+ return (a && b && ((a == b) ||
+ ((SDL_fabs(a->x - b->x) <= epsilon) &&
+ (SDL_fabs(a->y - b->y) <= epsilon) &&
+ (SDL_fabs(a->w - b->w) <= epsilon) &&
+ (SDL_fabs(a->h - b->h) <= epsilon))))
+ ? SDL_TRUE : SDL_FALSE;
+}
+
+/**
+ * Returns true if the two rectangles are equal, using a default epsilon.
+ *
+ * \since This function is available since SDL 2.0.22.
*/
SDL_FORCE_INLINE SDL_bool SDL_FRectEquals(const SDL_FRect *a, const SDL_FRect *b)
{
- return (a && b && (a->x == b->x) && (a->y == b->y) &&
- (a->w == b->w) && (a->h == b->h)) ? SDL_TRUE : SDL_FALSE;
+ return SDL_FRectEqualsEpsilon(a, b, SDL_FLT_EPSILON);
}
/**
diff --git a/Engine/lib/sdl/include/SDL_render.h b/Engine/lib/sdl/include/SDL_render.h
index 88620336b..d859e3fd6 100644
--- a/Engine/lib/sdl/include/SDL_render.h
+++ b/Engine/lib/sdl/include/SDL_render.h
@@ -261,6 +261,17 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateSoftwareRenderer(SDL_Surface *
*/
extern DECLSPEC SDL_Renderer * SDLCALL SDL_GetRenderer(SDL_Window * window);
+/**
+ * Get the window associated with a renderer.
+ *
+ * \param renderer the renderer to query
+ * \returns the window on success or NULL on failure; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.22.
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_RenderGetWindow(SDL_Renderer *renderer);
+
/**
* Get information about a rendering context.
*
@@ -1607,6 +1618,7 @@ extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer,
* vertex array Color and alpha modulation is done per vertex
* (SDL_SetTextureColorMod and SDL_SetTextureAlphaMod are ignored).
*
+ * \param renderer The rendering context.
* \param texture (optional) The SDL texture to use.
* \param vertices Vertices.
* \param num_vertices Number of vertices.
@@ -1631,6 +1643,7 @@ extern DECLSPEC int SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer,
* vertex arrays Color and alpha modulation is done per vertex
* (SDL_SetTextureColorMod and SDL_SetTextureAlphaMod are ignored).
*
+ * \param renderer The rendering context.
* \param texture (optional) The SDL texture to use.
* \param xy Vertex positions
* \param xy_stride Byte size to move from one element to the next element
diff --git a/Engine/lib/sdl/include/SDL_stdinc.h b/Engine/lib/sdl/include/SDL_stdinc.h
index 4554f9e71..449e6445c 100644
--- a/Engine/lib/sdl/include/SDL_stdinc.h
+++ b/Engine/lib/sdl/include/SDL_stdinc.h
@@ -234,6 +234,19 @@ typedef uint64_t Uint64;
/* @} *//* Basic data types */
+/**
+ * \name Floating-point constants
+ */
+/* @{ */
+
+#ifdef FLT_EPSILON
+#define SDL_FLT_EPSILON FLT_EPSILON
+#else
+#define SDL_FLT_EPSILON 1.1920928955078125e-07F /* 0x0.000002p0 */
+#endif
+
+/* @} *//* Floating-point constants */
+
/* Make sure we have macros for printing width-based integers.
* should define these but this is not true all platforms.
* (for example win32) */
@@ -355,9 +368,9 @@ typedef uint64_t Uint64;
#endif /* SDL_DISABLE_ANALYZE_MACROS */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
-#define SDL_COMPILE_TIME_ASSERT(name, x) _Static_assert(x, #x);
+#define SDL_COMPILE_TIME_ASSERT(name, x) _Static_assert(x, #x)
#elif defined(__cplusplus) && (__cplusplus >= 201103L)
-#define SDL_COMPILE_TIME_ASSERT(name, x) static_assert(x, #x);
+#define SDL_COMPILE_TIME_ASSERT(name, x) static_assert(x, #x)
#else /* universal, but may trigger -Wunused-local-typedefs */
#define SDL_COMPILE_TIME_ASSERT(name, x) \
typedef int SDL_compile_time_assert_ ## name[(x) * 2 - 1]
diff --git a/Engine/lib/sdl/include/SDL_syswm.h b/Engine/lib/sdl/include/SDL_syswm.h
index f7cd670cd..45f8e7540 100644
--- a/Engine/lib/sdl/include/SDL_syswm.h
+++ b/Engine/lib/sdl/include/SDL_syswm.h
@@ -298,6 +298,8 @@ struct SDL_SysWMinfo
struct wl_egl_window *egl_window; /**< Wayland EGL window (native window) */
struct xdg_surface *xdg_surface; /**< Wayland xdg surface (window manager handle) */
struct xdg_toplevel *xdg_toplevel; /**< Wayland xdg toplevel role */
+ struct xdg_popup *xdg_popup; /**< Wayland xdg popup role */
+ struct xdg_positioner *xdg_positioner; /**< Wayland xdg positioner, for popup */
} wl;
#endif
#if defined(SDL_VIDEO_DRIVER_MIR) /* no longer available, left for API/ABI compatibility. Remove in 2.1! */
diff --git a/Engine/lib/sdl/include/SDL_version.h b/Engine/lib/sdl/include/SDL_version.h
index a925dc432..3df4e041a 100644
--- a/Engine/lib/sdl/include/SDL_version.h
+++ b/Engine/lib/sdl/include/SDL_version.h
@@ -59,7 +59,7 @@ typedef struct SDL_version
*/
#define SDL_MAJOR_VERSION 2
#define SDL_MINOR_VERSION 0
-#define SDL_PATCHLEVEL 21
+#define SDL_PATCHLEVEL 22
/**
* Macro to determine SDL version program was compiled against.
diff --git a/Engine/lib/sdl/include/SDL_video.h b/Engine/lib/sdl/include/SDL_video.h
index e43cb27ec..c62e0891a 100644
--- a/Engine/lib/sdl/include/SDL_video.h
+++ b/Engine/lib/sdl/include/SDL_video.h
@@ -1337,6 +1337,7 @@ extern DECLSPEC void SDLCALL SDL_SetWindowKeyboardGrab(SDL_Window * window,
* Mouse grab confines the mouse cursor to the window.
*
* \param window The window for which the mouse grab mode should be set.
+ * \param grabbed This is SDL_TRUE to grab mouse, and SDL_FALSE to release.
*
* \since This function is available since SDL 2.0.16.
*
diff --git a/Engine/lib/sdl/include/begin_code.h b/Engine/lib/sdl/include/begin_code.h
index 63f064b6f..b1b1a3a9b 100644
--- a/Engine/lib/sdl/include/begin_code.h
+++ b/Engine/lib/sdl/include/begin_code.h
@@ -107,7 +107,7 @@
#ifdef __BORLANDC__
#pragma nopackwarning
#endif
-#ifdef _M_X64
+#ifdef _WIN64
/* Use 8-byte alignment on 64-bit architectures, so pointers are aligned */
#pragma pack(push,8)
#else
diff --git a/Engine/lib/sdl/src/SDL.c b/Engine/lib/sdl/src/SDL.c
index dfc4572f4..68a4f5da2 100644
--- a/Engine/lib/sdl/src/SDL.c
+++ b/Engine/lib/sdl/src/SDL.c
@@ -316,6 +316,8 @@ SDL_InitSubSystem(Uint32 flags)
#endif
}
+ (void) flags_initialized; /* make static analysis happy, since this only gets used in error cases. */
+
return (0);
quit_and_error:
diff --git a/Engine/lib/sdl/src/SDL_hints.c b/Engine/lib/sdl/src/SDL_hints.c
index 2eea5501e..d3fc8ab46 100644
--- a/Engine/lib/sdl/src/SDL_hints.c
+++ b/Engine/lib/sdl/src/SDL_hints.c
@@ -178,6 +178,11 @@ SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
return;
}
hint->name = SDL_strdup(name);
+ if (!hint->name) {
+ SDL_free(hint);
+ SDL_OutOfMemory();
+ return;
+ }
hint->value = NULL;
hint->priority = SDL_HINT_DEFAULT;
hint->callbacks = NULL;
diff --git a/Engine/lib/sdl/src/SDL_list.c b/Engine/lib/sdl/src/SDL_list.c
new file mode 100644
index 000000000..af9f8bf81
--- /dev/null
+++ b/Engine/lib/sdl/src/SDL_list.c
@@ -0,0 +1,93 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 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"
+
+#include "SDL.h"
+#include "./SDL_list.h"
+
+/* Push */
+int
+SDL_ListAdd(SDL_ListNode **head, void *ent)
+{
+ SDL_ListNode *node = SDL_malloc(sizeof (*node));
+
+ if (node == NULL) {
+ return SDL_OutOfMemory();
+ }
+
+ node->entry = ent;
+ node->next = *head;
+ *head = node;
+ return 0;
+}
+
+/* Pop from end as a FIFO (if add with SDL_ListAdd) */
+void
+SDL_ListPop(SDL_ListNode **head, void **ent)
+{
+ SDL_ListNode **ptr = head;
+
+ /* Invalid or empty */
+ if (head == NULL || *head == NULL) {
+ return;
+ }
+
+ while ((*ptr)->next) {
+ ptr = &(*ptr)->next;
+ }
+
+ if (ent) {
+ *ent = (*ptr)->entry;
+ }
+
+ SDL_free(*ptr);
+ *ptr = NULL;
+}
+
+void
+SDL_ListRemove(SDL_ListNode **head, void *ent)
+{
+ SDL_ListNode **ptr = head;
+
+ while (*ptr) {
+ if ((*ptr)->entry == ent) {
+ SDL_ListNode *tmp = *ptr;
+ *ptr = (*ptr)->next;
+ SDL_free(tmp);
+ return;
+ }
+ ptr = &(*ptr)->next;
+ }
+}
+
+void
+SDL_ListClear(SDL_ListNode **head)
+{
+ SDL_ListNode *l = *head;
+ *head = NULL;
+ while (l) {
+ SDL_ListNode *tmp = l;
+ l = l->next;
+ SDL_free(tmp);
+ }
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/SDL_list.h b/Engine/lib/sdl/src/SDL_list.h
new file mode 100644
index 000000000..a7ead1dcd
--- /dev/null
+++ b/Engine/lib/sdl/src/SDL_list.h
@@ -0,0 +1,39 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 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_list_h_
+#define SDL_list_h_
+
+typedef struct SDL_ListNode
+{
+ void *entry;
+ struct SDL_ListNode *next;
+} SDL_ListNode;
+
+
+int SDL_ListAdd(SDL_ListNode **head, void *ent);
+void SDL_ListPop(SDL_ListNode **head, void **ent);
+void SDL_ListRemove(SDL_ListNode **head, void *ent);
+void SDL_ListClear(SDL_ListNode **head);
+
+#endif /* SDL_list_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/audio/SDL_audio.c b/Engine/lib/sdl/src/audio/SDL_audio.c
index 3a841450c..fb363f771 100644
--- a/Engine/lib/sdl/src/audio/SDL_audio.c
+++ b/Engine/lib/sdl/src/audio/SDL_audio.c
@@ -936,7 +936,7 @@ SDL_AudioInit(const char *driver_name)
/* Select the proper audio driver */
if (driver_name == NULL) {
- driver_name = SDL_getenv("SDL_AUDIODRIVER");
+ driver_name = SDL_GetHint(SDL_HINT_AUDIODRIVER);
}
if (driver_name != NULL && *driver_name != 0) {
diff --git a/Engine/lib/sdl/src/audio/SDL_audiocvt.c b/Engine/lib/sdl/src/audio/SDL_audiocvt.c
index bd49ab008..539900d84 100644
--- a/Engine/lib/sdl/src/audio/SDL_audiocvt.c
+++ b/Engine/lib/sdl/src/audio/SDL_audiocvt.c
@@ -80,7 +80,7 @@ SDL_ConvertStereoToMono_SSE3(SDL_AudioCVT * cvt, SDL_AudioFormat format)
Just use unaligned load/stores, if the memory at runtime is
aligned it'll be just as fast on modern processors */
while (i >= 4) { /* 4 * float32 */
- _mm_storeu_ps(dst, _mm_mul_ps(_mm_hadd_ps(_mm_load_ps(src), _mm_loadu_ps(src+4)), divby2));
+ _mm_storeu_ps(dst, _mm_mul_ps(_mm_hadd_ps(_mm_loadu_ps(src), _mm_loadu_ps(src+4)), divby2));
i -= 4; src += 8; dst += 4;
}
diff --git a/Engine/lib/sdl/src/audio/SDL_wave.c b/Engine/lib/sdl/src/audio/SDL_wave.c
index 07eb10147..e49b55068 100644
--- a/Engine/lib/sdl/src/audio/SDL_wave.c
+++ b/Engine/lib/sdl/src/audio/SDL_wave.c
@@ -685,7 +685,7 @@ MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len)
state.output.pos = 0;
state.output.size = outputsize / sizeof(Sint16);
- state.output.data = (Sint16 *)SDL_malloc(outputsize);
+ state.output.data = (Sint16 *)SDL_calloc(1, outputsize);
if (state.output.data == NULL) {
return SDL_OutOfMemory();
}
diff --git a/Engine/lib/sdl/src/audio/emscripten/SDL_emscriptenaudio.c b/Engine/lib/sdl/src/audio/emscripten/SDL_emscriptenaudio.c
index bc2a0e10d..722f5d0fa 100644
--- a/Engine/lib/sdl/src/audio/emscripten/SDL_emscriptenaudio.c
+++ b/Engine/lib/sdl/src/audio/emscripten/SDL_emscriptenaudio.c
@@ -32,7 +32,7 @@ static void
FeedAudioDevice(_THIS, const void *buf, const int buflen)
{
const int framelen = (SDL_AUDIO_BITSIZE(this->spec.format) / 8) * this->spec.channels;
- EM_ASM_ARGS({
+ MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
var numChannels = SDL2.audio.currentOutputBuffer['numberOfChannels'];
for (var c = 0; c < numChannels; ++c) {
@@ -101,7 +101,7 @@ HandleCaptureProcess(_THIS)
return;
}
- EM_ASM_ARGS({
+ MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels;
for (var c = 0; c < numChannels; ++c) {
@@ -147,7 +147,7 @@ HandleCaptureProcess(_THIS)
static void
EMSCRIPTENAUDIO_CloseDevice(_THIS)
{
- EM_ASM_({
+ MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
if ($0) {
if (SDL2.capture.silenceTimer !== undefined) {
@@ -201,7 +201,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
/* based on parts of library_sdl.js */
/* create context */
- result = EM_ASM_INT({
+ result = MAIN_THREAD_EM_ASM_INT({
if(typeof(Module['SDL2']) === 'undefined') {
Module['SDL2'] = {};
}
@@ -280,7 +280,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
feels like it's a pretty inefficient tapdance in similar ways,
to be honest. */
- EM_ASM_({
+ MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
var have_microphone = function(stream) {
//console.log('SDL audio capture: we have a microphone! Replacing silence callback.');
@@ -323,7 +323,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
}, this->spec.channels, this->spec.samples, HandleCaptureProcess, this);
} else {
/* setup a ScriptProcessorNode */
- EM_ASM_ARGS({
+ MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0);
SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
@@ -359,7 +359,7 @@ EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->ProvidesOwnCallbackThread = SDL_TRUE;
/* check availability */
- available = EM_ASM_INT_V({
+ available = MAIN_THREAD_EM_ASM_INT({
if (typeof(AudioContext) !== 'undefined') {
return true;
} else if (typeof(webkitAudioContext) !== 'undefined') {
@@ -372,7 +372,7 @@ EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl * impl)
SDL_SetError("No audio context available");
}
- capture_available = available && EM_ASM_INT_V({
+ capture_available = available && MAIN_THREAD_EM_ASM_INT({
if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) {
return true;
} else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') {
diff --git a/Engine/lib/sdl/src/audio/vita/SDL_vitaaudio.c b/Engine/lib/sdl/src/audio/vita/SDL_vitaaudio.c
index 524124e80..88f4a3285 100644
--- a/Engine/lib/sdl/src/audio/vita/SDL_vitaaudio.c
+++ b/Engine/lib/sdl/src/audio/vita/SDL_vitaaudio.c
@@ -37,18 +37,35 @@
#include
#include
+#include
#define SCE_AUDIO_SAMPLE_ALIGN(s) (((s) + 63) & ~63)
#define SCE_AUDIO_MAX_VOLUME 0x8000
-/* The tag name used by VITA audio */
-#define VITAAUD_DRIVER_NAME "vita"
+static int
+VITAAUD_OpenCaptureDevice(_THIS)
+{
+ this->spec.freq = 16000;
+ this->spec.samples = 512;
+ this->spec.channels = 1;
+
+ SDL_CalculateAudioSpec(&this->spec);
+
+ this->hidden->port = sceAudioInOpenPort(SCE_AUDIO_IN_PORT_TYPE_VOICE , 512, 16000, SCE_AUDIO_IN_PARAM_FORMAT_S16_MONO);
+
+ if (this->hidden->port < 0) {
+ return SDL_SetError("Couldn't open audio in port: %x", this->hidden->port);
+ }
+
+ return 0;
+}
static int
VITAAUD_OpenDevice(_THIS, const char *devname)
{
int format, mixlen, i, port = SCE_AUDIO_OUT_PORT_TYPE_MAIN;
int vols[2] = {SCE_AUDIO_MAX_VOLUME, SCE_AUDIO_MAX_VOLUME};
+ SDL_AudioFormat test_format;
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc(sizeof(*this->hidden));
@@ -56,13 +73,20 @@ VITAAUD_OpenDevice(_THIS, const char *devname)
return SDL_OutOfMemory();
}
SDL_memset(this->hidden, 0, sizeof(*this->hidden));
- switch (this->spec.format & 0xff) {
- case 8:
- case 16:
- this->spec.format = AUDIO_S16LSB;
+
+ for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
+ if (test_format == AUDIO_S16LSB) {
+ this->spec.format = test_format;
break;
- default:
- return SDL_SetError("Unsupported audio format");
+ }
+ }
+
+ if(!test_format) {
+ return SDL_SetError("Unsupported audio format");
+ }
+
+ if (this->iscapture) {
+ return VITAAUD_OpenCaptureDevice(this);
}
/* The sample count must be a multiple of 64. */
@@ -91,14 +115,14 @@ VITAAUD_OpenDevice(_THIS, const char *devname)
port = SCE_AUDIO_OUT_PORT_TYPE_BGM;
}
- this->hidden->channel = sceAudioOutOpenPort(port, this->spec.samples, this->spec.freq, format);
- if (this->hidden->channel < 0) {
+ this->hidden->port = sceAudioOutOpenPort(port, this->spec.samples, this->spec.freq, format);
+ if (this->hidden->port < 0) {
free(this->hidden->rawbuf);
this->hidden->rawbuf = NULL;
- return SDL_SetError("Couldn't reserve hardware channel");
+ return SDL_SetError("Couldn't open audio out port: %x", this->hidden->port);
}
- sceAudioOutSetVolume(this->hidden->channel, SCE_AUDIO_VOLUME_FLAG_L_CH|SCE_AUDIO_VOLUME_FLAG_R_CH, vols);
+ sceAudioOutSetVolume(this->hidden->port, SCE_AUDIO_VOLUME_FLAG_L_CH|SCE_AUDIO_VOLUME_FLAG_R_CH, vols);
SDL_memset(this->hidden->rawbuf, 0, mixlen);
for (i = 0; i < NUM_BUFFERS; i++) {
@@ -113,7 +137,7 @@ static void VITAAUD_PlayDevice(_THIS)
{
Uint8 *mixbuf = this->hidden->mixbufs[this->hidden->next_buffer];
- sceAudioOutOutput(this->hidden->channel, mixbuf);
+ sceAudioOutOutput(this->hidden->port, mixbuf);
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
}
@@ -123,6 +147,7 @@ static void VITAAUD_WaitDevice(_THIS)
{
/* Because we block when sending audio, there's no need for this function to do anything. */
}
+
static Uint8 *VITAAUD_GetDeviceBuf(_THIS)
{
return this->hidden->mixbufs[this->hidden->next_buffer];
@@ -130,17 +155,32 @@ static Uint8 *VITAAUD_GetDeviceBuf(_THIS)
static void VITAAUD_CloseDevice(_THIS)
{
- if (this->hidden->channel >= 0) {
- sceAudioOutReleasePort(this->hidden->channel);
- this->hidden->channel = -1;
+ if (this->hidden->port >= 0) {
+ if (this->iscapture) {
+ sceAudioInReleasePort(this->hidden->port);
+ } else {
+ sceAudioOutReleasePort(this->hidden->port);
+ }
+ this->hidden->port = -1;
}
- if (this->hidden->rawbuf != NULL) {
+ if (!this->iscapture && this->hidden->rawbuf != NULL) {
free(this->hidden->rawbuf); /* this uses memalign(), not SDL_malloc(). */
this->hidden->rawbuf = NULL;
}
}
+static int VITAAUD_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+ int ret;
+ SDL_assert(buflen == this->spec.size);
+ ret = sceAudioInInput(this->hidden->port, buffer);
+ if (ret < 0) {
+ return SDL_SetError("Failed to capture from device: %x", ret);
+ }
+ return this->spec.size;
+}
+
static void VITAAUD_ThreadInit(_THIS)
{
/* Increase the priority of this audio thread by 1 to put it
@@ -165,12 +205,13 @@ VITAAUD_Init(SDL_AudioDriverImpl * impl)
impl->CloseDevice = VITAAUD_CloseDevice;
impl->ThreadInit = VITAAUD_ThreadInit;
- /* VITA audio device */
- impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
- /*
+ impl->CaptureFromDevice = VITAAUD_CaptureFromDevice;
+
+ /* and the capabilities */
impl->HasCaptureSupport = SDL_TRUE;
- impl->OnlyHasDefaultInputDevice = SDL_TRUE;
- */
+ impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
+ impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
+
return SDL_TRUE; /* this audio target is available. */
}
diff --git a/Engine/lib/sdl/src/audio/vita/SDL_vitaaudio.h b/Engine/lib/sdl/src/audio/vita/SDL_vitaaudio.h
index 73870759b..a5601b28c 100644
--- a/Engine/lib/sdl/src/audio/vita/SDL_vitaaudio.h
+++ b/Engine/lib/sdl/src/audio/vita/SDL_vitaaudio.h
@@ -30,8 +30,8 @@
#define NUM_BUFFERS 2
struct SDL_PrivateAudioData {
- /* The hardware output channel. */
- int channel;
+ /* The hardware input/output port. */
+ int port;
/* The raw allocated mixing buffer. */
Uint8 *rawbuf;
/* Individual mixing buffers. */
diff --git a/Engine/lib/sdl/src/audio/wasapi/SDL_wasapi.c b/Engine/lib/sdl/src/audio/wasapi/SDL_wasapi.c
index e7d640c12..862ed9f5e 100644
--- a/Engine/lib/sdl/src/audio/wasapi/SDL_wasapi.c
+++ b/Engine/lib/sdl/src/audio/wasapi/SDL_wasapi.c
@@ -558,12 +558,16 @@ WASAPI_PrepDevice(_THIS, const SDL_bool updatestream)
return WIN_SetErrorFromHRESULT("WASAPI can't determine minimum device period", ret);
}
+#if 1 /* we're getting reports that WASAPI's resampler introduces distortions, so it's disabled for now. --ryan. */
+ this->spec.freq = waveformat->nSamplesPerSec; /* force sampling rate so our resampler kicks in, if necessary. */
+#else
/* favor WASAPI's resampler over our own */
if (this->spec.freq != waveformat->nSamplesPerSec) {
streamflags |= (AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY);
waveformat->nSamplesPerSec = this->spec.freq;
waveformat->nAvgBytesPerSec = waveformat->nSamplesPerSec * waveformat->nChannels * (waveformat->wBitsPerSample / 8);
}
+#endif
streamflags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
ret = IAudioClient_Initialize(client, sharemode, streamflags, 0, 0, waveformat, NULL);
diff --git a/Engine/lib/sdl/src/core/linux/SDL_fcitx.c b/Engine/lib/sdl/src/core/linux/SDL_fcitx.c
index 3f0794736..bab5e88f3 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_fcitx.c
+++ b/Engine/lib/sdl/src/core/linux/SDL_fcitx.c
@@ -339,11 +339,11 @@ SDL_Fcitx_Reset(void)
}
SDL_bool
-SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
+SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
{
- Uint32 state = Fcitx_ModState();
+ Uint32 mod_state = Fcitx_ModState();
Uint32 handled = SDL_FALSE;
- Uint32 is_release = SDL_FALSE;
+ Uint32 is_release = (state == SDL_RELEASED);
Uint32 event_time = 0;
if (!fcitx_client.ic_path) {
@@ -351,7 +351,7 @@ SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
}
if (SDL_DBus_CallMethod(FCITX_DBUS_SERVICE, fcitx_client.ic_path, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent",
- DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &state, DBUS_TYPE_BOOLEAN, &is_release, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
+ DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &mod_state, DBUS_TYPE_BOOLEAN, &is_release, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID)) {
if (handled) {
SDL_Fcitx_UpdateTextRect(NULL);
diff --git a/Engine/lib/sdl/src/core/linux/SDL_fcitx.h b/Engine/lib/sdl/src/core/linux/SDL_fcitx.h
index f7884ea43..c3cea523d 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_fcitx.h
+++ b/Engine/lib/sdl/src/core/linux/SDL_fcitx.h
@@ -31,7 +31,7 @@ extern SDL_bool SDL_Fcitx_Init(void);
extern void SDL_Fcitx_Quit(void);
extern void SDL_Fcitx_SetFocus(SDL_bool focused);
extern void SDL_Fcitx_Reset(void);
-extern SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
+extern SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
extern void SDL_Fcitx_UpdateTextRect(SDL_Rect *rect);
extern void SDL_Fcitx_PumpEvents(void);
diff --git a/Engine/lib/sdl/src/core/linux/SDL_ibus.c b/Engine/lib/sdl/src/core/linux/SDL_ibus.c
index a7bafda35..60af0ba29 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_ibus.c
+++ b/Engine/lib/sdl/src/core/linux/SDL_ibus.c
@@ -503,15 +503,20 @@ SDL_IBus_Reset(void)
}
SDL_bool
-SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
+SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
{
Uint32 result = 0;
SDL_DBusContext *dbus = SDL_DBus_GetContext();
-
+
+
if (IBus_CheckConnection(dbus)) {
Uint32 mods = IBus_ModState();
+ Uint32 ibus_keycode = keycode - 8;
+ if (state == SDL_RELEASED) {
+ mods |= (1 << 30); // IBUS_RELEASE_MASK
+ }
if (!SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
- DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
+ DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &ibus_keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID)) {
result = 0;
}
diff --git a/Engine/lib/sdl/src/core/linux/SDL_ibus.h b/Engine/lib/sdl/src/core/linux/SDL_ibus.h
index 73a9f1b8b..71d1f2d30 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_ibus.h
+++ b/Engine/lib/sdl/src/core/linux/SDL_ibus.h
@@ -41,7 +41,7 @@ extern void SDL_IBus_Reset(void);
/* Sends a keypress event to IBus, returns SDL_TRUE if IBus used this event to
update its candidate list or change input methods. PumpEvents should be
called some time after this, to recieve the TextInput / TextEditing event back. */
-extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
+extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
/* Update the position of IBus' candidate list. If rect is NULL then this will
just reposition it relative to the focused window's new position. */
diff --git a/Engine/lib/sdl/src/core/linux/SDL_ime.c b/Engine/lib/sdl/src/core/linux/SDL_ime.c
index 84c461f8b..9c0cb80f0 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_ime.c
+++ b/Engine/lib/sdl/src/core/linux/SDL_ime.c
@@ -27,7 +27,7 @@ typedef SDL_bool (*_SDL_IME_Init)(void);
typedef void (*_SDL_IME_Quit)(void);
typedef void (*_SDL_IME_SetFocus)(SDL_bool);
typedef void (*_SDL_IME_Reset)(void);
-typedef SDL_bool (*_SDL_IME_ProcessKeyEvent)(Uint32, Uint32);
+typedef SDL_bool (*_SDL_IME_ProcessKeyEvent)(Uint32, Uint32, Uint8 state);
typedef void (*_SDL_IME_UpdateTextRect)(SDL_Rect *);
typedef void (*_SDL_IME_PumpEvents)(void);
@@ -127,10 +127,10 @@ SDL_IME_Reset(void)
}
SDL_bool
-SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
+SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
{
if (SDL_IME_ProcessKeyEvent_Real)
- return SDL_IME_ProcessKeyEvent_Real(keysym, keycode);
+ return SDL_IME_ProcessKeyEvent_Real(keysym, keycode, state);
return SDL_FALSE;
}
diff --git a/Engine/lib/sdl/src/core/linux/SDL_ime.h b/Engine/lib/sdl/src/core/linux/SDL_ime.h
index a28a4b430..cc5b105f0 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_ime.h
+++ b/Engine/lib/sdl/src/core/linux/SDL_ime.h
@@ -31,7 +31,7 @@ extern SDL_bool SDL_IME_Init(void);
extern void SDL_IME_Quit(void);
extern void SDL_IME_SetFocus(SDL_bool focused);
extern void SDL_IME_Reset(void);
-extern SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
+extern SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
extern void SDL_IME_UpdateTextRect(SDL_Rect *rect);
extern void SDL_IME_PumpEvents(void);
diff --git a/Engine/lib/sdl/src/core/windows/SDL_windows.c b/Engine/lib/sdl/src/core/windows/SDL_windows.c
index fcbf8e847..50e128fcc 100644
--- a/Engine/lib/sdl/src/core/windows/SDL_windows.c
+++ b/Engine/lib/sdl/src/core/windows/SDL_windows.c
@@ -25,7 +25,15 @@
#include "SDL_windows.h"
#include "SDL_error.h"
-#include /* for CoInitialize/CoUninitialize (Win32 only) */
+#include /* for CoInitialize/CoUninitialize (Win32 only) */
+#if defined(HAVE_ROAPI_H)
+#include /* For RoInitialize/RoUninitialize (Win32 only) */
+#else
+typedef enum RO_INIT_TYPE {
+ RO_INIT_SINGLETHREADED = 0,
+ RO_INIT_MULTITHREADED = 1
+} RO_INIT_TYPE;
+#endif
#ifndef _WIN32_WINNT_VISTA
#define _WIN32_WINNT_VISTA 0x0600
@@ -37,6 +45,10 @@
#define _WIN32_WINNT_WIN8 0x0602
#endif
+#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
+#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
+#endif
+
/* Sets an error message based on an HRESULT */
int
@@ -104,51 +116,66 @@ void
WIN_CoUninitialize(void)
{
#ifndef __WINRT__
- /* Don't uninitialize COM because of what appears to be a bug in Microsoft WGI reference counting.
- *
- * If you plug in a non-Xbox controller and let the application run for 30 seconds, then it crashes in CoUninitialize()
- * with this stack trace:
+ CoUninitialize();
+#endif
+}
- Windows.Gaming.Input.dll!GameController::~GameController(void) Unknown
- Windows.Gaming.Input.dll!GameController::`vector deleting destructor'(unsigned int) Unknown
- Windows.Gaming.Input.dll!Microsoft::WRL::Details::RuntimeClassImpl,1,1,0,struct Windows::Gaming::Input::IGameController,struct Windows::Gaming::Input::IGameControllerBatteryInfo,struct Microsoft::WRL::CloakedIid,class Microsoft::WRL::FtmBase>::Release(void) Unknown
- Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::AggregableRuntimeClass,struct Microsoft::WRL::CloakedIid,struct Microsoft::WRL::CloakedIid,struct Microsoft::WRL::CloakedIid,class Microsoft::WRL::Details::Nil,class Microsoft::WRL::Details::Nil,class Microsoft::WRL::Details::Nil>::Release(void) Unknown
- Windows.Gaming.Input.dll!Microsoft::WRL::ComPtr<`WaitForCompletion,Windows::Foundation::IAsyncOperationWithProgress>'::`2'::FTMEventDelegate>::~ComPtr<`WaitForCompletion,Windows::Foundation::IAsyncOperationWithProgress>'::`2'::FTMEventDelegate>() Unknown
- Windows.Gaming.Input.dll!`eh vector destructor iterator'(void *,unsigned int,int,void (*)(void *)) Unknown
- Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::GameControllerCollection::~GameControllerCollection(void) Unknown
- Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::GameControllerCollection::`vector deleting destructor'(unsigned int) Unknown
- Windows.Gaming.Input.dll!Microsoft::WRL::Details::RuntimeClassImpl,1,1,0,struct Windows::Foundation::Collections::IIterable,struct Windows::Foundation::Collections::IVectorView,class Microsoft::WRL::FtmBase>::Release(void) Unknown
- Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::CustomGameControllerFactoryBase::~CustomGameControllerFactoryBase(void) Unknown
- Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::CustomGameControllerFactoryBase::`vector deleting destructor'(unsigned int) Unknown
- Windows.Gaming.Input.dll!Microsoft::WRL::ActivationFactory >,struct Windows::Gaming::Input::IFlightStickStatics,class Microsoft::WRL::Details::Nil,0>::Release(void) Unknown
- Windows.Gaming.Input.dll!Microsoft::WRL::ComPtr<`WaitForCompletion,Windows::Foundation::IAsyncOperationWithProgress>'::`2'::FTMEventDelegate>::~ComPtr<`WaitForCompletion,Windows::Foundation::IAsyncOperationWithProgress>'::`2'::FTMEventDelegate>() Unknown
- Windows.Gaming.Input.dll!NtList::~NtList(void) Unknown
- Windows.Gaming.Input.dll!FactoryManager::`vector deleting destructor'(unsigned int) Unknown
- Windows.Gaming.Input.dll!Microsoft::WRL::ActivationFactory,struct Windows::Gaming::Input::Custom::IGameControllerFactoryManagerStatics2,struct Microsoft::WRL::CloakedIid,0>::Release(void) Unknown
- Windows.Gaming.Input.dll!Microsoft::WRL::Details::TerminateMap(class Microsoft::WRL::Details::ModuleBase *,unsigned short const *,bool) Unknown
- Windows.Gaming.Input.dll!Microsoft::WRL::Module<1,class Microsoft::WRL::Details::DefaultModule<1> >::~Module<1,class Microsoft::WRL::Details::DefaultModule<1> >(void) Unknown
- Windows.Gaming.Input.dll!Microsoft::WRL::Details::DefaultModule<1>::`vector deleting destructor'(unsigned int) Unknown
- Windows.Gaming.Input.dll!`dynamic atexit destructor for 'Microsoft::WRL::Details::StaticStorage,0,int>::instance_''() Unknown
- Windows.Gaming.Input.dll!__CRT_INIT@12() Unknown
- Windows.Gaming.Input.dll!__DllMainCRTStartup() Unknown
- ntdll.dll!_LdrxCallInitRoutine@16() Unknown
- ntdll.dll!LdrpCallInitRoutine() Unknown
- ntdll.dll!LdrpProcessDetachNode() Unknown
- ntdll.dll!LdrpUnloadNode() Unknown
- ntdll.dll!LdrpDecrementModuleLoadCountEx() Unknown
- ntdll.dll!LdrUnloadDll() Unknown
- KernelBase.dll!FreeLibrary() Unknown
- combase.dll!FreeLibraryWithLogging(LoadOrFreeWhy why, HINSTANCE__ * hMod, const wchar_t * pswzOptionalFileName) Line 193 C++
- combase.dll!CClassCache::CDllPathEntry::CFinishObject::Finish() Line 3311 C++
- combase.dll!CClassCache::CFinishComposite::Finish() Line 3421 C++
- combase.dll!CClassCache::CleanUpDllsForProcess() Line 7009 C++
- [Inline Frame] combase.dll!CCCleanUpDllsForProcess() Line 8773 C++
- combase.dll!ProcessUninitialize() Line 2243 C++
- combase.dll!DecrementProcessInitializeCount() Line 993 C++
- combase.dll!wCoUninitialize(COleTls & Tls, int fHostThread) Line 4126 C++
- combase.dll!CoUninitialize() Line 3945 C++
- */
- /*CoUninitialize();*/
+#ifndef __WINRT__
+void *
+WIN_LoadComBaseFunction(const char *name)
+{
+ static SDL_bool s_bLoaded;
+ static HMODULE s_hComBase;
+
+ if (!s_bLoaded) {
+ s_hComBase = LoadLibraryEx(TEXT("combase.dll"), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ s_bLoaded = SDL_TRUE;
+ }
+ if (s_hComBase) {
+ return GetProcAddress(s_hComBase, name);
+ } else {
+ return NULL;
+ }
+}
+#endif
+
+HRESULT
+WIN_RoInitialize(void)
+{
+#ifdef __WINRT__
+ return S_OK;
+#else
+ typedef HRESULT (WINAPI *RoInitialize_t)(RO_INIT_TYPE initType);
+ RoInitialize_t RoInitializeFunc = (RoInitialize_t)WIN_LoadComBaseFunction("RoInitialize");
+ if (RoInitializeFunc) {
+ /* RO_INIT_SINGLETHREADED is equivalent to COINIT_APARTMENTTHREADED */
+ HRESULT hr = RoInitializeFunc(RO_INIT_SINGLETHREADED);
+ if (hr == RPC_E_CHANGED_MODE) {
+ hr = RoInitializeFunc(RO_INIT_MULTITHREADED);
+ }
+
+ /* S_FALSE means success, but someone else already initialized. */
+ /* You still need to call RoUninitialize in this case! */
+ if (hr == S_FALSE) {
+ return S_OK;
+ }
+
+ return hr;
+ } else {
+ return E_NOINTERFACE;
+ }
+#endif
+}
+
+void
+WIN_RoUninitialize(void)
+{
+#ifndef __WINRT__
+ typedef void (WINAPI *RoUninitialize_t)(void);
+ RoUninitialize_t RoUninitializeFunc = (RoUninitialize_t)WIN_LoadComBaseFunction("RoUninitialize");
+ if (RoUninitializeFunc) {
+ RoUninitializeFunc();
+ }
#endif
}
diff --git a/Engine/lib/sdl/src/core/windows/SDL_windows.h b/Engine/lib/sdl/src/core/windows/SDL_windows.h
index 221c3bd87..917a8256f 100644
--- a/Engine/lib/sdl/src/core/windows/SDL_windows.h
+++ b/Engine/lib/sdl/src/core/windows/SDL_windows.h
@@ -63,10 +63,19 @@ extern int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr);
/* Sets an error message based on GetLastError(). Always return -1. */
extern int WIN_SetError(const char *prefix);
+#if !defined(__WINRT__)
+/* Load a function from combase.dll */
+void *WIN_LoadComBaseFunction(const char *name);
+#endif
+
/* Wrap up the oddities of CoInitialize() into a common function. */
extern HRESULT WIN_CoInitialize(void);
extern void WIN_CoUninitialize(void);
+/* Wrap up the oddities of RoInitialize() into a common function. */
+extern HRESULT WIN_RoInitialize(void);
+extern void WIN_RoUninitialize(void);
+
/* Returns SDL_TRUE if we're running on Windows Vista and newer */
extern BOOL WIN_IsWindowsVistaOrGreater(void);
diff --git a/Engine/lib/sdl/src/dynapi/SDL_dynapi_overrides.h b/Engine/lib/sdl/src/dynapi/SDL_dynapi_overrides.h
index 299dde303..526513ad5 100644
--- a/Engine/lib/sdl/src/dynapi/SDL_dynapi_overrides.h
+++ b/Engine/lib/sdl/src/dynapi/SDL_dynapi_overrides.h
@@ -864,3 +864,4 @@
#define SDL_UnionFRect SDL_UnionFRect_REAL
#define SDL_EncloseFPoints SDL_EncloseFPoints_REAL
#define SDL_IntersectFRectAndLine SDL_IntersectFRectAndLine_REAL
+#define SDL_RenderGetWindow SDL_RenderGetWindow_REAL
diff --git a/Engine/lib/sdl/src/dynapi/SDL_dynapi_procs.h b/Engine/lib/sdl/src/dynapi/SDL_dynapi_procs.h
index 2c0d5b03e..22bf870d9 100644
--- a/Engine/lib/sdl/src/dynapi/SDL_dynapi_procs.h
+++ b/Engine/lib/sdl/src/dynapi/SDL_dynapi_procs.h
@@ -935,3 +935,4 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_IntersectFRect,(const SDL_FRect *a, const SDL_FRect
SDL_DYNAPI_PROC(void,SDL_UnionFRect,(const SDL_FRect *a, const SDL_FRect *b, SDL_FRect *c),(a,b,c),)
SDL_DYNAPI_PROC(SDL_bool,SDL_EncloseFPoints,(const SDL_FPoint *a, int b, const SDL_FRect *c, SDL_FRect *d),(a,b,c,d),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_IntersectFRectAndLine,(const SDL_FRect *a, float *b, float *c, float *d, float *e),(a,b,c,d,e),return)
+SDL_DYNAPI_PROC(SDL_Window*,SDL_RenderGetWindow,(SDL_Renderer *a),(a),return)
diff --git a/Engine/lib/sdl/src/events/SDL_keyboard.c b/Engine/lib/sdl/src/events/SDL_keyboard.c
index cd150fab6..14e79ca49 100644
--- a/Engine/lib/sdl/src/events/SDL_keyboard.c
+++ b/Engine/lib/sdl/src/events/SDL_keyboard.c
@@ -638,6 +638,7 @@ SDL_SetKeyboardFocus(SDL_Window * window)
/* old window must lose an existing mouse capture. */
if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) {
SDL_CaptureMouse(SDL_FALSE); /* drop the capture. */
+ SDL_UpdateMouseCapture(SDL_TRUE);
SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE));
}
diff --git a/Engine/lib/sdl/src/events/SDL_mouse.c b/Engine/lib/sdl/src/events/SDL_mouse.c
index 2e88ee714..254182cc5 100644
--- a/Engine/lib/sdl/src/events/SDL_mouse.c
+++ b/Engine/lib/sdl/src/events/SDL_mouse.c
@@ -109,6 +109,28 @@ SDL_TouchMouseEventsChanged(void *userdata, const char *name, const char *oldVal
mouse->touch_mouse_events = SDL_GetStringBoolean(hint, SDL_TRUE);
}
+#if defined(__vita__)
+static void SDLCALL
+SDL_VitaTouchMouseDeviceChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
+{
+ SDL_Mouse *mouse = (SDL_Mouse *)userdata;
+ if (hint) {
+ switch(*hint) {
+ default:
+ case '0':
+ mouse->vita_touch_mouse_device = 0;
+ break;
+ case '1':
+ mouse->vita_touch_mouse_device = 1;
+ break;
+ case '2':
+ mouse->vita_touch_mouse_device = 2;
+ break;
+ }
+ }
+}
+#endif
+
static void SDLCALL
SDL_MouseTouchEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
@@ -134,12 +156,8 @@ SDL_MouseAutoCaptureChanged(void *userdata, const char *name, const char *oldVal
SDL_bool auto_capture = SDL_GetStringBoolean(hint, SDL_TRUE);
if (auto_capture != mouse->auto_capture) {
- /* Turn off mouse capture if it's currently active because of button presses */
- if (!auto_capture && SDL_GetMouseState(NULL, NULL) != 0) {
- SDL_CaptureMouse(SDL_FALSE);
- }
-
mouse->auto_capture = auto_capture;
+ SDL_UpdateMouseCapture(SDL_FALSE);
}
}
@@ -166,6 +184,11 @@ SDL_MouseInit(void)
SDL_AddHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS,
SDL_TouchMouseEventsChanged, mouse);
+#if defined(__vita__)
+ SDL_AddHintCallback(SDL_HINT_VITA_TOUCH_MOUSE_DEVICE,
+ SDL_VitaTouchMouseDeviceChanged, mouse);
+#endif
+
SDL_AddHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS,
SDL_MouseTouchEventsChanged, mouse);
@@ -384,12 +407,9 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
/* Ignore relative motion when first positioning the mouse */
if (!mouse->has_position) {
- xrel = 0;
- yrel = 0;
mouse->x = x;
mouse->y = y;
mouse->has_position = SDL_TRUE;
- return 0;
} else if (!xrel && !yrel) { /* Drop events that don't change state */
#ifdef DEBUG_MOUSE
SDL_Log("Mouse event didn't change state - dropped!\n");
@@ -540,7 +560,6 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state
Uint32 type;
Uint32 buttonstate;
SDL_MouseInputSource *source;
- SDL_bool had_buttons_pressed = (SDL_GetMouseState(NULL, NULL) ? SDL_TRUE : SDL_FALSE);
source = GetMouseInputSource(mouse, mouseID);
if (!source) {
@@ -643,10 +662,7 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state
/* Automatically capture the mouse while buttons are pressed */
if (mouse->auto_capture) {
- SDL_bool has_buttons_pressed = (SDL_GetMouseState(NULL, NULL) ? SDL_TRUE : SDL_FALSE);
- if (has_buttons_pressed != had_buttons_pressed) {
- SDL_CaptureMouse(has_buttons_pressed);
- }
+ SDL_UpdateMouseCapture(SDL_FALSE);
}
return posted;
@@ -743,6 +759,7 @@ SDL_MouseQuit(void)
if (mouse->CaptureMouse) {
SDL_CaptureMouse(SDL_FALSE);
+ SDL_UpdateMouseCapture(SDL_TRUE);
}
SDL_SetRelativeMouseMode(SDL_FALSE);
SDL_ShowCursor(1);
@@ -947,6 +964,8 @@ SDL_SetRelativeMouseMode(SDL_bool enabled)
if (!enabled) {
SDL_WarpMouseInWindow(focusWindow, mouse->x, mouse->y);
}
+
+ SDL_UpdateMouseCapture(SDL_FALSE);
}
if (!enabled) {
@@ -968,39 +987,59 @@ SDL_GetRelativeMouseMode()
return mouse->relative_mode;
}
+int
+SDL_UpdateMouseCapture(SDL_bool force_release)
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+ SDL_Window *capture_window = NULL;
+
+ if (!mouse->CaptureMouse) {
+ return 0;
+ }
+
+ if (!force_release) {
+ if (mouse->capture_desired || (mouse->auto_capture && SDL_GetMouseState(NULL, NULL) != 0)) {
+ if (!mouse->relative_mode) {
+ capture_window = SDL_GetKeyboardFocus();
+ }
+ }
+ }
+
+ if (capture_window != mouse->capture_window) {
+ if (mouse->capture_window) {
+ mouse->CaptureMouse(NULL);
+ mouse->capture_window->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
+ mouse->capture_window = NULL;
+ }
+
+ if (capture_window) {
+ if (mouse->CaptureMouse(capture_window) < 0) {
+ /* CaptureMouse() will have set an error */
+ return -1;
+ }
+ capture_window->flags |= SDL_WINDOW_MOUSE_CAPTURE;
+ }
+
+ mouse->capture_window = capture_window;
+ }
+ return 0;
+}
+
int
SDL_CaptureMouse(SDL_bool enabled)
{
SDL_Mouse *mouse = SDL_GetMouse();
- SDL_Window *focusWindow;
- SDL_bool isCaptured;
if (!mouse->CaptureMouse) {
return SDL_Unsupported();
}
- focusWindow = SDL_GetKeyboardFocus();
-
- isCaptured = focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE);
- if (isCaptured == enabled) {
- return 0; /* already done! */
+ if (enabled && SDL_GetKeyboardFocus() == NULL) {
+ return SDL_SetError("No window has focus");
}
+ mouse->capture_desired = enabled;
- if (enabled) {
- if (!focusWindow) {
- return SDL_SetError("No window has focus");
- } else if (mouse->CaptureMouse(focusWindow) == -1) {
- return -1; /* CaptureMouse() should call SetError */
- }
- focusWindow->flags |= SDL_WINDOW_MOUSE_CAPTURE;
- } else {
- if (mouse->CaptureMouse(NULL) == -1) {
- return -1; /* CaptureMouse() should call SetError */
- }
- focusWindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
- }
-
- return 0;
+ return SDL_UpdateMouseCapture(SDL_FALSE);
}
SDL_Cursor *
diff --git a/Engine/lib/sdl/src/events/SDL_mouse_c.h b/Engine/lib/sdl/src/events/SDL_mouse_c.h
index 7b020447a..f06934b6f 100644
--- a/Engine/lib/sdl/src/events/SDL_mouse_c.h
+++ b/Engine/lib/sdl/src/events/SDL_mouse_c.h
@@ -100,7 +100,12 @@ typedef struct
SDL_bool touch_mouse_events;
SDL_bool mouse_touch_events;
SDL_bool was_touch_mouse_events; /* Was a touch-mouse event pending? */
+#if defined(__vita__)
+ Uint8 vita_touch_mouse_device;
+#endif
SDL_bool auto_capture;
+ SDL_bool capture_desired;
+ SDL_Window *capture_window;
/* Data for input source state */
int num_sources;
@@ -132,6 +137,9 @@ extern void SDL_SetDefaultCursor(SDL_Cursor * cursor);
/* Set the mouse focus window */
extern void SDL_SetMouseFocus(SDL_Window * window);
+/* Update the mouse capture window */
+extern int SDL_UpdateMouseCapture(SDL_bool force_release);
+
/* Send a mouse motion event */
extern int SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y);
diff --git a/Engine/lib/sdl/src/events/SDL_touch.c b/Engine/lib/sdl/src/events/SDL_touch.c
index c3534f00e..ebf26e091 100644
--- a/Engine/lib/sdl/src/events/SDL_touch.c
+++ b/Engine/lib/sdl/src/events/SDL_touch.c
@@ -265,8 +265,13 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window * window,
#if SYNTHESIZE_TOUCH_TO_MOUSE
/* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
+ /* SDL_HINT_VITA_TOUCH_MOUSE_DEVICE: controlling which touchpad should generate synthetic mouse events, PSVita-only */
{
+#if defined(__vita__)
+ if (mouse->touch_mouse_events && ((mouse->vita_touch_mouse_device == id) || (mouse->vita_touch_mouse_device == 2)) ) {
+#else
if (mouse->touch_mouse_events) {
+#endif
/* FIXME: maybe we should only restrict to a few SDL_TouchDeviceType */
if (id != SDL_MOUSE_TOUCHID) {
if (window) {
diff --git a/Engine/lib/sdl/src/filesystem/windows/SDL_sysfilesystem.c b/Engine/lib/sdl/src/filesystem/windows/SDL_sysfilesystem.c
index d50fb511b..b57546c67 100644
--- a/Engine/lib/sdl/src/filesystem/windows/SDL_sysfilesystem.c
+++ b/Engine/lib/sdl/src/filesystem/windows/SDL_sysfilesystem.c
@@ -35,39 +35,23 @@
char *
SDL_GetBasePath(void)
{
- typedef DWORD (WINAPI *GetModuleFileNameExW_t)(HANDLE, HMODULE, LPWSTR, DWORD);
- GetModuleFileNameExW_t pGetModuleFileNameExW;
DWORD buflen = 128;
WCHAR *path = NULL;
- HANDLE psapi = LoadLibrary(TEXT("psapi.dll"));
char *retval = NULL;
DWORD len = 0;
int i;
- if (!psapi) {
- WIN_SetError("Couldn't load psapi.dll");
- return NULL;
- }
-
- pGetModuleFileNameExW = (GetModuleFileNameExW_t)GetProcAddress(psapi, "GetModuleFileNameExW");
- if (!pGetModuleFileNameExW) {
- WIN_SetError("Couldn't find GetModuleFileNameExW");
- FreeLibrary(psapi);
- return NULL;
- }
-
while (SDL_TRUE) {
void *ptr = SDL_realloc(path, buflen * sizeof (WCHAR));
if (!ptr) {
SDL_free(path);
- FreeLibrary(psapi);
SDL_OutOfMemory();
return NULL;
}
path = (WCHAR *) ptr;
- len = pGetModuleFileNameExW(GetCurrentProcess(), NULL, path, buflen);
+ len = GetModuleFileNameW(NULL, path, buflen);
/* if it truncated, then len >= buflen - 1 */
/* if there was enough room (or failure), len < buflen - 1 */
if (len < buflen - 1) {
@@ -78,8 +62,6 @@ SDL_GetBasePath(void)
buflen *= 2;
}
- FreeLibrary(psapi);
-
if (len == 0) {
SDL_free(path);
WIN_SetError("Couldn't locate our .exe");
diff --git a/Engine/lib/sdl/src/hidapi/SDL_hidapi.c b/Engine/lib/sdl/src/hidapi/SDL_hidapi.c
index aacff63bf..369b616f5 100644
--- a/Engine/lib/sdl/src/hidapi/SDL_hidapi.c
+++ b/Engine/lib/sdl/src/hidapi/SDL_hidapi.c
@@ -951,6 +951,7 @@ DeleteHIDDeviceWrapper(SDL_hid_device *device)
}
#if !SDL_HIDAPI_DISABLED
+#if HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND || defined(SDL_LIBUSB_DYNAMIC)
#define COPY_IF_EXISTS(var) \
if (pSrc->var != NULL) { \
@@ -987,6 +988,7 @@ CopyHIDDeviceInfo(struct SDL_hid_device_info *pSrc, struct SDL_hid_device_info *
#undef COPY_IF_EXISTS
#undef WCOPY_IF_EXISTS
+#endif /* HAVE_PLATFORM_BACKEND || HAVE_DRIVER_BACKEND || SDL_LIBUSB_DYNAMIC */
#endif /* !SDL_HIDAPI_DISABLED */
static int SDL_hidapi_refcount = 0;
@@ -1185,9 +1187,9 @@ struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned
#ifdef SDL_LIBUSB_DYNAMIC
if (libusb_ctx.libhandle) {
usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
- #ifdef DEBUG_HIDAPI
+#ifdef DEBUG_HIDAPI
SDL_Log("libusb devices found:");
- #endif
+#endif
for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
new_dev = (struct SDL_hid_device_info*) SDL_malloc(sizeof(struct SDL_hid_device_info));
if (!new_dev) {
@@ -1197,11 +1199,11 @@ struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned
return NULL;
}
CopyHIDDeviceInfo(usb_dev, new_dev);
- #ifdef DEBUG_HIDAPI
+#ifdef DEBUG_HIDAPI
SDL_Log(" - %ls %ls 0x%.4hx 0x%.4hx",
usb_dev->manufacturer_string, usb_dev->product_string,
usb_dev->vendor_id, usb_dev->product_id);
- #endif
+#endif
if (last != NULL) {
last->next = new_dev;
diff --git a/Engine/lib/sdl/src/hidapi/libusb/hid.c b/Engine/lib/sdl/src/hidapi/libusb/hid.c
index c54746e4d..9cb597fa8 100644
--- a/Engine/lib/sdl/src/hidapi/libusb/hid.c
+++ b/Engine/lib/sdl/src/hidapi/libusb/hid.c
@@ -1497,6 +1497,7 @@ void HID_API_EXPORT hid_close(hid_device *dev)
/* Clean up the Transfer objects allocated in read_thread(). */
free(dev->transfer->buffer);
+ dev->transfer->buffer = NULL;
libusb_free_transfer(dev->transfer);
/* release the interface */
diff --git a/Engine/lib/sdl/src/hidapi/mac/hid.c b/Engine/lib/sdl/src/hidapi/mac/hid.c
index a9a85b1f7..ec7ffaf16 100644
--- a/Engine/lib/sdl/src/hidapi/mac/hid.c
+++ b/Engine/lib/sdl/src/hidapi/mac/hid.c
@@ -572,8 +572,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
if ((vendor_id == 0x0 && product_id == 0x0) ||
(vendor_id == dev_vid && product_id == dev_pid)) {
struct hid_device_info *tmp;
- size_t len;
-
+
/* VID/PID match. Create the record. */
tmp = (struct hid_device_info *)calloc(1, sizeof(struct hid_device_info));
if (cur_dev) {
@@ -590,7 +589,7 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
/* Fill out the record */
cur_dev->next = NULL;
- len = make_path(dev, cbuf, sizeof(cbuf));
+ make_path(dev, cbuf, sizeof(cbuf));
cur_dev->path = strdup(cbuf);
/* Serial Number */
@@ -817,10 +816,9 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
CFSetGetValues(device_set, (const void **) device_array);
for (i = 0; i < num_devices; i++) {
char cbuf[BUF_LEN];
- size_t len;
IOHIDDeviceRef os_dev = device_array[i];
- len = make_path(os_dev, cbuf, sizeof(cbuf));
+ make_path(os_dev, cbuf, sizeof(cbuf));
if (!strcmp(cbuf, path)) {
// Matched Paths. Open this Device.
IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeNone);
@@ -833,6 +831,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
/* Create the buffers for receiving data */
dev->max_input_report_len = (CFIndex) get_max_report_length(os_dev);
+ SDL_assert(dev->max_input_report_len > 0);
dev->input_report_buf = (uint8_t *)calloc(dev->max_input_report_len, sizeof(uint8_t));
/* Create the Run Loop Mode for this device.
@@ -936,11 +935,14 @@ static int return_data(hid_device *dev, unsigned char *data, size_t length)
/* Copy the data out of the linked list item (rpt) into the
return buffer (data), and delete the liked list item. */
struct input_report *rpt = dev->input_reports;
- size_t len = (length < rpt->len)? length: rpt->len;
- memcpy(data, rpt->data, len);
- dev->input_reports = rpt->next;
- free(rpt->data);
- free(rpt);
+ size_t len = 0;
+ if (rpt != NULL) {
+ len = (length < rpt->len)? length: rpt->len;
+ memcpy(data, rpt->data, len);
+ dev->input_reports = rpt->next;
+ free(rpt->data);
+ free(rpt);
+ }
return (int)len;
}
diff --git a/Engine/lib/sdl/src/joystick/SDL_gamecontrollerdb.h b/Engine/lib/sdl/src/joystick/SDL_gamecontrollerdb.h
index 2aa9ca6e8..9dab7cbba 100644
--- a/Engine/lib/sdl/src/joystick/SDL_gamecontrollerdb.h
+++ b/Engine/lib/sdl/src/joystick/SDL_gamecontrollerdb.h
@@ -501,7 +501,7 @@ static const char *s_ControllerMappings [] =
"03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,",
#endif
-#if defined(__LINUX__)
+#ifdef SDL_JOYSTICK_LINUX
"xinput,*,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
@@ -762,6 +762,7 @@ static const char *s_ControllerMappings [] =
"0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,",
"030000004f0400000ed0000011010000,ThrustMaster eSwap PRO Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,",
+ "030000004f04000015b3000001010000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,",
"030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,",
"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,",
diff --git a/Engine/lib/sdl/src/joystick/SDL_joystick.c b/Engine/lib/sdl/src/joystick/SDL_joystick.c
index 3f3482b7d..ae4591223 100644
--- a/Engine/lib/sdl/src/joystick/SDL_joystick.c
+++ b/Engine/lib/sdl/src/joystick/SDL_joystick.c
@@ -1590,11 +1590,13 @@ SDL_JoystickUpdate(void)
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
if (joystick->attached) {
- /* This should always be true, but seeing a crash in the wild...? */
- if (joystick->driver) {
- joystick->driver->Update(joystick);
+ /* This driver should always be != NULL, but seeing a crash in the wild...? */
+ if (!joystick->driver) {
+ continue; /* nothing we can do, and other things use joystick->driver below here. */
}
+ joystick->driver->Update(joystick);
+
if (joystick->delayed_guide_button) {
SDL_GameControllerHandleDelayedGuideButton(joystick);
}
@@ -2158,7 +2160,10 @@ static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid)
MAKE_VIDPID(0x044f, 0xb65d), /* Thrustmaster Wheel FFB */
MAKE_VIDPID(0x044f, 0xb66d), /* Thrustmaster Wheel FFB */
MAKE_VIDPID(0x044f, 0xb677), /* Thrustmaster T150 */
- MAKE_VIDPID(0x044f, 0xb66e), /* Thrustmaster T300RS */
+ MAKE_VIDPID(0x044f, 0xb696), /* Thrustmaster T248 */
+ MAKE_VIDPID(0x044f, 0xb66e), /* Thrustmaster T300RS (normal mode) */
+ MAKE_VIDPID(0x044f, 0xb66f), /* Thrustmaster T300RS (advanced mode) */
+ MAKE_VIDPID(0x044f, 0xb66d), /* Thrustmaster T300RS (PS4 mode) */
MAKE_VIDPID(0x044f, 0xb65e), /* Thrustmaster T500RS */
MAKE_VIDPID(0x044f, 0xb664), /* Thrustmaster TX (initial mode) */
MAKE_VIDPID(0x044f, 0xb669), /* Thrustmaster TX (active mode) */
diff --git a/Engine/lib/sdl/src/joystick/hidapi/SDL_hidapi_ps5.c b/Engine/lib/sdl/src/joystick/hidapi/SDL_hidapi_ps5.c
index 6d7f87d59..2549c2afd 100644
--- a/Engine/lib/sdl/src/joystick/hidapi/SDL_hidapi_ps5.c
+++ b/Engine/lib/sdl/src/joystick/hidapi/SDL_hidapi_ps5.c
@@ -747,7 +747,11 @@ HIDAPI_DriverPS5_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joy
}
}
- return SDL_HIDAPI_SendRumbleAndUnlock(device, data, report_size);
+ if (SDL_HIDAPI_SendRumbleAndUnlock(device, data, report_size) != report_size) {
+ return -1;
+ }
+
+ return 0;
}
static int
@@ -957,7 +961,10 @@ HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev,
axis = ((int)packet->ucRightJoystickY * 257) - 32768;
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
- if (packet->ucBatteryLevel & 0x10) {
+ /* A check of packet->ucBatteryLevel & 0x10 should work as a check for BT vs USB but doesn't
+ * seem to always work. Possibly related to being 100% charged?
+ */
+ if (!ctx->is_bluetooth) {
/* 0x20 set means fully charged */
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED);
} else {
diff --git a/Engine/lib/sdl/src/joystick/hidapi/SDL_hidapijoystick.c b/Engine/lib/sdl/src/joystick/hidapi/SDL_hidapijoystick.c
index 55d9a1353..f54b3c3f2 100644
--- a/Engine/lib/sdl/src/joystick/hidapi/SDL_hidapijoystick.c
+++ b/Engine/lib/sdl/src/joystick/hidapi/SDL_hidapijoystick.c
@@ -227,7 +227,7 @@ HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
}
/* Disconnect any joysticks */
- while (device->num_joysticks) {
+ while (device->num_joysticks && device->joysticks) {
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
}
diff --git a/Engine/lib/sdl/src/joystick/iphoneos/SDL_mfijoystick.m b/Engine/lib/sdl/src/joystick/iphoneos/SDL_mfijoystick.m
index c75fbbae2..38ab3fe60 100644
--- a/Engine/lib/sdl/src/joystick/iphoneos/SDL_mfijoystick.m
+++ b/Engine/lib/sdl/src/joystick/iphoneos/SDL_mfijoystick.m
@@ -330,6 +330,19 @@ IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *controlle
subtype = 1;
}
+ if (SDL_strcmp(name, "Backbone One") == 0) {
+ /* The Backbone app uses the guide and share buttons */
+ if ((device->button_mask & (1 << SDL_CONTROLLER_BUTTON_GUIDE)) != 0) {
+ device->button_mask &= ~(1 << SDL_CONTROLLER_BUTTON_GUIDE);
+ --nbuttons;
+ }
+ if ((device->button_mask & (1 << SDL_CONTROLLER_BUTTON_MISC1)) != 0) {
+ device->button_mask &= ~(1 << SDL_CONTROLLER_BUTTON_MISC1);
+ --nbuttons;
+ device->has_xbox_share_button = SDL_FALSE;
+ }
+ }
+
device->naxes = 6; /* 2 thumbsticks and 2 triggers */
device->nhats = 1; /* d-pad */
device->nbuttons = nbuttons;
diff --git a/Engine/lib/sdl/src/joystick/linux/SDL_sysjoystick.c b/Engine/lib/sdl/src/joystick/linux/SDL_sysjoystick.c
index 851448acd..a268c0d9b 100644
--- a/Engine/lib/sdl/src/joystick/linux/SDL_sysjoystick.c
+++ b/Engine/lib/sdl/src/joystick/linux/SDL_sysjoystick.c
@@ -109,6 +109,7 @@ typedef struct SDL_joylist_item
/* Steam Controller support */
SDL_bool m_bSteamController;
+ SDL_bool checked_mapping;
SDL_GamepadMapping *mapping;
} SDL_joylist_item;
@@ -605,6 +606,26 @@ LINUX_InotifyJoystickDetect(void)
}
#endif /* HAVE_INOTIFY */
+static int get_event_joystick_index(int event)
+{
+ int joystick_index = -1;
+ int i, count;
+ struct dirent **entries = NULL;
+ char path[PATH_MAX];
+
+ SDL_snprintf(path, SDL_arraysize(path), "/sys/class/input/event%d/device", event);
+ count = scandir(path, &entries, NULL, alphasort);
+ for (i = 0; i < count; ++i) {
+ if (SDL_strncmp(entries[i]->d_name, "js", 2) == 0) {
+ joystick_index = SDL_atoi(entries[i]->d_name+2);
+ }
+ free(entries[i]); /* This should NOT be SDL_free() */
+ }
+ free(entries); /* This should NOT be SDL_free() */
+
+ return joystick_index;
+}
+
/* Detect devices by reading /dev/input. In the inotify code path we
* have to do this the first time, to detect devices that already existed
* before we started; in the non-inotify code path we do this repeatedly
@@ -615,12 +636,39 @@ filter_entries(const struct dirent *entry)
return IsJoystickDeviceNode(entry->d_name);
}
static int
-sort_entries(const struct dirent **a, const struct dirent **b)
+sort_entries(const void *_a, const void *_b)
{
- int numA = SDL_atoi((*a)->d_name+5);
- int numB = SDL_atoi((*b)->d_name+5);
+ const struct dirent **a = (const struct dirent **)_a;
+ const struct dirent **b = (const struct dirent **)_b;
+ int numA, numB;
+ int offset;
+
+ if (SDL_classic_joysticks) {
+ offset = 2; /* strlen("js") */
+ numA = SDL_atoi((*a)->d_name+offset);
+ numB = SDL_atoi((*b)->d_name+offset);
+ } else {
+ offset = 5; /* strlen("event") */
+ numA = SDL_atoi((*a)->d_name+offset);
+ numB = SDL_atoi((*b)->d_name+offset);
+
+ /* See if we can get the joystick ordering */
+ {
+ int jsA = get_event_joystick_index(numA);
+ int jsB = get_event_joystick_index(numB);
+ if (jsA >= 0 && jsB >= 0) {
+ numA = jsA;
+ numB = jsB;
+ } else if (jsA >= 0) {
+ return -1;
+ } else if (jsB >= 0) {
+ return 1;
+ }
+ }
+ }
return (numA - numB);
}
+
static void
LINUX_FallbackJoystickDetect(void)
{
@@ -633,10 +681,13 @@ LINUX_FallbackJoystickDetect(void)
/* Opening input devices can generate synchronous device I/O, so avoid it if we can */
if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) {
int i, count;
- struct dirent **entries;
+ struct dirent **entries = NULL;
char path[PATH_MAX];
- count = scandir("/dev/input", &entries, filter_entries, sort_entries);
+ count = scandir("/dev/input", &entries, filter_entries, NULL);
+ if (count > 1) {
+ qsort(entries, count, sizeof(*entries), sort_entries);
+ }
for (i = 0; i < count; ++i) {
SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", entries[i]->d_name);
MaybeAddDevice(path);
@@ -683,29 +734,7 @@ LINUX_JoystickInit(void)
SDL_classic_joysticks = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_CLASSIC, SDL_FALSE);
-#if SDL_USE_LIBUDEV
- if (enumeration_method == ENUMERATION_UNSET) {
- if (SDL_GetHintBoolean("SDL_JOYSTICK_DISABLE_UDEV", SDL_FALSE)) {
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
- "udev disabled by SDL_JOYSTICK_DISABLE_UDEV");
- enumeration_method = ENUMERATION_FALLBACK;
-
- } else if (access("/.flatpak-info", F_OK) == 0
- || access("/run/host/container-manager", F_OK) == 0) {
- /* Explicitly check `/.flatpak-info` because, for old versions of
- * Flatpak, this was the only available way to tell if we were in
- * a Flatpak container. */
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
- "Container detected, disabling udev integration");
- enumeration_method = ENUMERATION_FALLBACK;
-
- } else {
- SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
- "Using udev for joystick device discovery");
- enumeration_method = ENUMERATION_LIBUDEV;
- }
- }
-#endif
+ enumeration_method = ENUMERATION_UNSET;
/* First see if the user specified one or more joysticks to use */
if (devices != NULL) {
@@ -734,6 +763,28 @@ LINUX_JoystickInit(void)
LINUX_JoystickDetect();
#if SDL_USE_LIBUDEV
+ if (enumeration_method == ENUMERATION_UNSET) {
+ if (SDL_GetHintBoolean("SDL_JOYSTICK_DISABLE_UDEV", SDL_FALSE)) {
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
+ "udev disabled by SDL_JOYSTICK_DISABLE_UDEV");
+ enumeration_method = ENUMERATION_FALLBACK;
+
+ } else if (access("/.flatpak-info", F_OK) == 0
+ || access("/run/host/container-manager", F_OK) == 0) {
+ /* Explicitly check `/.flatpak-info` because, for old versions of
+ * Flatpak, this was the only available way to tell if we were in
+ * a Flatpak container. */
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
+ "Container detected, disabling udev integration");
+ enumeration_method = ENUMERATION_FALLBACK;
+
+ } else {
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
+ "Using udev for joystick device discovery");
+ enumeration_method = ENUMERATION_LIBUDEV;
+ }
+ }
+
if (enumeration_method == ENUMERATION_LIBUDEV) {
if (SDL_UDEV_Init() < 0) {
return SDL_SetError("Could not initialize UDEV");
@@ -1573,9 +1624,13 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
SDL_Joystick *joystick;
SDL_joylist_item *item = JoystickByDevIndex(device_index);
- if (item->mapping) {
- SDL_memcpy(out, item->mapping, sizeof(*out));
- return SDL_TRUE;
+ if (item->checked_mapping) {
+ if (item->mapping) {
+ SDL_memcpy(out, item->mapping, sizeof(*out));
+ return SDL_TRUE;
+ } else {
+ return SDL_FALSE;
+ }
}
/* We temporarily open the device to check how it's configured. Make
@@ -1595,6 +1650,8 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
return SDL_FALSE;
}
+ item->checked_mapping = SDL_TRUE;
+
if (PrepareJoystickHwdata(joystick, item) == -1) {
SDL_free(joystick->hwdata);
SDL_free(joystick);
diff --git a/Engine/lib/sdl/src/joystick/windows/SDL_rawinputjoystick.c b/Engine/lib/sdl/src/joystick/windows/SDL_rawinputjoystick.c
index 32b637827..df40232df 100644
--- a/Engine/lib/sdl/src/joystick/windows/SDL_rawinputjoystick.c
+++ b/Engine/lib/sdl/src/joystick/windows/SDL_rawinputjoystick.c
@@ -62,6 +62,7 @@ typedef struct WindowsGamingInputGamepadState WindowsGamingInputGamepadState;
#define GamepadButtons_GUIDE 0x40000000
#define COBJMACROS
#include "windows.gaming.input.h"
+#include
#endif
#if defined(SDL_JOYSTICK_RAWINPUT_XINPUT) || defined(SDL_JOYSTICK_RAWINPUT_WGI)
@@ -565,22 +566,24 @@ RAWINPUT_InitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
if (!wgi_state.initialized) {
static const IID SDL_IID_IGamepadStatics = { 0x8BBCE529, 0xD49C, 0x39E9, { 0x95, 0x60, 0xE4, 0x7D, 0xDE, 0x96, 0xB7, 0xC8 } };
HRESULT hr;
- HMODULE hModule;
- /* I think this takes care of RoInitialize() in a way that is compatible with the rest of SDL */
- if (FAILED(WIN_CoInitialize())) {
+ if (FAILED(WIN_RoInitialize())) {
return;
}
wgi_state.initialized = SDL_TRUE;
wgi_state.dirty = SDL_TRUE;
- hModule = LoadLibraryA("combase.dll");
- if (hModule != NULL) {
+ {
typedef HRESULT (WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING* string);
typedef HRESULT (WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void** factory);
- WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)GetProcAddress(hModule, "WindowsCreateStringReference");
- RoGetActivationFactory_t RoGetActivationFactoryFunc = (RoGetActivationFactory_t)GetProcAddress(hModule, "RoGetActivationFactory");
+#ifdef __WINRT__
+ WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = WindowsCreateStringReference;
+ RoGetActivationFactory_t RoGetActivationFactoryFunc = RoGetActivationFactory;
+#else
+ WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
+ RoGetActivationFactory_t RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
+#endif
if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) {
PCWSTR pNamespace = L"Windows.Gaming.Input.Gamepad";
HSTRING_HEADER hNamespaceStringHeader;
@@ -591,7 +594,6 @@ RAWINPUT_InitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
RoGetActivationFactoryFunc(hNamespaceString, &SDL_IID_IGamepadStatics, (void **)&wgi_state.gamepad_statics);
}
}
- FreeLibrary(hModule);
}
}
}
@@ -657,7 +659,7 @@ RAWINPUT_QuitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_Release(wgi_state.gamepad_statics);
wgi_state.gamepad_statics = NULL;
}
- WIN_CoUninitialize();
+ WIN_RoUninitialize();
wgi_state.initialized = SDL_FALSE;
}
}
@@ -1320,8 +1322,10 @@ RAWINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint
if (!SUCCEEDED(hr)) {
return SDL_SetError("Setting vibration failed: 0x%lx\n", hr);
}
+ return 0;
+ } else {
+ return SDL_SetError("Controller isn't correlated yet, try hitting a button first");
}
- return 0;
#else
return SDL_Unsupported();
#endif
diff --git a/Engine/lib/sdl/src/joystick/windows/SDL_windows_gaming_input.c b/Engine/lib/sdl/src/joystick/windows/SDL_windows_gaming_input.c
index a731dad63..6c5ec5528 100644
--- a/Engine/lib/sdl/src/joystick/windows/SDL_windows_gaming_input.c
+++ b/Engine/lib/sdl/src/joystick/windows/SDL_windows_gaming_input.c
@@ -68,6 +68,7 @@ static struct {
EventRegistrationToken controller_added_token;
EventRegistrationToken controller_removed_token;
int controller_count;
+ SDL_bool ro_initialized;
WindowsGamingInputControllerState *controllers;
} wgi;
@@ -260,10 +261,9 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
WindowsGetStringRawBufferFunc = WindowsGetStringRawBuffer;
WindowsDeleteStringFunc = WindowsDeleteString;
#else
- HMODULE hModule = LoadLibraryA("combase.dll");
- if (hModule != NULL) {
- WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)GetProcAddress(hModule, "WindowsGetStringRawBuffer");
- WindowsDeleteStringFunc = (WindowsDeleteString_t)GetProcAddress(hModule, "WindowsDeleteString");
+ {
+ WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)WIN_LoadComBaseFunction("WindowsGetStringRawBuffer");
+ WindowsDeleteStringFunc = (WindowsDeleteString_t)WIN_LoadComBaseFunction("WindowsDeleteString");
}
#endif /* __WINRT__ */
if (WindowsGetStringRawBufferFunc && WindowsDeleteStringFunc) {
@@ -277,11 +277,6 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
WindowsDeleteStringFunc(hString);
}
}
-#ifndef __WINRT__
- if (hModule != NULL) {
- FreeLibrary(hModule);
- }
-#endif
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2);
}
if (!name) {
@@ -444,23 +439,43 @@ WGI_JoystickInit(void)
WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = NULL;
RoGetActivationFactory_t RoGetActivationFactoryFunc = NULL;
-#ifndef __WINRT__
- HMODULE hModule;
-#endif
HRESULT hr;
- if (FAILED(WIN_CoInitialize())) {
- return SDL_SetError("CoInitialize() failed");
+ if (FAILED(WIN_RoInitialize())) {
+ return SDL_SetError("RoInitialize() failed");
}
+ wgi.ro_initialized = SDL_TRUE;
+
+#ifndef __WINRT__
+ {
+ /* There seems to be a bug in Windows where a dependency of WGI can be unloaded from memory prior to WGI itself.
+ * This results in Windows_Gaming_Input!GameController::~GameController() invoking an unloaded DLL and crashing.
+ * As a workaround, we will keep a reference to the MTA to prevent COM from unloading DLLs later.
+ * See https://github.com/libsdl-org/SDL/issues/5552 for more details.
+ */
+ static PVOID cookie = NULL;
+ if (!cookie) {
+ typedef HRESULT (WINAPI *CoIncrementMTAUsage_t)(PVOID* pCookie);
+ CoIncrementMTAUsage_t CoIncrementMTAUsageFunc = (CoIncrementMTAUsage_t)WIN_LoadComBaseFunction("CoIncrementMTAUsage");
+ if (CoIncrementMTAUsageFunc) {
+ if (FAILED(CoIncrementMTAUsageFunc(&cookie))) {
+ return SDL_SetError("CoIncrementMTAUsage() failed");
+ }
+ } else {
+ /* CoIncrementMTAUsage() is present since Win8, so we should never make it here. */
+ return SDL_SetError("CoIncrementMTAUsage() not found");
+ }
+ }
+ }
+#endif
#ifdef __WINRT__
WindowsCreateStringReferenceFunc = WindowsCreateStringReference;
RoGetActivationFactoryFunc = RoGetActivationFactory;
#else
- hModule = LoadLibraryA("combase.dll");
- if (hModule != NULL) {
- WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)GetProcAddress(hModule, "WindowsCreateStringReference");
- RoGetActivationFactoryFunc = (RoGetActivationFactory_t)GetProcAddress(hModule, "RoGetActivationFactory");
+ {
+ WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
+ RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
}
#endif /* __WINRT__ */
if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) {
@@ -519,11 +534,6 @@ WGI_JoystickInit(void)
}
}
}
-#ifndef __WINRT__
- if (hModule != NULL) {
- FreeLibrary(hModule);
- }
-#endif
if (wgi.statics) {
__FIVectorView_1_Windows__CGaming__CInput__CRawGameController *controllers;
@@ -863,9 +873,12 @@ WGI_JoystickQuit(void)
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_remove_RawGameControllerRemoved(wgi.statics, wgi.controller_removed_token);
__x_ABI_CWindows_CGaming_CInput_CIRawGameControllerStatics_Release(wgi.statics);
}
- SDL_zero(wgi);
- WIN_CoUninitialize();
+ if (wgi.ro_initialized) {
+ WIN_RoUninitialize();
+ }
+
+ SDL_zero(wgi);
}
static SDL_bool
diff --git a/Engine/lib/sdl/src/locale/vita/SDL_syslocale.c b/Engine/lib/sdl/src/locale/vita/SDL_syslocale.c
new file mode 100644
index 000000000..0a057cbfa
--- /dev/null
+++ b/Engine/lib/sdl/src/locale/vita/SDL_syslocale.c
@@ -0,0 +1,71 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 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"
+#include "../SDL_syslocale.h"
+
+#include
+#include
+
+void
+SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
+{
+ const char *vita_locales[] = {
+ "ja_JP",
+ "en_US",
+ "fr_FR",
+ "es_ES",
+ "de_DE",
+ "it_IT",
+ "nl_NL",
+ "pt_PT",
+ "ru_RU",
+ "ko_KR",
+ "zh_TW",
+ "zh_CN",
+ "fi_FI",
+ "sv_SE",
+ "da_DK",
+ "no_NO",
+ "pl_PL",
+ "pt_BR",
+ "en_GB",
+ "tr_TR",
+ };
+
+ Sint32 language = SCE_SYSTEM_PARAM_LANG_ENGLISH_US;
+ SceAppUtilInitParam initParam;
+ SceAppUtilBootParam bootParam;
+ SDL_zero(initParam);
+ SDL_zero(bootParam);
+ sceAppUtilInit(&initParam, &bootParam);
+ sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_LANG, &language);
+
+ if (language < 0 || language > SCE_SYSTEM_PARAM_LANG_TURKISH)
+ language = SCE_SYSTEM_PARAM_LANG_ENGLISH_US; // default to english
+
+ SDL_strlcpy(buf, vita_locales[language], buflen);
+
+ sceAppUtilShutdown();
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
+
diff --git a/Engine/lib/sdl/src/main/windows/version.rc b/Engine/lib/sdl/src/main/windows/version.rc
index 36ff39f12..11e1394f8 100644
--- a/Engine/lib/sdl/src/main/windows/version.rc
+++ b/Engine/lib/sdl/src/main/windows/version.rc
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,0,21,0
- PRODUCTVERSION 2,0,21,0
+ FILEVERSION 2,0,22,0
+ PRODUCTVERSION 2,0,22,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
@@ -23,12 +23,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SDL\0"
- VALUE "FileVersion", "2, 0, 21, 0\0"
+ VALUE "FileVersion", "2, 0, 22, 0\0"
VALUE "InternalName", "SDL\0"
VALUE "LegalCopyright", "Copyright (C) 2022 Sam Lantinga\0"
VALUE "OriginalFilename", "SDL2.dll\0"
VALUE "ProductName", "Simple DirectMedia Layer\0"
- VALUE "ProductVersion", "2, 0, 21, 0\0"
+ VALUE "ProductVersion", "2, 0, 22, 0\0"
END
END
BLOCK "VarFileInfo"
diff --git a/Engine/lib/sdl/src/render/SDL_render.c b/Engine/lib/sdl/src/render/SDL_render.c
index 441badbc6..58cda3d60 100644
--- a/Engine/lib/sdl/src/render/SDL_render.c
+++ b/Engine/lib/sdl/src/render/SDL_render.c
@@ -356,7 +356,7 @@ QueueCmdSetViewport(SDL_Renderer *renderer)
if (cmd != NULL) {
cmd->command = SDL_RENDERCMD_SETVIEWPORT;
cmd->data.viewport.first = 0; /* render backend will fill this in. */
- /* Convert SDL_FRect to SDL_Rect */
+ /* Convert SDL_DRect to SDL_Rect */
cmd->data.viewport.rect.x = (int)SDL_floor(renderer->viewport.x);
cmd->data.viewport.rect.y = (int)SDL_floor(renderer->viewport.y);
cmd->data.viewport.rect.w = (int)SDL_floor(renderer->viewport.w);
@@ -386,7 +386,7 @@ QueueCmdSetClipRect(SDL_Renderer *renderer)
} else {
cmd->command = SDL_RENDERCMD_SETCLIPRECT;
cmd->data.cliprect.enabled = renderer->clipping_enabled;
- /* Convert SDL_FRect to SDL_Rect */
+ /* Convert SDL_DRect to SDL_Rect */
cmd->data.cliprect.rect.x = (int)SDL_floor(renderer->clip_rect.x);
cmd->data.cliprect.rect.y = (int)SDL_floor(renderer->clip_rect.y);
cmd->data.cliprect.rect.w = (int)SDL_floor(renderer->clip_rect.w);
@@ -580,10 +580,10 @@ QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect * rects, const int cou
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
}
-
- SDL_small_free(xy, isstack1);
- SDL_small_free(indices, isstack2);
}
+ SDL_small_free(xy, isstack1);
+ SDL_small_free(indices, isstack2);
+
} else {
retval = renderer->QueueFillRects(renderer, cmd, rects, count);
if (retval < 0) {
@@ -676,7 +676,7 @@ SDL_GetRenderDriverInfo(int index, SDL_RendererInfo * info)
#endif
}
-static void GetWindowViewportValues(SDL_Renderer *renderer, int *logical_w, int *logical_h, SDL_FRect *viewport, SDL_FPoint *scale)
+static void GetWindowViewportValues(SDL_Renderer *renderer, int *logical_w, int *logical_h, SDL_DRect *viewport, SDL_FPoint *scale)
{
SDL_LockMutex(renderer->target_mutex);
*logical_w = renderer->target ? renderer->logical_w_backup : renderer->logical_w;
@@ -698,7 +698,17 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
renderer->WindowEvent(renderer, &event->window);
}
- if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
+ /* In addition to size changes, we also want to do this block for
+ * moves as well, for two reasons:
+ *
+ * 1. The window could be moved to a new display, which has a new
+ * DPI and therefore a new window/drawable ratio
+ * 2. For whatever reason, the viewport can get messed up during
+ * window movement (this has been observed on macOS), so this is
+ * also a good opportunity to force viewport updates
+ */
+ if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED ||
+ event->window.event == SDL_WINDOWEVENT_MOVED) {
/* Make sure we're operating on the default render target */
SDL_Texture *saved_target = SDL_GetRenderTarget(renderer);
if (saved_target) {
@@ -728,10 +738,10 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
SDL_GetWindowSize(renderer->window, &w, &h);
}
- renderer->viewport.x = 0;
- renderer->viewport.y = 0;
- renderer->viewport.w = (float) w;
- renderer->viewport.h = (float) h;
+ renderer->viewport.x = (double)0;
+ renderer->viewport.y = (double)0;
+ renderer->viewport.w = (double)w;
+ renderer->viewport.h = (double)h;
QueueCmdSetViewport(renderer);
FlushRenderCommandsIfNotBatching(renderer);
}
@@ -758,7 +768,7 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
SDL_Window *window = SDL_GetWindowFromID(event->motion.windowID);
if (window == renderer->window) {
int logical_w, logical_h;
- SDL_FRect viewport;
+ SDL_DRect viewport;
SDL_FPoint scale;
GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
if (logical_w) {
@@ -785,7 +795,7 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
SDL_Window *window = SDL_GetWindowFromID(event->button.windowID);
if (window == renderer->window) {
int logical_w, logical_h;
- SDL_FRect viewport;
+ SDL_DRect viewport;
SDL_FPoint scale;
GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
if (logical_w) {
@@ -800,7 +810,7 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
event->type == SDL_FINGERMOTION) {
int logical_w, logical_h;
float physical_w, physical_h;
- SDL_FRect viewport;
+ SDL_DRect viewport;
SDL_FPoint scale;
GetWindowViewportValues(renderer, &logical_w, &logical_h, &viewport, &scale);
@@ -1095,6 +1105,13 @@ SDL_GetRenderer(SDL_Window * window)
return (SDL_Renderer *)SDL_GetWindowData(window, SDL_WINDOWRENDERDATA);
}
+SDL_Window *
+SDL_RenderGetWindow(SDL_Renderer *renderer)
+{
+ CHECK_RENDERER_MAGIC(renderer, NULL);
+ return renderer->window;
+}
+
int
SDL_GetRendererInfo(SDL_Renderer * renderer, SDL_RendererInfo * info)
{
@@ -1585,10 +1602,11 @@ SDL_SetTextureScaleMode(SDL_Texture * texture, SDL_ScaleMode scaleMode)
CHECK_TEXTURE_MAGIC(texture, -1);
renderer = texture->renderer;
- renderer->SetTextureScaleMode(renderer, texture, scaleMode);
texture->scaleMode = scaleMode;
if (texture->native) {
return SDL_SetTextureScaleMode(texture->native, scaleMode);
+ } else {
+ renderer->SetTextureScaleMode(renderer, texture, scaleMode);
}
return 0;
}
@@ -2210,10 +2228,10 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
}
if (texture) {
- renderer->viewport.x = 0.0f;
- renderer->viewport.y = 0.0f;
- renderer->viewport.w = (float) texture->w;
- renderer->viewport.h = (float) texture->h;
+ renderer->viewport.x = (double)0;
+ renderer->viewport.y = (double)0;
+ renderer->viewport.w = (double)texture->w;
+ renderer->viewport.h = (double)texture->h;
SDL_zero(renderer->clip_rect);
renderer->clipping_enabled = SDL_FALSE;
renderer->scale.x = 1.0f;
@@ -2245,6 +2263,8 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
SDL_Texture *
SDL_GetRenderTarget(SDL_Renderer *renderer)
{
+ CHECK_RENDERER_MAGIC(renderer, NULL);
+
return renderer->target;
}
@@ -2420,19 +2440,19 @@ SDL_RenderSetViewport(SDL_Renderer * renderer, const SDL_Rect * rect)
CHECK_RENDERER_MAGIC(renderer, -1);
if (rect) {
- renderer->viewport.x = rect->x * renderer->scale.x;
- renderer->viewport.y = rect->y * renderer->scale.y;
- renderer->viewport.w = rect->w * renderer->scale.x;
- renderer->viewport.h = rect->h * renderer->scale.y;
+ renderer->viewport.x = (double)rect->x * renderer->scale.x;
+ renderer->viewport.y = (double)rect->y * renderer->scale.y;
+ renderer->viewport.w = (double)rect->w * renderer->scale.x;
+ renderer->viewport.h = (double)rect->h * renderer->scale.y;
} else {
int w, h;
if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) {
return -1;
}
- renderer->viewport.x = 0.0f;
- renderer->viewport.y = 0.0f;
- renderer->viewport.w = (float) w;
- renderer->viewport.h = (float) h;
+ renderer->viewport.x = (double)0;
+ renderer->viewport.y = (double)0;
+ renderer->viewport.w = (double)w;
+ renderer->viewport.h = (double)h;
}
retval = QueueCmdSetViewport(renderer);
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
@@ -2456,8 +2476,8 @@ RenderGetViewportSize(SDL_Renderer * renderer, SDL_FRect * rect)
{
rect->x = 0.0f;
rect->y = 0.0f;
- rect->w = renderer->viewport.w / renderer->scale.x;
- rect->h = renderer->viewport.h / renderer->scale.y;
+ rect->w = (float)(renderer->viewport.w / renderer->scale.x);
+ rect->h = (float)(renderer->viewport.h / renderer->scale.y);
}
int
@@ -2468,10 +2488,10 @@ SDL_RenderSetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect)
if (rect) {
renderer->clipping_enabled = SDL_TRUE;
- renderer->clip_rect.x = rect->x * renderer->scale.x;
- renderer->clip_rect.y = rect->y * renderer->scale.y;
- renderer->clip_rect.w = rect->w * renderer->scale.x;
- renderer->clip_rect.h = rect->h * renderer->scale.y;
+ renderer->clip_rect.x = (double)rect->x * renderer->scale.x;
+ renderer->clip_rect.y = (double)rect->y * renderer->scale.y;
+ renderer->clip_rect.w = (double)rect->w * renderer->scale.x;
+ renderer->clip_rect.h = (double)rect->h * renderer->scale.y;
} else {
renderer->clipping_enabled = SDL_FALSE;
SDL_zero(renderer->clip_rect);
@@ -2535,10 +2555,10 @@ SDL_RenderWindowToLogical(SDL_Renderer * renderer, int windowX, int windowY, flo
window_physical_y = ((float) windowY) / renderer->dpi_scale.y;
if (logicalX) {
- *logicalX = (window_physical_x - renderer->viewport.x) / renderer->scale.x;
+ *logicalX = (float)((window_physical_x - renderer->viewport.x) / renderer->scale.x);
}
if (logicalY) {
- *logicalY = (window_physical_y - renderer->viewport.y) / renderer->scale.y;
+ *logicalY = (float)((window_physical_y - renderer->viewport.y) / renderer->scale.y);
}
}
@@ -2549,8 +2569,8 @@ SDL_RenderLogicalToWindow(SDL_Renderer * renderer, float logicalX, float logical
CHECK_RENDERER_MAGIC(renderer, );
- window_physical_x = (logicalX * renderer->scale.x) + renderer->viewport.x;
- window_physical_y = (logicalY * renderer->scale.y) + renderer->viewport.y;
+ window_physical_x = (float)((logicalX * renderer->scale.x) + renderer->viewport.x);
+ window_physical_y = (float)((logicalY * renderer->scale.y) + renderer->viewport.y);
if (windowX) {
*windowX = (int)(window_physical_x * renderer->dpi_scale.x);
@@ -3138,10 +3158,11 @@ SDL_RenderDrawLinesF(SDL_Renderer * renderer,
num_vertices, indices, num_indices, size_indices,
1.0f, 1.0f);
- SDL_small_free(xy, isstack1);
- SDL_small_free(indices, isstack2);
}
+ SDL_small_free(xy, isstack1);
+ SDL_small_free(indices, isstack2);
+
} else if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
retval = RenderDrawLinesWithRectsF(renderer, points, count);
} else {
diff --git a/Engine/lib/sdl/src/render/SDL_sysrender.h b/Engine/lib/sdl/src/render/SDL_sysrender.h
index 5d92f6a26..7aeb46710 100644
--- a/Engine/lib/sdl/src/render/SDL_sysrender.h
+++ b/Engine/lib/sdl/src/render/SDL_sysrender.h
@@ -28,6 +28,19 @@
#include "SDL_mutex.h"
#include "SDL_yuv_sw_c.h"
+
+/**
+ * A rectangle, with the origin at the upper left (double precision).
+ */
+typedef struct SDL_DRect
+{
+ double x;
+ double y;
+ double w;
+ double h;
+} SDL_DRect;
+
+
/* The SDL 2D rendering system */
typedef struct SDL_RenderDriver SDL_RenderDriver;
@@ -201,12 +214,12 @@ struct SDL_Renderer
SDL_bool integer_scale;
/* The drawable area within the window */
- SDL_FRect viewport;
- SDL_FRect viewport_backup;
+ SDL_DRect viewport;
+ SDL_DRect viewport_backup;
/* The clip rectangle within the window */
- SDL_FRect clip_rect;
- SDL_FRect clip_rect_backup;
+ SDL_DRect clip_rect;
+ SDL_DRect clip_rect_backup;
/* Wether or not the clipping rectangle is used. */
SDL_bool clipping_enabled;
@@ -244,8 +257,8 @@ struct SDL_Renderer
SDL_RenderCommand *render_commands_pool;
Uint32 render_command_generation;
Uint32 last_queued_color;
- SDL_FRect last_queued_viewport;
- SDL_FRect last_queued_cliprect;
+ SDL_DRect last_queued_viewport;
+ SDL_DRect last_queued_cliprect;
SDL_bool last_queued_cliprect_enabled;
SDL_bool color_queued;
SDL_bool viewport_queued;
diff --git a/Engine/lib/sdl/src/render/direct3d/SDL_render_d3d.c b/Engine/lib/sdl/src/render/direct3d/SDL_render_d3d.c
index b267fb23e..477f4e975 100644
--- a/Engine/lib/sdl/src/render/direct3d/SDL_render_d3d.c
+++ b/Engine/lib/sdl/src/render/direct3d/SDL_render_d3d.c
@@ -347,7 +347,8 @@ D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
}
}
-static D3DBLEND GetBlendFunc(SDL_BlendFactor factor)
+static D3DBLEND
+GetBlendFunc(SDL_BlendFactor factor)
{
switch (factor) {
case SDL_BLENDFACTOR_ZERO:
@@ -370,9 +371,28 @@ static D3DBLEND GetBlendFunc(SDL_BlendFactor factor)
return D3DBLEND_DESTALPHA;
case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
return D3DBLEND_INVDESTALPHA;
- default:
- return (D3DBLEND)0;
+ default: break;
}
+ return (D3DBLEND) 0;
+}
+
+static D3DBLENDOP
+GetBlendEquation(SDL_BlendOperation operation)
+{
+ switch (operation) {
+ case SDL_BLENDOPERATION_ADD:
+ return D3DBLENDOP_ADD;
+ case SDL_BLENDOPERATION_SUBTRACT:
+ return D3DBLENDOP_SUBTRACT;
+ case SDL_BLENDOPERATION_REV_SUBTRACT:
+ return D3DBLENDOP_REVSUBTRACT;
+ case SDL_BLENDOPERATION_MINIMUM:
+ return D3DBLENDOP_MIN;
+ case SDL_BLENDOPERATION_MAXIMUM:
+ return D3DBLENDOP_MAX;
+ default: break;
+ }
+ return (D3DBLENDOP) 0;
}
static SDL_bool
@@ -387,14 +407,16 @@ D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
if (!GetBlendFunc(srcColorFactor) || !GetBlendFunc(srcAlphaFactor) ||
- !GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor)) {
+ !GetBlendEquation(colorOperation) ||
+ !GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor) ||
+ !GetBlendEquation(alphaOperation)) {
return SDL_FALSE;
}
- if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->enableSeparateAlphaBlend) {
- return SDL_FALSE;
- }
- if (colorOperation != SDL_BLENDOPERATION_ADD || alphaOperation != SDL_BLENDOPERATION_ADD) {
- return SDL_FALSE;
+
+ if (!data->enableSeparateAlphaBlend) {
+ if ((srcColorFactor != srcAlphaFactor) || (dstColorFactor != dstAlphaFactor) || (colorOperation != alphaOperation)) {
+ return SDL_FALSE;
+ }
}
return SDL_TRUE;
}
@@ -1040,11 +1062,15 @@ SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)));
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)));
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_BLENDOP,
+ GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
if (data->enableSeparateAlphaBlend) {
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)));
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_BLENDOPALPHA,
+ GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
}
}
diff --git a/Engine/lib/sdl/src/render/direct3d11/SDL_render_d3d11.c b/Engine/lib/sdl/src/render/direct3d11/SDL_render_d3d11.c
index 89e2ee544..714ca2e77 100644
--- a/Engine/lib/sdl/src/render/direct3d11/SDL_render_d3d11.c
+++ b/Engine/lib/sdl/src/render/direct3d11/SDL_render_d3d11.c
@@ -998,6 +998,16 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
goto done;
}
+ /* Set the swap chain target immediately, so that a target is always set
+ * even before we get to SetDrawState. Without this it's possible to hit
+ * null references in places like ReadPixels!
+ */
+ ID3D11DeviceContext_OMSetRenderTargets(data->d3dContext,
+ 1,
+ &data->mainRenderTargetView,
+ NULL
+ );
+
data->viewportDirty = SDL_TRUE;
done:
diff --git a/Engine/lib/sdl/src/render/opengl/SDL_render_gl.c b/Engine/lib/sdl/src/render/opengl/SDL_render_gl.c
index b5df73ace..b5af52af3 100644
--- a/Engine/lib/sdl/src/render/opengl/SDL_render_gl.c
+++ b/Engine/lib/sdl/src/render/opengl/SDL_render_gl.c
@@ -30,6 +30,11 @@
#include
#endif
+#ifdef SDL_VIDEO_VITA_PVR_OGL
+#include
+#include
+#endif
+
/* To prevent unnecessary window recreation,
* these should match the defaults selected in SDL_GL_ResetAttributes
*/
@@ -319,6 +324,20 @@ GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h)
return result;
}
+static void
+GL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
+{
+ /* If the window x/y/w/h changed at all, assume the viewport has been
+ * changed behind our backs. x/y changes might seem weird but viewport
+ * resets have been observed on macOS at minimum!
+ */
+ if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
+ event->event == SDL_WINDOWEVENT_MOVED) {
+ GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
+ data->drawstate.viewport_dirty = SDL_TRUE;
+ }
+}
+
static int
GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
{
@@ -1212,9 +1231,9 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
}
#ifdef __MACOSX__
- // On macOS, moving the window seems to invalidate the OpenGL viewport state,
- // so don't bother trying to persist it across frames; always reset it.
- // Workaround for: https://github.com/libsdl-org/SDL/issues/1504
+ // On macOS on older systems, the OpenGL view change and resize events aren't
+ // necessarily synchronized, so just always reset it.
+ // Workaround for: https://discourse.libsdl.org/t/sdl-2-0-22-prerelease/35306/6
data->drawstate.viewport_dirty = SDL_TRUE;
#endif
@@ -1733,6 +1752,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
+#ifndef SDL_VIDEO_VITA_PVR_OGL
window_flags = SDL_GetWindowFlags(window);
if (!(window_flags & SDL_WINDOW_OPENGL) ||
profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
@@ -1746,6 +1766,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
goto error;
}
}
+#endif
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
@@ -1760,6 +1781,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
goto error;
}
+ renderer->WindowEvent = GL_WindowEvent;
renderer->GetOutputSize = GL_GetOutputSize;
renderer->SupportsBlendMode = GL_SupportsBlendMode;
renderer->CreateTexture = GL_CreateTexture;
diff --git a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm.c b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm.c
index 8a8877849..98b03e629 100644
--- a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm.c
+++ b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm.c
@@ -61,6 +61,11 @@ static int VITA_GXM_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * text
const Uint8 *Uplane, int Upitch,
const Uint8 *Vplane, int Vpitch);
+static int VITA_GXM_UpdateTextureNV(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect,
+ const Uint8 *Yplane, int Ypitch,
+ const Uint8 *UVplane, int UVpitch);
+
static int VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, void **pixels, int *pitch);
@@ -105,12 +110,16 @@ SDL_RenderDriver VITA_GXM_RenderDriver = {
.info = {
.name = "VITA gxm",
.flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE,
- .num_texture_formats = 4,
+ .num_texture_formats = 8,
.texture_formats = {
[0] = SDL_PIXELFORMAT_ABGR8888,
[1] = SDL_PIXELFORMAT_ARGB8888,
[2] = SDL_PIXELFORMAT_RGB565,
- [3] = SDL_PIXELFORMAT_BGR565
+ [3] = SDL_PIXELFORMAT_BGR565,
+ [4] = SDL_PIXELFORMAT_YV12,
+ [5] = SDL_PIXELFORMAT_IYUV,
+ [6] = SDL_PIXELFORMAT_NV12,
+ [7] = SDL_PIXELFORMAT_NV21,
},
.max_texture_width = 4096,
.max_texture_height = 4096,
@@ -133,6 +142,15 @@ PixelFormatToVITAFMT(Uint32 format)
return SCE_GXM_TEXTURE_FORMAT_U5U6U5_RGB;
case SDL_PIXELFORMAT_BGR565:
return SCE_GXM_TEXTURE_FORMAT_U5U6U5_BGR;
+ case SDL_PIXELFORMAT_YV12:
+ return SCE_GXM_TEXTURE_FORMAT_YVU420P3_CSC0;
+ case SDL_PIXELFORMAT_IYUV:
+ return SCE_GXM_TEXTURE_FORMAT_YUV420P3_CSC0;
+ // should be the other way around. looks like SCE bug.
+ case SDL_PIXELFORMAT_NV12:
+ return SCE_GXM_TEXTURE_FORMAT_YVU420P2_CSC0;
+ case SDL_PIXELFORMAT_NV21:
+ return SCE_GXM_TEXTURE_FORMAT_YUV420P2_CSC0;
default:
return SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR;
}
@@ -228,6 +246,7 @@ VITA_GXM_CreateRenderer(SDL_Window *window, Uint32 flags)
renderer->UpdateTexture = VITA_GXM_UpdateTexture;
#if SDL_HAVE_YUV
renderer->UpdateTextureYUV = VITA_GXM_UpdateTextureYUV;
+ renderer->UpdateTextureNV = VITA_GXM_UpdateTextureNV;
#endif
renderer->LockTexture = VITA_GXM_LockTexture;
renderer->UnlockTexture = VITA_GXM_UnlockTexture;
@@ -295,7 +314,17 @@ VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
return SDL_OutOfMemory();
}
- vita_texture->tex = create_gxm_texture(data, texture->w, texture->h, PixelFormatToVITAFMT(texture->format), (texture->access == SDL_TEXTUREACCESS_TARGET));
+ vita_texture->tex = create_gxm_texture(
+ data,
+ texture->w,
+ texture->h,
+ PixelFormatToVITAFMT(texture->format),
+ (texture->access == SDL_TEXTUREACCESS_TARGET),
+ &(vita_texture->w),
+ &(vita_texture->h),
+ &(vita_texture->pitch),
+ &(vita_texture->wscale)
+ );
if (!vita_texture->tex) {
SDL_free(vita_texture);
@@ -306,38 +335,129 @@ VITA_GXM_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
VITA_GXM_SetTextureScaleMode(renderer, texture, texture->scaleMode);
- vita_texture->w = gxm_texture_get_width(vita_texture->tex);
- vita_texture->h = gxm_texture_get_height(vita_texture->tex);
- vita_texture->pitch = gxm_texture_get_stride(vita_texture->tex);
+#if SDL_HAVE_YUV
+ vita_texture->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
+ vita_texture->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
+#endif
return 0;
}
+static void VITA_GXM_SetYUVProfile(SDL_Renderer * renderer, SDL_Texture *texture)
+{
+ VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
+ int ret = 0;
+ switch (SDL_GetYUVConversionModeForResolution(texture->w, texture->h)) {
+ case SDL_YUV_CONVERSION_BT601:
+ ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT601_STANDARD);
+ break;
+ case SDL_YUV_CONVERSION_BT709:
+ ret = sceGxmSetYuvProfile(data->gxm_context, 0, SCE_GXM_YUV_PROFILE_BT709_STANDARD);
+ break;
+ case SDL_YUV_CONVERSION_JPEG:
+ default:
+ SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Unsupported YUV profile: %d\n", SDL_GetYUVConversionModeForResolution(texture->w, texture->h));
+ break;
+ }
+
+ if (ret < 0) {
+ SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Setting YUV profile failed: %x\n", ret);
+ }
+}
static int
VITA_GXM_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, const void *pixels, int pitch)
{
- const Uint8 *src;
+ VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata;
Uint8 *dst;
- int row, length,dpitch;
- src = pixels;
+ int row, length, dpitch;
+
+#if SDL_HAVE_YUV
+ if (vita_texture->yuv || vita_texture->nv12) {
+ VITA_GXM_SetYUVProfile(renderer, texture);
+ }
+#endif
VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch);
length = rect->w * SDL_BYTESPERPIXEL(texture->format);
if (length == pitch && length == dpitch) {
- SDL_memcpy(dst, src, length*rect->h);
+ SDL_memcpy(dst, pixels, length*rect->h);
} else {
for (row = 0; row < rect->h; ++row) {
- SDL_memcpy(dst, src, length);
- src += pitch;
+ SDL_memcpy(dst, pixels, length);
+ pixels += pitch;
dst += dpitch;
}
}
+#if SDL_HAVE_YUV
+ if (vita_texture->yuv) {
+ void *Udst;
+ void *Vdst;
+ int uv_pitch = (dpitch+1) / 2;
+ int uv_src_pitch = (pitch+1) / 2;
+ SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2};
+
+ // skip Y plane
+ Uint8 *Dpixels = gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h);
+
+ Udst = Dpixels + (UVrect.y * uv_pitch) + UVrect.x;
+ Vdst = Dpixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x;
+
+ length = UVrect.w;
+
+ // U plane
+ if (length == uv_src_pitch && length == uv_pitch) {
+ SDL_memcpy(Udst, pixels, length*UVrect.h);
+ } else {
+ for (row = 0; row < UVrect.h; ++row) {
+ SDL_memcpy(Udst, pixels, length);
+ pixels += uv_src_pitch;
+ Udst += uv_pitch;
+ }
+ }
+
+ // V plane
+ if (length == uv_src_pitch && length == uv_pitch) {
+ SDL_memcpy(Vdst, pixels, length*UVrect.h);
+ } else {
+ for (row = 0; row < UVrect.h; ++row) {
+ SDL_memcpy(Vdst, pixels, length);
+ pixels += uv_src_pitch;
+ Vdst += uv_pitch;
+ }
+ }
+
+ } else if (vita_texture->nv12) {
+ void *UVdst;
+ int uv_pitch = 2 * ((dpitch+1) / 2);
+ int uv_src_pitch = 2 * ((pitch+1) / 2);
+ SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2 , (rect->h + 1) / 2};
+
+ // skip Y plane
+ void *Dpixels = (void *) ((Uint8 *) gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h));
+ UVdst = Dpixels + (UVrect.y * uv_pitch) + UVrect.x;
+
+ length = UVrect.w*2;
+
+ // UV plane
+ if (length == uv_src_pitch && length == uv_pitch) {
+ SDL_memcpy(UVdst, pixels, length*UVrect.h);
+ } else {
+ for (row = 0; row < UVrect.h; ++row) {
+ SDL_memcpy(UVdst, pixels, length);
+ pixels += uv_src_pitch;
+ UVdst += uv_pitch;
+ }
+ }
+ }
+#endif
+
return 0;
}
+#if SDL_HAVE_YUV
static int
VITA_GXM_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect,
@@ -345,9 +465,133 @@ VITA_GXM_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
const Uint8 *Uplane, int Upitch,
const Uint8 *Vplane, int Vpitch)
{
+ Uint8 *dst;
+ int row, length, dpitch;
+ SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2};
+
+ VITA_GXM_SetYUVProfile(renderer, texture);
+
+ // copy Y plane
+ // obtain pixels via locking so that texture is flushed
+ VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch);
+
+ length = rect->w;
+
+ if (length == Ypitch && length == dpitch) {
+ SDL_memcpy(dst, Yplane, length*rect->h);
+ } else {
+ for (row = 0; row < rect->h; ++row) {
+ SDL_memcpy(dst, Yplane, length);
+ Yplane += Ypitch;
+ dst += dpitch;
+ }
+ }
+
+ // U/V planes
+ {
+ void *Udst;
+ void *Vdst;
+ VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata;
+ int uv_pitch = (dpitch+1) / 2;
+
+ // skip Y plane
+ void *pixels = (void *) ((Uint8 *) gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h));
+
+ if (texture->format == SDL_PIXELFORMAT_YV12) { // YVU
+ Vdst = pixels + (UVrect.y * uv_pitch) + UVrect.x;
+ Udst = pixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x;
+ } else { // YUV
+ Udst = pixels + (UVrect.y * uv_pitch) + UVrect.x;
+ Vdst = pixels + (uv_pitch * ((vita_texture->h + 1) / 2)) + (UVrect.y * uv_pitch) + UVrect.x;
+ }
+
+ length = UVrect.w;
+
+ // U plane
+ if (length == Upitch && length == uv_pitch) {
+ SDL_memcpy(Udst, Uplane, length*UVrect.h);
+ } else {
+ for (row = 0; row < UVrect.h; ++row) {
+ SDL_memcpy(Udst, Uplane, length);
+ Uplane += Upitch;
+ Udst += uv_pitch;
+ }
+ }
+
+ // V plane
+ if (length == Vpitch && length == uv_pitch) {
+ SDL_memcpy(Vdst, Vplane, length*UVrect.h);
+ } else {
+ for (row = 0; row < UVrect.h; ++row) {
+ SDL_memcpy(Vdst, Vplane, length);
+ Vplane += Vpitch;
+ Vdst += uv_pitch;
+ }
+ }
+
+ }
+
return 0;
}
+static int
+VITA_GXM_UpdateTextureNV(SDL_Renderer * renderer, SDL_Texture * texture,
+ const SDL_Rect * rect,
+ const Uint8 *Yplane, int Ypitch,
+ const Uint8 *UVplane, int UVpitch)
+{
+
+ Uint8 *dst;
+ int row, length, dpitch;
+ SDL_Rect UVrect = {rect->x / 2, rect->y / 2, (rect->w + 1) / 2, (rect->h + 1) / 2};
+
+ VITA_GXM_SetYUVProfile(renderer, texture);
+
+ // copy Y plane
+ VITA_GXM_LockTexture(renderer, texture, rect, (void **)&dst, &dpitch);
+
+ length = rect->w * SDL_BYTESPERPIXEL(texture->format);
+
+ if (length == Ypitch && length == dpitch) {
+ SDL_memcpy(dst, Yplane, length*rect->h);
+ } else {
+ for (row = 0; row < rect->h; ++row) {
+ SDL_memcpy(dst, Yplane, length);
+ Yplane += Ypitch;
+ dst += dpitch;
+ }
+ }
+
+ // UV plane
+ {
+ void *UVdst;
+ VITA_GXM_TextureData *vita_texture = (VITA_GXM_TextureData *) texture->driverdata;
+ int uv_pitch = 2 * ((dpitch+1) / 2);
+
+ // skip Y plane
+ void *pixels = (void *) ((Uint8 *) gxm_texture_get_datap(vita_texture->tex) + (vita_texture->pitch * vita_texture->h));
+
+ UVdst = pixels + (UVrect.y * uv_pitch) + UVrect.x;
+
+ length = UVrect.w * 2;
+
+ // UV plane
+ if (length == UVpitch && length == uv_pitch) {
+ SDL_memcpy(UVdst, UVplane, length*UVrect.h);
+ } else {
+ for (row = 0; row < UVrect.h; ++row) {
+ SDL_memcpy(UVdst, UVplane, length);
+ UVplane += UVpitch;
+ UVdst += uv_pitch;
+ }
+ }
+ }
+
+ return 0;
+}
+
+#endif
+
static int
VITA_GXM_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
const SDL_Rect *rect, void **pixels, int *pitch)
@@ -519,6 +763,7 @@ VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Textu
size_indices = indices ? size_indices : 0;
if (texture) {
+ VITA_GXM_TextureData* vita_texture = (VITA_GXM_TextureData*) texture->driverdata;
texture_vertex *vertices;
vertices = (texture_vertex *)pool_malloc(
@@ -551,7 +796,7 @@ VITA_GXM_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Textu
vertices[i].x = xy_[0] * scale_x;
vertices[i].y = xy_[1] * scale_y;
- vertices[i].u = uv_[0];
+ vertices[i].u = uv_[0] * vita_texture->wscale;
vertices[i].v = uv_[1];
vertices[i].color = col_;
}
@@ -730,14 +975,6 @@ SetDrawState(VITA_GXM_RenderData *data, const SDL_RenderCommand *cmd)
return 0;
}
-static int
-SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
-{
- VITA_GXM_RenderData *data = (VITA_GXM_RenderData *) renderer->driverdata;
-
- return SetDrawState(data, cmd);
-}
-
static int
VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
@@ -824,11 +1061,7 @@ VITA_GXM_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *
nextcmd = nextcmd->next;
}
- if (thistexture) {
- ret = SetCopyState(renderer, cmd);
- } else {
- ret = SetDrawState(data, cmd);
- }
+ ret = SetDrawState(data, cmd);
if (ret == 0) {
int op = SCE_GXM_PRIMITIVE_TRIANGLES;
@@ -1013,7 +1246,7 @@ VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
sceGxmFinish(data->gxm_context);
- free_gxm_texture(vita_texture->tex);
+ free_gxm_texture(data, vita_texture->tex);
SDL_free(vita_texture);
diff --git a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_memory.c b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_memory.c
index d3322730a..85d682ad7 100644
--- a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_memory.c
+++ b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_memory.c
@@ -26,7 +26,7 @@
#include "SDL_render_vita_gxm_memory.h"
void *
-mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid)
+vita_mem_alloc(unsigned int type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid)
{
void *mem;
@@ -51,7 +51,7 @@ mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignm
}
void
-mem_gpu_free(SceUID uid)
+vita_mem_free(SceUID uid)
{
void *mem = NULL;
if (sceKernelGetMemBlockBase(uid, &mem) < 0)
@@ -61,7 +61,71 @@ mem_gpu_free(SceUID uid)
}
void *
-mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
+vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size)
+{
+ void *mem;
+
+ if (data->texturePool == NULL) {
+ int poolsize;
+ int ret;
+ SceKernelFreeMemorySizeInfo info;
+ info.size = sizeof(SceKernelFreeMemorySizeInfo);
+ sceKernelGetFreeMemorySize(&info);
+
+ poolsize = ALIGN(info.size_cdram, 256*1024);
+ if (poolsize > info.size_cdram) {
+ poolsize = ALIGN(info.size_cdram - 256*1024, 256*1024);
+ }
+ data->texturePoolUID = sceKernelAllocMemBlock("gpu_texture_pool", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, poolsize, NULL);
+ if (data->texturePoolUID < 0) {
+ return NULL;
+ }
+
+ ret = sceKernelGetMemBlockBase(data->texturePoolUID, &mem);
+ if ( ret < 0)
+ {
+ return NULL;
+ }
+ data->texturePool = sceClibMspaceCreate(mem, poolsize);
+
+ if (data->texturePool == NULL) {
+ return NULL;
+ }
+ ret = sceGxmMapMemory(mem, poolsize, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE);
+ if (ret < 0)
+ {
+ return NULL;
+ }
+ }
+ return sceClibMspaceMemalign(data->texturePool, SCE_GXM_TEXTURE_ALIGNMENT, size);
+}
+
+void
+vita_gpu_mem_free(VITA_GXM_RenderData *data, void* ptr)
+{
+ if (data->texturePool != NULL)
+ {
+ sceClibMspaceFree(data->texturePool, ptr);
+ }
+}
+
+void
+vita_gpu_mem_destroy(VITA_GXM_RenderData *data)
+{
+ void *mem = NULL;
+ if (data->texturePool != NULL)
+ {
+ sceClibMspaceDestroy(data->texturePool);
+ data->texturePool = NULL;
+ if (sceKernelGetMemBlockBase(data->texturePoolUID, &mem) < 0)
+ return;
+ sceGxmUnmapMemory(mem);
+ sceKernelFreeMemBlock(data->texturePoolUID);
+ }
+}
+
+void *
+vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
{
void *mem = NULL;
@@ -77,7 +141,7 @@ mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
}
void
-mem_vertex_usse_free(SceUID uid)
+vita_mem_vertex_usse_free(SceUID uid)
{
void *mem = NULL;
if (sceKernelGetMemBlockBase(uid, &mem) < 0)
@@ -87,7 +151,7 @@ mem_vertex_usse_free(SceUID uid)
}
void *
-mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
+vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
{
void *mem = NULL;
@@ -103,7 +167,7 @@ mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offse
}
void
-mem_fragment_usse_free(SceUID uid)
+vita_mem_fragment_usse_free(SceUID uid)
{
void *mem = NULL;
if (sceKernelGetMemBlockBase(uid, &mem) < 0)
diff --git a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_memory.h b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_memory.h
index 51bc8a80a..93b9f3498 100644
--- a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_memory.h
+++ b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_memory.h
@@ -25,15 +25,19 @@
#include
#include
#include
+#include "SDL_render_vita_gxm_types.h"
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
-void *mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid);
-void mem_gpu_free(SceUID uid);
-void *mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
-void mem_vertex_usse_free(SceUID uid);
-void *mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
-void mem_fragment_usse_free(SceUID uid);
+void *vita_mem_alloc(unsigned int type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid);
+void vita_mem_free(SceUID uid);
+void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size);
+void vita_gpu_mem_free(VITA_GXM_RenderData *data, void* ptr);
+void vita_gpu_mem_destroy(VITA_GXM_RenderData *data);
+void *vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
+void vita_mem_vertex_usse_free(SceUID uid);
+void *vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
+void vita_mem_fragment_usse_free(SceUID uid);
#endif /* SDL_RENDER_VITA_GXM_MEMORY_H */
diff --git a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_tools.c b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_tools.c
index e043b55ab..035e8a63c 100644
--- a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_tools.c
+++ b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_tools.c
@@ -117,6 +117,8 @@ tex_format_to_bytespp(SceGxmTextureFormat format)
case SCE_GXM_TEXTURE_BASE_FORMAT_U8:
case SCE_GXM_TEXTURE_BASE_FORMAT_S8:
case SCE_GXM_TEXTURE_BASE_FORMAT_P8:
+ case SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2: // YUV actually uses 12 bits per pixel. UV planes bits/mem are handled elsewhere
+ case SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3:
return 1;
case SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4:
case SCE_GXM_TEXTURE_BASE_FORMAT_U8U3U3U2:
@@ -414,28 +416,28 @@ gxm_init(SDL_Renderer *renderer)
}
// allocate ring buffer memory using default sizes
- vdmRingBuffer = mem_gpu_alloc(
+ vdmRingBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE,
4,
SCE_GXM_MEMORY_ATTRIB_READ,
&data->vdmRingBufferUid);
- vertexRingBuffer = mem_gpu_alloc(
+ vertexRingBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE,
4,
SCE_GXM_MEMORY_ATTRIB_READ,
&data->vertexRingBufferUid);
- fragmentRingBuffer = mem_gpu_alloc(
+ fragmentRingBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE,
4,
SCE_GXM_MEMORY_ATTRIB_READ,
&data->fragmentRingBufferUid);
- fragmentUsseRingBuffer = mem_fragment_usse_alloc(
+ fragmentUsseRingBuffer = vita_mem_fragment_usse_alloc(
SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE,
&data->fragmentUsseRingBufferUid,
&fragmentUsseRingBufferOffset);
@@ -480,7 +482,7 @@ gxm_init(SDL_Renderer *renderer)
for (i = 0; i < VITA_GXM_BUFFERS; i++) {
// allocate memory for display
- data->displayBufferData[i] = mem_gpu_alloc(
+ data->displayBufferData[i] = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
@@ -525,7 +527,7 @@ gxm_init(SDL_Renderer *renderer)
// allocate the depth buffer
- data->depthBufferData = mem_gpu_alloc(
+ data->depthBufferData = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
4 * sampleCount,
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@@ -533,7 +535,7 @@ gxm_init(SDL_Renderer *renderer)
&data->depthBufferUid);
// allocate the stencil buffer
- data->stencilBufferData = mem_gpu_alloc(
+ data->stencilBufferData = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
4 * sampleCount,
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@@ -565,19 +567,19 @@ gxm_init(SDL_Renderer *renderer)
// allocate memory for buffers and USSE code
- patcherBuffer = mem_gpu_alloc(
+ patcherBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
patcherBufferSize,
4,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&data->patcherBufferUid);
- patcherVertexUsse = mem_vertex_usse_alloc(
+ patcherVertexUsse = vita_mem_vertex_usse_alloc(
patcherVertexUsseSize,
&data->patcherVertexUsseUid,
&patcherVertexUsseOffset);
- patcherFragmentUsse = mem_fragment_usse_alloc(
+ patcherFragmentUsse = vita_mem_fragment_usse_alloc(
patcherFragmentUsseSize,
&data->patcherFragmentUsseUid,
&patcherFragmentUsseOffset);
@@ -728,7 +730,7 @@ gxm_init(SDL_Renderer *renderer)
}
// create the clear triangle vertex/index data
- data->clearVertices = (clear_vertex *)mem_gpu_alloc(
+ data->clearVertices = (clear_vertex *)vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
3*sizeof(clear_vertex),
4,
@@ -740,7 +742,7 @@ gxm_init(SDL_Renderer *renderer)
// Allocate a 64k * 2 bytes = 128 KiB buffer and store all possible
// 16-bit indices in linear ascending order, so we can use this for
// all drawing operations where we don't want to use indexing.
- data->linearIndices = (uint16_t *)mem_gpu_alloc(
+ data->linearIndices = (uint16_t *)vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
UINT16_MAX*sizeof(uint16_t),
sizeof(uint16_t),
@@ -871,7 +873,7 @@ gxm_init(SDL_Renderer *renderer)
data->textureWvpParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(textureVertexProgramGxp, "wvp");
// Allocate memory for the memory pool
- data->pool_addr[0] = mem_gpu_alloc(
+ data->pool_addr[0] = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW,
VITA_GXM_POOL_SIZE,
sizeof(void *),
@@ -879,7 +881,7 @@ gxm_init(SDL_Renderer *renderer)
&data->poolUid[0]
);
- data->pool_addr[1] = mem_gpu_alloc(
+ data->pool_addr[1] = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW,
VITA_GXM_POOL_SIZE,
sizeof(void *),
@@ -918,28 +920,28 @@ void gxm_finish(SDL_Renderer *renderer)
free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mod);
free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mul);
- mem_gpu_free(data->linearIndicesUid);
- mem_gpu_free(data->clearVerticesUid);
+ vita_mem_free(data->linearIndicesUid);
+ vita_mem_free(data->clearVerticesUid);
// wait until display queue is finished before deallocating display buffers
sceGxmDisplayQueueFinish();
// clean up display queue
- mem_gpu_free(data->depthBufferUid);
+ vita_mem_free(data->depthBufferUid);
for (size_t i = 0; i < VITA_GXM_BUFFERS; i++)
{
// clear the buffer then deallocate
SDL_memset(data->displayBufferData[i], 0, VITA_GXM_SCREEN_HEIGHT * VITA_GXM_SCREEN_STRIDE * 4);
- mem_gpu_free(data->displayBufferUid[i]);
+ vita_mem_free(data->displayBufferUid[i]);
// destroy the sync object
sceGxmSyncObjectDestroy(data->displayBufferSync[i]);
}
// Free the depth and stencil buffer
- mem_gpu_free(data->depthBufferUid);
- mem_gpu_free(data->stencilBufferUid);
+ vita_mem_free(data->depthBufferUid);
+ vita_mem_free(data->stencilBufferUid);
// unregister programs and destroy shader patcher
sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->clearFragmentProgramId);
@@ -950,23 +952,24 @@ void gxm_finish(SDL_Renderer *renderer)
sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureVertexProgramId);
sceGxmShaderPatcherDestroy(data->shaderPatcher);
- mem_fragment_usse_free(data->patcherFragmentUsseUid);
- mem_vertex_usse_free(data->patcherVertexUsseUid);
- mem_gpu_free(data->patcherBufferUid);
+ vita_mem_fragment_usse_free(data->patcherFragmentUsseUid);
+ vita_mem_vertex_usse_free(data->patcherVertexUsseUid);
+ vita_mem_free(data->patcherBufferUid);
// destroy the render target
sceGxmDestroyRenderTarget(data->renderTarget);
// destroy the gxm context
sceGxmDestroyContext(data->gxm_context);
- mem_fragment_usse_free(data->fragmentUsseRingBufferUid);
- mem_gpu_free(data->fragmentRingBufferUid);
- mem_gpu_free(data->vertexRingBufferUid);
- mem_gpu_free(data->vdmRingBufferUid);
+ vita_mem_fragment_usse_free(data->fragmentUsseRingBufferUid);
+ vita_mem_free(data->fragmentRingBufferUid);
+ vita_mem_free(data->vertexRingBufferUid);
+ vita_mem_free(data->vdmRingBufferUid);
SDL_free(data->contextParams.hostMem);
- mem_gpu_free(data->poolUid[0]);
- mem_gpu_free(data->poolUid[1]);
+ vita_mem_free(data->poolUid[0]);
+ vita_mem_free(data->poolUid[1]);
+ vita_gpu_mem_destroy(data);
// terminate libgxm
sceGxmTerminate();
@@ -975,16 +978,20 @@ void gxm_finish(SDL_Renderer *renderer)
// textures
void
-free_gxm_texture(gxm_texture *texture)
+free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture)
{
if (texture) {
if (texture->gxm_rendertarget) {
sceGxmDestroyRenderTarget(texture->gxm_rendertarget);
}
if (texture->depth_UID) {
- mem_gpu_free(texture->depth_UID);
+ vita_mem_free(texture->depth_UID);
+ }
+ if (texture->cdram) {
+ vita_gpu_mem_free(data, sceGxmTextureGetData(&texture->gxm_tex));
+ } else {
+ vita_mem_free(texture->data_UID);
}
- mem_gpu_free(texture->data_UID);
SDL_free(texture);
}
}
@@ -995,25 +1002,6 @@ gxm_texture_get_format(const gxm_texture *texture)
return sceGxmTextureGetFormat(&texture->gxm_tex);
}
-unsigned int
-gxm_texture_get_width(const gxm_texture *texture)
-{
- return sceGxmTextureGetWidth(&texture->gxm_tex);
-}
-
-unsigned int
-gxm_texture_get_height(const gxm_texture *texture)
-{
- return sceGxmTextureGetHeight(&texture->gxm_tex);
-}
-
-unsigned int
-gxm_texture_get_stride(const gxm_texture *texture)
-{
- return ((gxm_texture_get_width(texture) + 7) & ~7)
- * tex_format_to_bytespp(gxm_texture_get_format(texture));
-}
-
void *
gxm_texture_get_datap(const gxm_texture *texture)
{
@@ -1021,34 +1009,53 @@ gxm_texture_get_datap(const gxm_texture *texture)
}
gxm_texture *
-create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget)
+create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale)
{
gxm_texture *texture = SDL_calloc(1, sizeof(gxm_texture));
- const int tex_size = ((w + 7) & ~ 7) * h * tex_format_to_bytespp(format);
+ int aligned_w = ALIGN(w, 8);
+ int texture_w = w;
+ int tex_size = aligned_w * h * tex_format_to_bytespp(format);
void *texture_data;
+ int ret;
+
+ *return_wscale = 1.0f;
+
+ // SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3/P2 based formats require width aligned to 16
+ if ( (format & 0x9f000000U) == SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P3 || (format & 0x9f000000U) == SCE_GXM_TEXTURE_BASE_FORMAT_YUV420P2) {
+ aligned_w = ALIGN(w, 16);
+ texture_w = aligned_w;
+ tex_size = aligned_w * h * tex_format_to_bytespp(format);
+ *return_wscale = (float) (w) / texture_w;
+ // add storage for UV planes
+ tex_size += (((aligned_w + 1) / 2) * ((h + 1) / 2)) * 2;
+ }
if (!texture)
return NULL;
+ *return_w = w;
+ *return_h = h;
+ *return_pitch = aligned_w * tex_format_to_bytespp(format);
+
/* Allocate a GPU buffer for the texture */
- texture_data = mem_gpu_alloc(
- SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
- tex_size,
- SCE_GXM_TEXTURE_ALIGNMENT,
- SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
- &texture->data_UID
+ texture_data = vita_gpu_mem_alloc(
+ data,
+ tex_size
);
/* Try SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE in case we're out of VRAM */
if (!texture_data) {
SDL_LogWarn(SDL_LOG_CATEGORY_RENDER, "CDRAM texture allocation failed\n");
- texture_data = mem_gpu_alloc(
+ texture_data = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
tex_size,
SCE_GXM_TEXTURE_ALIGNMENT,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&texture->data_UID
);
+ texture->cdram = 0;
+ } else {
+ texture->cdram = 1;
}
if (!texture_data) {
@@ -1060,7 +1067,12 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
SDL_memset(texture_data, 0, tex_size);
/* Create the gxm texture */
- sceGxmTextureInitLinear( &texture->gxm_tex, texture_data, format, w, h, 0);
+ ret = sceGxmTextureInitLinear( &texture->gxm_tex, texture_data, format, texture_w, h, 0);
+ if (ret < 0) {
+ free_gxm_texture(data, texture);
+ SDL_LogError(SDL_LOG_CATEGORY_RENDER, "texture init failed: %x\n", ret);
+ return NULL;
+ }
if (isRenderTarget) {
void *depthBufferData;
@@ -1083,13 +1095,13 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
);
if (err < 0) {
- free_gxm_texture(texture);
- SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %d\n", err);
+ free_gxm_texture(data, texture);
+ SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %x\n", err);
return NULL;
}
// allocate it
- depthBufferData = mem_gpu_alloc(
+ depthBufferData = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
4*sampleCount,
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@@ -1106,8 +1118,8 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
NULL);
if (err < 0) {
- free_gxm_texture(texture);
- SDL_LogError(SDL_LOG_CATEGORY_RENDER, "depth stencil init failed: %d\n", err);
+ free_gxm_texture(data, texture);
+ SDL_LogError(SDL_LOG_CATEGORY_RENDER, "depth stencil init failed: %x\n", err);
return NULL;
}
@@ -1131,8 +1143,8 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
texture->gxm_rendertarget = tgt;
if (err < 0) {
- free_gxm_texture(texture);
- SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create render target failed: %d\n", err);
+ free_gxm_texture(data, texture);
+ SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create render target failed: %x\n", err);
return NULL;
}
}
@@ -1181,7 +1193,7 @@ void gxm_init_for_common_dialog(void)
for (int i = 0; i < VITA_GXM_BUFFERS; i += 1)
{
buffer_for_common_dialog[i].displayData.wait_vblank = SDL_TRUE;
- buffer_for_common_dialog[i].displayData.address = mem_gpu_alloc(
+ buffer_for_common_dialog[i].displayData.address = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
@@ -1229,7 +1241,7 @@ void gxm_term_for_common_dialog(void)
sceGxmDisplayQueueFinish();
for (int i = 0; i < VITA_GXM_BUFFERS; i += 1)
{
- mem_gpu_free(buffer_for_common_dialog[i].uid);
+ vita_mem_free(buffer_for_common_dialog[i].uid);
sceGxmSyncObjectDestroy(buffer_for_common_dialog[i].sync);
}
}
diff --git a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_tools.h b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_tools.h
index 351bdc2e6..67659889d 100644
--- a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_tools.h
+++ b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_tools.h
@@ -48,15 +48,12 @@ void unset_clip_rectangle(VITA_GXM_RenderData *data);
int gxm_init(SDL_Renderer *renderer);
void gxm_finish(SDL_Renderer *renderer);
-gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget);
-void free_gxm_texture(gxm_texture *texture);
+gxm_texture *create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, SceGxmTextureFormat format, unsigned int isRenderTarget, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale);
+void free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture);
void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter);
SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture);
-unsigned int gxm_texture_get_width(const gxm_texture *texture);
-unsigned int gxm_texture_get_height(const gxm_texture *texture);
-unsigned int gxm_texture_get_stride(const gxm_texture *texture);
void *gxm_texture_get_datap(const gxm_texture *texture);
void gxm_minimal_init_for_common_dialog(void);
diff --git a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_types.h b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_types.h
index 898a92d9c..c5cbf5898 100644
--- a/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_types.h
+++ b/Engine/lib/sdl/src/render/vitagxm/SDL_render_vita_gxm_types.h
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include
@@ -79,6 +80,7 @@ typedef struct gxm_texture {
SceGxmColorSurface gxm_colorsurface;
SceGxmDepthStencilSurface gxm_depthstencil;
SceUID depth_UID;
+ SDL_bool cdram;
} gxm_texture;
typedef struct fragment_programs {
@@ -186,14 +188,19 @@ typedef struct
blend_fragment_programs blendFragmentPrograms;
gxm_drawstate_cache drawstate;
+ SceClibMspace texturePool;
+ SceUID texturePoolUID;
} VITA_GXM_RenderData;
typedef struct
{
gxm_texture *tex;
- unsigned int pitch;
- unsigned int w;
- unsigned int h;
+ unsigned int pitch;
+ unsigned int w;
+ unsigned int h;
+ float wscale;
+ SDL_bool yuv;
+ SDL_bool nv12;
} VITA_GXM_TextureData;
#endif /* SDL_RENDER_VITA_GXM_TYPES_H */
diff --git a/Engine/lib/sdl/src/test/SDL_test_common.c b/Engine/lib/sdl/src/test/SDL_test_common.c
index 48c6c72f0..93a0e7c74 100644
--- a/Engine/lib/sdl/src/test/SDL_test_common.c
+++ b/Engine/lib/sdl/src/test/SDL_test_common.c
@@ -1464,10 +1464,12 @@ default: return "???";
static void
SDLTest_PrintEvent(SDL_Event * event)
{
+#ifndef VERBOSE_MOTION_EVENTS
if ((event->type == SDL_MOUSEMOTION) || (event->type == SDL_FINGERMOTION)) {
/* Mouse and finger motion are really spammy */
return;
}
+#endif
switch (event->type) {
case SDL_DISPLAYEVENT:
diff --git a/Engine/lib/sdl/src/thread/os2/SDL_sysmutex.c b/Engine/lib/sdl/src/thread/os2/SDL_sysmutex.c
index 984ae10fe..d3fc7a3bd 100644
--- a/Engine/lib/sdl/src/thread/os2/SDL_sysmutex.c
+++ b/Engine/lib/sdl/src/thread/os2/SDL_sysmutex.c
@@ -56,12 +56,12 @@ SDL_CreateMutex(void)
void
SDL_DestroyMutex(SDL_mutex * mutex)
{
- ULONG ulRC;
HMTX hMtx = (HMTX)mutex;
-
- ulRC = DosCloseMutexSem(hMtx);
- if (ulRC != NO_ERROR) {
- debug_os2("DosCloseMutexSem(), rc = %u", ulRC);
+ if (hMtx != NULLHANDLE) {
+ const ULONG ulRC = DosCloseMutexSem(hMtx);
+ if (ulRC != NO_ERROR) {
+ debug_os2("DosCloseMutexSem(), rc = %u", ulRC);
+ }
}
}
diff --git a/Engine/lib/sdl/src/timer/os2/SDL_systimer.c b/Engine/lib/sdl/src/timer/os2/SDL_systimer.c
index c5bcf64b7..8a8425d29 100644
--- a/Engine/lib/sdl/src/timer/os2/SDL_systimer.c
+++ b/Engine/lib/sdl/src/timer/os2/SDL_systimer.c
@@ -39,6 +39,7 @@
typedef unsigned long long ULLONG;
+static SDL_bool ticks_started = SDL_FALSE;
static ULONG ulTmrFreq = 0;
static ULLONG ullTmrStart = 0;
@@ -46,7 +47,14 @@ void
SDL_TicksInit(void)
{
ULONG ulTmrStart; /* for 32-bit fallback. */
- ULONG ulRC = DosTmrQueryFreq(&ulTmrFreq);
+ ULONG ulRC;
+
+ if (ticks_started) {
+ return;
+ }
+ ticks_started = SDL_TRUE;
+
+ ulRC = DosTmrQueryFreq(&ulTmrFreq);
if (ulRC != NO_ERROR) {
debug_os2("DosTmrQueryFreq() failed, rc = %u", ulRC);
} else {
@@ -65,6 +73,7 @@ SDL_TicksInit(void)
void
SDL_TicksQuit(void)
{
+ ticks_started = SDL_FALSE;
}
Uint64
@@ -73,7 +82,7 @@ SDL_GetTicks64(void)
Uint64 ui64Result;
ULLONG ullTmrNow;
- if (ulTmrFreq == 0) { /* Was not initialized. */
+ if (!ticks_started) {
SDL_TicksInit();
}
diff --git a/Engine/lib/sdl/src/video/SDL_bmp.c b/Engine/lib/sdl/src/video/SDL_bmp.c
index 0987f5435..cb220440a 100644
--- a/Engine/lib/sdl/src/video/SDL_bmp.c
+++ b/Engine/lib/sdl/src/video/SDL_bmp.c
@@ -412,6 +412,12 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
goto done;
}
+ if (biBitCount >= 32) { /* we shift biClrUsed by this value later. */
+ SDL_SetError("Unsupported or incorrect biBitCount field");
+ was_error = SDL_TRUE;
+ goto done;
+ }
+
if (biClrUsed == 0) {
biClrUsed = 1 << biBitCount;
}
diff --git a/Engine/lib/sdl/src/video/SDL_egl.c b/Engine/lib/sdl/src/video/SDL_egl.c
index c9fb476b0..e62fe9931 100644
--- a/Engine/lib/sdl/src/video/SDL_egl.c
+++ b/Engine/lib/sdl/src/video/SDL_egl.c
@@ -27,7 +27,6 @@
#endif
#if SDL_VIDEO_DRIVER_ANDROID
#include
-#include "../core/android/SDL_android.h"
#include "../video/android/SDL_androidvideo.h"
#endif
#if SDL_VIDEO_DRIVER_RPI
@@ -99,7 +98,7 @@
#define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
#endif /* SDL_VIDEO_DRIVER_RPI */
-#if SDL_VIDEO_OPENGL
+#if SDL_VIDEO_OPENGL && !SDL_VIDEO_VITA_PVR_OGL
#include "SDL_opengl.h"
#endif
@@ -530,7 +529,7 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
}
#endif
/* Try the implementation-specific eglGetDisplay even if eglGetPlatformDisplay fails */
- if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
+ if ((_this->egl_data->egl_display == EGL_NO_DISPLAY) && (_this->egl_data->eglGetDisplay != NULL)) {
_this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
}
if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
@@ -1062,7 +1061,7 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
if (SDL_GL_ExtensionSupported("GL_OES_surfaceless_context")) {
_this->gl_allow_no_surface = SDL_TRUE;
}
-#if SDL_VIDEO_OPENGL
+#if SDL_VIDEO_OPENGL && !defined(SDL_VIDEO_DRIVER_VITA)
} else {
/* Desktop OpenGL supports it by default from version 3.0 on. */
void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);
diff --git a/Engine/lib/sdl/src/video/SDL_pixels.c b/Engine/lib/sdl/src/video/SDL_pixels.c
index b76161d03..858ccba7b 100644
--- a/Engine/lib/sdl/src/video/SDL_pixels.c
+++ b/Engine/lib/sdl/src/video/SDL_pixels.c
@@ -28,6 +28,7 @@
#include "SDL_blit.h"
#include "SDL_pixels_c.h"
#include "SDL_RLEaccel_c.h"
+#include "../SDL_list.h"
/* Lookup tables to expand partial bytes to the full 0..255 range */
@@ -1024,12 +1025,6 @@ SDL_AllocBlitMap(void)
}
-typedef struct SDL_ListNode
-{
- void *entry;
- struct SDL_ListNode *next;
-} SDL_ListNode;
-
void
SDL_InvalidateAllBlitMap(SDL_Surface *surface)
{
@@ -1045,40 +1040,6 @@ SDL_InvalidateAllBlitMap(SDL_Surface *surface)
}
}
-static void SDL_ListAdd(SDL_ListNode **head, void *ent);
-static void SDL_ListRemove(SDL_ListNode **head, void *ent);
-
-void
-SDL_ListAdd(SDL_ListNode **head, void *ent)
-{
- SDL_ListNode *node = SDL_malloc(sizeof (*node));
-
- if (node == NULL) {
- SDL_OutOfMemory();
- return;
- }
-
- node->entry = ent;
- node->next = *head;
- *head = node;
-}
-
-void
-SDL_ListRemove(SDL_ListNode **head, void *ent)
-{
- SDL_ListNode **ptr = head;
-
- while (*ptr) {
- if ((*ptr)->entry == ent) {
- SDL_ListNode *tmp = *ptr;
- *ptr = (*ptr)->next;
- SDL_free(tmp);
- return;
- }
- ptr = &(*ptr)->next;
- }
-}
-
void
SDL_InvalidateMap(SDL_BlitMap * map)
{
diff --git a/Engine/lib/sdl/src/video/SDL_sysvideo.h b/Engine/lib/sdl/src/video/SDL_sysvideo.h
index e2a65045b..2384a64ac 100644
--- a/Engine/lib/sdl/src/video/SDL_sysvideo.h
+++ b/Engine/lib/sdl/src/video/SDL_sysvideo.h
@@ -345,6 +345,7 @@ struct SDL_VideoDevice
Uint32 next_object_id;
char *clipboard_text;
SDL_bool setting_display_mode;
+ SDL_bool disable_display_mode_switching;
/* * * */
/* Data used by the GL drivers */
diff --git a/Engine/lib/sdl/src/video/SDL_video.c b/Engine/lib/sdl/src/video/SDL_video.c
index 3be98806d..93c803e70 100644
--- a/Engine/lib/sdl/src/video/SDL_video.c
+++ b/Engine/lib/sdl/src/video/SDL_video.c
@@ -61,12 +61,12 @@ static VideoBootStrap *bootstrap[] = {
#if SDL_VIDEO_DRIVER_COCOA
&COCOA_bootstrap,
#endif
-#if SDL_VIDEO_DRIVER_WAYLAND
- &Wayland_bootstrap,
-#endif
#if SDL_VIDEO_DRIVER_X11
&X11_bootstrap,
#endif
+#if SDL_VIDEO_DRIVER_WAYLAND
+ &Wayland_bootstrap,
+#endif
#if SDL_VIDEO_DRIVER_VIVANTE
&VIVANTE_bootstrap,
#endif
@@ -261,6 +261,7 @@ SDL_CreateWindowTexture(SDL_VideoDevice *_this, SDL_Window * window, Uint32 * fo
SDL_TEXTUREACCESS_STREAMING,
window->w, window->h);
if (!data->texture) {
+ /* codechecker_false_positive [Malloc] Static analyzer doesn't realize allocated `data` is saved to SDL_WINDOWTEXTUREDATA and not leaked here. */
return -1;
}
@@ -424,7 +425,7 @@ SDL_VideoInit(const char *driver_name)
i = index = 0;
video = NULL;
if (driver_name == NULL) {
- driver_name = SDL_getenv("SDL_VIDEODRIVER");
+ driver_name = SDL_GetHint(SDL_HINT_VIDEODRIVER);
}
if (driver_name != NULL && *driver_name != 0) {
const char *driver_attempt = driver_name;
@@ -1184,6 +1185,7 @@ SDL_GetWindowDisplayMode(SDL_Window * window, SDL_DisplayMode * mode)
} else if (!SDL_GetClosestDisplayModeForDisplay(SDL_GetDisplayForWindow(window),
&fullscreen_mode,
&fullscreen_mode)) {
+ SDL_zerop(mode);
return SDL_SetError("Couldn't find display mode match");
}
@@ -1337,14 +1339,17 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
resized = SDL_FALSE;
}
- /* only do the mode change if we want exclusive fullscreen */
- if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
- if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) {
- return -1;
- }
- } else {
- if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) {
- return -1;
+ /* Don't try to change the display mode if the driver doesn't want it. */
+ if (_this->disable_display_mode_switching == SDL_FALSE) {
+ /* only do the mode change if we want exclusive fullscreen */
+ if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
+ if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) {
+ return -1;
+ }
+ } else {
+ if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) {
+ return -1;
+ }
}
}
@@ -3055,7 +3060,8 @@ ShouldMinimizeOnFocusLoss(SDL_Window * window)
/* Real fullscreen windows should minimize on focus loss so the desktop video mode is restored */
hint = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS);
if (!hint || !*hint || SDL_strcasecmp(hint, "auto") == 0) {
- if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
+ if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP ||
+ _this->disable_display_mode_switching == SDL_TRUE) {
return SDL_FALSE;
} else {
return SDL_TRUE;
@@ -3919,6 +3925,10 @@ SDL_GL_MakeCurrent(SDL_Window * window, SDL_GLContext ctx)
{
int retval;
+ if (!_this) {
+ return SDL_UninitializedVideo();
+ }
+
if (window == SDL_GL_GetCurrentWindow() &&
ctx == SDL_GL_GetCurrentContext()) {
/* We're already current. */
@@ -4262,12 +4272,12 @@ SDL_IsScreenKeyboardShown(SDL_Window *window)
#if SDL_VIDEO_DRIVER_UIKIT
#include "uikit/SDL_uikitmessagebox.h"
#endif
-#if SDL_VIDEO_DRIVER_WAYLAND
-#include "wayland/SDL_waylandmessagebox.h"
-#endif
#if SDL_VIDEO_DRIVER_X11
#include "x11/SDL_x11messagebox.h"
#endif
+#if SDL_VIDEO_DRIVER_WAYLAND
+#include "wayland/SDL_waylandmessagebox.h"
+#endif
#if SDL_VIDEO_DRIVER_HAIKU
#include "haiku/SDL_bmessagebox.h"
#endif
@@ -4375,13 +4385,6 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
retval = 0;
}
#endif
-#if SDL_VIDEO_DRIVER_WAYLAND
- if (retval == -1 &&
- SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_WAYLAND) &&
- Wayland_ShowMessageBox(messageboxdata, buttonid) == 0) {
- retval = 0;
- }
-#endif
#if SDL_VIDEO_DRIVER_X11
if (retval == -1 &&
SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_X11) &&
@@ -4389,6 +4392,13 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
retval = 0;
}
#endif
+#if SDL_VIDEO_DRIVER_WAYLAND
+ if (retval == -1 &&
+ SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_WAYLAND) &&
+ Wayland_ShowMessageBox(messageboxdata, buttonid) == 0) {
+ retval = 0;
+ }
+#endif
#if SDL_VIDEO_DRIVER_HAIKU
if (retval == -1 &&
SDL_MessageboxValidForDriver(messageboxdata, SDL_SYSWM_HAIKU) &&
diff --git a/Engine/lib/sdl/src/video/android/SDL_androidvideo.c b/Engine/lib/sdl/src/video/android/SDL_androidvideo.c
index 61b9a87e9..9555ea078 100644
--- a/Engine/lib/sdl/src/video/android/SDL_androidvideo.c
+++ b/Engine/lib/sdl/src/video/android/SDL_androidvideo.c
@@ -122,6 +122,7 @@ Android_CreateDevice(int devindex)
device->SetWindowTitle = Android_SetWindowTitle;
device->SetWindowFullscreen = Android_SetWindowFullscreen;
device->MinimizeWindow = Android_MinimizeWindow;
+ device->SetWindowResizable = Android_SetWindowResizable;
device->DestroyWindow = Android_DestroyWindow;
device->GetWindowWMInfo = Android_GetWindowWMInfo;
diff --git a/Engine/lib/sdl/src/video/android/SDL_androidwindow.c b/Engine/lib/sdl/src/video/android/SDL_androidwindow.c
index c5f8919ea..f9ae3f10c 100644
--- a/Engine/lib/sdl/src/video/android/SDL_androidwindow.c
+++ b/Engine/lib/sdl/src/video/android/SDL_androidwindow.c
@@ -167,6 +167,12 @@ Android_MinimizeWindow(_THIS, SDL_Window *window)
Android_JNI_MinizeWindow();
}
+void Android_SetWindowResizable(_THIS, SDL_Window *window, SDL_bool resizable)
+{
+ /* Set orientation */
+ Android_JNI_SetOrientation(window->w, window->h, window->flags & SDL_WINDOW_RESIZABLE, SDL_GetHint(SDL_HINT_ORIENTATIONS));
+}
+
void
Android_DestroyWindow(_THIS, SDL_Window *window)
{
diff --git a/Engine/lib/sdl/src/video/android/SDL_androidwindow.h b/Engine/lib/sdl/src/video/android/SDL_androidwindow.h
index e78d5068e..58e459006 100644
--- a/Engine/lib/sdl/src/video/android/SDL_androidwindow.h
+++ b/Engine/lib/sdl/src/video/android/SDL_androidwindow.h
@@ -30,6 +30,7 @@ extern int Android_CreateWindow(_THIS, SDL_Window *window);
extern void Android_SetWindowTitle(_THIS, SDL_Window *window);
extern void Android_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen);
extern void Android_MinimizeWindow(_THIS, SDL_Window *window);
+extern void Android_SetWindowResizable(_THIS, SDL_Window *window, SDL_bool resizable);
extern void Android_DestroyWindow(_THIS, SDL_Window *window);
extern SDL_bool Android_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info);
diff --git a/Engine/lib/sdl/src/video/dummy/SDL_nullvideo.c b/Engine/lib/sdl/src/video/dummy/SDL_nullvideo.c
index aafed848d..a7fb1aac2 100644
--- a/Engine/lib/sdl/src/video/dummy/SDL_nullvideo.c
+++ b/Engine/lib/sdl/src/video/dummy/SDL_nullvideo.c
@@ -46,6 +46,7 @@
#include "SDL_nullvideo.h"
#include "SDL_nullevents_c.h"
#include "SDL_nullframebuffer_c.h"
+#include "SDL_hints.h"
#define DUMMYVID_DRIVER_NAME "dummy"
@@ -59,7 +60,7 @@ static void DUMMY_VideoQuit(_THIS);
static int
DUMMY_Available(void)
{
- const char *envr = SDL_getenv("SDL_VIDEODRIVER");
+ const char *envr = SDL_GetHint(SDL_HINT_VIDEODRIVER);
if ((envr) && (SDL_strcmp(envr, DUMMYVID_DRIVER_NAME) == 0)) {
return (1);
}
diff --git a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenframebuffer.c b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenframebuffer.c
index d4e9cb8e8..372c6f5ac 100644
--- a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenframebuffer.c
+++ b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenframebuffer.c
@@ -26,6 +26,8 @@
#include "SDL_emscriptenframebuffer.h"
#include "SDL_hints.h"
+#include
+
int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
{
@@ -57,18 +59,9 @@ int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * form
return 0;
}
-int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
+static void
+Emscripten_UpdateWindowFramebufferWorker(SDL_Surface* surface)
{
- SDL_Surface *surface;
-
- SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
- surface = data->surface;
- if (!surface) {
- return SDL_SetError("Couldn't find framebuffer surface for window");
- }
-
- /* Send the data to the display */
-
EM_ASM_INT({
var w = $0;
var h = $1;
@@ -156,6 +149,29 @@ int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rec
SDL2.ctx.putImageData(SDL2.image, 0, 0);
return 0;
}, surface->w, surface->h, surface->pixels);
+}
+
+int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
+{
+ SDL_Surface *surface;
+
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ surface = data->surface;
+ if (!surface) {
+ return SDL_SetError("Couldn't find framebuffer surface for window");
+ }
+
+ /* Send the data to the display */
+
+ if (emscripten_is_main_runtime_thread()) {
+ Emscripten_UpdateWindowFramebufferWorker(surface);
+ } else {
+ emscripten_sync_run_in_main_runtime_thread(
+ EM_FUNC_SIG_VI,
+ Emscripten_UpdateWindowFramebufferWorker,
+ (uint32_t)surface
+ );
+ }
if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) {
/* give back control to browser for screen refresh */
diff --git a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenmouse.c b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenmouse.c
index e73072590..e41480725 100644
--- a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenmouse.c
+++ b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenmouse.c
@@ -24,6 +24,7 @@
#include
#include
+#include
#include "SDL_emscriptenmouse.h"
#include "SDL_emscriptenvideo.h"
@@ -62,19 +63,10 @@ Emscripten_CreateDefaultCursor()
return Emscripten_CreateCursorFromString("default", SDL_FALSE);
}
-static SDL_Cursor*
-Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
+static const char*
+Emscripten_GetCursorUrl(int w, int h, int hot_x, int hot_y, void* pixels)
{
- const char *cursor_url = NULL;
- SDL_Surface *conv_surf;
-
- conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
-
- if (!conv_surf) {
- return NULL;
- }
-
- cursor_url = (const char *)EM_ASM_INT({
+ return (const char *)EM_ASM_INT({
var w = $0;
var h = $1;
var hot_x = $2;
@@ -122,7 +114,40 @@ Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
stringToUTF8(url, urlBuf, url.length + 1);
return urlBuf;
- }, surface->w, surface->h, hot_x, hot_y, conv_surf->pixels);
+ }, w, h, hot_x, hot_y, pixels);
+}
+
+static SDL_Cursor*
+Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
+{
+ const char *cursor_url = NULL;
+ SDL_Surface *conv_surf;
+
+ conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
+
+ if (!conv_surf) {
+ return NULL;
+ }
+
+ if (emscripten_is_main_runtime_thread()) {
+ cursor_url = Emscripten_GetCursorUrl(
+ surface->w,
+ surface->h,
+ hot_x,
+ hot_y,
+ conv_surf->pixels
+ );
+ } else {
+ cursor_url = (const char *)emscripten_sync_run_in_main_runtime_thread(
+ EM_FUNC_SIG_IIIIIII,
+ Emscripten_GetCursorUrl,
+ surface->w,
+ surface->h,
+ hot_x,
+ hot_y,
+ conv_surf->pixels
+ );
+ }
SDL_FreeSurface(conv_surf);
@@ -206,16 +231,15 @@ Emscripten_ShowCursor(SDL_Cursor* cursor)
curdata = (Emscripten_CursorData *) cursor->driverdata;
if(curdata->system_cursor) {
- EM_ASM_INT({
+ MAIN_THREAD_EM_ASM({
if (Module['canvas']) {
Module['canvas'].style['cursor'] = UTF8ToString($0);
}
- return 0;
}, curdata->system_cursor);
}
}
else {
- EM_ASM(
+ MAIN_THREAD_EM_ASM(
if (Module['canvas']) {
Module['canvas'].style['cursor'] = 'none';
}
diff --git a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.c b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.c
index f6ee1e7e5..4c6038f09 100644
--- a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.c
+++ b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.c
@@ -174,10 +174,10 @@ Emscripten_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect *
if (rect) {
rect->x = 0;
rect->y = 0;
- rect->w = EM_ASM_INT_V({
+ rect->w = MAIN_THREAD_EM_ASM_INT({
return window.innerWidth;
});
- rect->h = EM_ASM_INT_V({
+ rect->h = MAIN_THREAD_EM_ASM_INT({
return window.innerHeight;
});
}
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitmessagebox.m b/Engine/lib/sdl/src/video/uikit/SDL_uikitmessagebox.m
index fdc20c086..b6d56f350 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitmessagebox.m
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitmessagebox.m
@@ -186,8 +186,8 @@ UIKit_ShowMessageBoxAlertView(const SDL_MessageBoxData *messageboxdata, int *but
#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
}
-int
-UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+static void
+UIKit_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid, int *returnValue)
{
BOOL success = NO;
@@ -199,12 +199,26 @@ UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
}
if (!success) {
- return SDL_SetError("Could not show message box.");
+ *returnValue = SDL_SetError("Could not show message box.");
+ } else {
+ *returnValue = 0;
}
-
- return 0;
}
+int
+UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+{ @autoreleasepool
+{
+ __block int returnValue = 0;
+
+ if ([NSThread isMainThread]) {
+ UIKit_ShowMessageBoxImpl(messageboxdata, buttonid, &returnValue);
+ } else {
+ dispatch_sync(dispatch_get_main_queue(), ^{ UIKit_ShowMessageBoxImpl(messageboxdata, buttonid, &returnValue); });
+ }
+ return returnValue;
+}}
+
#endif /* SDL_VIDEO_DRIVER_UIKIT */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/vita/SDL_vitaframebuffer.c b/Engine/lib/sdl/src/video/vita/SDL_vitaframebuffer.c
index 992c7af84..1c558486b 100644
--- a/Engine/lib/sdl/src/video/vita/SDL_vitaframebuffer.c
+++ b/Engine/lib/sdl/src/video/vita/SDL_vitaframebuffer.c
@@ -31,7 +31,7 @@
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
#define DISPLAY_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8
-void *vita_gpu_alloc(SceKernelMemBlockType type, unsigned int size, SceUID *uid)
+void *vita_gpu_alloc(unsigned int type, unsigned int size, SceUID *uid)
{
void *mem;
diff --git a/Engine/lib/sdl/src/video/vita/SDL_vitagl_pvr.c b/Engine/lib/sdl/src/video/vita/SDL_vitagl_pvr.c
index 3b7fb7477..d51150c03 100644
--- a/Engine/lib/sdl/src/video/vita/SDL_vitagl_pvr.c
+++ b/Engine/lib/sdl/src/video/vita/SDL_vitagl_pvr.c
@@ -20,11 +20,12 @@
*/
#include "../../SDL_internal.h"
-#if SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR
+#if SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR && SDL_VIDEO_VITA_PVR_OGL
#include
#include
#include
#include
+#include
#include "SDL_error.h"
#include "SDL_log.h"
@@ -34,6 +35,16 @@
#define MAX_PATH 256 // vita limits are somehow wrong
+/* Defaults */
+int FB_WIDTH = 960;
+int FB_HEIGHT = 544;
+
+void getFBSize(int *width, int *height)
+{
+ *width = FB_WIDTH;
+ *height = FB_HEIGHT;
+}
+
int
VITA_GL_LoadLibrary(_THIS, const char *path)
{
@@ -53,6 +64,9 @@ VITA_GL_LoadLibrary(_THIS, const char *path)
sceKernelLoadStartModule("vs0:sys/external/libfios2.suprx", 0, NULL, 0, NULL, NULL);
sceKernelLoadStartModule("vs0:sys/external/libc.suprx", 0, NULL, 0, NULL, NULL);
+ SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libGL.suprx");
+ sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
+
SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libgpu_es4_ext.suprx");
sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
@@ -74,30 +88,45 @@ VITA_GL_LoadLibrary(_THIS, const char *path)
SDL_GLContext
VITA_GL_CreateContext(_THIS, SDL_Window * window)
{
- return SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
-}
+ char gl_version[3];
+ SDL_GLContext context = NULL;
+ int temp_major = _this->gl_config.major_version;
+ int temp_minor = _this->gl_config.minor_version;
+ int temp_profile = _this->gl_config.profile_mask;
-int
-VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
-{
- if (window && context) {
- return SDL_EGL_MakeCurrent(_this, ((SDL_WindowData *) window->driverdata)->egl_surface, context);
- } else {
- return SDL_EGL_MakeCurrent(_this, NULL, NULL);
+ /* Set version to 2.0 and PROFILE to ES */
+ _this->gl_config.major_version = 2;
+ _this->gl_config.minor_version = 0;
+ _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
+
+ context = SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
+
+ if (context != NULL)
+ {
+ FB_WIDTH = window->w;
+ FB_HEIGHT = window->h;
+ set_getprocaddress((void *(*)(const char *))eglGetProcAddress);
+ set_getmainfbsize(getFBSize);
+ SDL_snprintf(gl_version, 3, "%d%d", temp_major, temp_minor);
+ gl4es_setenv("LIBGL_NOTEXRECT", "1", 1); /* Currently broken in driver */
+ gl4es_setenv("LIBGL_GL", gl_version, 1);
+ initialize_gl4es();
}
+
+ /* Restore gl_config */
+ _this->gl_config.major_version = temp_major;
+ _this->gl_config.minor_version = temp_minor;
+ _this->gl_config.profile_mask = temp_profile;
+
+ return context;
}
-int
-VITA_GL_SwapWindow(_THIS, SDL_Window * window)
+void *
+VITA_GL_GetProcAddress(_THIS, const char *proc)
{
- SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
- if (videodata->ime_active) {
- sceImeUpdate();
- }
- return SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
+ return gl4es_GetProcAddress(proc);
}
-
#endif /* SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/vita/SDL_vitagl_pvr_c.h b/Engine/lib/sdl/src/video/vita/SDL_vitagl_pvr_c.h
index 670eaebb0..2329d472b 100644
--- a/Engine/lib/sdl/src/video/vita/SDL_vitagl_pvr_c.h
+++ b/Engine/lib/sdl/src/video/vita/SDL_vitagl_pvr_c.h
@@ -19,17 +19,16 @@
3. This notice may not be removed or altered from any source distribution.
*/
-#ifndef SDL_vitagl_c_h_
-#define SDL_vitagl_c_h_
+#ifndef SDL_vitagl_pvr_c_h_
+#define SDL_vitagl_pvr_c_h_
#include "SDL_vitavideo.h"
-extern int VITA_GL_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
-extern int VITA_GL_SwapWindow(_THIS, SDL_Window * window);
extern SDL_GLContext VITA_GL_CreateContext(_THIS, SDL_Window * window);
extern int VITA_GL_LoadLibrary(_THIS, const char *path);
+extern void *VITA_GL_GetProcAddress(_THIS, const char *proc);
-#endif /* SDL_vitagl_c_h_ */
+#endif /* SDL_vitagl_pvr_c_h_ */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/vita/SDL_vitagl.c b/Engine/lib/sdl/src/video/vita/SDL_vitagles.c
similarity index 91%
rename from Engine/lib/sdl/src/video/vita/SDL_vitagl.c
rename to Engine/lib/sdl/src/video/vita/SDL_vitagles.c
index f65022865..18ca7d57b 100644
--- a/Engine/lib/sdl/src/video/vita/SDL_vitagl.c
+++ b/Engine/lib/sdl/src/video/vita/SDL_vitagles.c
@@ -27,7 +27,7 @@
#include "SDL_error.h"
#include "SDL_log.h"
#include "SDL_vitavideo.h"
-#include "SDL_vitagl_c.h"
+#include "SDL_vitagles_c.h"
/*****************************************************************************/
/* SDL OpenGL/OpenGL ES functions */
@@ -45,7 +45,7 @@
} while (0)
void
-VITA_GL_KeyboardCallback(ScePigletPreSwapData *data)
+VITA_GLES_KeyboardCallback(ScePigletPreSwapData *data)
{
SceCommonDialogUpdateParam commonDialogParam;
SDL_zero(commonDialogParam);
@@ -62,20 +62,20 @@ VITA_GL_KeyboardCallback(ScePigletPreSwapData *data)
}
int
-VITA_GL_LoadLibrary(_THIS, const char *path)
+VITA_GLES_LoadLibrary(_THIS, const char *path)
{
pibInit(PIB_SHACCCG | PIB_GET_PROC_ADDR_CORE);
return 0;
}
void *
-VITA_GL_GetProcAddress(_THIS, const char *proc)
+VITA_GLES_GetProcAddress(_THIS, const char *proc)
{
return eglGetProcAddress(proc);
}
void
-VITA_GL_UnloadLibrary(_THIS)
+VITA_GLES_UnloadLibrary(_THIS)
{
eglTerminate(_this->gl_data->display);
}
@@ -84,7 +84,7 @@ static EGLint width = 960;
static EGLint height = 544;
SDL_GLContext
-VITA_GL_CreateContext(_THIS, SDL_Window * window)
+VITA_GLES_CreateContext(_THIS, SDL_Window * window)
{
SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
@@ -159,13 +159,13 @@ VITA_GL_CreateContext(_THIS, SDL_Window * window)
_this->gl_data->surface = surface;
preSwapCallback = (PFNEGLPIGLETVITASETPRESWAPCALLBACKSCEPROC) eglGetProcAddress("eglPigletVitaSetPreSwapCallbackSCE");
- preSwapCallback(VITA_GL_KeyboardCallback);
+ preSwapCallback(VITA_GLES_KeyboardCallback);
return context;
}
int
-VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
+VITA_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
{
if (!eglMakeCurrent(_this->gl_data->display, _this->gl_data->surface,
_this->gl_data->surface, _this->gl_data->context))
@@ -176,7 +176,7 @@ VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
}
int
-VITA_GL_SetSwapInterval(_THIS, int interval)
+VITA_GLES_SetSwapInterval(_THIS, int interval)
{
EGLBoolean status;
status = eglSwapInterval(_this->gl_data->display, interval);
@@ -190,13 +190,13 @@ VITA_GL_SetSwapInterval(_THIS, int interval)
}
int
-VITA_GL_GetSwapInterval(_THIS)
+VITA_GLES_GetSwapInterval(_THIS)
{
return _this->gl_data->swapinterval;
}
int
-VITA_GL_SwapWindow(_THIS, SDL_Window * window)
+VITA_GLES_SwapWindow(_THIS, SDL_Window * window)
{
if (!eglSwapBuffers(_this->gl_data->display, _this->gl_data->surface)) {
return SDL_SetError("eglSwapBuffers() failed");
@@ -205,7 +205,7 @@ VITA_GL_SwapWindow(_THIS, SDL_Window * window)
}
void
-VITA_GL_DeleteContext(_THIS, SDL_GLContext context)
+VITA_GLES_DeleteContext(_THIS, SDL_GLContext context)
{
SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
EGLBoolean status;
diff --git a/Engine/lib/sdl/src/video/vita/SDL_vitagl_c.h b/Engine/lib/sdl/src/video/vita/SDL_vitagles_c.h
similarity index 67%
rename from Engine/lib/sdl/src/video/vita/SDL_vitagl_c.h
rename to Engine/lib/sdl/src/video/vita/SDL_vitagles_c.h
index 272653d70..10fd8533a 100644
--- a/Engine/lib/sdl/src/video/vita/SDL_vitagl_c.h
+++ b/Engine/lib/sdl/src/video/vita/SDL_vitagles_c.h
@@ -19,8 +19,8 @@
3. This notice may not be removed or altered from any source distribution.
*/
-#ifndef SDL_vitagl_c_h_
-#define SDL_vitagl_c_h_
+#ifndef SDL_vitagles_c_h_
+#define SDL_vitagles_c_h_
#include
@@ -39,19 +39,19 @@ typedef struct SDL_GLDriverData {
uint32_t swapinterval;
}SDL_GLDriverData;
-extern void * VITA_GL_GetProcAddress(_THIS, const char *proc);
-extern int VITA_GL_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
-extern void VITA_GL_SwapBuffers(_THIS);
+extern void * VITA_GLES_GetProcAddress(_THIS, const char *proc);
+extern int VITA_GLES_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
+extern void VITA_GLES_SwapBuffers(_THIS);
-extern int VITA_GL_SwapWindow(_THIS, SDL_Window * window);
-extern SDL_GLContext VITA_GL_CreateContext(_THIS, SDL_Window * window);
+extern int VITA_GLES_SwapWindow(_THIS, SDL_Window * window);
+extern SDL_GLContext VITA_GLES_CreateContext(_THIS, SDL_Window * window);
-extern int VITA_GL_LoadLibrary(_THIS, const char *path);
-extern void VITA_GL_UnloadLibrary(_THIS);
-extern int VITA_GL_SetSwapInterval(_THIS, int interval);
-extern int VITA_GL_GetSwapInterval(_THIS);
+extern int VITA_GLES_LoadLibrary(_THIS, const char *path);
+extern void VITA_GLES_UnloadLibrary(_THIS);
+extern int VITA_GLES_SetSwapInterval(_THIS, int interval);
+extern int VITA_GLES_GetSwapInterval(_THIS);
-#endif /* SDL_vitagl_c_h_ */
+#endif /* SDL_vitagles_c_h_ */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/vita/SDL_vitagles_pvr.c b/Engine/lib/sdl/src/video/vita/SDL_vitagles_pvr.c
new file mode 100644
index 000000000..bb06d2946
--- /dev/null
+++ b/Engine/lib/sdl/src/video/vita/SDL_vitagles_pvr.c
@@ -0,0 +1,103 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 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_VITA && SDL_VIDEO_VITA_PVR
+#include
+#include
+#include
+#include
+
+#include "SDL_error.h"
+#include "SDL_log.h"
+#include "SDL_vitavideo.h"
+#include "../SDL_egl_c.h"
+#include "SDL_vitagles_pvr_c.h"
+
+#define MAX_PATH 256 // vita limits are somehow wrong
+
+int
+VITA_GLES_LoadLibrary(_THIS, const char *path)
+{
+ PVRSRV_PSP2_APPHINT hint;
+ char* override = SDL_getenv("VITA_MODULE_PATH");
+ char* skip_init = SDL_getenv("VITA_PVR_SKIP_INIT");
+ char* default_path = "app0:module";
+ char target_path[MAX_PATH];
+
+ if (skip_init == NULL) // we don't care about actual value
+ {
+ if (override != NULL)
+ {
+ default_path = override;
+ }
+
+ sceKernelLoadStartModule("vs0:sys/external/libfios2.suprx", 0, NULL, 0, NULL, NULL);
+ sceKernelLoadStartModule("vs0:sys/external/libc.suprx", 0, NULL, 0, NULL, NULL);
+
+ SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libgpu_es4_ext.suprx");
+ sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
+
+ SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libIMGEGL.suprx");
+ sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
+
+ PVRSRVInitializeAppHint(&hint);
+
+ SDL_snprintf(hint.szGLES1, MAX_PATH, "%s/%s", default_path, "libGLESv1_CM.suprx");
+ SDL_snprintf(hint.szGLES2, MAX_PATH, "%s/%s", default_path, "libGLESv2.suprx");
+ SDL_snprintf(hint.szWindowSystem, MAX_PATH, "%s/%s", default_path, "libpvrPSP2_WSEGL.suprx");
+
+ PVRSRVCreateVirtualAppHint(&hint);
+ }
+
+ return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) 0, 0);
+}
+
+SDL_GLContext
+VITA_GLES_CreateContext(_THIS, SDL_Window * window)
+{
+ return SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
+}
+
+int
+VITA_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
+{
+ if (window && context) {
+ return SDL_EGL_MakeCurrent(_this, ((SDL_WindowData *) window->driverdata)->egl_surface, context);
+ } else {
+ return SDL_EGL_MakeCurrent(_this, NULL, NULL);
+ }
+}
+
+int
+VITA_GLES_SwapWindow(_THIS, SDL_Window * window)
+{
+ SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
+ if (videodata->ime_active) {
+ sceImeUpdate();
+ }
+ return SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
+}
+
+
+#endif /* SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/vita/SDL_vitagles_pvr_c.h b/Engine/lib/sdl/src/video/vita/SDL_vitagles_pvr_c.h
new file mode 100644
index 000000000..c3a13c436
--- /dev/null
+++ b/Engine/lib/sdl/src/video/vita/SDL_vitagles_pvr_c.h
@@ -0,0 +1,35 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2022 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_vitagles_pvr_c_h_
+#define SDL_vitagles_pvr_c_h_
+
+#include "SDL_vitavideo.h"
+
+extern int VITA_GLES_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
+extern int VITA_GLES_SwapWindow(_THIS, SDL_Window * window);
+extern SDL_GLContext VITA_GLES_CreateContext(_THIS, SDL_Window * window);
+extern int VITA_GLES_LoadLibrary(_THIS, const char *path);
+
+
+#endif /* SDL_vitagles_pvr_c_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/vita/SDL_vitavideo.c b/Engine/lib/sdl/src/video/vita/SDL_vitavideo.c
index 778a87073..60bd18f45 100644
--- a/Engine/lib/sdl/src/video/vita/SDL_vitavideo.c
+++ b/Engine/lib/sdl/src/video/vita/SDL_vitavideo.c
@@ -41,15 +41,17 @@
#include "SDL_vitaframebuffer.h"
#if defined(SDL_VIDEO_VITA_PIB)
- #include "SDL_vitagl_c.h"
+ #include "SDL_vitagles_c.h"
#elif defined(SDL_VIDEO_VITA_PVR)
+ #include "SDL_vitagles_pvr_c.h"
+#if defined(SDL_VIDEO_VITA_PVR_OGL)
#include "SDL_vitagl_pvr_c.h"
- #include "../SDL_egl_c.h"
- #define VITA_GL_GetProcAddress SDL_EGL_GetProcAddress
- #define VITA_GL_UnloadLibrary SDL_EGL_UnloadLibrary
- #define VITA_GL_SetSwapInterval SDL_EGL_SetSwapInterval
- #define VITA_GL_GetSwapInterval SDL_EGL_GetSwapInterval
- #define VITA_GL_DeleteContext SDL_EGL_DeleteContext
+#endif
+ #define VITA_GLES_GetProcAddress SDL_EGL_GetProcAddress
+ #define VITA_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
+ #define VITA_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
+ #define VITA_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
+ #define VITA_GLES_DeleteContext SDL_EGL_DeleteContext
#endif
SDL_Window *Vita_Window;
@@ -140,15 +142,26 @@ VITA_Create()
*/
#if defined(SDL_VIDEO_VITA_PIB) || defined(SDL_VIDEO_VITA_PVR)
+#if defined(SDL_VIDEO_VITA_PVR_OGL)
+if(SDL_getenv("VITA_PVR_OGL") != NULL) {
device->GL_LoadLibrary = VITA_GL_LoadLibrary;
- device->GL_GetProcAddress = VITA_GL_GetProcAddress;
- device->GL_UnloadLibrary = VITA_GL_UnloadLibrary;
device->GL_CreateContext = VITA_GL_CreateContext;
- device->GL_MakeCurrent = VITA_GL_MakeCurrent;
- device->GL_SetSwapInterval = VITA_GL_SetSwapInterval;
- device->GL_GetSwapInterval = VITA_GL_GetSwapInterval;
- device->GL_SwapWindow = VITA_GL_SwapWindow;
- device->GL_DeleteContext = VITA_GL_DeleteContext;
+ device->GL_GetProcAddress = VITA_GL_GetProcAddress;
+} else {
+#endif
+ device->GL_LoadLibrary = VITA_GLES_LoadLibrary;
+ device->GL_CreateContext = VITA_GLES_CreateContext;
+ device->GL_GetProcAddress = VITA_GLES_GetProcAddress;
+#if defined(SDL_VIDEO_VITA_PVR_OGL)
+}
+#endif
+
+ device->GL_UnloadLibrary = VITA_GLES_UnloadLibrary;
+ device->GL_MakeCurrent = VITA_GLES_MakeCurrent;
+ device->GL_SetSwapInterval = VITA_GLES_SetSwapInterval;
+ device->GL_GetSwapInterval = VITA_GLES_GetSwapInterval;
+ device->GL_SwapWindow = VITA_GLES_SwapWindow;
+ device->GL_DeleteContext = VITA_GLES_DeleteContext;
#endif
device->HasScreenKeyboardSupport = VITA_HasScreenKeyboardSupport;
@@ -245,6 +258,9 @@ VITA_CreateWindow(_THIS, SDL_Window * window)
SDL_WindowData *wdata;
#if defined(SDL_VIDEO_VITA_PVR)
Psp2NativeWindow win;
+ int temp_major = 2;
+ int temp_minor = 1;
+ int temp_profile = 0;
#endif
/* Allocate window internal data */
@@ -282,11 +298,26 @@ VITA_CreateWindow(_THIS, SDL_Window * window)
win.windowSize = PSP2_WINDOW_960X544;
}
if ((window->flags & SDL_WINDOW_OPENGL) != 0) {
- wdata->egl_surface = SDL_EGL_CreateSurface(_this, &win);
+ if(SDL_getenv("VITA_PVR_OGL") != NULL) {
+ /* Set version to 2.1 and PROFILE to ES */
+ temp_major = _this->gl_config.major_version;
+ temp_minor = _this->gl_config.minor_version;
+ temp_profile = _this->gl_config.profile_mask;
+ _this->gl_config.major_version = 2;
+ _this->gl_config.minor_version = 1;
+ _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
+ }
+ wdata->egl_surface = SDL_EGL_CreateSurface(_this, &win);
if (wdata->egl_surface == EGL_NO_SURFACE) {
return SDL_SetError("Could not create GLES window surface");
}
+ if(SDL_getenv("VITA_PVR_OGL") != NULL) {
+ /* Revert */
+ _this->gl_config.major_version = temp_major;
+ _this->gl_config.minor_version = temp_minor;
+ _this->gl_config.profile_mask = temp_profile;
+ }
}
#endif
diff --git a/Engine/lib/sdl/src/video/vita/SDL_vitavideo.h b/Engine/lib/sdl/src/video/vita/SDL_vitavideo.h
index 04488dde3..9fdf7e69c 100644
--- a/Engine/lib/sdl/src/video/vita/SDL_vitavideo.h
+++ b/Engine/lib/sdl/src/video/vita/SDL_vitavideo.h
@@ -90,16 +90,23 @@ SDL_bool VITA_GetWindowWMInfo(_THIS, SDL_Window * window,
struct SDL_SysWMinfo *info);
#if SDL_VIDEO_DRIVER_VITA
+#if defined(SDL_VIDEO_VITA_PVR_OGL)
/* OpenGL functions */
int VITA_GL_LoadLibrary(_THIS, const char *path);
-void *VITA_GL_GetProcAddress(_THIS, const char *proc);
-void VITA_GL_UnloadLibrary(_THIS);
SDL_GLContext VITA_GL_CreateContext(_THIS, SDL_Window * window);
-int VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
-int VITA_GL_SetSwapInterval(_THIS, int interval);
-int VITA_GL_GetSwapInterval(_THIS);
-int VITA_GL_SwapWindow(_THIS, SDL_Window * window);
-void VITA_GL_DeleteContext(_THIS, SDL_GLContext context);
+void *VITA_GL_GetProcAddress(_THIS, const char *proc);
+#endif
+
+/* OpenGLES functions */
+int VITA_GLES_LoadLibrary(_THIS, const char *path);
+void *VITA_GLES_GetProcAddress(_THIS, const char *proc);
+void VITA_GLES_UnloadLibrary(_THIS);
+SDL_GLContext VITA_GLES_CreateContext(_THIS, SDL_Window * window);
+int VITA_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
+int VITA_GLES_SetSwapInterval(_THIS, int interval);
+int VITA_GLES_GetSwapInterval(_THIS);
+int VITA_GLES_SwapWindow(_THIS, SDL_Window * window);
+void VITA_GLES_DeleteContext(_THIS, SDL_GLContext context);
#endif
/* VITA on screen keyboard */
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.h b/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.h
index c867ec001..3d8d973cc 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.h
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.h
@@ -52,6 +52,14 @@ enum libdecor_window_state;
#include "xkbcommon/xkbcommon.h"
#include "xkbcommon/xkbcommon-compose.h"
+/* Must be included before our #defines, see Bugzilla #4957 */
+#include "wayland-client-core.h"
+
+#define SDL_WAYLAND_CHECK_VERSION(x, y, z) \
+ (WAYLAND_VERSION_MAJOR > x || \
+ (WAYLAND_VERSION_MAJOR == x && WAYLAND_VERSION_MINOR > y) || \
+ (WAYLAND_VERSION_MAJOR == x && WAYLAND_VERSION_MINOR == y && WAYLAND_VERSION_MICRO >= z))
+
#ifdef __cplusplus
extern "C"
{
@@ -71,9 +79,6 @@ void SDL_WAYLAND_UnloadSymbols(void);
}
#endif
-/* Must be included before our #defines, see Bugzilla #4957 */
-#include "wayland-client-core.h"
-
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
#if defined(_WAYLAND_CLIENT_H) || defined(WAYLAND_CLIENT_H)
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandevents.c b/Engine/lib/sdl/src/video/wayland/SDL_waylandevents.c
index 55893201b..e515d9d6f 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandevents.c
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandevents.c
@@ -40,6 +40,7 @@
#include "xdg-shell-client-protocol.h"
#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h"
#include "text-input-unstable-v3-client-protocol.h"
+#include "tablet-unstable-v2-client-protocol.h"
#ifdef HAVE_LIBDECOR_H
#include
@@ -83,6 +84,7 @@ static const struct {
{ XKB_KEY_Super_R, SDLK_RGUI },
{ XKB_KEY_Hyper_L, SDLK_LGUI },
{ XKB_KEY_Hyper_R, SDLK_RGUI },
+ { XKB_KEY_BackSpace, SDLK_BACKSPACE },
};
struct SDL_WaylandTouchPoint {
@@ -387,8 +389,10 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
input->sx_w = sx_w;
input->sy_w = sy_w;
if (input->pointer_focus) {
- const int sx = wl_fixed_to_int(sx_w);
- const int sy = wl_fixed_to_int(sy_w);
+ const float sx_f = (float)wl_fixed_to_double(sx_w);
+ const float sy_f = (float)wl_fixed_to_double(sy_w);
+ const int sx = (int)SDL_floorf(sx_f * window->pointer_scale_x);
+ const int sy = (int)SDL_floorf(sy_f * window->pointer_scale_y);
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
}
}
@@ -472,6 +476,9 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
const uint32_t *directions_libdecor = directions;
#endif
+ /* Hit tests shouldn't apply to xdg_popups, right? */
+ SDL_assert(!WINDOW_IS_XDG_POPUP(window));
+
switch (rc) {
case SDL_HITTEST_DRAGGABLE:
#ifdef HAVE_LIBDECOR_H
@@ -715,8 +722,8 @@ touch_handler_down(void *data, struct wl_touch *touch, unsigned int serial,
int id, wl_fixed_t fx, wl_fixed_t fy)
{
SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(surface);
- const double dblx = wl_fixed_to_double(fx);
- const double dbly = wl_fixed_to_double(fy);
+ const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
+ const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
const float x = dblx / window_data->sdlwindow->w;
const float y = dbly / window_data->sdlwindow->h;
@@ -748,8 +755,8 @@ touch_handler_motion(void *data, struct wl_touch *touch, unsigned int timestamp,
int id, wl_fixed_t fx, wl_fixed_t fy)
{
SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(touch_surface(id));
- const double dblx = wl_fixed_to_double(fx);
- const double dbly = wl_fixed_to_double(fy);
+ const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
+ const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
const float x = dblx / window_data->sdlwindow->w;
const float y = dbly / window_data->sdlwindow->h;
@@ -815,6 +822,16 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
return;
}
+ #define GET_MOD_INDEX(mod) \
+ WAYLAND_xkb_keymap_mod_get_index(input->xkb.keymap, XKB_MOD_NAME_##mod)
+ input->xkb.idx_shift = 1 << GET_MOD_INDEX(SHIFT);
+ input->xkb.idx_ctrl = 1 << GET_MOD_INDEX(CTRL);
+ input->xkb.idx_alt = 1 << GET_MOD_INDEX(ALT);
+ input->xkb.idx_gui = 1 << GET_MOD_INDEX(LOGO);
+ input->xkb.idx_num = 1 << GET_MOD_INDEX(NUM);
+ input->xkb.idx_caps = 1 << GET_MOD_INDEX(CAPS);
+ #undef GET_MOD_INDEX
+
input->xkb.state = WAYLAND_xkb_state_new(input->xkb.keymap);
if (!input->xkb.state) {
fprintf(stderr, "failed to create XKB state\n");
@@ -829,10 +846,14 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
*/
/* Look up the preferred locale, falling back to "C" as default */
- if (!(locale = SDL_getenv("LC_ALL")))
- if (!(locale = SDL_getenv("LC_CTYPE")))
- if (!(locale = SDL_getenv("LANG")))
+ if (!(locale = SDL_getenv("LC_ALL"))) {
+ if (!(locale = SDL_getenv("LC_CTYPE"))) {
+ if (!(locale = SDL_getenv("LANG"))) {
locale = "C";
+ }
+ }
+ }
+
/* Set up XKB compose table */
input->xkb.compose_table = WAYLAND_xkb_compose_table_new_from_locale(input->display->xkb_context,
locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
@@ -903,7 +924,7 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
}
static SDL_bool
-keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key, SDL_bool *handled_by_ime)
+keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key, Uint8 state, SDL_bool *handled_by_ime)
{
SDL_WindowData *window = input->keyboard_focus;
const xkb_keysym_t *syms;
@@ -920,12 +941,16 @@ keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint
sym = syms[0];
#ifdef SDL_USE_IME
- if (SDL_IME_ProcessKeyEvent(sym, key + 8)) {
+ if (SDL_IME_ProcessKeyEvent(sym, key + 8, state)) {
*handled_by_ime = SDL_TRUE;
return SDL_TRUE;
}
#endif
+ if (state == SDL_RELEASED) {
+ return SDL_FALSE;
+ }
+
if (input->xkb.compose_state && WAYLAND_xkb_compose_state_feed(input->xkb.compose_state, sym) == XKB_COMPOSE_FEED_ACCEPTED) {
switch(WAYLAND_xkb_compose_state_get_status(input->xkb.compose_state)) {
case XKB_COMPOSE_COMPOSING:
@@ -959,7 +984,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
SDL_bool handled_by_ime = SDL_FALSE;
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
- has_text = keyboard_input_get_text(text, input, key, &handled_by_ime);
+ has_text = keyboard_input_get_text(text, input, key, SDL_PRESSED, &handled_by_ime);
} else {
if (keyboard_repeat_is_set(&input->keyboard_repeat)) {
// Send any due key repeat events before stopping the repeat and generating the key up event
@@ -969,6 +994,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
keyboard_repeat_handle(&input->keyboard_repeat, time - input->keyboard_repeat.wl_press_time);
keyboard_repeat_clear(&input->keyboard_repeat);
}
+ keyboard_input_get_text(text, input, key, SDL_RELEASED, &handled_by_ime);
}
if (!handled_by_ime && key < SDL_arraysize(xfree86_scancode_table2)) {
@@ -1054,10 +1080,24 @@ keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
{
struct SDL_WaylandInput *input = data;
Wayland_Keymap keymap;
+ uint32_t modstate = (mods_depressed | mods_latched | mods_locked);
WAYLAND_xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
mods_locked, 0, 0, group);
+ SDL_ToggleModState(KMOD_SHIFT, modstate & input->xkb.idx_shift);
+ SDL_ToggleModState(KMOD_CTRL, modstate & input->xkb.idx_ctrl);
+ SDL_ToggleModState(KMOD_ALT, modstate & input->xkb.idx_alt);
+ SDL_ToggleModState(KMOD_GUI, modstate & input->xkb.idx_gui);
+ SDL_ToggleModState(KMOD_NUM, modstate & input->xkb.idx_num);
+ SDL_ToggleModState(KMOD_CAPS, modstate & input->xkb.idx_caps);
+
+ if (group == input->xkb.current_group) {
+ return;
+ }
+
+ /* The layout changed, remap and fire an event */
+ input->xkb.current_group = group;
keymap.layout = group;
SDL_GetDefaultKeymap(keymap.keymap);
WAYLAND_xkb_keymap_key_for_each(input->xkb.keymap,
@@ -1646,6 +1686,363 @@ Wayland_add_text_input_manager(SDL_VideoData *d, uint32_t id, uint32_t version)
}
}
+static void
+tablet_tool_handle_type(void* data, struct zwp_tablet_tool_v2* tool, uint32_t type)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_hardware_serial(void* data, struct zwp_tablet_tool_v2* tool, uint32_t serial_hi, uint32_t serial_lo)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_hardware_id_wacom(void* data, struct zwp_tablet_tool_v2* tool, uint32_t id_hi, uint32_t id_lo)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_capability(void* data, struct zwp_tablet_tool_v2* tool, uint32_t capability)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_done(void* data, struct zwp_tablet_tool_v2* tool)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_removed(void* data, struct zwp_tablet_tool_v2* tool)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_proximity_in(void* data, struct zwp_tablet_tool_v2* tool, uint32_t serial, struct zwp_tablet_v2* tablet, struct wl_surface* surface)
+{
+ struct SDL_WaylandTabletInput* input = data;
+ SDL_WindowData* window;
+
+ if (!surface) {
+ return;
+ }
+
+ if (!SDL_WAYLAND_own_surface(surface)) {
+ return;
+ }
+
+ window = (SDL_WindowData*)wl_surface_get_user_data(surface);
+
+ if (window) {
+ input->tool_focus = window;
+ input->tool_prox_serial = serial;
+
+ input->is_down = SDL_FALSE;
+
+ input->btn_stylus = SDL_FALSE;
+ input->btn_stylus2 = SDL_FALSE;
+ input->btn_stylus3 = SDL_FALSE;
+
+ SDL_SetMouseFocus(window->sdlwindow);
+ SDL_SetCursor(NULL);
+ }
+}
+
+static void
+tablet_tool_handle_proximity_out(void* data, struct zwp_tablet_tool_v2* tool)
+{
+ struct SDL_WaylandTabletInput* input = data;
+
+ if (input->tool_focus) {
+ SDL_SetMouseFocus(NULL);
+ input->tool_focus = NULL;
+ }
+}
+
+uint32_t
+tablet_tool_btn_to_sdl_button(struct SDL_WaylandTabletInput* input)
+{
+ unsigned int tool_btn = input->btn_stylus3 << 2 | input->btn_stylus2 << 1 | input->btn_stylus << 0;
+ switch (tool_btn) {
+ case 0b000:
+ return SDL_BUTTON_LEFT;
+ case 0b001:
+ return SDL_BUTTON_RIGHT;
+ case 0b010:
+ return SDL_BUTTON_MIDDLE;
+ case 0b100:
+ return SDL_BUTTON_X1;
+ default:
+ return SDL_BUTTON_LEFT;
+ }
+}
+
+static void
+tablet_tool_handle_down(void* data, struct zwp_tablet_tool_v2* tool, uint32_t serial)
+{
+ struct SDL_WaylandTabletInput* input = data;
+ SDL_WindowData* window = input->tool_focus;
+ input->is_down = SDL_TRUE;
+ if (!window) {
+ /* tablet_tool_handle_proximity_out gets called when moving over the libdecoration csd.
+ * that sets input->tool_focus (window) to NULL, but handle_{down,up} events are still
+ * received. To prevent SIGSEGV this returns when this is the case.
+ */
+ return;
+ }
+
+ SDL_SendMouseButton(window->sdlwindow, 0, SDL_PRESSED, tablet_tool_btn_to_sdl_button(input));
+}
+
+static void
+tablet_tool_handle_up(void* data, struct zwp_tablet_tool_v2* tool)
+{
+ struct SDL_WaylandTabletInput* input = data;
+ SDL_WindowData* window = input->tool_focus;
+
+ input->is_down = SDL_FALSE;
+
+ if (!window) {
+ /* tablet_tool_handle_proximity_out gets called when moving over the libdecoration csd.
+ * that sets input->tool_focus (window) to NULL, but handle_{down,up} events are still
+ * received. To prevent SIGSEGV this returns when this is the case.
+ */
+ return;
+ }
+
+ SDL_SendMouseButton(window->sdlwindow, 0, SDL_RELEASED, tablet_tool_btn_to_sdl_button(input));
+}
+
+static void
+tablet_tool_handle_motion(void* data, struct zwp_tablet_tool_v2* tool, wl_fixed_t sx_w, wl_fixed_t sy_w)
+{
+ struct SDL_WaylandTabletInput* input = data;
+ SDL_WindowData* window = input->tool_focus;
+
+ input->sx_w = sx_w;
+ input->sy_w = sy_w;
+ if (input->tool_focus) {
+ const float sx_f = (float)wl_fixed_to_double(sx_w);
+ const float sy_f = (float)wl_fixed_to_double(sy_w);
+ const int sx = (int)SDL_floorf(sx_f * window->pointer_scale_x);
+ const int sy = (int)SDL_floorf(sy_f * window->pointer_scale_y);
+ SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
+ }
+}
+
+static void
+tablet_tool_handle_pressure(void* data, struct zwp_tablet_tool_v2* tool, uint32_t pressure)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_distance(void* data, struct zwp_tablet_tool_v2* tool, uint32_t distance)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_tilt(void* data, struct zwp_tablet_tool_v2* tool, wl_fixed_t xtilt, wl_fixed_t ytilt)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_button(void* data, struct zwp_tablet_tool_v2* tool, uint32_t serial, uint32_t button, uint32_t state)
+{
+ struct SDL_WaylandTabletInput* input = data;
+
+ if (input->is_down) {
+ tablet_tool_handle_up(data, tool);
+ input->is_down = SDL_TRUE;
+ }
+
+ switch (button) {
+ /* see %{_includedir}/linux/input-event-codes.h */
+ case 0x14b: /* BTN_STYLUS */
+ input->btn_stylus = state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ? SDL_TRUE : SDL_FALSE;
+ break;
+ case 0x14c: /* BTN_STYLUS2 */
+ input->btn_stylus2 = state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ? SDL_TRUE : SDL_FALSE;
+ break;
+ case 0x149: /* BTN_STYLUS3 */
+ input->btn_stylus3 = state == ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED ? SDL_TRUE : SDL_FALSE;
+ break;
+ }
+
+ if (input->is_down) {
+ tablet_tool_handle_down(data, tool, serial);
+ }
+}
+
+static void
+tablet_tool_handle_rotation(void* data, struct zwp_tablet_tool_v2* tool, wl_fixed_t degrees)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_slider(void* data, struct zwp_tablet_tool_v2* tool, int32_t position)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_wheel(void* data, struct zwp_tablet_tool_v2* tool, int32_t degrees, int32_t clicks)
+{
+ /* unimplemented */
+}
+
+static void
+tablet_tool_handle_frame(void* data, struct zwp_tablet_tool_v2* tool, uint32_t time)
+{
+ /* unimplemented */
+}
+
+
+static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
+ tablet_tool_handle_type,
+ tablet_tool_handle_hardware_serial,
+ tablet_tool_handle_hardware_id_wacom,
+ tablet_tool_handle_capability,
+ tablet_tool_handle_done,
+ tablet_tool_handle_removed,
+ tablet_tool_handle_proximity_in,
+ tablet_tool_handle_proximity_out,
+ tablet_tool_handle_down,
+ tablet_tool_handle_up,
+ tablet_tool_handle_motion,
+ tablet_tool_handle_pressure,
+ tablet_tool_handle_distance,
+ tablet_tool_handle_tilt,
+ tablet_tool_handle_rotation,
+ tablet_tool_handle_slider,
+ tablet_tool_handle_wheel,
+ tablet_tool_handle_button,
+ tablet_tool_handle_frame
+};
+
+struct SDL_WaylandTabletObjectListNode*
+tablet_object_list_new_node(void* object)
+{
+ struct SDL_WaylandTabletObjectListNode* node;
+
+ node = SDL_calloc(1, sizeof *node);
+ if (node == NULL) {
+ return NULL;
+ }
+
+ node->next = NULL;
+ node->object = object;
+
+ return node;
+}
+
+void tablet_object_list_append(struct SDL_WaylandTabletObjectListNode* head, void* object)
+{
+ if (head->object == NULL) {
+ head->object = object;
+ return;
+ }
+
+ while (head->next) {
+ head = head->next;
+ }
+
+ head->next = tablet_object_list_new_node(object);
+}
+
+void tablet_object_list_destroy(struct SDL_WaylandTabletObjectListNode* head, void (*deleter)(void* object))
+{
+ while (head) {
+ struct SDL_WaylandTabletObjectListNode* next = head->next;
+ if (head->object) {
+ (*deleter)(head->object);
+ }
+ SDL_free(head);
+ head = next;
+ }
+}
+
+
+static void
+tablet_seat_handle_tablet_added(void* data, struct zwp_tablet_seat_v2* seat, struct zwp_tablet_v2* tablet)
+{
+ struct SDL_WaylandTabletInput* input = data;
+
+ tablet_object_list_append(input->tablets, tablet);
+}
+
+static void
+tablet_seat_handle_tool_added(void* data, struct zwp_tablet_seat_v2* seat, struct zwp_tablet_tool_v2* tool)
+{
+ struct SDL_WaylandTabletInput* input = data;
+
+ zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, data);
+ zwp_tablet_tool_v2_set_user_data(tool, data);
+
+ tablet_object_list_append(input->tools, tool);
+}
+
+static void
+tablet_seat_handle_pad_added(void* data, struct zwp_tablet_seat_v2* seat, struct zwp_tablet_pad_v2* pad)
+{
+ struct SDL_WaylandTabletInput* input = data;
+
+ tablet_object_list_append(input->pads, pad);
+}
+
+static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = {
+ tablet_seat_handle_tablet_added,
+ tablet_seat_handle_tool_added,
+ tablet_seat_handle_pad_added
+};
+
+void
+Wayland_input_add_tablet(struct SDL_WaylandInput *input, struct SDL_WaylandTabletManager* tablet_manager)
+{
+ struct SDL_WaylandTabletInput* tablet_input;
+
+ if (!tablet_manager || !input || !input->seat) {
+ return;
+ }
+
+ tablet_input = SDL_calloc(1, sizeof *tablet_input);
+ if (tablet_input == NULL) {
+ return;
+ }
+
+ input->tablet = tablet_input;
+
+ tablet_input->seat = (struct SDL_WaylandTabletSeat*)zwp_tablet_manager_v2_get_tablet_seat((struct zwp_tablet_manager_v2*)tablet_manager, input->seat);
+
+ tablet_input->tablets = tablet_object_list_new_node(NULL);
+ tablet_input->tools = tablet_object_list_new_node(NULL);
+ tablet_input->pads = tablet_object_list_new_node(NULL);
+
+ zwp_tablet_seat_v2_add_listener((struct zwp_tablet_seat_v2*)tablet_input->seat, &tablet_seat_listener, tablet_input);
+}
+
+#define TABLET_OBJECT_LIST_DELETER(fun) (void (*)(void*))fun
+void
+Wayland_input_destroy_tablet(struct SDL_WaylandInput* input)
+{
+ tablet_object_list_destroy(input->tablet->pads, TABLET_OBJECT_LIST_DELETER(zwp_tablet_pad_v2_destroy));
+ tablet_object_list_destroy(input->tablet->tools, TABLET_OBJECT_LIST_DELETER(zwp_tablet_tool_v2_destroy));
+ tablet_object_list_destroy(input->tablet->tablets, TABLET_OBJECT_LIST_DELETER(zwp_tablet_v2_destroy));
+
+ zwp_tablet_seat_v2_destroy((struct zwp_tablet_seat_v2*)input->tablet->seat);
+
+ SDL_free(input->tablet);
+ input->tablet = NULL;
+}
+
void
Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
{
@@ -1659,6 +2056,7 @@ Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, SDL_min(5, version));
input->sx_w = wl_fixed_from_int(0);
input->sy_w = wl_fixed_from_int(0);
+ input->xkb.current_group = ~0;
d->input = input;
if (d->data_device_manager != NULL) {
@@ -1671,6 +2069,10 @@ Wayland_display_add_input(SDL_VideoData *d, uint32_t id, uint32_t version)
wl_seat_add_listener(input->seat, &seat_listener, input);
wl_seat_set_user_data(input->seat, input);
+ if (d->tablet_manager) {
+ Wayland_input_add_tablet(input, d->tablet_manager);
+ }
+
WAYLAND_wl_display_flush(d->display);
}
@@ -1711,6 +2113,10 @@ void Wayland_display_destroy_input(SDL_VideoData *d)
wl_touch_destroy(input->touch);
}
+ if (input->tablet) {
+ Wayland_input_destroy_tablet(input);
+ }
+
if (input->seat)
wl_seat_destroy(input->seat);
@@ -1951,12 +2357,19 @@ int Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *wi
if (SDL_RectEmpty(&window->mouse_rect)) {
confine_rect = NULL;
} else {
+ SDL_Rect scaled_mouse_rect;
+
+ scaled_mouse_rect.x = (int)SDL_floorf((float)window->mouse_rect.x / w->pointer_scale_x);
+ scaled_mouse_rect.y = (int)SDL_floorf((float)window->mouse_rect.y / w->pointer_scale_y);
+ scaled_mouse_rect.w = (int)SDL_ceilf((float)window->mouse_rect.w / w->pointer_scale_x);
+ scaled_mouse_rect.h = (int)SDL_ceilf((float)window->mouse_rect.h / w->pointer_scale_y);
+
confine_rect = wl_compositor_create_region(d->compositor);
wl_region_add(confine_rect,
- window->mouse_rect.x,
- window->mouse_rect.y,
- window->mouse_rect.w,
- window->mouse_rect.h);
+ scaled_mouse_rect.x,
+ scaled_mouse_rect.y,
+ scaled_mouse_rect.w,
+ scaled_mouse_rect.h);
}
confined_pointer =
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandevents_c.h b/Engine/lib/sdl/src/video/wayland/SDL_waylandevents_c.h
index 24256a7d0..59dc0c8af 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandevents_c.h
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandevents_c.h
@@ -29,6 +29,34 @@
#include "SDL_waylanddatamanager.h"
#include "SDL_waylandkeyboard.h"
+struct SDL_WaylandTabletSeat;
+
+struct SDL_WaylandTabletObjectListNode {
+ void* object;
+ struct SDL_WaylandTabletObjectListNode* next;
+};
+
+struct SDL_WaylandTabletInput {
+ struct SDL_WaylandTabletSeat* seat;
+
+ struct SDL_WaylandTabletObjectListNode* tablets;
+ struct SDL_WaylandTabletObjectListNode* tools;
+ struct SDL_WaylandTabletObjectListNode* pads;
+
+ SDL_WindowData *tool_focus;
+ uint32_t tool_prox_serial;
+
+ /* Last motion location */
+ wl_fixed_t sx_w;
+ wl_fixed_t sy_w;
+
+ SDL_bool is_down;
+
+ SDL_bool btn_stylus;
+ SDL_bool btn_stylus2;
+ SDL_bool btn_stylus3;
+};
+
typedef struct {
// repeat_rate in range of [1, 1000]
int32_t repeat_rate;
@@ -68,6 +96,17 @@ struct SDL_WaylandInput {
struct xkb_state *state;
struct xkb_compose_table *compose_table;
struct xkb_compose_state *compose_state;
+
+ /* Keyboard layout "group" */
+ uint32_t current_group;
+
+ /* Modifier bitshift values */
+ uint32_t idx_shift;
+ uint32_t idx_ctrl;
+ uint32_t idx_alt;
+ uint32_t idx_gui;
+ uint32_t idx_num;
+ uint32_t idx_caps;
} xkb;
/* information about axis events on current frame */
@@ -80,6 +119,8 @@ struct SDL_WaylandInput {
} pointer_curr_axis_info;
SDL_WaylandKeyboardRepeat keyboard_repeat;
+
+ struct SDL_WaylandTabletInput* tablet;
};
extern void Wayland_PumpEvents(_THIS);
@@ -107,6 +148,9 @@ extern void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d);
extern int Wayland_input_grab_keyboard(SDL_Window *window, struct SDL_WaylandInput *input);
extern int Wayland_input_ungrab_keyboard(SDL_Window *window);
+extern void Wayland_input_add_tablet(struct SDL_WaylandInput *input, struct SDL_WaylandTabletManager* tablet_manager);
+extern void Wayland_input_destroy_tablet(struct SDL_WaylandInput *input);
+
#endif /* SDL_waylandevents_h_ */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandopengles.c b/Engine/lib/sdl/src/video/wayland/SDL_waylandopengles.c
index 6b10cbee7..4c834fd86 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandopengles.c
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandopengles.c
@@ -205,11 +205,11 @@ Wayland_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
data = (SDL_WindowData *) window->driverdata;
if (w) {
- *w = window->w * data->scale_factor;
+ *w = data->drawable_width;
}
if (h) {
- *h = window->h * data->scale_factor;
+ *h = data->drawable_height;
}
}
}
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandsym.h b/Engine/lib/sdl/src/video/wayland/SDL_waylandsym.h
index fa29bedb1..6891325c7 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandsym.h
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandsym.h
@@ -72,21 +72,19 @@ SDL_WAYLAND_SYM(void, wl_list_remove, (struct wl_list *))
SDL_WAYLAND_SYM(int, wl_list_length, (const struct wl_list *))
SDL_WAYLAND_SYM(int, wl_list_empty, (const struct wl_list *))
SDL_WAYLAND_SYM(void, wl_list_insert_list, (struct wl_list *, struct wl_list *))
-
-/* These functions are available in Wayland >= 1.4 */
-SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_4)
SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_marshal_constructor, (struct wl_proxy *, uint32_t opcode, const struct wl_interface *interface, ...))
-
-SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_10)
SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_marshal_constructor_versioned, (struct wl_proxy *proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, ...))
-
-SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_18)
SDL_WAYLAND_SYM(void, wl_proxy_set_tag, (struct wl_proxy *, const char * const *))
SDL_WAYLAND_SYM(const char * const *, wl_proxy_get_tag, (struct wl_proxy *))
-SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_20)
+#if SDL_WAYLAND_CHECK_VERSION(1, 20, 0)
+/* wayland-scanner 1.20 generates code that will call these, so these are
+ * non-optional when we are compiling against Wayland 1.20. We don't
+ * explicitly call them ourselves, though, so if we are only compiling
+ * against Wayland 1.18, they're unnecessary. */
SDL_WAYLAND_SYM(struct wl_proxy*, wl_proxy_marshal_flags, (struct wl_proxy *proxy, uint32_t opcode, const struct wl_interface *interfac, uint32_t version, uint32_t flags, ...))
SDL_WAYLAND_SYM(struct wl_proxy*, wl_proxy_marshal_array_flags, (struct wl_proxy *proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, uint32_t flags, union wl_argument *args))
+#endif
SDL_WAYLAND_INTERFACE(wl_seat_interface)
SDL_WAYLAND_INTERFACE(wl_surface_interface)
@@ -149,6 +147,8 @@ SDL_WAYLAND_SYM(int, xkb_keymap_key_get_syms_by_level, (struct xkb_keymap *,
xkb_layout_index_t,
const xkb_keysym_t **) )
SDL_WAYLAND_SYM(uint32_t, xkb_keysym_to_utf32, (xkb_keysym_t) )
+SDL_WAYLAND_SYM(uint32_t, xkb_keymap_mod_get_index, (struct xkb_keymap *,
+ const char *) )
#ifdef HAVE_LIBDECOR_H
SDL_WAYLAND_MODULE(WAYLAND_LIBDECOR)
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.c b/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.c
index 61940cca4..0305c46a1 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.c
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.c
@@ -52,6 +52,9 @@
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "xdg-activation-v1-client-protocol.h"
#include "text-input-unstable-v3-client-protocol.h"
+#include "tablet-unstable-v2-client-protocol.h"
+#include "xdg-output-unstable-v1-client-protocol.h"
+#include "viewporter-client-protocol.h"
#ifdef HAVE_LIBDECOR_H
#include
@@ -59,6 +62,9 @@
#define WAYLANDVID_DRIVER_NAME "wayland"
+static void
+display_handle_done(void *data, struct wl_output *output);
+
/* Initialization/Query functions */
static int
Wayland_VideoInit(_THIS);
@@ -133,32 +139,22 @@ static const char *SDL_WAYLAND_output_tag = "sdl-output";
void SDL_WAYLAND_register_surface(struct wl_surface *surface)
{
- if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT_1_18) {
- wl_proxy_set_tag((struct wl_proxy *)surface, &SDL_WAYLAND_surface_tag);
- }
+ wl_proxy_set_tag((struct wl_proxy *)surface, &SDL_WAYLAND_surface_tag);
}
void SDL_WAYLAND_register_output(struct wl_output *output)
{
- if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT_1_18) {
- wl_proxy_set_tag((struct wl_proxy *)output, &SDL_WAYLAND_output_tag);
- }
+ wl_proxy_set_tag((struct wl_proxy *)output, &SDL_WAYLAND_output_tag);
}
SDL_bool SDL_WAYLAND_own_surface(struct wl_surface *surface)
{
- if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT_1_18) {
- return wl_proxy_get_tag((struct wl_proxy *) surface) == &SDL_WAYLAND_surface_tag;
- }
- return SDL_TRUE; /* For older clients we have to assume this is us... */
+ return wl_proxy_get_tag((struct wl_proxy *) surface) == &SDL_WAYLAND_surface_tag;
}
SDL_bool SDL_WAYLAND_own_output(struct wl_output *output)
{
- if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT_1_18) {
- return wl_proxy_get_tag((struct wl_proxy *) output) == &SDL_WAYLAND_output_tag;
- }
- return SDL_TRUE; /* For older clients we have to assume this is us... */
+ return wl_proxy_get_tag((struct wl_proxy *) output) == &SDL_WAYLAND_output_tag;
}
static void
@@ -283,6 +279,8 @@ Wayland_CreateDevice(int devindex)
device->free = Wayland_DeleteDevice;
+ device->disable_display_mode_switching = SDL_TRUE;
+
return device;
}
@@ -291,6 +289,155 @@ VideoBootStrap Wayland_bootstrap = {
Wayland_CreateDevice
};
+static void
+xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output,
+ int32_t x, int32_t y)
+{
+ SDL_WaylandOutputData* driverdata = data;
+
+ driverdata->x = x;
+ driverdata->y = y;
+ driverdata->has_logical_position = SDL_TRUE;
+}
+
+static void
+xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output,
+ int32_t width, int32_t height)
+{
+ SDL_WaylandOutputData* driverdata = data;
+
+ if (driverdata->width != 0 && driverdata->height != 0) {
+ /* FIXME: GNOME has a bug where the logical size does not account for
+ * scale, resulting in bogus viewport sizes.
+ *
+ * Until this is fixed, validate that _some_ kind of scaling is being
+ * done (we can't match exactly because fractional scaling can't be
+ * detected otherwise), then override if necessary.
+ * -flibit
+ */
+ const float scale = (float) driverdata->width / (float) width;
+ if ((scale == 1.0f) && (driverdata->scale_factor != 1.0f)) {
+ SDL_LogWarn(
+ SDL_LOG_CATEGORY_VIDEO,
+ "xdg_output scale did not match, overriding with wl_output scale"
+ );
+ return;
+ }
+ }
+
+ driverdata->width = width;
+ driverdata->height = height;
+ driverdata->has_logical_size = SDL_TRUE;
+}
+
+static void
+xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
+{
+ SDL_WaylandOutputData* driverdata = data;
+
+ /*
+ * xdg-output.done events are deprecated and only apply below version 3 of the protocol.
+ * A wl-output.done event will be emitted in version 3 or higher.
+ */
+ if (zxdg_output_v1_get_version(driverdata->xdg_output) < 3) {
+ display_handle_done(data, driverdata->output);
+ }
+}
+
+static void
+xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output,
+ const char *name)
+{
+}
+
+static void
+xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output,
+ const char *description)
+{
+}
+
+static const struct zxdg_output_v1_listener xdg_output_listener = {
+ xdg_output_handle_logical_position,
+ xdg_output_handle_logical_size,
+ xdg_output_handle_done,
+ xdg_output_handle_name,
+ xdg_output_handle_description,
+};
+
+static void
+AddEmulatedModes(SDL_VideoDisplay *dpy, SDL_bool rot_90)
+{
+ struct EmulatedMode
+ {
+ int w;
+ int h;
+ };
+
+ /* Resolution lists courtesy of XWayland */
+ const struct EmulatedMode mode_list[] = {
+ /* 16:9 (1.77) */
+ { 7680, 4320 },
+ { 6144, 3160 },
+ { 5120, 2880 },
+ { 4096, 2304 },
+ { 3840, 2160 },
+ { 3200, 1800 },
+ { 2880, 1620 },
+ { 2560, 1440 },
+ { 2048, 1152 },
+ { 1920, 1080 },
+ { 1600, 900 },
+ { 1368, 768 },
+ { 1280, 720 },
+ { 864, 486 },
+
+ /* 16:10 (1.6) */
+ { 2560, 1600 },
+ { 1920, 1200 },
+ { 1680, 1050 },
+ { 1440, 900 },
+ { 1280, 800 },
+
+ /* 3:2 (1.5) */
+ { 720, 480 },
+
+ /* 4:3 (1.33) */
+ { 2048, 1536 },
+ { 1920, 1440 },
+ { 1600, 1200 },
+ { 1440, 1080 },
+ { 1400, 1050 },
+ { 1280, 1024 },
+ { 1280, 960 },
+ { 1152, 864 },
+ { 1024, 768 },
+ { 800, 600 },
+ { 640, 480 }
+ };
+
+ int i;
+ const int native_width = dpy->display_modes->w;
+ const int native_height = dpy->display_modes->h;
+
+ for (i = 0; i < SDL_arraysize(mode_list); ++i) {
+ /* Only add modes that are smaller than the native mode */
+ if ((mode_list[i].w < native_width && mode_list[i].h < native_height) ||
+ (mode_list[i].w < native_width && mode_list[i].h == native_height)) {
+ SDL_DisplayMode mode = *dpy->display_modes;
+
+ if (rot_90) {
+ mode.w = mode_list[i].h;
+ mode.h = mode_list[i].w;
+ } else {
+ mode.w = mode_list[i].w;
+ mode.h = mode_list[i].h;
+ }
+
+ SDL_AddDisplayMode(dpy, &mode);
+ }
+ }
+}
+
static void
display_handle_geometry(void *data,
struct wl_output *output,
@@ -307,7 +454,7 @@ display_handle_geometry(void *data,
SDL_VideoDisplay *display;
int i;
- if (driverdata->done) {
+ if (driverdata->wl_output_done_count) {
/* Clear the wl_output ref so Reset doesn't free it */
display = SDL_GetDisplay(driverdata->index);
for (i = 0; i < display->num_display_modes; i += 1) {
@@ -318,11 +465,14 @@ display_handle_geometry(void *data,
SDL_ResetDisplayModes(driverdata->index);
/* The display has officially started over. */
- driverdata->done = SDL_FALSE;
+ driverdata->wl_output_done_count = 0;
}
- driverdata->x = x;
- driverdata->y = y;
+ /* Apply the change from wl-output only if xdg-output is not supported */
+ if (!driverdata->has_logical_position) {
+ driverdata->x = x;
+ driverdata->y = y;
+ }
driverdata->physical_width = physical_width;
driverdata->physical_height = physical_height;
if (driverdata->index == -1) {
@@ -369,36 +519,21 @@ display_handle_mode(void *data,
int refresh)
{
SDL_WaylandOutputData* driverdata = data;
- SDL_DisplayMode mode;
if (flags & WL_OUTPUT_MODE_CURRENT) {
- /* Don't rotate this yet, handle_done will do it later */
- driverdata->width = width;
- driverdata->height = height;
- driverdata->refresh = refresh;
- }
+ driverdata->native_width = width;
+ driverdata->native_height = height;
- /* Note that the width/height are NOT multiplied by scale_factor!
- * This is intentional and is designed to get the unscaled modes, which is
- * important for high-DPI games intending to use the display mode as the
- * target drawable size. The scaled desktop mode will be added at the end
- * when display_handle_done is called (see below).
- */
- SDL_zero(mode);
- mode.format = SDL_PIXELFORMAT_RGB888;
- if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
- mode.w = height;
- mode.h = width;
- } else {
- mode.w = width;
- mode.h = height;
- }
- mode.refresh_rate = (int)SDL_round(refresh / 1000.0); /* mHz to Hz */
- mode.driverdata = driverdata->output;
- if (driverdata->index > -1) {
- SDL_AddDisplayMode(SDL_GetDisplay(driverdata->index), &mode);
- } else {
- SDL_AddDisplayMode(&driverdata->placeholder, &mode);
+ /*
+ * Don't rotate this yet, wl-output coordinates are transformed in
+ * handle_done and xdg-output coordinates are pre-transformed.
+ */
+ if (!driverdata->has_logical_size) {
+ driverdata->width = width;
+ driverdata->height = height;
+ }
+
+ driverdata->refresh = refresh;
}
}
@@ -407,20 +542,73 @@ display_handle_done(void *data,
struct wl_output *output)
{
SDL_WaylandOutputData* driverdata = data;
- SDL_DisplayMode mode;
+ SDL_VideoData* video = driverdata->videodata;
+ SDL_DisplayMode native_mode, desktop_mode;
SDL_VideoDisplay *dpy;
- if (driverdata->done)
+ /*
+ * When using xdg-output, two wl-output.done events will be emitted:
+ * one at the completion of wl-display and one at the completion of xdg-output.
+ *
+ * All required events must be received before proceeding.
+ */
+ const int event_await_count = 1 + (driverdata->xdg_output != NULL);
+
+ driverdata->wl_output_done_count = SDL_min(driverdata->wl_output_done_count + 1, event_await_count + 1);
+
+ if (driverdata->wl_output_done_count != event_await_count) {
return;
+ }
- driverdata->done = SDL_TRUE;
+ /* The native display resolution */
+ SDL_zero(native_mode);
+ native_mode.format = SDL_PIXELFORMAT_RGB888;
- SDL_zero(mode);
- mode.format = SDL_PIXELFORMAT_RGB888;
if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
- mode.w = driverdata->height / driverdata->scale_factor;
- mode.h = driverdata->width / driverdata->scale_factor;
+ native_mode.w = driverdata->native_height;
+ native_mode.h = driverdata->native_width;
+ } else {
+ native_mode.w = driverdata->native_width;
+ native_mode.h = driverdata->native_height;
+ }
+ native_mode.refresh_rate = (int)SDL_round(driverdata->refresh / 1000.0); /* mHz to Hz */
+ native_mode.driverdata = driverdata->output;
+ /* The scaled desktop mode */
+ SDL_zero(desktop_mode);
+ desktop_mode.format = SDL_PIXELFORMAT_RGB888;
+
+ /* Scale the desktop coordinates, if xdg-output isn't present */
+ if (!driverdata->has_logical_size) {
+ driverdata->width /= driverdata->scale_factor;
+ driverdata->height /= driverdata->scale_factor;
+ }
+
+ /* xdg-output dimensions are already transformed, so no need to rotate. */
+ if (driverdata->has_logical_size || !(driverdata->transform & WL_OUTPUT_TRANSFORM_90)) {
+ desktop_mode.w = driverdata->width;
+ desktop_mode.h = driverdata->height;
+ } else {
+ desktop_mode.w = driverdata->height;
+ desktop_mode.h = driverdata->width;
+ }
+ desktop_mode.refresh_rate = (int)SDL_round(driverdata->refresh / 1000.0); /* mHz to Hz */
+ desktop_mode.driverdata = driverdata->output;
+
+ /*
+ * The native display mode is only exposed separately from the desktop size if:
+ * the desktop is scaled and the wp_viewporter protocol is supported.
+ */
+ if (driverdata->scale_factor > 1.0f && video->viewporter != NULL) {
+ if (driverdata->index > -1) {
+ SDL_AddDisplayMode(SDL_GetDisplay(driverdata->index), &native_mode);
+ } else {
+ SDL_AddDisplayMode(&driverdata->placeholder, &native_mode);
+ }
+ }
+
+ /* Calculate the display DPI */
+ if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
driverdata->hdpi = driverdata->physical_height ?
(((float) driverdata->height) * 25.4f / driverdata->physical_height) :
0.0f;
@@ -432,9 +620,6 @@ display_handle_done(void *data,
((float) driverdata->physical_height) / 25.4f,
((float) driverdata->physical_width) / 25.4f);
} else {
- mode.w = driverdata->width / driverdata->scale_factor;
- mode.h = driverdata->height / driverdata->scale_factor;
-
driverdata->hdpi = driverdata->physical_width ?
(((float) driverdata->width) * 25.4f / driverdata->physical_width) :
0.0f;
@@ -446,8 +631,6 @@ display_handle_done(void *data,
((float) driverdata->physical_width) / 25.4f,
((float) driverdata->physical_height) / 25.4f);
}
- mode.refresh_rate = (int)SDL_round(driverdata->refresh / 1000.0); /* mHz to Hz */
- mode.driverdata = driverdata->output;
if (driverdata->index > -1) {
dpy = SDL_GetDisplay(driverdata->index);
@@ -455,9 +638,14 @@ display_handle_done(void *data,
dpy = &driverdata->placeholder;
}
- SDL_AddDisplayMode(dpy, &mode);
- SDL_SetCurrentDisplayMode(dpy, &mode);
- SDL_SetDesktopDisplayMode(dpy, &mode);
+ SDL_AddDisplayMode(dpy, &desktop_mode);
+ SDL_SetCurrentDisplayMode(dpy, &desktop_mode);
+ SDL_SetDesktopDisplayMode(dpy, &desktop_mode);
+
+ /* Add emulated modes if wp_viewporter is supported. */
+ if (video->viewporter) {
+ AddEmulatedModes(dpy, (driverdata->transform & WL_OUTPUT_TRANSFORM_90) != 0);
+ }
if (driverdata->index == -1) {
/* First time getting display info, create the VideoDisplay */
@@ -504,11 +692,29 @@ Wayland_add_display(SDL_VideoData *d, uint32_t id)
data->videodata = d;
data->output = output;
data->registry_id = id;
- data->scale_factor = 1.0;
+ data->scale_factor = 1.0f;
data->index = -1;
wl_output_add_listener(output, &output_listener, data);
SDL_WAYLAND_register_output(output);
+
+ /* Keep a list of outputs for deferred xdg-output initialization. */
+ if (d->output_list != NULL) {
+ SDL_WaylandOutputData *node = (SDL_WaylandOutputData*)d->output_list;
+
+ while (node->next != NULL) {
+ node = (SDL_WaylandOutputData*)node->next;
+ }
+
+ node->next = (struct SDL_WaylandOutputData*)data;
+ } else {
+ d->output_list = (struct SDL_WaylandOutputData*)data;
+ }
+
+ if (data->videodata->xdg_output_manager) {
+ data->xdg_output = zxdg_output_manager_v1_get_xdg_output(data->videodata->xdg_output_manager, output);
+ zxdg_output_v1_add_listener(data->xdg_output, &xdg_output_listener, data);
+ }
}
static void
@@ -524,6 +730,9 @@ Wayland_free_display(uint32_t id)
data = (SDL_WaylandOutputData *) display->driverdata;
if (data->registry_id == id) {
SDL_DelVideoDisplay(i);
+ if (data->xdg_output) {
+ zxdg_output_v1_destroy(data->xdg_output);
+ }
wl_output_destroy(data->output);
SDL_free(data);
@@ -540,6 +749,16 @@ Wayland_free_display(uint32_t id)
}
}
+static void
+Wayland_init_xdg_output(SDL_VideoData *d)
+{
+ SDL_WaylandOutputData *node;
+ for (node = d->output_list; node != NULL; node = node->next) {
+ node->xdg_output = zxdg_output_manager_v1_get_xdg_output(node->videodata->xdg_output_manager, node->output);
+ zxdg_output_v1_add_listener(node->xdg_output, &xdg_output_listener, node);
+ }
+}
+
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
static void
windowmanager_hints(void *data, struct qt_windowmanager *qt_windowmanager,
@@ -600,7 +819,7 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
} else if (SDL_strcmp(interface, "wl_seat") == 0) {
Wayland_display_add_input(d, id, version);
} else if (SDL_strcmp(interface, "xdg_wm_base") == 0) {
- d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, 1);
+ d->shell.xdg = wl_registry_bind(d->registry, id, &xdg_wm_base_interface, SDL_min(version, 3));
xdg_wm_base_add_listener(d->shell.xdg, &shell_listener_xdg, NULL);
} else if (SDL_strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
@@ -620,6 +839,17 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
Wayland_add_data_device_manager(d, id, version);
} else if (SDL_strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
d->decoration_manager = wl_registry_bind(d->registry, id, &zxdg_decoration_manager_v1_interface, 1);
+ } else if (SDL_strcmp(interface, "zwp_tablet_manager_v2") == 0) {
+ d->tablet_manager = wl_registry_bind(d->registry, id, &zwp_tablet_manager_v2_interface, 1);
+ if (d->input) {
+ Wayland_input_add_tablet(d->input, d->tablet_manager);
+ }
+ } else if (SDL_strcmp(interface, "zxdg_output_manager_v1") == 0) {
+ version = SDL_min(version, 3); /* Versions 1 through 3 are supported. */
+ d->xdg_output_manager = wl_registry_bind(d->registry, id, &zxdg_output_manager_v1_interface, version);
+ Wayland_init_xdg_output(d);
+ } else if (SDL_strcmp(interface, "wp_viewporter") == 0) {
+ d->viewporter = wl_registry_bind(d->registry, id, &wp_viewporter_interface, 1);
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
} else if (SDL_strcmp(interface, "qt_touch_extension") == 0) {
@@ -646,6 +876,29 @@ static const struct wl_registry_listener registry_listener = {
display_handle_global,
display_remove_global
};
+
+#ifdef HAVE_LIBDECOR_H
+static SDL_bool should_use_libdecor(SDL_VideoData *data)
+{
+ if (!SDL_WAYLAND_HAVE_WAYLAND_LIBDECOR) {
+ return SDL_FALSE;
+ }
+
+ if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR, SDL_TRUE)) {
+ return SDL_FALSE;
+ }
+
+ if (SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR, SDL_FALSE)) {
+ return SDL_TRUE;
+ }
+
+ if (data->decoration_manager) {
+ return SDL_FALSE;
+ }
+
+ return SDL_TRUE;
+}
+#endif
int
Wayland_VideoInit(_THIS)
@@ -669,14 +922,8 @@ Wayland_VideoInit(_THIS)
#ifdef HAVE_LIBDECOR_H
/* Don't have server-side decorations? Try client-side instead. */
- if (!data->decoration_manager && SDL_WAYLAND_HAVE_WAYLAND_LIBDECOR && SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR, SDL_TRUE)) {
+ if (should_use_libdecor(data)) {
data->shell.libdecor = libdecor_new(data->display, &libdecor_interface);
-
- /* If libdecor works, we don't need xdg-shell anymore. */
- if (data->shell.libdecor && data->shell.xdg) {
- xdg_wm_base_destroy(data->shell.xdg);
- data->shell.xdg = NULL;
- }
}
#endif
@@ -737,6 +984,10 @@ Wayland_VideoQuit(_THIS)
for (i = 0; i < _this->num_displays; ++i) {
SDL_VideoDisplay *display = &_this->displays[i];
+ if (((SDL_WaylandOutputData*)display->driverdata)->xdg_output) {
+ zxdg_output_v1_destroy(((SDL_WaylandOutputData*)display->driverdata)->xdg_output);
+ }
+
wl_output_destroy(((SDL_WaylandOutputData*)display->driverdata)->output);
SDL_free(display->driverdata);
display->driverdata = NULL;
@@ -779,6 +1030,9 @@ Wayland_VideoQuit(_THIS)
Wayland_touch_destroy(data);
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
+ if (data->tablet_manager)
+ zwp_tablet_manager_v2_destroy((struct zwp_tablet_manager_v2*)data->tablet_manager);
+
if (data->data_device_manager)
wl_data_device_manager_destroy(data->data_device_manager);
@@ -798,6 +1052,14 @@ Wayland_VideoQuit(_THIS)
}
#endif
+ if (data->xdg_output_manager) {
+ zxdg_output_manager_v1_destroy(data->xdg_output_manager);
+ }
+
+ if (data->viewporter) {
+ wp_viewporter_destroy(data->viewporter);
+ }
+
if (data->compositor)
wl_compositor_destroy(data->compositor);
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.h b/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.h
index 31168a9d5..6f941db80 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.h
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.h
@@ -34,6 +34,7 @@
struct xkb_context;
struct SDL_WaylandInput;
+struct SDL_WaylandTabletManager;
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
struct SDL_WaylandTouch;
@@ -46,6 +47,8 @@ typedef struct {
int size;
} SDL_WaylandCursorTheme;
+typedef struct SDL_WaylandOutputData SDL_WaylandOutputData;
+
typedef struct {
SDL_bool initializing;
struct wl_display *display;
@@ -70,6 +73,8 @@ typedef struct {
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
struct xdg_activation_v1 *activation_manager;
struct zwp_text_input_manager_v3 *text_input_manager;
+ struct zxdg_output_manager_v1 *xdg_output_manager;
+ struct wp_viewporter *viewporter;
EGLDisplay edpy;
EGLContext context;
@@ -77,6 +82,8 @@ typedef struct {
struct xkb_context *xkb_context;
struct SDL_WaylandInput *input;
+ struct SDL_WaylandTabletManager *tablet_manager;
+ SDL_WaylandOutputData *output_list;
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
struct SDL_WaylandTouch *touch;
@@ -89,19 +96,23 @@ typedef struct {
int relative_mouse_mode;
} SDL_VideoData;
-typedef struct {
+struct SDL_WaylandOutputData {
SDL_VideoData *videodata;
struct wl_output *output;
+ struct zxdg_output_v1 *xdg_output;
uint32_t registry_id;
float scale_factor;
+ int native_width, native_height;
int x, y, width, height, refresh, transform;
SDL_DisplayOrientation orientation;
int physical_width, physical_height;
float ddpi, hdpi, vdpi;
+ SDL_bool has_logical_position, has_logical_size;
int index;
SDL_VideoDisplay placeholder;
- SDL_bool done;
-} SDL_WaylandOutputData;
+ int wl_output_done_count;
+ SDL_WaylandOutputData *next;
+};
/* Needed here to get wl_surface declaration, fixes GitHub#4594 */
#include "SDL_waylanddyn.h"
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandvulkan.c b/Engine/lib/sdl/src/video/wayland/SDL_waylandvulkan.c
index eb4435131..90b318fc8 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandvulkan.c
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandvulkan.c
@@ -139,11 +139,11 @@ void Wayland_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
data = (SDL_WindowData *) window->driverdata;
if (w) {
- *w = window->w * data->scale_factor;
+ *w = data->drawable_width;
}
if (h) {
- *h = window->h * data->scale_factor;
+ *h = data->drawable_height;
}
}
}
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.c b/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.c
index 635546af4..0bbae4691 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.c
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.c
@@ -25,22 +25,294 @@
#include "../SDL_sysvideo.h"
#include "../../events/SDL_windowevents_c.h"
+#include "../../events/SDL_mouse_c.h"
#include "../SDL_egl_c.h"
#include "SDL_waylandevents_c.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandtouch.h"
#include "SDL_hints.h"
+#include "SDL_events.h"
#include "xdg-shell-client-protocol.h"
#include "xdg-decoration-unstable-v1-client-protocol.h"
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "xdg-activation-v1-client-protocol.h"
+#include "viewporter-client-protocol.h"
#ifdef HAVE_LIBDECOR_H
#include
#endif
+static void
+GetFullScreenDimensions(SDL_Window *window, int *width, int *height, int *drawable_width, int *drawable_height)
+{
+ SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
+
+ int fs_width, fs_height;
+ int buf_width, buf_height;
+
+ /*
+ * Fullscreen desktop mandates a desktop sized window, so that's what applications will get.
+ * If the application is DPI aware, it will need to handle the transformations between the
+ * differently sized window and backbuffer spaces on its own.
+ */
+ if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
+ fs_width = output->width;
+ fs_height = output->height;
+
+ /* If the application is DPI aware, we can expose the true backbuffer size */
+ if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
+ buf_width = output->native_width;
+ buf_height = output->native_height;
+ } else {
+ buf_width = fs_width;
+ buf_height = fs_height;
+ }
+ } else {
+ /*
+ * If a mode was set, use it, otherwise use the native resolution
+ * for DPI aware apps and the desktop size for legacy apps.
+ */
+ if (window->fullscreen_mode.w != 0 && window->fullscreen_mode.h != 0) {
+ fs_width = window->fullscreen_mode.w;
+ fs_height = window->fullscreen_mode.h;
+ } else if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
+ fs_width = output->native_width;
+ fs_height = output->native_height;
+ } else {
+ fs_width = output->width;
+ fs_height = output->height;
+ }
+
+ buf_width = fs_width;
+ buf_height = fs_height;
+ }
+
+ if (width) {
+ *width = fs_width;
+ }
+ if (height) {
+ *height = fs_height;
+ }
+ if (drawable_width) {
+ *drawable_width = buf_width;
+ }
+ if (drawable_height) {
+ *drawable_height = buf_height;
+ }
+}
+
+static inline SDL_bool
+DesktopIsScaled(SDL_Window *window)
+{
+ SDL_WindowData *data = window->driverdata;
+
+ return data->scale_factor != 1.0f;
+}
+
+static inline SDL_bool
+DesktopIsFractionalScaled(SDL_Window *window)
+{
+ SDL_WindowData *data = window->driverdata;
+ SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
+
+ if ((output->native_width != (int)(output->width * data->scale_factor) ||
+ output->native_height != (int)(output->height * data->scale_factor))) {
+ return SDL_TRUE;
+ }
+
+ return SDL_FALSE;
+}
+
+static SDL_bool
+NeedFullscreenViewport(SDL_Window *window)
+{
+ SDL_WindowData *data = window->driverdata;
+ SDL_VideoData *video = data->waylandData;
+ SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
+
+ int fs_width, fs_height;
+
+ GetFullScreenDimensions(window, &fs_width, &fs_height, NULL, NULL);
+
+ /*
+ * Fullscreen needs a viewport:
+ * - If the desktop uses fractional scaling
+ * - Fullscreen desktop was not requested OR the window is DPI aware
+ *
+ * - The desktop uses non-fractional scaling
+ * - Fullscreen desktop was NOT requested
+ *
+ * - The desktop is not scaled
+ * - A non-native fullscreen mode was explicitly set by the client
+ */
+ if (video->viewporter != NULL && (window->flags & SDL_WINDOW_FULLSCREEN)) {
+ if (DesktopIsFractionalScaled(window)) {
+ if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP ||
+ (window->flags & SDL_WINDOW_ALLOW_HIGHDPI)) {
+ return SDL_TRUE;
+ }
+ } else if (DesktopIsScaled(window)) {
+ if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
+ return SDL_TRUE;
+ }
+ } else if (fs_width != output->native_width && fs_height != output->native_height) {
+ return SDL_TRUE;
+ }
+ }
+
+ return SDL_FALSE;
+}
+
+static inline SDL_bool
+NeedWindowedViewport(SDL_Window *window)
+{
+ SDL_WindowData *data = window->driverdata;
+ SDL_VideoData *video = data->waylandData;
+
+ return !(window->flags & SDL_WINDOW_FULLSCREEN) && (video->viewporter != NULL) &&
+ DesktopIsFractionalScaled(window) && (window->flags & SDL_WINDOW_ALLOW_HIGHDPI);
+}
+
+/* Never set a fullscreen window size larger than the desktop. */
+SDL_FORCE_INLINE int
+GetWindowWidth(SDL_Window *window)
+{
+ return NeedFullscreenViewport(window) ? ((SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata)->width : window->w;
+}
+
+SDL_FORCE_INLINE int
+GetWindowHeight(SDL_Window *window)
+{
+ return NeedFullscreenViewport(window) ? ((SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata)->height : window->h;
+}
+
+static void
+GetWindowBufferSize(SDL_Window *window, int *width, int *height)
+{
+ SDL_WindowData *data = window->driverdata;
+ SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
+ int buf_width;
+ int buf_height;
+
+ if (NeedWindowedViewport(window)) {
+ const float frac_scale_x = (float)output->native_width / (float)output->width;
+ const float frac_scale_y = (float)output->native_height / (float)output->height;
+
+ buf_width = (int)SDL_lroundf(window->w * frac_scale_x);
+ buf_height = (int)SDL_lroundf(window->h * frac_scale_y);
+ } else { /* Windowed or fullscreen with no viewport */
+ buf_width = window->w * data->scale_factor;
+ buf_height = window->h * data->scale_factor;
+ }
+
+ if (width) {
+ *width = buf_width;
+ }
+ if (height) {
+ *height = buf_height;
+ }
+}
+
+static void
+SetViewport(SDL_Window *window, int src_width, int src_height, int dst_width, int dst_height)
+{
+ SDL_WindowData *wind = window->driverdata;
+ SDL_VideoData *video = wind->waylandData;
+
+ if (video->viewporter) {
+ if (wind->viewport == NULL) {
+ wind->viewport = wp_viewporter_get_viewport(video->viewporter, wind->surface);
+ }
+
+ wp_viewport_set_source(wind->viewport, wl_fixed_from_int(0), wl_fixed_from_int(0), wl_fixed_from_int(src_width), wl_fixed_from_int(src_height));
+ wp_viewport_set_destination(wind->viewport, dst_width, dst_height);
+ }
+}
+
+static void
+UnsetViewport(SDL_Window *window)
+{
+ SDL_WindowData *wind = window->driverdata;
+
+ if (wind->viewport) {
+ wp_viewport_destroy(wind->viewport);
+ wind->viewport = NULL;
+ }
+}
+
+static void
+ConfigureViewport(SDL_Window *window)
+{
+ SDL_WindowData *data = window->driverdata;
+ SDL_VideoData *viddata = data->waylandData;
+ SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
+
+ if (NeedFullscreenViewport(window)) {
+ int fs_width, fs_height;
+ int src_width, src_height;
+
+ GetFullScreenDimensions(window, &fs_width, &fs_height, &src_width, &src_height);
+ SetViewport(window, src_width, src_height, output->width, output->height);
+
+ data->damage_region.x = 0;
+ data->damage_region.y = 0;
+ data->damage_region.w = output->width;
+ data->damage_region.h = output->height;
+
+ data->pointer_scale_x = (float)fs_width / (float)output->width;
+ data->pointer_scale_y = (float)fs_height / (float)output->height;
+ } else {
+ if (NeedWindowedViewport(window)) {
+ int src_width, src_height;
+
+ GetWindowBufferSize(window, &src_width, &src_height);
+ SetViewport(window, src_width, src_height, window->w, window->h);
+ } else {
+ UnsetViewport(window);
+ }
+
+ SDL_zero(data->damage_region);
+
+ data->pointer_scale_x = 1.0f;
+ data->pointer_scale_y = 1.0f;
+ }
+
+ /*
+ * If mouse_rect is not empty, re-create the confinement region with the new scale value.
+ * If the pointer is locked to the general surface with unspecified coordinates, it will
+ * be confined to the viewport region, so no update is required.
+ */
+ if (!SDL_RectEmpty(&window->mouse_rect)) {
+ Wayland_input_confine_pointer(viddata->input, window);
+ }
+}
+
+static void
+SetDrawScale(SDL_Window *window)
+{
+ SDL_WindowData *data = window->driverdata;
+
+ if (NeedFullscreenViewport(window)) {
+ int fs_width, fs_height;
+
+ GetFullScreenDimensions(window, &fs_width, &fs_height, &data->drawable_width, &data->drawable_height);
+
+ /* Set the buffer scale to 1 since a viewport will be used. */
+ wl_surface_set_buffer_scale(data->surface, 1);
+ } else {
+ GetWindowBufferSize(window, &data->drawable_width, &data->drawable_height);
+
+ if (NeedWindowedViewport(window)) {
+ /* Set the buffer scale to 1 since a viewport will be used. */
+ wl_surface_set_buffer_scale(data->surface, 1);
+ } else {
+ wl_surface_set_buffer_scale(data->surface, (int32_t)data->scale_factor);
+ }
+ }
+}
+
static void
SetMinMaxDimensions(SDL_Window *window, SDL_bool commit)
{
@@ -48,6 +320,15 @@ SetMinMaxDimensions(SDL_Window *window, SDL_bool commit)
SDL_VideoData *viddata = wind->waylandData;
int min_width, min_height, max_width, max_height;
+ /* Pop-ups don't get to change size */
+ if (WINDOW_IS_XDG_POPUP(window)) {
+ /* ... but we still want to commit, particularly for ShowWindow */
+ if (commit) {
+ wl_surface_commit(wind->surface);
+ }
+ return;
+ }
+
if (window->flags & SDL_WINDOW_FULLSCREEN) {
min_width = 0;
min_height = 0;
@@ -66,7 +347,7 @@ SetMinMaxDimensions(SDL_Window *window, SDL_bool commit)
}
#ifdef HAVE_LIBDECOR_H
- if (viddata->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(viddata, window)) {
if (wind->shell_surface.libdecor.frame == NULL) {
return; /* Can't do anything yet, wait for ShowWindow */
}
@@ -100,13 +381,22 @@ SetFullscreen(SDL_Window *window, struct wl_output *output, SDL_bool commit)
SDL_WindowData *wind = window->driverdata;
SDL_VideoData *viddata = wind->waylandData;
+ /* Pop-ups don't get to be fullscreened */
+ if (WINDOW_IS_XDG_POPUP(window)) {
+ /* ... but we still want to commit, particularly for ShowWindow */
+ if (commit) {
+ wl_surface_commit(wind->surface);
+ }
+ return;
+ }
+
/* The desktop may try to enforce min/max sizes here, so turn them off for
* fullscreen and on (if applicable) for windowed
*/
SetMinMaxDimensions(window, SDL_FALSE);
#ifdef HAVE_LIBDECOR_H
- if (viddata->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(viddata, window)) {
if (wind->shell_surface.libdecor.frame == NULL) {
return; /* Can't do anything yet, wait for ShowWindow */
}
@@ -150,6 +440,11 @@ handle_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time)
SDL_WindowData *wind = (SDL_WindowData *) data;
SDL_AtomicSet(&wind->swap_interval_ready, 1); /* mark window as ready to present again. */
+ if (!SDL_RectEmpty(&wind->damage_region)) {
+ wl_surface_damage(wind->surface, wind->damage_region.x, wind->damage_region.y,
+ wind->damage_region.w, wind->damage_region.h);
+ }
+
/* reset this callback to fire again once a new frame was presented and compositor wants the next one. */
wind->frame_callback = wl_surface_frame(wind->frame_surface_wrapper);
wl_callback_destroy(cb);
@@ -303,9 +598,14 @@ handle_configure_xdg_toplevel(void *data,
* UPDATE: Nope, sure enough a compositor sends 0,0. This is a known bug:
* https://bugs.kde.org/show_bug.cgi?id=444962
*/
- if (width != 0 && height != 0 && (window->w != width || window->h != height)) {
- window->w = width;
- window->h = height;
+ if (!NeedFullscreenViewport(window)) {
+ if (width != 0 && height != 0 && (window->w != width || window->h != height)) {
+ window->w = width;
+ window->h = height;
+ wind->needs_resize_event = SDL_TRUE;
+ }
+ } else {
+ GetFullScreenDimensions(window, &window->w, &window->h, NULL, NULL);
wind->needs_resize_event = SDL_TRUE;
}
@@ -329,6 +629,60 @@ static const struct xdg_toplevel_listener toplevel_listener_xdg = {
handle_close_xdg_toplevel
};
+static void
+handle_configure_xdg_popup(void *data,
+ struct xdg_popup *xdg_popup,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height)
+{
+ /* No-op, we don't use x/y and width/height are fixed-size */
+}
+
+static void
+handle_done_xdg_popup(void *data, struct xdg_popup *xdg_popup)
+{
+ SDL_WindowData *window = (SDL_WindowData *)data;
+ SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
+}
+
+static void
+handle_repositioned_xdg_popup(void *data,
+ struct xdg_popup *xdg_popup,
+ uint32_t token)
+{
+ /* No-op, configure does all the work we care about */
+}
+
+static const struct xdg_popup_listener popup_listener_xdg = {
+ handle_configure_xdg_popup,
+ handle_done_xdg_popup,
+ handle_repositioned_xdg_popup
+};
+
+#define TOOLTIP_CURSOR_OFFSET 8 /* FIXME: Arbitrary, eyeballed from X tooltip */
+
+static int
+Wayland_PopupWatch(void *data, SDL_Event *event)
+{
+ if (event->type == SDL_MOUSEMOTION) {
+ SDL_Window *window = (SDL_Window *) data;
+ SDL_WindowData *wind = window->driverdata;
+
+ /* Coordinates might be relative to the popup, which we don't want */
+ if (event->motion.windowID == wind->shell_surface.xdg.roleobj.popup.parentID) {
+ xdg_positioner_set_offset(wind->shell_surface.xdg.roleobj.popup.positioner,
+ event->motion.x + TOOLTIP_CURSOR_OFFSET,
+ event->motion.y + TOOLTIP_CURSOR_OFFSET);
+ xdg_popup_reposition(wind->shell_surface.xdg.roleobj.popup.popup,
+ wind->shell_surface.xdg.roleobj.popup.positioner,
+ 0);
+ }
+ }
+ return 1;
+}
+
#ifdef HAVE_LIBDECOR_H
static void
decoration_frame_configure(struct libdecor_frame *frame,
@@ -399,17 +753,23 @@ decoration_frame_configure(struct libdecor_frame *frame,
* Always assume the configure is wrong.
*/
if (fullscreen) {
- /* FIXME: We have been explicitly told to respect the fullscreen size
- * parameters here, even though they are known to be wrong on GNOME at
- * bare minimum. If this is wrong, don't blame us, we were explicitly
- * told to do this.
- */
- if (!libdecor_configuration_get_content_size(configuration, frame,
- &width, &height)) {
- width = window->w;
- height = window->h;
+ if (!NeedFullscreenViewport(window)) {
+ /* FIXME: We have been explicitly told to respect the fullscreen size
+ * parameters here, even though they are known to be wrong on GNOME at
+ * bare minimum. If this is wrong, don't blame us, we were explicitly
+ * told to do this.
+ */
+ if (!libdecor_configuration_get_content_size(configuration, frame,
+ &width, &height)) {
+ width = window->w;
+ height = window->h;
+ }
+ } else {
+ GetFullScreenDimensions(window, &width, &height, NULL, NULL);
}
+ wind->needs_resize_event = SDL_TRUE;
+
/* This part is good though. */
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
scale_factor = driverdata->scale_factor;
@@ -445,7 +805,7 @@ decoration_frame_configure(struct libdecor_frame *frame,
wind->shell_surface.libdecor.initial_configure_seen = SDL_TRUE;
/* ... then commit the changes on the libdecor side. */
- state = libdecor_state_new(width, height);
+ state = libdecor_state_new(GetWindowWidth(window), GetWindowHeight(window));
libdecor_frame_commit(frame, state, configuration);
libdecor_state_free(state);
@@ -554,9 +914,28 @@ Wayland_move_window(SDL_Window *window,
int i, numdisplays = SDL_GetNumVideoDisplays();
for (i = 0; i < numdisplays; i += 1) {
if (SDL_GetDisplay(i)->driverdata == driverdata) {
- SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED,
- SDL_WINDOWPOS_CENTERED_DISPLAY(i),
- SDL_WINDOWPOS_CENTERED_DISPLAY(i));
+ /* We want to send a very very specific combination here:
+ *
+ * 1. A coordinate that tells the application what display we're on
+ * 2. Exactly (0, 0)
+ *
+ * Part 1 is useful information but is also really important for
+ * ensuring we end up on the right display for fullscreen, while
+ * part 2 is important because numerous applications use a specific
+ * combination of GetWindowPosition and GetGlobalMouseState, and of
+ * course neither are supported by Wayland. Since global mouse will
+ * fall back to just GetMouseState, we need the window position to
+ * be zero so the cursor math works without it going off in some
+ * random direction. See UE5 Editor for a notable example of this!
+ *
+ * This may be an issue some day if we're ever able to implement
+ * SDL_GetDisplayUsableBounds!
+ *
+ * -flibit
+ */
+ SDL_Rect bounds;
+ SDL_GetDisplayBounds(i, &bounds);
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, bounds.x, bounds.y);
break;
}
}
@@ -624,6 +1003,19 @@ static const struct wl_surface_listener surface_listener = {
handle_surface_leave
};
+static void
+Wayland_FillEmptyShellInfo(SDL_SysWMinfo * info, const Uint32 version)
+{
+ info->info.wl.xdg_surface = NULL;
+ if (version >= SDL_VERSIONNUM(2, 0, 17)) {
+ info->info.wl.xdg_toplevel = NULL;
+ if (version >= SDL_VERSIONNUM(2, 0, 22)) {
+ info->info.wl.xdg_popup = NULL;
+ info->info.wl.xdg_positioner = NULL;
+ }
+ }
+}
+
SDL_bool
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
{
@@ -656,23 +1048,40 @@ Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
info->info.wl.egl_window = data->egl_window;
#ifdef HAVE_LIBDECOR_H
- if (viddata->shell.libdecor && data->shell_surface.libdecor.frame != NULL) {
- info->info.wl.xdg_surface = libdecor_frame_get_xdg_surface(data->shell_surface.libdecor.frame);
- if (version >= SDL_VERSIONNUM(2, 0, 17)) {
- info->info.wl.xdg_toplevel = libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame);
+ if (WINDOW_IS_LIBDECOR(viddata, window)) {
+ if (data->shell_surface.libdecor.frame != NULL) {
+ info->info.wl.xdg_surface = libdecor_frame_get_xdg_surface(data->shell_surface.libdecor.frame);
+ if (version >= SDL_VERSIONNUM(2, 0, 17)) {
+ info->info.wl.xdg_toplevel = libdecor_frame_get_xdg_toplevel(data->shell_surface.libdecor.frame);
+ if (version >= SDL_VERSIONNUM(2, 0, 22)) {
+ info->info.wl.xdg_popup = NULL;
+ info->info.wl.xdg_positioner = NULL;
+ }
+ }
+ } else {
+ /* Not mapped yet */
+ Wayland_FillEmptyShellInfo(info, version);
}
} else
#endif
if (viddata->shell.xdg && data->shell_surface.xdg.surface != NULL) {
info->info.wl.xdg_surface = data->shell_surface.xdg.surface;
if (version >= SDL_VERSIONNUM(2, 0, 17)) {
- info->info.wl.xdg_toplevel = data->shell_surface.xdg.roleobj.toplevel;
+ SDL_bool popup = WINDOW_IS_XDG_POPUP(window);
+ info->info.wl.xdg_toplevel = popup ? NULL : data->shell_surface.xdg.roleobj.toplevel;
+ if (version >= SDL_VERSIONNUM(2, 0, 22)) {
+ if (popup) {
+ info->info.wl.xdg_popup = data->shell_surface.xdg.roleobj.popup.popup;
+ info->info.wl.xdg_positioner = data->shell_surface.xdg.roleobj.popup.positioner;
+ } else {
+ info->info.wl.xdg_popup = NULL;
+ info->info.wl.xdg_positioner = NULL;
+ }
+ }
}
} else {
- info->info.wl.xdg_surface = NULL;
- if (version >= SDL_VERSIONNUM(2, 0, 17)) {
- info->info.wl.xdg_toplevel = NULL;
- }
+ /* Either it's not mapped yet or we don't have a shell protocol */
+ Wayland_FillEmptyShellInfo(info, version);
}
}
@@ -697,6 +1106,10 @@ Wayland_SetWindowModalFor(_THIS, SDL_Window *modal_window, SDL_Window *parent_wi
SDL_WindowData *modal_data = modal_window->driverdata;
SDL_WindowData *parent_data = parent_window->driverdata;
+ if (WINDOW_IS_XDG_POPUP(modal_window) || WINDOW_IS_XDG_POPUP(parent_window)) {
+ return SDL_SetError("Modal/Parent was a popup, not a toplevel");
+ }
+
#ifdef HAVE_LIBDECOR_H
if (viddata->shell.libdecor) {
if (modal_data->shell_surface.libdecor.frame == NULL) {
@@ -731,9 +1144,26 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
SDL_VideoData *c = _this->driverdata;
SDL_WindowData *data = window->driverdata;
- /* Create the shell surface and map the toplevel */
+ /* Detach any previous buffers before resetting everything, otherwise when
+ * calling this a second time you'll get an annoying protocol error!
+ *
+ * FIXME: This was originally moved to HideWindow, which _should_ make
+ * sense, but for whatever reason UE5's popups require that this actually
+ * be in both places at once? Possibly from renderers making commits? I can't
+ * fully remember if this location caused crashes or if I was fixing a pair
+ * of Hide/Show calls. In any case, UE gives us a pretty good test and having
+ * both detach calls passes. This bug may be relevant if I'm wrong:
+ *
+ * https://bugs.kde.org/show_bug.cgi?id=448856
+ *
+ * -flibit
+ */
+ wl_surface_attach(data->surface, NULL, 0, 0);
+ wl_surface_commit(data->surface);
+
+ /* Create the shell surface and map the toplevel/popup */
#ifdef HAVE_LIBDECOR_H
- if (c->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(c, window)) {
data->shell_surface.libdecor.frame = libdecor_decorate(c->shell.libdecor,
data->surface,
&libdecor_frame_interface,
@@ -751,10 +1181,42 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
xdg_surface_set_user_data(data->shell_surface.xdg.surface, data);
xdg_surface_add_listener(data->shell_surface.xdg.surface, &shell_surface_listener_xdg, data);
- /* !!! FIXME: add popup role */
- data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
- xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
- xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
+ if (WINDOW_IS_XDG_POPUP(window)) {
+ SDL_Mouse *mouse = SDL_GetMouse();
+ SDL_Window *focused = SDL_GetMouseFocus();
+ SDL_WindowData *focuseddata = focused->driverdata;
+
+ /* This popup may be a child of another popup! */
+ data->shell_surface.xdg.roleobj.popup.parentID = SDL_GetWindowID(focused);
+ data->shell_surface.xdg.roleobj.popup.child = NULL;
+ if (WINDOW_IS_XDG_POPUP(focused)) {
+ SDL_assert(focuseddata->shell_surface.xdg.roleobj.popup.child == NULL);
+ focuseddata->shell_surface.xdg.roleobj.popup.child = window;
+ }
+
+ /* Set up the positioner for the popup */
+ data->shell_surface.xdg.roleobj.popup.positioner = xdg_wm_base_create_positioner(c->shell.xdg);
+ xdg_positioner_set_offset(data->shell_surface.xdg.roleobj.popup.positioner,
+ mouse->x + TOOLTIP_CURSOR_OFFSET,
+ mouse->y + TOOLTIP_CURSOR_OFFSET);
+
+ /* Assign the popup role */
+ data->shell_surface.xdg.roleobj.popup.popup = xdg_surface_get_popup(data->shell_surface.xdg.surface,
+ focuseddata->shell_surface.xdg.surface,
+ data->shell_surface.xdg.roleobj.popup.positioner);
+ xdg_popup_add_listener(data->shell_surface.xdg.roleobj.popup.popup, &popup_listener_xdg, data);
+
+ /* For tooltips, track mouse motion so it follows the cursor */
+ if (window->flags & SDL_WINDOW_TOOLTIP) {
+ if (xdg_popup_get_version(data->shell_surface.xdg.roleobj.popup.popup) >= 3) {
+ SDL_AddEventWatch(Wayland_PopupWatch, window);
+ }
+ }
+ } else {
+ data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface);
+ xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname);
+ xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data);
+ }
}
/* Restore state that was set prior to this call */
@@ -770,7 +1232,7 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
* this surface will fail. This is a new rule for xdg_shell.
*/
#ifdef HAVE_LIBDECOR_H
- if (c->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(c, window)) {
if (data->shell_surface.libdecor.frame) {
while (!data->shell_surface.libdecor.initial_configure_seen) {
WAYLAND_wl_display_flush(c->display);
@@ -794,7 +1256,7 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
}
/* Create the window decorations */
- if (data->shell_surface.xdg.roleobj.toplevel && c->decoration_manager) {
+ if (!WINDOW_IS_XDG_POPUP(window) && data->shell_surface.xdg.roleobj.toplevel && c->decoration_manager) {
data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel);
}
} else {
@@ -807,11 +1269,11 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
* them immediately afterward.
*/
#ifdef HAVE_LIBDECOR_H
- if (c->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(c, window)) {
/* ... but don't call it redundantly for libdecor, the decorator
* may not interpret a redundant call nicely and cause weird stuff to happen
*/
- if (window->flags & SDL_WINDOW_BORDERLESS) {
+ if (data->shell_surface.libdecor.frame && window->flags & SDL_WINDOW_BORDERLESS) {
Wayland_SetWindowBordered(_this, window, SDL_FALSE);
}
} else
@@ -837,6 +1299,42 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
}
}
+static void
+Wayland_ReleasePopup(_THIS, SDL_Window *popup)
+{
+ SDL_WindowData *popupdata;
+
+ /* Basic sanity checks to weed out the weird popup closures */
+ if (popup == NULL || popup->magic != &_this->window_magic) {
+ return;
+ }
+ popupdata = popup->driverdata;
+ if (popupdata == NULL) {
+ return;
+ }
+
+ /* This may already be freed by a parent popup! */
+ if (popupdata->shell_surface.xdg.roleobj.popup.popup == NULL) {
+ return;
+ }
+
+ /* Release the child _first_, otherwise a protocol error triggers */
+ if (popupdata->shell_surface.xdg.roleobj.popup.child != NULL) {
+ Wayland_ReleasePopup(_this, popupdata->shell_surface.xdg.roleobj.popup.child);
+ popupdata->shell_surface.xdg.roleobj.popup.child = NULL;
+ }
+
+ if (popup->flags & SDL_WINDOW_TOOLTIP) {
+ if (xdg_popup_get_version(popupdata->shell_surface.xdg.roleobj.popup.popup) >= 3) {
+ SDL_DelEventWatch(Wayland_PopupWatch, popup);
+ }
+ }
+ xdg_popup_destroy(popupdata->shell_surface.xdg.roleobj.popup.popup);
+ xdg_positioner_destroy(popupdata->shell_surface.xdg.roleobj.popup.positioner);
+ popupdata->shell_surface.xdg.roleobj.popup.popup = NULL;
+ popupdata->shell_surface.xdg.roleobj.popup.positioner = NULL;
+}
+
void Wayland_HideWindow(_THIS, SDL_Window *window)
{
SDL_VideoData *data = _this->driverdata;
@@ -848,7 +1346,7 @@ void Wayland_HideWindow(_THIS, SDL_Window *window)
}
#ifdef HAVE_LIBDECOR_H
- if (data->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(data, window)) {
if (wind->shell_surface.libdecor.frame) {
libdecor_frame_unref(wind->shell_surface.libdecor.frame);
wind->shell_surface.libdecor.frame = NULL;
@@ -856,7 +1354,9 @@ void Wayland_HideWindow(_THIS, SDL_Window *window)
} else
#endif
if (data->shell.xdg) {
- if (wind->shell_surface.xdg.roleobj.toplevel) {
+ if (WINDOW_IS_XDG_POPUP(window)) {
+ Wayland_ReleasePopup(_this, window);
+ } else if (wind->shell_surface.xdg.roleobj.toplevel) {
xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel);
wind->shell_surface.xdg.roleobj.toplevel = NULL;
}
@@ -1073,13 +1573,17 @@ Wayland_RestoreWindow(_THIS, SDL_Window * window)
SDL_WindowData *wind = window->driverdata;
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
+ if (WINDOW_IS_XDG_POPUP(window)) {
+ return;
+ }
+
/* Set this flag now even if we never actually maximized, eventually
* ShowWindow will take care of it along with the other window state.
*/
window->flags &= ~SDL_WINDOW_MAXIMIZED;
#ifdef HAVE_LIBDECOR_H
- if (viddata->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(viddata, window)) {
if (wind->shell_surface.libdecor.frame == NULL) {
return; /* Can't do anything yet, wait for ShowWindow */
}
@@ -1102,8 +1606,13 @@ Wayland_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
{
SDL_WindowData *wind = window->driverdata;
const SDL_VideoData *viddata = (const SDL_VideoData *) _this->driverdata;
+
+ if (WINDOW_IS_XDG_POPUP(window)) {
+ return;
+ }
+
#ifdef HAVE_LIBDECOR_H
- if (viddata->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(viddata, window)) {
if (wind->shell_surface.libdecor.frame) {
libdecor_frame_set_visibility(wind->shell_surface.libdecor.frame, bordered);
}
@@ -1122,7 +1631,7 @@ Wayland_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
SDL_VideoData *data = _this->driverdata;
const SDL_WindowData *wind = window->driverdata;
- if (data->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(data, window)) {
if (wind->shell_surface.libdecor.frame == NULL) {
return; /* Can't do anything yet, wait for ShowWindow */
}
@@ -1144,6 +1653,10 @@ Wayland_MaximizeWindow(_THIS, SDL_Window * window)
SDL_WindowData *wind = window->driverdata;
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
+ if (WINDOW_IS_XDG_POPUP(window)) {
+ return;
+ }
+
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
return;
}
@@ -1154,7 +1667,7 @@ Wayland_MaximizeWindow(_THIS, SDL_Window * window)
window->flags |= SDL_WINDOW_MAXIMIZED;
#ifdef HAVE_LIBDECOR_H
- if (viddata->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(viddata, window)) {
if (wind->shell_surface.libdecor.frame == NULL) {
return; /* Can't do anything yet, wait for ShowWindow */
}
@@ -1177,8 +1690,12 @@ Wayland_MinimizeWindow(_THIS, SDL_Window * window)
SDL_WindowData *wind = window->driverdata;
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
+ if (WINDOW_IS_XDG_POPUP(window)) {
+ return;
+ }
+
#ifdef HAVE_LIBDECOR_H
- if (viddata->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(viddata, window)) {
if (wind->shell_surface.libdecor.frame == NULL) {
return; /* Can't do anything yet, wait for ShowWindow */
}
@@ -1269,7 +1786,9 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
data->waylandData = c;
data->sdlwindow = window;
- data->scale_factor = 1.0;
+ data->scale_factor = 1.0f;
+ data->pointer_scale_x = 1.0f;
+ data->pointer_scale_y = 1.0f;
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
int i;
@@ -1316,16 +1835,18 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
+ data->drawable_width = window->w * data->scale_factor;
+ data->drawable_height = window->h * data->scale_factor;
+
if (window->flags & SDL_WINDOW_OPENGL) {
- data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
- window->w * data->scale_factor, window->h * data->scale_factor);
+ data->egl_window = WAYLAND_wl_egl_window_create(data->surface, data->drawable_width, data->drawable_height);
#if SDL_VIDEO_OPENGL_EGL
/* Create the GLES window surface */
data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->egl_window);
if (data->egl_surface == EGL_NO_SURFACE) {
- return SDL_SetError("failed to create an EGL window surface");
+ return -1; /* SDL_EGL_CreateSurface should have set error */
}
#endif
}
@@ -1375,12 +1896,13 @@ Wayland_HandleResize(SDL_Window *window, int width, int height, float scale)
data->needs_resize_event = SDL_FALSE;
}
- wl_surface_set_buffer_scale(data->surface, data->scale_factor);
+ /* Configure the backbuffer size and scale factors */
+ SetDrawScale(window);
if (data->egl_window) {
WAYLAND_wl_egl_window_resize(data->egl_window,
- window->w * data->scale_factor,
- window->h * data->scale_factor,
+ data->drawable_width,
+ data->drawable_height,
0, 0);
}
@@ -1394,9 +1916,18 @@ Wayland_HandleResize(SDL_Window *window, int width, int height, float scale)
* It doesn't fix the first frames after resize being glitched visually,
* but at least lets us not be terminated by the compositor.
* Can be removed once SDL's resize logic becomes compliant. */
- if (viddata->shell.xdg && data->shell_surface.xdg.surface) {
- xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, window->w, window->h);
+ if (
+#ifdef HAVE_LIBDECOR_H
+ !WINDOW_IS_LIBDECOR(viddata, window) &&
+#endif
+ viddata->shell.xdg &&
+ data->shell_surface.xdg.surface) {
+ xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0,
+ GetWindowWidth(window), GetWindowHeight(window));
}
+
+ /* Update the viewport */
+ ConfigureViewport(window);
}
void
@@ -1422,7 +1953,7 @@ void Wayland_SetWindowSize(_THIS, SDL_Window * window)
#ifdef HAVE_LIBDECOR_H
/* we must not resize the window while we have a static (non-floating) size */
- if (data->shell.libdecor &&
+ if (WINDOW_IS_LIBDECOR(data, window) &&
wind->shell_surface.libdecor.frame &&
!libdecor_frame_is_floating(wind->shell_surface.libdecor.frame)) {
/* Commit the resize when we re-enter floating state */
@@ -1431,18 +1962,18 @@ void Wayland_SetWindowSize(_THIS, SDL_Window * window)
}
#endif
- wl_surface_set_buffer_scale(wind->surface, wind->scale_factor);
+ SetDrawScale(window);
if (wind->egl_window) {
WAYLAND_wl_egl_window_resize(wind->egl_window,
- window->w * wind->scale_factor,
- window->h * wind->scale_factor,
+ wind->drawable_width,
+ wind->drawable_height,
0, 0);
}
#ifdef HAVE_LIBDECOR_H
- if (data->shell.libdecor && wind->shell_surface.libdecor.frame) {
- state = libdecor_state_new(window->w, window->h);
+ if (WINDOW_IS_LIBDECOR(data, window) && wind->shell_surface.libdecor.frame) {
+ state = libdecor_state_new(GetWindowWidth(window), GetWindowHeight(window));
libdecor_frame_commit(wind->shell_surface.libdecor.frame, state, NULL);
libdecor_state_free(state);
}
@@ -1458,8 +1989,14 @@ void Wayland_SetWindowSize(_THIS, SDL_Window * window)
wl_region_destroy(region);
/* Update the geometry which may have been set by a hack in Wayland_HandleResize */
- if (data->shell.xdg && wind->shell_surface.xdg.surface) {
- xdg_surface_set_window_geometry(wind->shell_surface.xdg.surface, 0, 0, window->w, window->h);
+ if (
+#ifdef HAVE_LIBDECOR_H
+ !WINDOW_IS_LIBDECOR(data, window) &&
+#endif
+ data->shell.xdg &&
+ wind->shell_surface.xdg.surface) {
+ xdg_surface_set_window_geometry(wind->shell_surface.xdg.surface, 0, 0,
+ GetWindowWidth(window), GetWindowHeight(window));
}
}
@@ -1468,9 +2005,13 @@ void Wayland_SetWindowTitle(_THIS, SDL_Window * window)
SDL_WindowData *wind = window->driverdata;
SDL_VideoData *viddata = _this->driverdata;
+ if (WINDOW_IS_XDG_POPUP(window)) {
+ return;
+ }
+
if (window->title != NULL) {
#ifdef HAVE_LIBDECOR_H
- if (viddata->shell.libdecor) {
+ if (WINDOW_IS_LIBDECOR(viddata, window)) {
if (wind->shell_surface.libdecor.frame == NULL) {
return; /* Can't do anything yet, wait for ShowWindow */
}
@@ -1549,6 +2090,10 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window)
xdg_activation_token_v1_destroy(wind->activation_token);
}
+ if (wind->viewport) {
+ wp_viewport_destroy(wind->viewport);
+ }
+
SDL_free(wind->outputs);
if (wind->frame_callback) {
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.h b/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.h
index 90e4d8cf6..b1ba98cf9 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.h
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.h
@@ -36,16 +36,27 @@ typedef struct {
struct xdg_surface *surface;
union {
struct xdg_toplevel *toplevel;
- struct xdg_popup *popup;
+ struct {
+ struct xdg_popup *popup;
+ struct xdg_positioner *positioner;
+ Uint32 parentID;
+ SDL_Window *child;
+ } popup;
} roleobj;
SDL_bool initial_configure_seen;
} SDL_xdg_shell_surface;
+#define WINDOW_IS_XDG_POPUP(window) \
+ (window->flags & (SDL_WINDOW_TOOLTIP | SDL_WINDOW_POPUP_MENU))
+
#ifdef HAVE_LIBDECOR_H
typedef struct {
struct libdecor_frame *frame;
SDL_bool initial_configure_seen;
} SDL_libdecor_surface;
+
+#define WINDOW_IS_LIBDECOR(viddata, window) \
+ (viddata->shell.libdecor && !WINDOW_IS_XDG_POPUP(window))
#endif
typedef struct {
@@ -72,6 +83,7 @@ typedef struct {
struct zwp_keyboard_shortcuts_inhibitor_v1 *key_inhibitor;
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
struct xdg_activation_token_v1 *activation_token;
+ struct wp_viewport *viewport;
/* floating dimensions for restoring from maximized and fullscreen */
int floating_width, floating_height;
@@ -86,6 +98,10 @@ typedef struct {
int num_outputs;
float scale_factor;
+ float pointer_scale_x;
+ float pointer_scale_y;
+ int drawable_width, drawable_height;
+ SDL_Rect damage_region;
SDL_bool needs_resize_event;
SDL_bool floating_resize_pending;
} SDL_WindowData;
diff --git a/Engine/lib/sdl/src/video/windows/SDL_windowsevents.c b/Engine/lib/sdl/src/video/windows/SDL_windowsevents.c
index 0619f67dd..ebd0dd1f9 100644
--- a/Engine/lib/sdl/src/video/windows/SDL_windowsevents.c
+++ b/Engine/lib/sdl/src/video/windows/SDL_windowsevents.c
@@ -378,14 +378,14 @@ WIN_CheckAsyncMouseRelease(SDL_WindowData *data)
}
static void
-WIN_UpdateFocus(SDL_Window *window)
+WIN_UpdateFocus(SDL_Window *window, SDL_bool expect_focus)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
HWND hwnd = data->hwnd;
SDL_bool had_focus = (SDL_GetKeyboardFocus() == window) ? SDL_TRUE : SDL_FALSE;
SDL_bool has_focus = (GetForegroundWindow() == hwnd) ? SDL_TRUE : SDL_FALSE;
- if (had_focus == has_focus) {
+ if (had_focus == has_focus || has_focus != expect_focus) {
return;
}
@@ -686,7 +686,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
/* Update the focus here, since it's possible to get WM_ACTIVATE and WM_SETFOCUS without
actually being the foreground window, but this appears to get called in all cases where
the global foreground window changes to and from this window. */
- WIN_UpdateFocus(data->window);
+ WIN_UpdateFocus(data->window, !!wParam);
WIN_CheckICMProfileChanged(data->window);
}
break;
@@ -694,16 +694,22 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_ACTIVATE:
{
/* Update the focus in case we changed focus to a child window and then away from the application */
- WIN_UpdateFocus(data->window);
+ WIN_UpdateFocus(data->window, !!LOWORD(wParam));
}
break;
case WM_SETFOCUS:
+ {
+ /* Update the focus in case it's changing between top-level windows in the same application */
+ WIN_UpdateFocus(data->window, SDL_TRUE);
+ }
+ break;
+
case WM_KILLFOCUS:
case WM_ENTERIDLE:
{
/* Update the focus in case it's changing between top-level windows in the same application */
- WIN_UpdateFocus(data->window);
+ WIN_UpdateFocus(data->window, SDL_FALSE);
}
break;
diff --git a/Engine/lib/sdl/src/video/windows/SDL_windowswindow.c b/Engine/lib/sdl/src/video/windows/SDL_windowswindow.c
index 890d790ea..6dcea5bf2 100644
--- a/Engine/lib/sdl/src/video/windows/SDL_windowswindow.c
+++ b/Engine/lib/sdl/src/video/windows/SDL_windowswindow.c
@@ -158,7 +158,7 @@ WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
int w, h;
/* Figure out what the window area will be */
- if (SDL_ShouldAllowTopmost() && ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS) || (window->flags & SDL_WINDOW_ALWAYS_ON_TOP))) {
+ if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_ALWAYS_ON_TOP)) {
top = HWND_TOPMOST;
} else {
top = HWND_NOTOPMOST;
@@ -734,7 +734,14 @@ WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display,
int x, y;
int w, h;
- if (SDL_ShouldAllowTopmost() && ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS) || window->flags & SDL_WINDOW_ALWAYS_ON_TOP)) {
+ if (!fullscreen && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0) {
+ /* Resizing the window on hide causes problems restoring it in Wine, and it's unnecessary.
+ * Also, Windows would preview the minimized window with the wrong size.
+ */
+ return;
+ }
+
+ if (SDL_ShouldAllowTopmost() && (window->flags & SDL_WINDOW_ALWAYS_ON_TOP)) {
top = HWND_TOPMOST;
} else {
top = HWND_NOTOPMOST;
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11events.c b/Engine/lib/sdl/src/video/x11/SDL_x11events.c
index c1260215d..63091fe98 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11events.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11events.c
@@ -380,7 +380,7 @@ X11_GetScrollLockModifierMask(_THIS)
return num_mask;
}
-static void
+void
X11_ReconcileKeyboardState(_THIS)
{
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
@@ -408,7 +408,22 @@ X11_ReconcileKeyboardState(_THIS)
SDL_bool sdlKeyPressed = keyboardState[scancode] == SDL_PRESSED;
if (x11KeyPressed && !sdlKeyPressed) {
- SDL_SendKeyboardKey(SDL_PRESSED, scancode);
+ /* Only update modifier state for keys that are pressed in another application */
+ switch (SDL_GetKeyFromScancode(scancode)) {
+ case SDLK_LCTRL:
+ case SDLK_RCTRL:
+ case SDLK_LSHIFT:
+ case SDLK_RSHIFT:
+ case SDLK_LALT:
+ case SDLK_RALT:
+ case SDLK_LGUI:
+ case SDLK_RGUI:
+ case SDLK_MODE:
+ SDL_SendKeyboardKey(SDL_PRESSED, scancode);
+ break;
+ default:
+ break;
+ }
} else if (!x11KeyPressed && sdlKeyPressed) {
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
}
@@ -718,7 +733,6 @@ static void
X11_DispatchEvent(_THIS, XEvent *xevent)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
- XkbEvent* xkbEvent = (XkbEvent*) xevent;
Display *display;
SDL_WindowData *data;
int orig_event_type;
@@ -805,11 +819,13 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
if (!data) {
/* The window for KeymapNotify, etc events is 0 */
if (xevent->type == KeymapNotify) {
+#ifdef DEBUG_XEVENTS
+ printf("window %p: KeymapNotify!\n", data);
+#endif
if (SDL_GetKeyboardFocus() != NULL) {
X11_ReconcileKeyboardState(_this);
}
- } else if (xevent->type == MappingNotify ||
- (xevent->type == videodata->xkb_event && xkbEvent->any.xkb_type == XkbStateNotify)) {
+ } else if (xevent->type == MappingNotify) {
/* Has the keyboard layout changed? */
const int request = xevent->xmapping.request;
@@ -996,8 +1012,9 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
}
break;
- /* Key press? */
- case KeyPress:{
+ /* Key press/release? */
+ case KeyPress:
+ case KeyRelease: {
KeyCode keycode = xevent->xkey.keycode;
KeySym keysym = NoSymbol;
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
@@ -1005,7 +1022,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
SDL_bool handled_by_ime = SDL_FALSE;
#ifdef DEBUG_XEVENTS
- printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode);
+ printf("window %p: %s (X11 keycode = 0x%X)\n", data, (xevent->type == KeyPress ? "KeyPress" : "KeyRelease"), xevent->xkey.keycode);
#endif
#if 1
if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
@@ -1021,7 +1038,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
/* */
SDL_zeroa(text);
#ifdef X_HAVE_UTF8_STRING
- if (data->ic) {
+ if (data->ic && xevent->type == KeyPress) {
X11_Xutf8LookupString(data->ic, &xevent->xkey, text, sizeof(text),
&keysym, &status);
} else {
@@ -1033,35 +1050,30 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
#ifdef SDL_USE_IME
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
- handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode);
+ handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode, (xevent->type == KeyPress ? SDL_PRESSED : SDL_RELEASED));
}
#endif
if (!handled_by_ime) {
- /* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */
- if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) {
- SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
- }
- if(*text) {
- SDL_SendKeyboardText(text);
+ if (xevent->type == KeyPress) {
+ /* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */
+ if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) {
+ SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
+ }
+ if(*text) {
+ SDL_SendKeyboardText(text);
+ }
+ } else {
+ if (X11_KeyRepeat(display, xevent)) {
+ /* We're about to get a repeated key down, ignore the key up */
+ break;
+ }
+ SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
}
}
- X11_UpdateUserTime(data, xevent->xkey.time);
- }
- break;
-
- /* Key release? */
- case KeyRelease:{
- KeyCode keycode = xevent->xkey.keycode;
-
-#ifdef DEBUG_XEVENTS
- printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode);
-#endif
- if (X11_KeyRepeat(display, xevent)) {
- /* We're about to get a repeated key down, ignore the key up */
- break;
+ if (xevent->type == KeyPress) {
+ X11_UpdateUserTime(data, xevent->xkey.time);
}
- SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
}
break;
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11events.h b/Engine/lib/sdl/src/video/x11/SDL_x11events.h
index fc8a57ae2..de89110d0 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11events.h
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11events.h
@@ -27,6 +27,7 @@ extern void X11_PumpEvents(_THIS);
extern int X11_WaitEventTimeout(_THIS, int timeout);
extern void X11_SendWakeupEvent(_THIS, SDL_Window *window);
extern void X11_SuspendScreenSaver(_THIS);
+extern void X11_ReconcileKeyboardState(_THIS);
#endif /* SDL_x11events_h_ */
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.c b/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.c
index c82570c62..c84bcc798 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.c
@@ -409,6 +409,8 @@ X11_InitKeyboard(_THIS)
SDL_IME_Init();
#endif
+ X11_ReconcileKeyboardState(_this);
+
return 0;
}
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11messagebox.c b/Engine/lib/sdl/src/video/x11/SDL_x11messagebox.c
index aafccca9b..9bc9702c0 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11messagebox.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11messagebox.c
@@ -830,10 +830,11 @@ X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
int exitcode = 0;
close(fds[0]);
status = X11_ShowMessageBoxImpl(messageboxdata, buttonid);
- if (write(fds[1], &status, sizeof (int)) != sizeof (int))
+ if (write(fds[1], &status, sizeof (int)) != sizeof (int)) {
exitcode = 1;
- else if (write(fds[1], buttonid, sizeof (int)) != sizeof (int))
+ } else if (write(fds[1], buttonid, sizeof (int)) != sizeof (int)) {
exitcode = 1;
+ }
close(fds[1]);
_exit(exitcode); /* don't run atexit() stuff, static destructors, etc. */
} else { /* we're the parent */
@@ -846,13 +847,12 @@ X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
SDL_assert(rc == pid); /* not sure what to do if this fails. */
if ((rc == -1) || (!WIFEXITED(status)) || (WEXITSTATUS(status) != 0)) {
- return SDL_SetError("msgbox child process failed");
+ status = SDL_SetError("msgbox child process failed");
+ } else if ( (read(fds[0], &status, sizeof (int)) != sizeof (int)) ||
+ (read(fds[0], buttonid, sizeof (int)) != sizeof (int)) ) {
+ status = SDL_SetError("read from msgbox child process failed");
+ *buttonid = 0;
}
-
- if (read(fds[0], &status, sizeof (int)) != sizeof (int))
- status = -1;
- else if (read(fds[0], buttonid, sizeof (int)) != sizeof (int))
- status = -1;
close(fds[0]);
return status;
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11modes.c b/Engine/lib/sdl/src/video/x11/SDL_x11modes.c
index c1efe243c..f2cbdb45f 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11modes.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11modes.c
@@ -1011,7 +1011,13 @@ static int (*PreXRRSetScreenSizeErrorHandler)(Display *, XErrorEvent *) = NULL;
static int
SDL_XRRSetScreenSizeErrHandler(Display *d, XErrorEvent *e)
{
- return (e->error_code == BadMatch) ? 0 : PreXRRSetScreenSizeErrorHandler(d, e);
+ /* BadMatch: https://github.com/libsdl-org/SDL/issues/4561 */
+ /* BadValue: https://github.com/libsdl-org/SDL/issues/4840 */
+ if ((e->error_code == BadMatch) || (e->error_code == BadValue)) {
+ return 0;
+ }
+
+ return PreXRRSetScreenSizeErrorHandler(d, e);
}
int
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11opengl.c b/Engine/lib/sdl/src/video/x11/SDL_x11opengl.c
index 64b06340a..3e17e97ff 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11opengl.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11opengl.c
@@ -247,11 +247,6 @@ X11_GL_LoadLibrary(_THIS, const char *path)
X11_GL_UseEGL(_this) ) {
#if SDL_VIDEO_OPENGL_EGL
X11_GL_UnloadLibrary(_this);
- /* Better avoid conflicts! */
- if (_this->gl_config.dll_handle != NULL ) {
- GL_UnloadObject(_this->gl_config.dll_handle);
- _this->gl_config.dll_handle = NULL;
- }
_this->GL_LoadLibrary = X11_GLES_LoadLibrary;
_this->GL_GetProcAddress = X11_GLES_GetProcAddress;
_this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11sym.h b/Engine/lib/sdl/src/video/x11/SDL_x11sym.h
index 67b0a793a..762a86596 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11sym.h
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11sym.h
@@ -185,7 +185,6 @@ SDL_X11_SYM(XkbDescPtr,XkbGetMap,(Display* a,unsigned int b,unsigned int c),(a,b
SDL_X11_SYM(void,XkbFreeClientMap,(XkbDescPtr a,unsigned int b, Bool c),(a,b,c),)
SDL_X11_SYM(void,XkbFreeKeyboard,(XkbDescPtr a,unsigned int b, Bool c),(a,b,c),)
SDL_X11_SYM(Bool,XkbSetDetectableAutoRepeat,(Display* a, Bool b, Bool* c),(a,b,c),return)
-SDL_X11_SYM(Bool,XkbSelectEvents,(Display* a, unsigned int b, unsigned int c, unsigned int d),(a,b,c,d),return)
#endif
#if NeedWidePrototypes
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11window.c b/Engine/lib/sdl/src/video/x11/SDL_x11window.c
index a6bd91d72..d31ac012a 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11window.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11window.c
@@ -678,8 +678,6 @@ X11_CreateWindow(_THIS, SDL_Window * window)
/* For _ICC_PROFILE. */
X11_XSelectInput(display, RootWindow(display, screen), PropertyChangeMask);
- X11_XkbSelectEvents(display, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask);
-
X11_XFlush(display);
return 0;
@@ -782,11 +780,22 @@ X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
X11_XFlush(display);
}
+static SDL_bool caught_x11_error = SDL_FALSE;
+static int
+X11_CatchAnyError(Display * d, XErrorEvent * e)
+{
+ /* this may happen during tumultuous times when we are polling anyhow,
+ so just note we had an error and return control. */
+ caught_x11_error = SDL_TRUE;
+ return 0;
+}
+
void
X11_SetWindowPosition(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
+ int (*prev_handler) (Display *, XErrorEvent *) = NULL;
unsigned int childCount;
Window childReturn, root, parent;
Window* children;
@@ -805,20 +814,27 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
/* Wait a brief time to see if the window manager decided to let this move happen.
If the window changes at all, even to an unexpected value, we break out. */
+ X11_XSync(display, False);
+ prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
+
timeout = SDL_GetTicks() + 100;
while (SDL_TRUE) {
int x, y;
+
+ caught_x11_error = SDL_FALSE;
X11_XSync(display, False);
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
attrs.x, attrs.y, &x, &y, &childReturn);
- if ((x != orig_x) || (y != orig_y)) {
- window->x = x;
- window->y = y;
- break; /* window moved, time to go. */
- } else if ((x == window->x) && (y == window->y)) {
- break; /* we're at the place we wanted to be anyhow, drop out. */
+ if (!caught_x11_error) {
+ if ((x != orig_x) || (y != orig_y)) {
+ window->x = x;
+ window->y = y;
+ break; /* window moved, time to go. */
+ } else if ((x == window->x) && (y == window->y)) {
+ break; /* we're at the place we wanted to be anyhow, drop out. */
+ }
}
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
@@ -827,6 +843,9 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
SDL_Delay(10);
}
+
+ X11_XSetErrorHandler(prev_handler);
+ caught_x11_error = SDL_FALSE;
}
void
@@ -892,6 +911,7 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
+ int (*prev_handler) (Display *, XErrorEvent *) = NULL;
XWindowAttributes attrs;
int orig_w, orig_h;
Uint32 timeout;
@@ -943,19 +963,25 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
}
+ X11_XSync(display, False);
+ prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
+
/* Wait a brief time to see if the window manager decided to let this resize happen.
If the window changes at all, even to an unexpected value, we break out. */
timeout = SDL_GetTicks() + 100;
while (SDL_TRUE) {
+ caught_x11_error = SDL_FALSE;
X11_XSync(display, False);
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
- if ((attrs.width != orig_w) || (attrs.height != orig_h)) {
- window->w = attrs.width;
- window->h = attrs.height;
- break; /* window changed, time to go. */
- } else if ((attrs.width == window->w) && (attrs.height == window->h)) {
- break; /* we're at the place we wanted to be anyhow, drop out. */
+ if (!caught_x11_error) {
+ if ((attrs.width != orig_w) || (attrs.height != orig_h)) {
+ window->w = attrs.width;
+ window->h = attrs.height;
+ break; /* window changed, time to go. */
+ } else if ((attrs.width == window->w) && (attrs.height == window->h)) {
+ break; /* we're at the place we wanted to be anyhow, drop out. */
+ }
}
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
@@ -964,6 +990,9 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
SDL_Delay(10);
}
+
+ X11_XSetErrorHandler(prev_handler);
+ caught_x11_error = SDL_FALSE;
}
int
@@ -1281,6 +1310,22 @@ X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _dis
if (X11_IsWindowMapped(_this, window)) {
XEvent e;
+ /* !!! FIXME: most of this waiting code is copy/pasted from elsewhere. */
+ int (*prev_handler) (Display *, XErrorEvent *) = NULL;
+ unsigned int childCount;
+ Window childReturn, root, parent;
+ Window* children;
+ XWindowAttributes attrs;
+ int orig_w, orig_h, orig_x, orig_y;
+ Uint64 timeout;
+
+ X11_XSync(display, False);
+ X11_XQueryTree(display, data->xwindow, &root, &parent, &children, &childCount);
+ X11_XGetWindowAttributes(display, data->xwindow, &attrs);
+ X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
+ attrs.x, attrs.y, &orig_x, &orig_y, &childReturn);
+ orig_w = attrs.width;
+ orig_h = attrs.height;
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
/* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we
@@ -1330,6 +1375,41 @@ X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _dis
X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
SubstructureNotifyMask | SubstructureRedirectMask, &e);
}
+
+ /* Wait a brief time to see if the window manager decided to let this happen.
+ If the window changes at all, even to an unexpected value, we break out. */
+ X11_XSync(display, False);
+ prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
+
+ timeout = SDL_GetTicks64() + 100;
+ while (SDL_TRUE) {
+ int x, y;
+
+ caught_x11_error = SDL_FALSE;
+ X11_XSync(display, False);
+ X11_XGetWindowAttributes(display, data->xwindow, &attrs);
+ X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
+ attrs.x, attrs.y, &x, &y, &childReturn);
+
+ if (!caught_x11_error) {
+ if ((x != orig_x) || (y != orig_y) || (attrs.width != orig_w) || (attrs.height != orig_h)) {
+ window->x = x;
+ window->y = y;
+ window->w = attrs.width;
+ window->h = attrs.height;
+ break; /* window moved, time to go. */
+ }
+ }
+
+ if (SDL_GetTicks64() >= timeout) {
+ break;
+ }
+
+ SDL_Delay(10);
+ }
+
+ X11_XSetErrorHandler(prev_handler);
+ caught_x11_error = SDL_FALSE;
} else {
Uint32 flags;
diff --git a/Engine/lib/sdl/src/video/yuv2rgb/yuv_rgb_sse_func.h b/Engine/lib/sdl/src/video/yuv2rgb/yuv_rgb_sse_func.h
index 3c5ee0db4..f541017a4 100644
--- a/Engine/lib/sdl/src/video/yuv2rgb/yuv_rgb_sse_func.h
+++ b/Engine/lib/sdl/src/video/yuv2rgb/yuv_rgb_sse_func.h
@@ -426,9 +426,17 @@ void SSE_FUNCTION_NAME(uint32_t width, uint32_t height,
const int fix_read_nv12 = 0;
#endif
+#if YUV_FORMAT == YUV_FORMAT_422
+ /* Avoid invalid read on last line */
+ const int fix_read_422 = 1;
+#else
+ const int fix_read_422 = 0;
+#endif
+
+
if (width >= 32) {
uint32_t xpos, ypos;
- for(ypos=0; ypos<(height-(uv_y_sample_interval-1)); ypos+=uv_y_sample_interval)
+ for(ypos=0; ypos<(height-(uv_y_sample_interval-1)) - fix_read_422; ypos+=uv_y_sample_interval)
{
const uint8_t *y_ptr1=Y+ypos*Y_stride,
*y_ptr2=Y+(ypos+1)*Y_stride,
@@ -459,6 +467,15 @@ void SSE_FUNCTION_NAME(uint32_t width, uint32_t height,
}
}
+ if (fix_read_422) {
+ const uint8_t *y_ptr=Y+ypos*Y_stride,
+ *u_ptr=U+(ypos/uv_y_sample_interval)*UV_stride,
+ *v_ptr=V+(ypos/uv_y_sample_interval)*UV_stride;
+ uint8_t *rgb_ptr=RGB+ypos*RGB_stride;
+ STD_FUNCTION_NAME(width, 1, y_ptr, u_ptr, v_ptr, Y_stride, UV_stride, rgb_ptr, RGB_stride, yuv_type);
+ ypos += uv_y_sample_interval;
+ }
+
/* Catch the last line, if needed */
if (uv_y_sample_interval == 2 && ypos == (height-1))
{
diff --git a/Engine/lib/sdl/test/Makefile.in b/Engine/lib/sdl/test/Makefile.in
index d29dc6ecf..f724618c6 100644
--- a/Engine/lib/sdl/test/Makefile.in
+++ b/Engine/lib/sdl/test/Makefile.in
@@ -364,6 +364,7 @@ DATA = \
testgles2_sdf_img_sdf.bmp \
testyuv.bmp \
unifont-13.0.06.hex \
+ utf8.txt \
$(NULL)
ifneq ($(srcdir), .)
diff --git a/Engine/lib/sdl/test/testautomation_rect.c b/Engine/lib/sdl/test/testautomation_rect.c
index 26f03e9bb..cd8f65c34 100644
--- a/Engine/lib/sdl/test/testautomation_rect.c
+++ b/Engine/lib/sdl/test/testautomation_rect.c
@@ -408,6 +408,32 @@ void _validateRectEqualsResults(
refRectB->x, refRectB->y, refRectB->w, refRectB->h);
}
+/* !
+ * \brief Private helper to check SDL_FRectEquals results
+ */
+void _validateFRectEqualsResults(
+ SDL_bool equals, SDL_bool expectedEquals,
+ SDL_FRect *rectA, SDL_FRect *rectB, SDL_FRect *refRectA, SDL_FRect *refRectB)
+{
+ int cmpRes;
+ SDLTest_AssertCheck(equals == expectedEquals,
+ "Check for correct equals result: expected %s, got %s testing (%f,%f,%f,%f) and (%f,%f,%f,%f)",
+ (expectedEquals == SDL_TRUE) ? "SDL_TRUE" : "SDL_FALSE",
+ (equals == SDL_TRUE) ? "SDL_TRUE" : "SDL_FALSE",
+ rectA->x, rectA->y, rectA->w, rectA->h,
+ rectB->x, rectB->y, rectB->w, rectB->h);
+ cmpRes = SDL_memcmp(rectA, refRectA, sizeof(*rectA));
+ SDLTest_AssertCheck(cmpRes == 0,
+ "Check that source rectangle A was not modified: got (%f,%f,%f,%f) expected (%f,%f,%f,%f)",
+ rectA->x, rectA->y, rectA->w, rectA->h,
+ refRectA->x, refRectA->y, refRectA->w, refRectA->h);
+ cmpRes = SDL_memcmp(rectB, refRectB, sizeof(*rectB));
+ SDLTest_AssertCheck(cmpRes == 0,
+ "Check that source rectangle B was not modified: got (%f,%f,%f,%f) expected (%f,%f,%f,%f)",
+ rectB->x, rectB->y, rectB->w, rectB->h,
+ refRectB->x, refRectB->y, refRectB->w, refRectB->h);
+}
+
/* !
* \brief Tests SDL_IntersectRect() with B fully inside A
*
@@ -1574,6 +1600,69 @@ int rect_testRectEqualsParam(void *arg)
return TEST_COMPLETED;
}
+/* !
+ * \brief Tests SDL_FRectEquals() with various inputs
+ *
+ * \sa
+ * http://wiki.libsdl.org/SDL_FRectEquals
+ */
+int rect_testFRectEquals(void *arg)
+{
+ SDL_FRect refRectA;
+ SDL_FRect refRectB;
+ SDL_FRect rectA;
+ SDL_FRect rectB;
+ SDL_bool expectedResult;
+ SDL_bool result;
+
+ /* Equals */
+ refRectA.x=(float)SDLTest_RandomIntegerInRange(-1024, 1024);
+ refRectA.y=(float)SDLTest_RandomIntegerInRange(-1024, 1024);
+ refRectA.w=(float)SDLTest_RandomIntegerInRange(1, 1024);
+ refRectA.h=(float)SDLTest_RandomIntegerInRange(1, 1024);
+ refRectB = refRectA;
+ expectedResult = SDL_TRUE;
+ rectA = refRectA;
+ rectB = refRectB;
+ result = (SDL_bool)SDL_FRectEquals((const SDL_FRect *)&rectA, (const SDL_FRect *)&rectB);
+ _validateFRectEqualsResults(result, expectedResult, &rectA, &rectB, &refRectA, &refRectB);
+
+ return TEST_COMPLETED;
+}
+
+/* !
+ * \brief Negative tests against SDL_FRectEquals() with invalid parameters
+ *
+ * \sa
+ * http://wiki.libsdl.org/SDL_FRectEquals
+ */
+int rect_testFRectEqualsParam(void *arg)
+{
+ SDL_FRect rectA;
+ SDL_FRect rectB;
+ SDL_bool result;
+
+ /* data setup -- For the purpose of this test, the values don't matter. */
+ rectA.x=SDLTest_RandomFloat();
+ rectA.y=SDLTest_RandomFloat();
+ rectA.w=SDLTest_RandomFloat();
+ rectA.h=SDLTest_RandomFloat();
+ rectB.x=SDLTest_RandomFloat();
+ rectB.y=SDLTest_RandomFloat();
+ rectB.w=SDLTest_RandomFloat();
+ rectB.h=SDLTest_RandomFloat();
+
+ /* invalid parameter combinations */
+ result = (SDL_bool)SDL_FRectEquals((const SDL_FRect *)NULL, (const SDL_FRect *)&rectB);
+ SDLTest_AssertCheck(result == SDL_FALSE, "Check that function returns SDL_FALSE when 1st parameter is NULL");
+ result = (SDL_bool)SDL_FRectEquals((const SDL_FRect *)&rectA, (const SDL_FRect *)NULL);
+ SDLTest_AssertCheck(result == SDL_FALSE, "Check that function returns SDL_FALSE when 2nd parameter is NULL");
+ result = (SDL_bool)SDL_FRectEquals((const SDL_FRect *)NULL, (const SDL_FRect *)NULL);
+ SDLTest_AssertCheck(result == SDL_FALSE, "Check that function returns SDL_FALSE when 1st and 2nd parameter are NULL");
+
+ return TEST_COMPLETED;
+}
+
/* ================= Test References ================== */
/* Rect test cases */
@@ -1673,6 +1762,13 @@ static const SDLTest_TestCaseReference rectTest28 =
static const SDLTest_TestCaseReference rectTest29 =
{ (SDLTest_TestCaseFp)rect_testRectEqualsParam, "rect_testRectEqualsParam", "Negative tests against SDL_RectEquals with invalid parameters", TEST_ENABLED };
+/* SDL_FRectEquals */
+
+static const SDLTest_TestCaseReference rectTest30 =
+ { (SDLTest_TestCaseFp)rect_testFRectEquals, "rect_testFRectEquals", "Tests SDL_FRectEquals with various inputs", TEST_ENABLED };
+
+static const SDLTest_TestCaseReference rectTest31 =
+ { (SDLTest_TestCaseFp)rect_testFRectEqualsParam, "rect_testFRectEqualsParam", "Negative tests against SDL_FRectEquals with invalid parameters", TEST_ENABLED };
/* !
* \brief Sequence of Rect test cases; functions that handle simple rectangles including overlaps and merges.
@@ -1683,7 +1779,7 @@ static const SDLTest_TestCaseReference rectTest29 =
static const SDLTest_TestCaseReference *rectTests[] = {
&rectTest1, &rectTest2, &rectTest3, &rectTest4, &rectTest5, &rectTest6, &rectTest7, &rectTest8, &rectTest9, &rectTest10, &rectTest11, &rectTest12, &rectTest13, &rectTest14,
&rectTest15, &rectTest16, &rectTest17, &rectTest18, &rectTest19, &rectTest20, &rectTest21, &rectTest22, &rectTest23, &rectTest24, &rectTest25, &rectTest26, &rectTest27,
- &rectTest28, &rectTest29, NULL
+ &rectTest28, &rectTest29, &rectTest30, &rectTest31, NULL
};
diff --git a/Engine/lib/sdl/test/testevdev.c b/Engine/lib/sdl/test/testevdev.c
index 572c60a05..76a12ef7e 100644
--- a/Engine/lib/sdl/test/testevdev.c
+++ b/Engine/lib/sdl/test/testevdev.c
@@ -41,6 +41,7 @@ static const struct
CLS(SOUND),
CLS(TOUCHSCREEN),
CLS(ACCELEROMETER),
+ CLS(TOUCHPAD),
#undef CLS
{ 0, NULL }
};
@@ -185,9 +186,7 @@ static const GuessTest guess_tests[] =
.bus_type = 0x0003,
.vendor_id = 0x054c,
.product_id = 0x09cc,
- /* TODO: Should this be MOUSE? That's what it most closely
- * resembles */
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
+ .expected = SDL_UDEV_DEVICE_TOUCHPAD,
/* SYN, KEY, ABS */
.ev = { 0x0b },
/* X, Y, multitouch */
@@ -596,7 +595,7 @@ static const GuessTest guess_tests[] =
* to the arrow, page up and page down keys, so it's a joystick
* with a subset of a keyboard attached. */
/* TODO: Should this be JOYSTICK, or even JOYSTICK|KEYBOARD? */
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
+ .expected = SDL_UDEV_DEVICE_KEYBOARD,
/* SYN, KEY */
.ev = { 0x03 },
.keys = {
@@ -608,7 +607,7 @@ static const GuessTest guess_tests[] =
/* BTN_1, BTN_2, BTN_A, BTN_B, BTN_MODE */
/* 0x100 */ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x10,
/* 0x140 */ ZEROx8,
- /* next, previous */
+ /* next (keyboard page down), previous (keyboard page up) */
/* 0x180 */ 0x00, 0x00, 0x80, 0x10, ZEROx4,
},
},
@@ -659,7 +658,7 @@ static const GuessTest guess_tests[] =
.name = "Wiimote - Classic Controller",
/* TODO: Should this be JOYSTICK, or maybe JOYSTICK|KEYBOARD?
* It's unusual in the same ways as the Wiimote */
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
+ .expected = SDL_UDEV_DEVICE_KEYBOARD,
/* SYN, KEY, ABS */
.ev = { 0x0b },
/* Hat 1-3 */
@@ -673,7 +672,7 @@ static const GuessTest guess_tests[] =
/* A, B, X, Y, MODE, TL, TL2, TR, TR2 */
/* 0x100 */ ZEROx4, 0x00, 0x13, 0xdb, 0x10,
/* 0x140 */ ZEROx8,
- /* next, previous */
+ /* next (keyboard page down), previous (keyboard page up) */
/* 0x180 */ 0x00, 0x00, 0x80, 0x10, ZEROx4,
},
},
@@ -718,9 +717,7 @@ static const GuessTest guess_tests[] =
.vendor_id = 0x06cb,
.product_id = 0x0000,
.version = 0x0000,
- /* TODO: Should this be MOUSE? That's what it most closely
- * resembles */
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
+ .expected = SDL_UDEV_DEVICE_TOUCHPAD,
/* SYN, KEY, ABS */
.ev = { 0x0b },
/* X, Y, pressure, multitouch */
@@ -756,7 +753,8 @@ static const GuessTest guess_tests[] =
},
{
.name = "Thinkpad ACPI buttons",
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
+ /* SDL treats this as a keyboard because it has a power button */
+ .expected = SDL_UDEV_DEVICE_KEYBOARD,
/* SYN, KEY, MSC, SW */
.ev = { 0x33 },
.keys = {
@@ -815,7 +813,8 @@ static const GuessTest guess_tests[] =
.vendor_id = 0x0000,
.product_id = 0x0003,
.version = 0x0000,
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
+ /* SDL treats KEY_SLEEP as indicating a keyboard */
+ .expected = SDL_UDEV_DEVICE_KEYBOARD,
/* SYN, KEY */
.ev = { 0x03 },
.keys = {
@@ -841,7 +840,8 @@ static const GuessTest guess_tests[] =
.vendor_id = 0x0000,
.product_id = 0x0001,
.version = 0x0000,
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
+ /* SDL treats KEY_POWER as indicating a keyboard */
+ .expected = SDL_UDEV_DEVICE_KEYBOARD,
/* SYN, KEY */
.ev = { 0x03 },
.keys = {
@@ -856,7 +856,8 @@ static const GuessTest guess_tests[] =
.vendor_id = 0x0000,
.product_id = 0x0006,
.version = 0x0000,
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
+ /* SDL treats brightness control, etc. as keyboard keys */
+ .expected = SDL_UDEV_DEVICE_KEYBOARD,
/* SYN, KEY */
.ev = { 0x03 },
.keys = {
@@ -873,7 +874,7 @@ static const GuessTest guess_tests[] =
.vendor_id = 0x17aa,
.product_id = 0x5054,
.version = 0x4101,
- .expected = SDL_UDEV_DEVICE_UNKNOWN,
+ .expected = SDL_UDEV_DEVICE_KEYBOARD,
/* SYN, KEY */
.ev = { 0x03 },
.keys = {
@@ -911,9 +912,8 @@ static const GuessTest guess_tests[] =
.product_id = 0x6009,
/* For some reason the special keys like mute and wlan toggle
* show up here instead of, or in addition to, as part of
- * the keyboard - so udev reports this as having keys too.
- * SDL currently doesn't. */
- .expected = SDL_UDEV_DEVICE_MOUSE,
+ * the keyboard - so both udev and SDL report this as having keys too. */
+ .expected = SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD,
/* SYN, KEY, REL, MSC, LED */
.ev = { 0x17, 0x00, 0x02 },
/* X, Y */
diff --git a/Engine/lib/sdl/test/testgles2.c b/Engine/lib/sdl/test/testgles2.c
index 153ebe499..c42835ebb 100644
--- a/Engine/lib/sdl/test/testgles2.c
+++ b/Engine/lib/sdl/test/testgles2.c
@@ -38,6 +38,18 @@ typedef struct GLES2_Context
#undef SDL_PROC
} GLES2_Context;
+typedef struct shader_data
+{
+ GLuint shader_program, shader_frag, shader_vert;
+
+ GLint attr_position;
+ GLint attr_color, attr_mvp;
+
+ int angle_x, angle_y, angle_z;
+
+ GLuint position_buffer;
+ GLuint color_buffer;
+} shader_data;
static SDLTest_CommonState *state;
static SDL_GLContext *context = NULL;
@@ -197,13 +209,13 @@ multiply_matrix(float *lhs, float *rhs, float *r)
* source: Passed-in shader source code.
* shader_type: Passed to GL, e.g. GL_VERTEX_SHADER.
*/
-void
+static void
process_shader(GLuint *shader, const char * source, GLint shader_type)
{
GLint status = GL_FALSE;
const char *shaders[1] = { NULL };
char buffer[1024];
- GLsizei length;
+ GLsizei length = 0;
/* Create shader and load into GL. */
*shader = GL_CHECK(ctx.glCreateShader(shader_type));
@@ -221,13 +233,35 @@ process_shader(GLuint *shader, const char * source, GLint shader_type)
/* Dump debug info (source and log) if compilation failed. */
if(status != GL_TRUE) {
- ctx.glGetProgramInfoLog(*shader, sizeof(buffer), &length, &buffer[0]);
+ ctx.glGetShaderInfoLog(*shader, sizeof(buffer), &length, &buffer[0]);
buffer[length] = '\0';
- SDL_Log("Shader compilation failed: %s", buffer);fflush(stderr);
+ SDL_Log("Shader compilation failed: %s", buffer);
+ fflush(stderr);
quit(-1);
}
}
+static void
+link_program(struct shader_data *data)
+{
+ GLint status = GL_FALSE;
+ char buffer[1024];
+ GLsizei length = 0;
+
+ GL_CHECK(ctx.glAttachShader(data->shader_program, data->shader_vert));
+ GL_CHECK(ctx.glAttachShader(data->shader_program, data->shader_frag));
+ GL_CHECK(ctx.glLinkProgram(data->shader_program));
+ GL_CHECK(ctx.glGetProgramiv(data->shader_program, GL_LINK_STATUS, &status));
+
+ if(status != GL_TRUE) {
+ ctx.glGetProgramInfoLog(data->shader_program, sizeof(buffer), &length, &buffer[0]);
+ buffer[length] = '\0';
+ SDL_Log("Program linking failed: %s", buffer);
+ fflush(stderr);
+ quit(-1);
+ }
+}
+
/* 3D data. Vertex range -0.5..0.5 in all axes.
* Z -0.5 is near, 0.5 is far. */
const float _vertices[] =
@@ -363,19 +397,6 @@ const char* _shader_frag_src =
" gl_FragColor = vec4(vv3color, 1.0); "
" } ";
-typedef struct shader_data
-{
- GLuint shader_program, shader_frag, shader_vert;
-
- GLint attr_position;
- GLint attr_color, attr_mvp;
-
- int angle_x, angle_y, angle_z;
-
- GLuint position_buffer;
- GLuint color_buffer;
-} shader_data;
-
static void
Render(unsigned int width, unsigned int height, shader_data* data)
{
@@ -672,9 +693,7 @@ main(int argc, char *argv[])
data->shader_program = GL_CHECK(ctx.glCreateProgram());
/* Attach shaders and link shader_program */
- GL_CHECK(ctx.glAttachShader(data->shader_program, data->shader_vert));
- GL_CHECK(ctx.glAttachShader(data->shader_program, data->shader_frag));
- GL_CHECK(ctx.glLinkProgram(data->shader_program));
+ link_program(data);
/* Get attribute locations of non-fixed attributes like color and texture coordinates. */
data->attr_position = GL_CHECK(ctx.glGetAttribLocation(data->shader_program, "av4position"));
@@ -693,13 +712,13 @@ main(int argc, char *argv[])
GL_CHECK(ctx.glGenBuffers(1, &data->position_buffer));
GL_CHECK(ctx.glBindBuffer(GL_ARRAY_BUFFER, data->position_buffer));
- GL_CHECK(ctx.glBufferData(GL_ARRAY_BUFFER, sizeof(_vertices) * 4, _vertices, GL_STATIC_DRAW));
+ GL_CHECK(ctx.glBufferData(GL_ARRAY_BUFFER, sizeof(_vertices), _vertices, GL_STATIC_DRAW));
GL_CHECK(ctx.glVertexAttribPointer(data->attr_position, 3, GL_FLOAT, GL_FALSE, 0, 0));
GL_CHECK(ctx.glBindBuffer(GL_ARRAY_BUFFER, 0));
GL_CHECK(ctx.glGenBuffers(1, &data->color_buffer));
GL_CHECK(ctx.glBindBuffer(GL_ARRAY_BUFFER, data->color_buffer));
- GL_CHECK(ctx.glBufferData(GL_ARRAY_BUFFER, sizeof(_colors) * 4, _colors, GL_STATIC_DRAW));
+ GL_CHECK(ctx.glBufferData(GL_ARRAY_BUFFER, sizeof(_colors), _colors, GL_STATIC_DRAW));
GL_CHECK(ctx.glVertexAttribPointer(data->attr_color, 3, GL_FLOAT, GL_FALSE, 0, 0));
GL_CHECK(ctx.glBindBuffer(GL_ARRAY_BUFFER, 0));
diff --git a/Engine/lib/sdl/test/testmouse.c b/Engine/lib/sdl/test/testmouse.c
index c73adca51..11a176066 100644
--- a/Engine/lib/sdl/test/testmouse.c
+++ b/Engine/lib/sdl/test/testmouse.c
@@ -39,6 +39,11 @@ static Line *active = NULL;
static Line *lines = NULL;
static int buttons = 0;
+static SDL_bool wheel_x_active = SDL_FALSE;
+static SDL_bool wheel_y_active = SDL_FALSE;
+static float wheel_x = SCREEN_WIDTH * 0.5f;
+static float wheel_y = SCREEN_HEIGHT * 0.5f;
+
static SDL_bool done = SDL_FALSE;
void
@@ -81,6 +86,25 @@ loop(void *arg)
/* Check for events */
while (SDL_PollEvent(&event)) {
switch (event.type) {
+ case SDL_MOUSEWHEEL:
+ if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) {
+ event.wheel.preciseX *= -1.0f;
+ event.wheel.preciseY *= -1.0f;
+ event.wheel.x *= -1;
+ event.wheel.y *= -1;
+ }
+ if (event.wheel.preciseX != 0.0f) {
+ wheel_x_active = SDL_TRUE;
+ /* "positive to the right and negative to the left" */
+ wheel_x += event.wheel.preciseX * 10.0f;
+ }
+ if (event.wheel.preciseY != 0.0f) {
+ wheel_y_active = SDL_TRUE;
+ /* "positive away from the user and negative towards the user" */
+ wheel_y -= event.wheel.preciseY * 10.0f;
+ }
+ break;
+
case SDL_MOUSEMOTION:
if (!active)
break;
@@ -134,6 +158,16 @@ loop(void *arg)
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
+ /* Mouse wheel */
+ SDL_SetRenderDrawColor(renderer, 0, 255, 128, 255);
+ if (wheel_x_active) {
+ SDL_RenderDrawLine(renderer, wheel_x, 0, wheel_x, SCREEN_HEIGHT);
+ }
+ if (wheel_y_active) {
+ SDL_RenderDrawLine(renderer, 0, wheel_y, SCREEN_WIDTH, wheel_y);
+ }
+
+ /* Lines from mouse clicks */
DrawLines(renderer);
if (active)
DrawLine(renderer, active);
diff --git a/Engine/lib/sdl/test/testshader.c b/Engine/lib/sdl/test/testshader.c
index 2cee7d9b3..3c2da590f 100644
--- a/Engine/lib/sdl/test/testshader.c
+++ b/Engine/lib/sdl/test/testshader.c
@@ -126,21 +126,52 @@ static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
static SDL_bool CompileShader(GLhandleARB shader, const char *source)
{
- GLint status;
+ GLint status = 0;
glShaderSourceARB(shader, 1, &source, NULL);
glCompileShaderARB(shader);
glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
if (status == 0) {
- GLint length;
+ GLint length = 0;
char *info;
glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
- info = SDL_stack_alloc(char, length+1);
- glGetInfoLogARB(shader, length, NULL, info);
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile shader:\n%s\n%s", source, info);
- SDL_stack_free(info);
+ info = (char *) SDL_malloc(length + 1);
+ if (!info) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
+ } else {
+ glGetInfoLogARB(shader, length, NULL, info);
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile shader:\n%s\n%s", source, info);
+ SDL_free(info);
+ }
+ return SDL_FALSE;
+ } else {
+ return SDL_TRUE;
+ }
+}
+static SDL_bool LinkProgram(ShaderData *data)
+{
+ GLint status = 0;
+
+ glAttachObjectARB(data->program, data->vert_shader);
+ glAttachObjectARB(data->program, data->frag_shader);
+ glLinkProgramARB(data->program);
+
+ glGetObjectParameterivARB(data->program, GL_OBJECT_LINK_STATUS_ARB, &status);
+ if (status == 0) {
+ GLint length = 0;
+ char *info;
+
+ glGetObjectParameterivARB(data->program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
+ info = (char *) SDL_malloc(length + 1);
+ if (!info) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
+ } else {
+ glGetInfoLogARB(data->program, length, NULL, info);
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to link program:\n%s", info);
+ SDL_free(info);
+ }
return SDL_FALSE;
} else {
return SDL_TRUE;
@@ -171,9 +202,9 @@ static SDL_bool CompileShaderProgram(ShaderData *data)
}
/* ... and in the darkness bind them */
- glAttachObjectARB(data->program, data->vert_shader);
- glAttachObjectARB(data->program, data->frag_shader);
- glLinkProgramARB(data->program);
+ if (!LinkProgram(data)) {
+ return SDL_FALSE;
+ }
/* Set up some uniform variables */
glUseProgramObjectARB(data->program);
diff --git a/Engine/lib/sdl/wayland-protocols/tablet-unstable-v2.xml b/Engine/lib/sdl/wayland-protocols/tablet-unstable-v2.xml
new file mode 100644
index 000000000..b286d964a
--- /dev/null
+++ b/Engine/lib/sdl/wayland-protocols/tablet-unstable-v2.xml
@@ -0,0 +1,1178 @@
+
+
+
+
+ Copyright 2014 © Stephen "Lyude" Chandler Paul
+ Copyright 2015-2016 © Red Hat, Inc.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation files
+ (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the
+ next paragraph) shall be included in all copies or substantial
+ portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+
+
+ This description provides a high-level overview of the interplay between
+ the interfaces defined this protocol. For details, see the protocol
+ specification.
+
+ More than one tablet may exist, and device-specifics matter. Tablets are
+ not represented by a single virtual device like wl_pointer. A client
+ binds to the tablet manager object which is just a proxy object. From
+ that, the client requests wp_tablet_manager.get_tablet_seat(wl_seat)
+ and that returns the actual interface that has all the tablets. With
+ this indirection, we can avoid merging wp_tablet into the actual Wayland
+ protocol, a long-term benefit.
+
+ The wp_tablet_seat sends a "tablet added" event for each tablet
+ connected. That event is followed by descriptive events about the
+ hardware; currently that includes events for name, vid/pid and
+ a wp_tablet.path event that describes a local path. This path can be
+ used to uniquely identify a tablet or get more information through
+ libwacom. Emulated or nested tablets can skip any of those, e.g. a
+ virtual tablet may not have a vid/pid. The sequence of descriptive
+ events is terminated by a wp_tablet.done event to signal that a client
+ may now finalize any initialization for that tablet.
+
+ Events from tablets require a tool in proximity. Tools are also managed
+ by the tablet seat; a "tool added" event is sent whenever a tool is new
+ to the compositor. That event is followed by a number of descriptive
+ events about the hardware; currently that includes capabilities,
+ hardware id and serial number, and tool type. Similar to the tablet
+ interface, a wp_tablet_tool.done event is sent to terminate that initial
+ sequence.
+
+ Any event from a tool happens on the wp_tablet_tool interface. When the
+ tool gets into proximity of the tablet, a proximity_in event is sent on
+ the wp_tablet_tool interface, listing the tablet and the surface. That
+ event is followed by a motion event with the coordinates. After that,
+ it's the usual motion, axis, button, etc. events. The protocol's
+ serialisation means events are grouped by wp_tablet_tool.frame events.
+
+ Two special events (that don't exist in X) are down and up. They signal
+ "tip touching the surface". For tablets without real proximity
+ detection, the sequence is: proximity_in, motion, down, frame.
+
+ When the tool leaves proximity, a proximity_out event is sent. If any
+ button is still down, a button release event is sent before this
+ proximity event. These button events are sent in the same frame as the
+ proximity event to signal to the client that the buttons were held when
+ the tool left proximity.
+
+ If the tool moves out of the surface but stays in proximity (i.e.
+ between windows), compositor-specific grab policies apply. This usually
+ means that the proximity-out is delayed until all buttons are released.
+
+ Moving a tool physically from one tablet to the other has no real effect
+ on the protocol, since we already have the tool object from the "tool
+ added" event. All the information is already there and the proximity
+ events on both tablets are all a client needs to reconstruct what
+ happened.
+
+ Some extra axes are normalized, i.e. the client knows the range as
+ specified in the protocol (e.g. [0, 65535]), the granularity however is
+ unknown. The current normalized axes are pressure, distance, and slider.
+
+ Other extra axes are in physical units as specified in the protocol.
+ The current extra axes with physical units are tilt, rotation and
+ wheel rotation.
+
+ Since tablets work independently of the pointer controlled by the mouse,
+ the focus handling is independent too and controlled by proximity.
+ The wp_tablet_tool.set_cursor request sets a tool-specific cursor.
+ This cursor surface may be the same as the mouse cursor, and it may be
+ the same across tools but it is possible to be more fine-grained. For
+ example, a client may set different cursors for the pen and eraser.
+
+ Tools are generally independent of tablets and it is
+ compositor-specific policy when a tool can be removed. Common approaches
+ will likely include some form of removing a tool when all tablets the
+ tool was used on are removed.
+
+ Warning! The protocol described in this file is experimental and
+ backward incompatible changes may be made. Backward compatible changes
+ may be added together with the corresponding interface version bump.
+ Backward incompatible changes are done by bumping the version number in
+ the protocol and interface names and resetting the interface version.
+ Once the protocol is to be declared stable, the 'z' prefix and the
+ version number in the protocol and interface names are removed and the
+ interface version number is reset.
+
+
+
+
+ An object that provides access to the graphics tablets available on this
+ system. All tablets are associated with a seat, to get access to the
+ actual tablets, use wp_tablet_manager.get_tablet_seat.
+
+
+
+
+ Get the wp_tablet_seat object for the given seat. This object
+ provides access to all graphics tablets in this seat.
+
+
+
+
+
+
+
+ Destroy the wp_tablet_manager object. Objects created from this
+ object are unaffected and should be destroyed separately.
+
+
+
+
+
+
+ An object that provides access to the graphics tablets available on this
+ seat. After binding to this interface, the compositor sends a set of
+ wp_tablet_seat.tablet_added and wp_tablet_seat.tool_added events.
+
+
+
+
+ Destroy the wp_tablet_seat object. Objects created from this
+ object are unaffected and should be destroyed separately.
+
+
+
+
+
+ This event is sent whenever a new tablet becomes available on this
+ seat. This event only provides the object id of the tablet, any
+ static information about the tablet (device name, vid/pid, etc.) is
+ sent through the wp_tablet interface.
+
+
+
+
+
+
+ This event is sent whenever a tool that has not previously been used
+ with a tablet comes into use. This event only provides the object id
+ of the tool; any static information about the tool (capabilities,
+ type, etc.) is sent through the wp_tablet_tool interface.
+
+
+
+
+
+
+ This event is sent whenever a new pad is known to the system. Typically,
+ pads are physically attached to tablets and a pad_added event is
+ sent immediately after the wp_tablet_seat.tablet_added.
+ However, some standalone pad devices logically attach to tablets at
+ runtime, and the client must wait for wp_tablet_pad.enter to know
+ the tablet a pad is attached to.
+
+ This event only provides the object id of the pad. All further
+ features (buttons, strips, rings) are sent through the wp_tablet_pad
+ interface.
+
+
+
+
+
+
+
+ An object that represents a physical tool that has been, or is
+ currently in use with a tablet in this seat. Each wp_tablet_tool
+ object stays valid until the client destroys it; the compositor
+ reuses the wp_tablet_tool object to indicate that the object's
+ respective physical tool has come into proximity of a tablet again.
+
+ A wp_tablet_tool object's relation to a physical tool depends on the
+ tablet's ability to report serial numbers. If the tablet supports
+ this capability, then the object represents a specific physical tool
+ and can be identified even when used on multiple tablets.
+
+ A tablet tool has a number of static characteristics, e.g. tool type,
+ hardware_serial and capabilities. These capabilities are sent in an
+ event sequence after the wp_tablet_seat.tool_added event before any
+ actual events from this tool. This initial event sequence is
+ terminated by a wp_tablet_tool.done event.
+
+ Tablet tool events are grouped by wp_tablet_tool.frame events.
+ Any events received before a wp_tablet_tool.frame event should be
+ considered part of the same hardware state change.
+
+
+
+
+ Sets the surface of the cursor used for this tool on the given
+ tablet. This request only takes effect if the tool is in proximity
+ of one of the requesting client's surfaces or the surface parameter
+ is the current pointer surface. If there was a previous surface set
+ with this request it is replaced. If surface is NULL, the cursor
+ image is hidden.
+
+ The parameters hotspot_x and hotspot_y define the position of the
+ pointer surface relative to the pointer location. Its top-left corner
+ is always at (x, y) - (hotspot_x, hotspot_y), where (x, y) are the
+ coordinates of the pointer location, in surface-local coordinates.
+
+ On surface.attach requests to the pointer surface, hotspot_x and
+ hotspot_y are decremented by the x and y parameters passed to the
+ request. Attach must be confirmed by wl_surface.commit as usual.
+
+ The hotspot can also be updated by passing the currently set pointer
+ surface to this request with new values for hotspot_x and hotspot_y.
+
+ The current and pending input regions of the wl_surface are cleared,
+ and wl_surface.set_input_region is ignored until the wl_surface is no
+ longer used as the cursor. When the use as a cursor ends, the current
+ and pending input regions become undefined, and the wl_surface is
+ unmapped.
+
+ This request gives the surface the role of a wp_tablet_tool cursor. A
+ surface may only ever be used as the cursor surface for one
+ wp_tablet_tool. If the surface already has another role or has
+ previously been used as cursor surface for a different tool, a
+ protocol error is raised.
+
+
+
+
+
+
+
+
+
+ This destroys the client's resource for this tool object.
+
+
+
+
+
+ Describes the physical type of a tool. The physical type of a tool
+ generally defines its base usage.
+
+ The mouse tool represents a mouse-shaped tool that is not a relative
+ device but bound to the tablet's surface, providing absolute
+ coordinates.
+
+ The lens tool is a mouse-shaped tool with an attached lens to
+ provide precision focus.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The tool type is the high-level type of the tool and usually decides
+ the interaction expected from this tool.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_tool.done event.
+
+
+
+
+
+
+ If the physical tool can be identified by a unique 64-bit serial
+ number, this event notifies the client of this serial number.
+
+ If multiple tablets are available in the same seat and the tool is
+ uniquely identifiable by the serial number, that tool may move
+ between tablets.
+
+ Otherwise, if the tool has no serial number and this event is
+ missing, the tool is tied to the tablet it first comes into
+ proximity with. Even if the physical tool is used on multiple
+ tablets, separate wp_tablet_tool objects will be created, one per
+ tablet.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_tool.done event.
+
+
+
+
+
+
+
+ This event notifies the client of a hardware id available on this tool.
+
+ The hardware id is a device-specific 64-bit id that provides extra
+ information about the tool in use, beyond the wl_tool.type
+ enumeration. The format of the id is specific to tablets made by
+ Wacom Inc. For example, the hardware id of a Wacom Grip
+ Pen (a stylus) is 0x802.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_tool.done event.
+
+
+
+
+
+
+
+ Describes extra capabilities on a tablet.
+
+ Any tool must provide x and y values, extra axes are
+ device-specific.
+
+
+
+
+
+
+
+
+
+
+
+ This event notifies the client of any capabilities of this tool,
+ beyond the main set of x/y axes and tip up/down detection.
+
+ One event is sent for each extra capability available on this tool.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_tool.done event.
+
+
+
+
+
+
+ This event signals the end of the initial burst of descriptive
+ events. A client may consider the static description of the tool to
+ be complete and finalize initialization of the tool.
+
+
+
+
+
+ This event is sent when the tool is removed from the system and will
+ send no further events. Should the physical tool come back into
+ proximity later, a new wp_tablet_tool object will be created.
+
+ It is compositor-dependent when a tool is removed. A compositor may
+ remove a tool on proximity out, tablet removal or any other reason.
+ A compositor may also keep a tool alive until shutdown.
+
+ If the tool is currently in proximity, a proximity_out event will be
+ sent before the removed event. See wp_tablet_tool.proximity_out for
+ the handling of any buttons logically down.
+
+ When this event is received, the client must wp_tablet_tool.destroy
+ the object.
+
+
+
+
+
+ Notification that this tool is focused on a certain surface.
+
+ This event can be received when the tool has moved from one surface to
+ another, or when the tool has come back into proximity above the
+ surface.
+
+ If any button is logically down when the tool comes into proximity,
+ the respective button event is sent after the proximity_in event but
+ within the same frame as the proximity_in event.
+
+
+
+
+
+
+
+
+ Notification that this tool has either left proximity, or is no
+ longer focused on a certain surface.
+
+ When the tablet tool leaves proximity of the tablet, button release
+ events are sent for each button that was held down at the time of
+ leaving proximity. These events are sent before the proximity_out
+ event but within the same wp_tablet.frame.
+
+ If the tool stays within proximity of the tablet, but the focus
+ changes from one surface to another, a button release event may not
+ be sent until the button is actually released or the tool leaves the
+ proximity of the tablet.
+
+
+
+
+
+ Sent whenever the tablet tool comes in contact with the surface of the
+ tablet.
+
+ If the tool is already in contact with the tablet when entering the
+ input region, the client owning said region will receive a
+ wp_tablet.proximity_in event, followed by a wp_tablet.down
+ event and a wp_tablet.frame event.
+
+ Note that this event describes logical contact, not physical
+ contact. On some devices, a compositor may not consider a tool in
+ logical contact until a minimum physical pressure threshold is
+ exceeded.
+
+
+
+
+
+
+ Sent whenever the tablet tool stops making contact with the surface of
+ the tablet, or when the tablet tool moves out of the input region
+ and the compositor grab (if any) is dismissed.
+
+ If the tablet tool moves out of the input region while in contact
+ with the surface of the tablet and the compositor does not have an
+ ongoing grab on the surface, the client owning said region will
+ receive a wp_tablet.up event, followed by a wp_tablet.proximity_out
+ event and a wp_tablet.frame event. If the compositor has an ongoing
+ grab on this device, this event sequence is sent whenever the grab
+ is dismissed in the future.
+
+ Note that this event describes logical contact, not physical
+ contact. On some devices, a compositor may not consider a tool out
+ of logical contact until physical pressure falls below a specific
+ threshold.
+
+
+
+
+
+ Sent whenever a tablet tool moves.
+
+
+
+
+
+
+
+ Sent whenever the pressure axis on a tool changes. The value of this
+ event is normalized to a value between 0 and 65535.
+
+ Note that pressure may be nonzero even when a tool is not in logical
+ contact. See the down and up events for more details.
+
+
+
+
+
+
+ Sent whenever the distance axis on a tool changes. The value of this
+ event is normalized to a value between 0 and 65535.
+
+ Note that distance may be nonzero even when a tool is not in logical
+ contact. See the down and up events for more details.
+
+
+
+
+
+
+ Sent whenever one or both of the tilt axes on a tool change. Each tilt
+ value is in degrees, relative to the z-axis of the tablet.
+ The angle is positive when the top of a tool tilts along the
+ positive x or y axis.
+
+
+
+
+
+
+
+ Sent whenever the z-rotation axis on the tool changes. The
+ rotation value is in degrees clockwise from the tool's
+ logical neutral position.
+
+
+
+
+
+
+ Sent whenever the slider position on the tool changes. The
+ value is normalized between -65535 and 65535, with 0 as the logical
+ neutral position of the slider.
+
+ The slider is available on e.g. the Wacom Airbrush tool.
+
+
+
+
+
+
+ Sent whenever the wheel on the tool emits an event. This event
+ contains two values for the same axis change. The degrees value is
+ in the same orientation as the wl_pointer.vertical_scroll axis. The
+ clicks value is in discrete logical clicks of the mouse wheel. This
+ value may be zero if the movement of the wheel was less
+ than one logical click.
+
+ Clients should choose either value and avoid mixing degrees and
+ clicks. The compositor may accumulate values smaller than a logical
+ click and emulate click events when a certain threshold is met.
+ Thus, wl_tablet_tool.wheel events with non-zero clicks values may
+ have different degrees values.
+
+
+
+
+
+
+
+ Describes the physical state of a button that produced the button event.
+
+
+
+
+
+
+
+ Sent whenever a button on the tool is pressed or released.
+
+ If a button is held down when the tool moves in or out of proximity,
+ button events are generated by the compositor. See
+ wp_tablet_tool.proximity_in and wp_tablet_tool.proximity_out for
+ details.
+
+
+
+
+
+
+
+
+ Marks the end of a series of axis and/or button updates from the
+ tablet. The Wayland protocol requires axis updates to be sent
+ sequentially, however all events within a frame should be considered
+ one hardware event.
+
+
+
+
+
+
+
+
+
+
+
+ The wp_tablet interface represents one graphics tablet device. The
+ tablet interface itself does not generate events; all events are
+ generated by wp_tablet_tool objects when in proximity above a tablet.
+
+ A tablet has a number of static characteristics, e.g. device name and
+ pid/vid. These capabilities are sent in an event sequence after the
+ wp_tablet_seat.tablet_added event. This initial event sequence is
+ terminated by a wp_tablet.done event.
+
+
+
+
+ This destroys the client's resource for this tablet object.
+
+
+
+
+
+ This event is sent in the initial burst of events before the
+ wp_tablet.done event.
+
+
+
+
+
+
+ This event is sent in the initial burst of events before the
+ wp_tablet.done event.
+
+
+
+
+
+
+
+ A system-specific device path that indicates which device is behind
+ this wp_tablet. This information may be used to gather additional
+ information about the device, e.g. through libwacom.
+
+ A device may have more than one device path. If so, multiple
+ wp_tablet.path events are sent. A device may be emulated and not
+ have a device path, and in that case this event will not be sent.
+
+ The format of the path is unspecified, it may be a device node, a
+ sysfs path, or some other identifier. It is up to the client to
+ identify the string provided.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet.done event.
+
+
+
+
+
+
+ This event is sent immediately to signal the end of the initial
+ burst of descriptive events. A client may consider the static
+ description of the tablet to be complete and finalize initialization
+ of the tablet.
+
+
+
+
+
+ Sent when the tablet has been removed from the system. When a tablet
+ is removed, some tools may be removed.
+
+ When this event is received, the client must wp_tablet.destroy
+ the object.
+
+
+
+
+
+
+ A circular interaction area, such as the touch ring on the Wacom Intuos
+ Pro series tablets.
+
+ Events on a ring are logically grouped by the wl_tablet_pad_ring.frame
+ event.
+
+
+
+
+ Request that the compositor use the provided feedback string
+ associated with this ring. This request should be issued immediately
+ after a wp_tablet_pad_group.mode_switch event from the corresponding
+ group is received, or whenever the ring is mapped to a different
+ action. See wp_tablet_pad_group.mode_switch for more details.
+
+ Clients are encouraged to provide context-aware descriptions for
+ the actions associated with the ring; compositors may use this
+ information to offer visual feedback about the button layout
+ (eg. on-screen displays).
+
+ The provided string 'description' is a UTF-8 encoded string to be
+ associated with this ring, and is considered user-visible; general
+ internationalization rules apply.
+
+ The serial argument will be that of the last
+ wp_tablet_pad_group.mode_switch event received for the group of this
+ ring. Requests providing other serials than the most recent one will be
+ ignored.
+
+
+
+
+
+
+
+ This destroys the client's resource for this ring object.
+
+
+
+
+
+ Describes the source types for ring events. This indicates to the
+ client how a ring event was physically generated; a client may
+ adjust the user interface accordingly. For example, events
+ from a "finger" source may trigger kinetic scrolling.
+
+
+
+
+
+
+ Source information for ring events.
+
+ This event does not occur on its own. It is sent before a
+ wp_tablet_pad_ring.frame event and carries the source information
+ for all events within that frame.
+
+ The source specifies how this event was generated. If the source is
+ wp_tablet_pad_ring.source.finger, a wp_tablet_pad_ring.stop event
+ will be sent when the user lifts the finger off the device.
+
+ This event is optional. If the source is unknown for an interaction,
+ no event is sent.
+
+
+
+
+
+
+ Sent whenever the angle on a ring changes.
+
+ The angle is provided in degrees clockwise from the logical
+ north of the ring in the pad's current rotation.
+
+
+
+
+
+
+ Stop notification for ring events.
+
+ For some wp_tablet_pad_ring.source types, a wp_tablet_pad_ring.stop
+ event is sent to notify a client that the interaction with the ring
+ has terminated. This enables the client to implement kinetic scrolling.
+ See the wp_tablet_pad_ring.source documentation for information on
+ when this event may be generated.
+
+ Any wp_tablet_pad_ring.angle events with the same source after this
+ event should be considered as the start of a new interaction.
+
+
+
+
+
+ Indicates the end of a set of ring events that logically belong
+ together. A client is expected to accumulate the data in all events
+ within the frame before proceeding.
+
+ All wp_tablet_pad_ring events before a wp_tablet_pad_ring.frame event belong
+ logically together. For example, on termination of a finger interaction
+ on a ring the compositor will send a wp_tablet_pad_ring.source event,
+ a wp_tablet_pad_ring.stop event and a wp_tablet_pad_ring.frame event.
+
+ A wp_tablet_pad_ring.frame event is sent for every logical event
+ group, even if the group only contains a single wp_tablet_pad_ring
+ event. Specifically, a client may get a sequence: angle, frame,
+ angle, frame, etc.
+
+
+
+
+
+
+
+ A linear interaction area, such as the strips found in Wacom Cintiq
+ models.
+
+ Events on a strip are logically grouped by the wl_tablet_pad_strip.frame
+ event.
+
+
+
+
+ Requests the compositor to use the provided feedback string
+ associated with this strip. This request should be issued immediately
+ after a wp_tablet_pad_group.mode_switch event from the corresponding
+ group is received, or whenever the strip is mapped to a different
+ action. See wp_tablet_pad_group.mode_switch for more details.
+
+ Clients are encouraged to provide context-aware descriptions for
+ the actions associated with the strip, and compositors may use this
+ information to offer visual feedback about the button layout
+ (eg. on-screen displays).
+
+ The provided string 'description' is a UTF-8 encoded string to be
+ associated with this ring, and is considered user-visible; general
+ internationalization rules apply.
+
+ The serial argument will be that of the last
+ wp_tablet_pad_group.mode_switch event received for the group of this
+ strip. Requests providing other serials than the most recent one will be
+ ignored.
+
+
+
+
+
+
+
+ This destroys the client's resource for this strip object.
+
+
+
+
+
+ Describes the source types for strip events. This indicates to the
+ client how a strip event was physically generated; a client may
+ adjust the user interface accordingly. For example, events
+ from a "finger" source may trigger kinetic scrolling.
+
+
+
+
+
+
+ Source information for strip events.
+
+ This event does not occur on its own. It is sent before a
+ wp_tablet_pad_strip.frame event and carries the source information
+ for all events within that frame.
+
+ The source specifies how this event was generated. If the source is
+ wp_tablet_pad_strip.source.finger, a wp_tablet_pad_strip.stop event
+ will be sent when the user lifts their finger off the device.
+
+ This event is optional. If the source is unknown for an interaction,
+ no event is sent.
+
+
+
+
+
+
+ Sent whenever the position on a strip changes.
+
+ The position is normalized to a range of [0, 65535], the 0-value
+ represents the top-most and/or left-most position of the strip in
+ the pad's current rotation.
+
+
+
+
+
+
+ Stop notification for strip events.
+
+ For some wp_tablet_pad_strip.source types, a wp_tablet_pad_strip.stop
+ event is sent to notify a client that the interaction with the strip
+ has terminated. This enables the client to implement kinetic
+ scrolling. See the wp_tablet_pad_strip.source documentation for
+ information on when this event may be generated.
+
+ Any wp_tablet_pad_strip.position events with the same source after this
+ event should be considered as the start of a new interaction.
+
+
+
+
+
+ Indicates the end of a set of events that represent one logical
+ hardware strip event. A client is expected to accumulate the data
+ in all events within the frame before proceeding.
+
+ All wp_tablet_pad_strip events before a wp_tablet_pad_strip.frame event belong
+ logically together. For example, on termination of a finger interaction
+ on a strip the compositor will send a wp_tablet_pad_strip.source event,
+ a wp_tablet_pad_strip.stop event and a wp_tablet_pad_strip.frame
+ event.
+
+ A wp_tablet_pad_strip.frame event is sent for every logical event
+ group, even if the group only contains a single wp_tablet_pad_strip
+ event. Specifically, a client may get a sequence: position, frame,
+ position, frame, etc.
+
+
+
+
+
+
+
+ A pad group describes a distinct (sub)set of buttons, rings and strips
+ present in the tablet. The criteria of this grouping is usually positional,
+ eg. if a tablet has buttons on the left and right side, 2 groups will be
+ presented. The physical arrangement of groups is undisclosed and may
+ change on the fly.
+
+ Pad groups will announce their features during pad initialization. Between
+ the corresponding wp_tablet_pad.group event and wp_tablet_pad_group.done, the
+ pad group will announce the buttons, rings and strips contained in it,
+ plus the number of supported modes.
+
+ Modes are a mechanism to allow multiple groups of actions for every element
+ in the pad group. The number of groups and available modes in each is
+ persistent across device plugs. The current mode is user-switchable, it
+ will be announced through the wp_tablet_pad_group.mode_switch event both
+ whenever it is switched, and after wp_tablet_pad.enter.
+
+ The current mode logically applies to all elements in the pad group,
+ although it is at clients' discretion whether to actually perform different
+ actions, and/or issue the respective .set_feedback requests to notify the
+ compositor. See the wp_tablet_pad_group.mode_switch event for more details.
+
+
+
+
+ Destroy the wp_tablet_pad_group object. Objects created from this object
+ are unaffected and should be destroyed separately.
+
+
+
+
+
+ Sent on wp_tablet_pad_group initialization to announce the available
+ buttons in the group. Button indices start at 0, a button may only be
+ in one group at a time.
+
+ This event is first sent in the initial burst of events before the
+ wp_tablet_pad_group.done event.
+
+ Some buttons are reserved by the compositor. These buttons may not be
+ assigned to any wp_tablet_pad_group. Compositors may broadcast this
+ event in the case of changes to the mapping of these reserved buttons.
+ If the compositor happens to reserve all buttons in a group, this event
+ will be sent with an empty array.
+
+
+
+
+
+
+ Sent on wp_tablet_pad_group initialization to announce available rings.
+ One event is sent for each ring available on this pad group.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad_group.done event.
+
+
+
+
+
+
+ Sent on wp_tablet_pad initialization to announce available strips.
+ One event is sent for each strip available on this pad group.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad_group.done event.
+
+
+
+
+
+
+ Sent on wp_tablet_pad_group initialization to announce that the pad
+ group may switch between modes. A client may use a mode to store a
+ specific configuration for buttons, rings and strips and use the
+ wl_tablet_pad_group.mode_switch event to toggle between these
+ configurations. Mode indices start at 0.
+
+ Switching modes is compositor-dependent. See the
+ wp_tablet_pad_group.mode_switch event for more details.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad_group.done event. This event is only sent when more than
+ more than one mode is available.
+
+
+
+
+
+
+ This event is sent immediately to signal the end of the initial
+ burst of descriptive events. A client may consider the static
+ description of the tablet to be complete and finalize initialization
+ of the tablet group.
+
+
+
+
+
+ Notification that the mode was switched.
+
+ A mode applies to all buttons, rings and strips in a group
+ simultaneously, but a client is not required to assign different actions
+ for each mode. For example, a client may have mode-specific button
+ mappings but map the ring to vertical scrolling in all modes. Mode
+ indices start at 0.
+
+ Switching modes is compositor-dependent. The compositor may provide
+ visual cues to the client about the mode, e.g. by toggling LEDs on
+ the tablet device. Mode-switching may be software-controlled or
+ controlled by one or more physical buttons. For example, on a Wacom
+ Intuos Pro, the button inside the ring may be assigned to switch
+ between modes.
+
+ The compositor will also send this event after wp_tablet_pad.enter on
+ each group in order to notify of the current mode. Groups that only
+ feature one mode will use mode=0 when emitting this event.
+
+ If a button action in the new mode differs from the action in the
+ previous mode, the client should immediately issue a
+ wp_tablet_pad.set_feedback request for each changed button.
+
+ If a ring or strip action in the new mode differs from the action
+ in the previous mode, the client should immediately issue a
+ wp_tablet_ring.set_feedback or wp_tablet_strip.set_feedback request
+ for each changed ring or strip.
+
+
+
+
+
+
+
+
+
+ A pad device is a set of buttons, rings and strips
+ usually physically present on the tablet device itself. Some
+ exceptions exist where the pad device is physically detached, e.g. the
+ Wacom ExpressKey Remote.
+
+ Pad devices have no axes that control the cursor and are generally
+ auxiliary devices to the tool devices used on the tablet surface.
+
+ A pad device has a number of static characteristics, e.g. the number
+ of rings. These capabilities are sent in an event sequence after the
+ wp_tablet_seat.pad_added event before any actual events from this pad.
+ This initial event sequence is terminated by a wp_tablet_pad.done
+ event.
+
+ All pad features (buttons, rings and strips) are logically divided into
+ groups and all pads have at least one group. The available groups are
+ notified through the wp_tablet_pad.group event; the compositor will
+ emit one event per group before emitting wp_tablet_pad.done.
+
+ Groups may have multiple modes. Modes allow clients to map multiple
+ actions to a single pad feature. Only one mode can be active per group,
+ although different groups may have different active modes.
+
+
+
+
+ Requests the compositor to use the provided feedback string
+ associated with this button. This request should be issued immediately
+ after a wp_tablet_pad_group.mode_switch event from the corresponding
+ group is received, or whenever a button is mapped to a different
+ action. See wp_tablet_pad_group.mode_switch for more details.
+
+ Clients are encouraged to provide context-aware descriptions for
+ the actions associated with each button, and compositors may use
+ this information to offer visual feedback on the button layout
+ (e.g. on-screen displays).
+
+ Button indices start at 0. Setting the feedback string on a button
+ that is reserved by the compositor (i.e. not belonging to any
+ wp_tablet_pad_group) does not generate an error but the compositor
+ is free to ignore the request.
+
+ The provided string 'description' is a UTF-8 encoded string to be
+ associated with this ring, and is considered user-visible; general
+ internationalization rules apply.
+
+ The serial argument will be that of the last
+ wp_tablet_pad_group.mode_switch event received for the group of this
+ button. Requests providing other serials than the most recent one will
+ be ignored.
+
+
+
+
+
+
+
+
+ Destroy the wp_tablet_pad object. Objects created from this object
+ are unaffected and should be destroyed separately.
+
+
+
+
+
+ Sent on wp_tablet_pad initialization to announce available groups.
+ One event is sent for each pad group available.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad.done event. At least one group will be announced.
+
+
+
+
+
+
+ A system-specific device path that indicates which device is behind
+ this wp_tablet_pad. This information may be used to gather additional
+ information about the device, e.g. through libwacom.
+
+ The format of the path is unspecified, it may be a device node, a
+ sysfs path, or some other identifier. It is up to the client to
+ identify the string provided.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad.done event.
+
+
+
+
+
+
+ Sent on wp_tablet_pad initialization to announce the available
+ buttons.
+
+ This event is sent in the initial burst of events before the
+ wp_tablet_pad.done event. This event is only sent when at least one
+ button is available.
+
+
+
+
+
+
+ This event signals the end of the initial burst of descriptive
+ events. A client may consider the static description of the pad to
+ be complete and finalize initialization of the pad.
+
+
+
+
+
+ Describes the physical state of a button that caused the button
+ event.
+
+
+
+
+
+
+
+ Sent whenever the physical state of a button changes.
+
+
+
+
+
+
+
+
+ Notification that this pad is focused on the specified surface.
+
+
+
+
+
+
+
+
+ Notification that this pad is no longer focused on the specified
+ surface.
+
+
+
+
+
+
+
+ Sent when the pad has been removed from the system. When a tablet
+ is removed its pad(s) will be removed too.
+
+ When this event is received, the client must destroy all rings, strips
+ and groups that were offered by this pad, and issue wp_tablet_pad.destroy
+ the pad itself.
+
+
+
+
diff --git a/Engine/lib/sdl/wayland-protocols/viewporter.xml b/Engine/lib/sdl/wayland-protocols/viewporter.xml
new file mode 100644
index 000000000..c732d8c35
--- /dev/null
+++ b/Engine/lib/sdl/wayland-protocols/viewporter.xml
@@ -0,0 +1,186 @@
+
+
+
+
+ Copyright © 2013-2016 Collabora, Ltd.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+
+
+
+ The global interface exposing surface cropping and scaling
+ capabilities is used to instantiate an interface extension for a
+ wl_surface object. This extended interface will then allow
+ cropping and scaling the surface contents, effectively
+ disconnecting the direct relationship between the buffer and the
+ surface size.
+
+
+
+
+ Informs the server that the client will not be using this
+ protocol object anymore. This does not affect any other objects,
+ wp_viewport objects included.
+
+
+
+
+
+
+
+
+
+ Instantiate an interface extension for the given wl_surface to
+ crop and scale its content. If the given wl_surface already has
+ a wp_viewport object associated, the viewport_exists
+ protocol error is raised.
+
+
+
+
+
+
+
+
+ An additional interface to a wl_surface object, which allows the
+ client to specify the cropping and scaling of the surface
+ contents.
+
+ This interface works with two concepts: the source rectangle (src_x,
+ src_y, src_width, src_height), and the destination size (dst_width,
+ dst_height). The contents of the source rectangle are scaled to the
+ destination size, and content outside the source rectangle is ignored.
+ This state is double-buffered, and is applied on the next
+ wl_surface.commit.
+
+ The two parts of crop and scale state are independent: the source
+ rectangle, and the destination size. Initially both are unset, that
+ is, no scaling is applied. The whole of the current wl_buffer is
+ used as the source, and the surface size is as defined in
+ wl_surface.attach.
+
+ If the destination size is set, it causes the surface size to become
+ dst_width, dst_height. The source (rectangle) is scaled to exactly
+ this size. This overrides whatever the attached wl_buffer size is,
+ unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface
+ has no content and therefore no size. Otherwise, the size is always
+ at least 1x1 in surface local coordinates.
+
+ If the source rectangle is set, it defines what area of the wl_buffer is
+ taken as the source. If the source rectangle is set and the destination
+ size is not set, then src_width and src_height must be integers, and the
+ surface size becomes the source rectangle size. This results in cropping
+ without scaling. If src_width or src_height are not integers and
+ destination size is not set, the bad_size protocol error is raised when
+ the surface state is applied.
+
+ The coordinate transformations from buffer pixel coordinates up to
+ the surface-local coordinates happen in the following order:
+ 1. buffer_transform (wl_surface.set_buffer_transform)
+ 2. buffer_scale (wl_surface.set_buffer_scale)
+ 3. crop and scale (wp_viewport.set*)
+ This means, that the source rectangle coordinates of crop and scale
+ are given in the coordinates after the buffer transform and scale,
+ i.e. in the coordinates that would be the surface-local coordinates
+ if the crop and scale was not applied.
+
+ If src_x or src_y are negative, the bad_value protocol error is raised.
+ Otherwise, if the source rectangle is partially or completely outside of
+ the non-NULL wl_buffer, then the out_of_buffer protocol error is raised
+ when the surface state is applied. A NULL wl_buffer does not raise the
+ out_of_buffer error.
+
+ The x, y arguments of wl_surface.attach are applied as normal to
+ the surface. They indicate how many pixels to remove from the
+ surface size from the left and the top. In other words, they are
+ still in the surface-local coordinate system, just like dst_width
+ and dst_height are.
+
+ If the wl_surface associated with the wp_viewport is destroyed,
+ all wp_viewport requests except 'destroy' raise the protocol error
+ no_surface.
+
+ If the wp_viewport object is destroyed, the crop and scale
+ state is removed from the wl_surface. The change will be applied
+ on the next wl_surface.commit.
+
+
+
+
+ The associated wl_surface's crop and scale state is removed.
+ The change is applied on the next wl_surface.commit.
+
+
+
+
+
+
+
+
+
+
+
+
+ Set the source rectangle of the associated wl_surface. See
+ wp_viewport for the description, and relation to the wl_buffer
+ size.
+
+ If all of x, y, width and height are -1.0, the source rectangle is
+ unset instead. Any other set of values where width or height are zero
+ or negative, or x or y are negative, raise the bad_value protocol
+ error.
+
+ The crop and scale state is double-buffered state, and will be
+ applied on the next wl_surface.commit.
+
+
+
+
+
+
+
+
+
+ Set the destination size of the associated wl_surface. See
+ wp_viewport for the description, and relation to the wl_buffer
+ size.
+
+ If width is -1 and height is -1, the destination size is unset
+ instead. Any other pair of values for width and height that
+ contains zero or negative values raises the bad_value protocol
+ error.
+
+ The crop and scale state is double-buffered state, and will be
+ applied on the next wl_surface.commit.
+
+
+
+
+
+
+
diff --git a/Engine/lib/sdl/wayland-protocols/xdg-output-unstable-v1.xml b/Engine/lib/sdl/wayland-protocols/xdg-output-unstable-v1.xml
new file mode 100644
index 000000000..9a5b79000
--- /dev/null
+++ b/Engine/lib/sdl/wayland-protocols/xdg-output-unstable-v1.xml
@@ -0,0 +1,220 @@
+
+
+
+
+ Copyright © 2017 Red Hat Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+
+
+ This protocol aims at describing outputs in a way which is more in line
+ with the concept of an output on desktop oriented systems.
+
+ Some information are more specific to the concept of an output for
+ a desktop oriented system and may not make sense in other applications,
+ such as IVI systems for example.
+
+ Typically, the global compositor space on a desktop system is made of
+ a contiguous or overlapping set of rectangular regions.
+
+ Some of the information provided in this protocol might be identical
+ to their counterparts already available from wl_output, in which case
+ the information provided by this protocol should be preferred to their
+ equivalent in wl_output. The goal is to move the desktop specific
+ concepts (such as output location within the global compositor space,
+ the connector name and types, etc.) out of the core wl_output protocol.
+
+ Warning! The protocol described in this file is experimental and
+ backward incompatible changes may be made. Backward compatible
+ changes may be added together with the corresponding interface
+ version bump.
+ Backward incompatible changes are done by bumping the version
+ number in the protocol and interface names and resetting the
+ interface version. Once the protocol is to be declared stable,
+ the 'z' prefix and the version number in the protocol and
+ interface names are removed and the interface version number is
+ reset.
+
+
+
+
+ A global factory interface for xdg_output objects.
+
+
+
+
+ Using this request a client can tell the server that it is not
+ going to use the xdg_output_manager object anymore.
+
+ Any objects already created through this instance are not affected.
+
+
+
+
+
+ This creates a new xdg_output object for the given wl_output.
+
+
+
+
+
+
+
+
+ An xdg_output describes part of the compositor geometry.
+
+ This typically corresponds to a monitor that displays part of the
+ compositor space.
+
+ For objects version 3 onwards, after all xdg_output properties have been
+ sent (when the object is created and when properties are updated), a
+ wl_output.done event is sent. This allows changes to the output
+ properties to be seen as atomic, even if they happen via multiple events.
+
+
+
+
+ Using this request a client can tell the server that it is not
+ going to use the xdg_output object anymore.
+
+
+
+
+
+ The position event describes the location of the wl_output within
+ the global compositor space.
+
+ The logical_position event is sent after creating an xdg_output
+ (see xdg_output_manager.get_xdg_output) and whenever the location
+ of the output changes within the global compositor space.
+
+
+
+
+
+
+
+ The logical_size event describes the size of the output in the
+ global compositor space.
+
+ For example, a surface without any buffer scale, transformation
+ nor rotation set, with the size matching the logical_size will
+ have the same size as the corresponding output when displayed.
+
+ Most regular Wayland clients should not pay attention to the
+ logical size and would rather rely on xdg_shell interfaces.
+
+ Some clients such as Xwayland, however, need this to configure
+ their surfaces in the global compositor space as the compositor
+ may apply a different scale from what is advertised by the output
+ scaling property (to achieve fractional scaling, for example).
+
+ For example, for a wl_output mode 3840×2160 and a scale factor 2:
+
+ - A compositor not scaling the surface buffers will advertise a
+ logical size of 3840×2160,
+
+ - A compositor automatically scaling the surface buffers will
+ advertise a logical size of 1920×1080,
+
+ - A compositor using a fractional scale of 1.5 will advertise a
+ logical size of 2560×1440.
+
+ For example, for a wl_output mode 1920×1080 and a 90 degree rotation,
+ the compositor will advertise a logical size of 1080x1920.
+
+ The logical_size event is sent after creating an xdg_output
+ (see xdg_output_manager.get_xdg_output) and whenever the logical
+ size of the output changes, either as a result of a change in the
+ applied scale or because of a change in the corresponding output
+ mode(see wl_output.mode) or transform (see wl_output.transform).
+
+
+
+
+
+
+
+ This event is sent after all other properties of an xdg_output
+ have been sent.
+
+ This allows changes to the xdg_output properties to be seen as
+ atomic, even if they happen via multiple events.
+
+ For objects version 3 onwards, this event is deprecated. Compositors
+ are not required to send it anymore and must send wl_output.done
+ instead.
+
+
+
+
+
+
+
+ Many compositors will assign names to their outputs, show them to the
+ user, allow them to be configured by name, etc. The client may wish to
+ know this name as well to offer the user similar behaviors.
+
+ The naming convention is compositor defined, but limited to
+ alphanumeric characters and dashes (-). Each name is unique among all
+ wl_output globals, but if a wl_output global is destroyed the same name
+ may be reused later. The names will also remain consistent across
+ sessions with the same hardware and software configuration.
+
+ Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
+ not assume that the name is a reflection of an underlying DRM
+ connector, X11 connection, etc.
+
+ The name event is sent after creating an xdg_output (see
+ xdg_output_manager.get_xdg_output). This event is only sent once per
+ xdg_output, and the name does not change over the lifetime of the
+ wl_output global.
+
+
+
+
+
+
+ Many compositors can produce human-readable descriptions of their
+ outputs. The client may wish to know this description as well, to
+ communicate the user for various purposes.
+
+ The description is a UTF-8 string with no convention defined for its
+ contents. Examples might include 'Foocorp 11" Display' or 'Virtual X11
+ output via :1'.
+
+ The description event is sent after creating an xdg_output (see
+ xdg_output_manager.get_xdg_output) and whenever the description
+ changes. The description is optional, and may not be sent at all.
+
+ For objects of version 2 and lower, this event is only sent once per
+ xdg_output, and the description does not change over the lifetime of
+ the wl_output global.
+
+
+
+
+
+