LIBS: updated sdl2

master
Martin Gerhardy 2022-03-25 19:54:24 +01:00
parent 1cf6d667c8
commit e00739e233
79 changed files with 3922 additions and 1084 deletions

View File

@ -297,7 +297,7 @@ if(CYGWIN)
# We build SDL on cygwin without the UNIX emulation layer
target_include_directories(sdl-build-options INTERFACE "/usr/include/mingw")
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -mno-cygwin")
check_c_source_compiles("int main(int argc, char **argv) {}"
check_c_source_compiles("int main(int argc, char **argv) { return 0; }"
HAVE_GCC_NO_CYGWIN)
set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
if(HAVE_GCC_NO_CYGWIN)
@ -462,8 +462,8 @@ dep_option(SDL_STATIC_PIC "Static version of the library should be built wi
set_option(SDL_TEST "Build the test directory" OFF)
if(VITA)
set_option(VIDEO_VITA_PIB "Build with PSVita piglet gles2 support" OFF)
set_option(VIDEO_VITA_PVR "Build with PSVita PVR gles/gles2 support" OFF)
set_option(VIDEO_VITA_PIB "Build with PSVita piglet gles2 support" OFF)
set_option(VIDEO_VITA_PVR "Build with PSVita PVR gles/gles2 support" OFF)
endif()
# General source files
@ -475,6 +475,7 @@ file(GLOB SOURCE_FILES
${SDL2_SOURCE_DIR}/src/dynapi/*.c
${SDL2_SOURCE_DIR}/src/events/*.c
${SDL2_SOURCE_DIR}/src/file/*.c
${SDL2_SOURCE_DIR}/src/joystick/*.c
${SDL2_SOURCE_DIR}/src/haptic/*.c
${SDL2_SOURCE_DIR}/src/hidapi/*.c
${SDL2_SOURCE_DIR}/src/libm/*.c
@ -548,7 +549,7 @@ if(USE_GCC OR USE_CLANG)
#if !defined(__GNUC__) || __GNUC__ < 3
#error Dependency tracking requires GCC 3.0 or newer
#endif
int main(int argc, char **argv) { }" HAVE_DEPENDENCY_TRACKING)
int main(int argc, char **argv) { return 0; }" HAVE_DEPENDENCY_TRACKING)
endif()
if(SDL_GCC_ATOMICS)
@ -559,17 +560,19 @@ if(USE_GCC OR USE_CLANG)
__sync_lock_test_and_set(&x, y);
__sync_fetch_and_add(&a, 1);
__sync_bool_compare_and_swap(&a, 5, 10);
__sync_bool_compare_and_swap(&x, y, z); }" HAVE_GCC_ATOMICS)
__sync_bool_compare_and_swap(&x, y, z);
return 0; }" HAVE_GCC_ATOMICS)
if(NOT HAVE_GCC_ATOMICS)
check_c_source_compiles("int main(int argc, char **argv) {
int a;
__sync_lock_test_and_set(&a, 1);
__sync_lock_release(&a); }" HAVE_GCC_SYNC_LOCK_TEST_AND_SET)
__sync_lock_release(&a);
return 0; }" HAVE_GCC_SYNC_LOCK_TEST_AND_SET)
endif()
endif()
set(CMAKE_REQUIRED_FLAGS "-mpreferred-stack-boundary=2")
check_c_source_compiles("int x = 0; int main(int argc, char **argv) {}"
check_c_source_compiles("int x = 0; int main(int argc, char **argv) { return 0; }"
HAVE_GCC_PREFERRED_STACK_BOUNDARY)
set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
@ -578,7 +581,7 @@ if(USE_GCC OR USE_CLANG)
#if !defined(__GNUC__) || __GNUC__ < 4
#error SDL only uses visibility attributes in GCC 4 or newer
#endif
int main(int argc, char **argv) {}" HAVE_GCC_FVISIBILITY)
int main(int argc, char **argv) { return 0; }" HAVE_GCC_FVISIBILITY)
if(HAVE_GCC_FVISIBILITY)
list(APPEND EXTRA_CFLAGS "-fvisibility=hidden")
endif()
@ -634,7 +637,7 @@ if(SDL_ASSEMBLY)
#ifndef __MMX__
#error Assembler CPP flag not enabled
#endif
int main(int argc, char **argv) { }" HAVE_MMX)
int main(int argc, char **argv) { return 0; }" HAVE_MMX)
if(HAVE_MMX)
list(APPEND EXTRA_CFLAGS "-mmmx")
endif()
@ -651,6 +654,7 @@ if(SDL_ASSEMBLY)
int main(int argc, char **argv) {
void *p = 0;
_m_prefetch(p);
return 0;
}" HAVE_3DNOW)
if(HAVE_3DNOW)
list(APPEND EXTRA_CFLAGS "-m3dnow")
@ -674,7 +678,7 @@ if(SDL_ASSEMBLY)
#ifndef __SSE__
#error Assembler CPP flag not enabled
#endif
int main(int argc, char **argv) { }" HAVE_SSE)
int main(int argc, char **argv) { return 0; }" HAVE_SSE)
if(HAVE_SSE)
list(APPEND EXTRA_CFLAGS "-msse")
endif()
@ -697,7 +701,7 @@ if(SDL_ASSEMBLY)
#ifndef __SSE2__
#error Assembler CPP flag not enabled
#endif
int main(int argc, char **argv) { }" HAVE_SSE2)
int main(int argc, char **argv) { return 0; }" HAVE_SSE2)
if(HAVE_SSE2)
list(APPEND EXTRA_CFLAGS "-msse2")
endif()
@ -720,7 +724,7 @@ if(SDL_ASSEMBLY)
#ifndef __SSE3__
#error Assembler CPP flag not enabled
#endif
int main(int argc, char **argv) { }" HAVE_SSE3)
int main(int argc, char **argv) { return 0; }" HAVE_SSE3)
if(HAVE_SSE3)
list(APPEND EXTRA_CFLAGS "-msse3")
endif()
@ -749,12 +753,12 @@ if(SDL_ASSEMBLY)
vector unsigned int vzero() {
return vec_splat_u32(0);
}
int main(int argc, char **argv) { }" HAVE_ALTIVEC_H_HDR)
int main(int argc, char **argv) { return 0; }" HAVE_ALTIVEC_H_HDR)
check_c_source_compiles("
vector unsigned int vzero() {
return vec_splat_u32(0);
}
int main(int argc, char **argv) { }" HAVE_ALTIVEC)
int main(int argc, char **argv) { return 0; }" HAVE_ALTIVEC)
set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
if(HAVE_ALTIVEC OR HAVE_ALTIVEC_H_HDR)
set(HAVE_ALTIVEC TRUE) # if only HAVE_ALTIVEC_H_HDR is set
@ -881,7 +885,7 @@ if(SDL_LIBC)
# TODO: refine the mprotect check
check_c_source_compiles("#include <sys/types.h>
#include <sys/mman.h>
int main() { }" HAVE_MPROTECT)
int main(void) { return 0; }" HAVE_MPROTECT)
foreach(_FN
strtod malloc calloc realloc free getenv setenv putenv unsetenv
qsort abs bcopy memset memcpy memmove memcmp strlen strlcpy strlcat
@ -965,10 +969,6 @@ foreach(_SUB ${SDL_SUBSYSTEMS})
set(SDL_${_OPT}_DISABLED 1)
endif()
endforeach()
if(SDL_JOYSTICK)
file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
endif()
if(SDL_HAPTIC)
if(NOT SDL_JOYSTICK)
# Haptic requires some private functions from the joystick subsystem.
@ -1163,9 +1163,7 @@ if(ANDROID)
#if defined(__ARM_ARCH) && __ARM_ARCH < 7
#error Vulkan doesn't work on this configuration
#endif
int main(void) {
return 0;
}
int main(int argc, char **argv) { return 0; }
" VULKAN_PASSED_ANDROID_CHECKS)
if(VULKAN_PASSED_ANDROID_CHECKS)
set(SDL_VIDEO_VULKAN 1)
@ -1181,10 +1179,11 @@ elseif(EMSCRIPTEN)
# project. Uncomment at will for verbose cross-compiling -I/../ path info.
target_compile_options(sdl-build-options INTERFACE "-Wno-warn-absolute-paths")
file(GLOB EMSRIPTEN_MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/emscripten/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${EMSRIPTEN_MISC_SOURCES})
set(HAVE_SDL_MISC TRUE)
if(SDL_MISC)
file(GLOB EMSRIPTEN_MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/emscripten/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${EMSRIPTEN_MISC_SOURCES})
set(HAVE_SDL_MISC TRUE)
endif()
if(SDL_AUDIO)
set(SDL_AUDIO_DRIVER_EMSCRIPTEN 1)
file(GLOB EM_AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/emscripten/*.c)
@ -1301,28 +1300,26 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT RISCOS AND NOT HAIKU)
#ifndef EVIOCGNAME
#error EVIOCGNAME() ioctl not available
#endif
int main(int argc, char** argv) {}" HAVE_INPUT_EVENTS)
int main(int argc, char** argv) { return 0; }" HAVE_INPUT_EVENTS)
if(LINUX)
check_c_source_compiles("
#include <linux/kd.h>
#include <linux/keyboard.h>
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
struct kbentry kbe;
kbe.kb_table = KG_CTRL;
ioctl(0, KDGKBENT, &kbe);
return 0;
}" HAVE_INPUT_KD)
elseif(FREEBSD)
check_c_source_compiles("
#include <sys/kbio.h>
#include <sys/ioctl.h>
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
accentmap_t accTable;
ioctl(0, KDENABIO, 1);
return 0;
}" HAVE_INPUT_KBIO)
endif()
@ -1522,7 +1519,7 @@ elseif(WINDOWS)
check_c_source_compiles("
#include <windows.h>
int main(int argc, char **argv) { }" HAVE_WIN32_CC)
int main(int argc, char **argv) { return 0; }" HAVE_WIN32_CC)
file(GLOB CORE_SOURCES ${SDL2_SOURCE_DIR}/src/core/windows/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${CORE_SOURCES})
@ -1587,22 +1584,22 @@ elseif(WINDOWS)
check_c_source_compiles("
#include <windows.h>
#include <xinput.h>
int main(int argc, char **argv) { }" HAVE_XINPUT_H)
int main(int argc, char **argv) { return 0; }" HAVE_XINPUT_H)
check_c_source_compiles("
#include <windows.h>
#include <xinput.h>
XINPUT_GAMEPAD_EX x1;
int main(int argc, char **argv) { }" HAVE_XINPUT_GAMEPAD_EX)
int main(int argc, char **argv) { return 0; }" HAVE_XINPUT_GAMEPAD_EX)
check_c_source_compiles("
#include <windows.h>
#include <xinput.h>
XINPUT_STATE_EX s1;
int main(int argc, char **argv) { }" HAVE_XINPUT_STATE_EX)
int main(int argc, char **argv) { return 0; }" HAVE_XINPUT_STATE_EX)
check_c_source_compiles("
#define COBJMACROS
#include <windows.gaming.input.h>
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2 *s2;
int main(int argc, char **argv) { }" HAVE_WINDOWS_GAMING_INPUT_H)
int main(int argc, char **argv) { return 0; }" HAVE_WINDOWS_GAMING_INPUT_H)
endif()
# headers needed elsewhere
@ -1845,8 +1842,6 @@ elseif(APPLE)
if(SDL_FILE)
file(GLOB EXTRA_SOURCES ${SDL2_SOURCE_DIR}/src/file/cocoa/*.m)
set(SOURCE_FILES ${EXTRA_SOURCES} ${SOURCE_FILES})
# !!! FIXME: modern CMake doesn't need "LANGUAGE C" for Objective-C.
set_source_files_properties(${EXTRA_SOURCES} PROPERTIES LANGUAGE C)
set(HAVE_SDL_FILE TRUE)
endif()
@ -1867,8 +1862,6 @@ elseif(APPLE)
if(SDL_AUDIO)
set(SDL_AUDIO_DRIVER_COREAUDIO 1)
file(GLOB AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/coreaudio/*.m)
# !!! FIXME: modern CMake doesn't need "LANGUAGE C" for Objective-C.
set_source_files_properties(${AUDIO_SOURCES} PROPERTIES LANGUAGE C)
set(SOURCE_FILES ${SOURCE_FILES} ${AUDIO_SOURCES})
set(HAVE_SDL_AUDIO TRUE)
set(SDL_FRAMEWORK_COREAUDIO 1)
@ -1904,13 +1897,13 @@ elseif(APPLE)
#if TARGET_CPU_X86
#error GameController framework doesn't work on this configuration
#endif
int main() {}" HAVE_FRAMEWORK_GAMECONTROLLER)
int main() { return 0; }" HAVE_FRAMEWORK_GAMECONTROLLER)
check_objc_source_compiles("
#include <AvailabilityMacros.h>
#include <TargetConditionals.h>
#import <Foundation/Foundation.h>
#import <CoreHaptics/CoreHaptics.h>
int main() {}" HAVE_FRAMEWORK_COREHAPTICS)
int main() { return 0; }" HAVE_FRAMEWORK_COREHAPTICS)
if(HAVE_FRAMEWORK_GAMECONTROLLER AND HAVE_FRAMEWORK_COREHAPTICS)
# Only enable MFI if we also have CoreHaptics to ensure rumble works
set(SDL_JOYSTICK_MFI 1)
@ -1968,8 +1961,6 @@ elseif(APPLE)
if(SDL_FILESYSTEM)
set(SDL_FILESYSTEM_COCOA 1)
file(GLOB FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/cocoa/*.m)
# !!! FIXME: modern CMake doesn't need "LANGUAGE C" for Objective-C.
set_source_files_properties(${FILESYSTEM_SOURCES} PROPERTIES LANGUAGE C)
set(SOURCE_FILES ${SOURCE_FILES} ${FILESYSTEM_SOURCES})
set(HAVE_SDL_FILESYSTEM TRUE)
endif()
@ -2027,7 +2018,7 @@ elseif(APPLE)
#if (!TARGET_CPU_X86_64 && !TARGET_CPU_ARM64)
#error Metal doesn't work on this configuration
#endif
int main(void) {}" HAVE_FRAMEWORK_METAL)
int main(int argc, char **argv) { return 0; }" HAVE_FRAMEWORK_METAL)
if(HAVE_FRAMEWORK_METAL)
set(SDL_FRAMEWORK_METAL 1)
set(SDL_FRAMEWORK_QUARTZCORE 1)
@ -2562,10 +2553,8 @@ if(NOT HAVE_SDL_VIDEO)
endif()
if(NOT HAVE_SDL_JOYSTICK)
set(SDL_JOYSTICK_DUMMY 1)
if(SDL_JOYSTICK AND NOT APPLE) # results in unresolved symbols on OSX
file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/dummy/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
endif()
file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/dummy/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
endif()
if(NOT HAVE_SDL_HAPTIC)
set(SDL_HAPTIC_DUMMY 1)

View File

@ -530,8 +530,7 @@ macro(CheckX11)
#include <X11/extensions/XInput2.h>
int event_type = XI_TouchBegin;
XITouchClassInfo *t;
Status XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f)
{
Status XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f) {
return (Status)0;
}
int main(int argc, char **argv) { return 0; }" HAVE_XINPUT2_MULTITOUCH)
@ -633,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)
@ -793,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)

View File

@ -65,6 +65,15 @@ _m_prefetch(void *__P)
#elif defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/endian.h>
#define SDL_BYTEORDER BYTE_ORDER
/* predefs from newer gcc and clang versions: */
#elif defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__BYTE_ORDER__)
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define SDL_BYTEORDER SDL_LIL_ENDIAN
#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#define SDL_BYTEORDER SDL_BIG_ENDIAN
#else
#error Unsupported endianness
#endif /**/
#else
#if defined(__hppa__) || \
defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \

View File

@ -933,6 +933,22 @@ extern "C" {
*/
#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE "SDL_MOUSE_NORMAL_SPEED_SCALE"
/**
* \brief A variable controlling whether relative mouse mode constrains the mouse to the center of the window
*
* This variable can be set to the following values:
* "0" - Relative mouse mode constrains the mouse to the window
* "1" - Relative mouse mode constrains the mouse to the center of the window
*
* Constraining to the center of the window works better for FPS games and when the
* application is running over RDP. Constraining to the whole window works better
* for 2D games and increases the chance that the mouse will be in the correct
* position when using high DPI mice.
*
* By default SDL will constrain the mouse to the center of the window
*/
#define SDL_HINT_MOUSE_RELATIVE_MODE_CENTER "SDL_MOUSE_RELATIVE_MODE_CENTER"
/**
* \brief A variable controlling whether relative mouse mode is implemented using mouse warping
*
@ -969,6 +985,19 @@ extern "C" {
*/
#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS"
/**
* \brief A variable controlling whether the mouse is captured while mouse buttons are pressed
*
* This variable can be set to the following values:
* "0" - The mouse is not captured while mouse buttons are pressed
* "1" - The mouse is captured while mouse buttons are pressed
*
* By default the mouse is captured while mouse buttons are pressed so if the mouse is dragged
* outside the window, the application continues to receive mouse events until the button is
* released.
*/
#define SDL_HINT_MOUSE_AUTO_CAPTURE "SDL_MOUSE_AUTO_CAPTURE"
/**
* \brief Tell SDL not to catch the SIGINT or SIGTERM signals.
*
@ -1453,6 +1482,28 @@ extern "C" {
*/
#define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT"
/**
* \brief When calling SDL_CreateWindowFrom(), make the window compatible with OpenGL.
*
* This variable can be set to the following values:
* "0" - Don't add any graphics flags to the SDL_WindowFlags
* "1" - Add SDL_WINDOW_OPENGL to the SDL_WindowFlags
*
* By default SDL will not make the foreign window compatible with OpenGL.
*/
#define SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL "SDL_VIDEO_FOREIGN_WINDOW_OPENGL"
/**
* \brief When calling SDL_CreateWindowFrom(), make the window compatible with Vulkan.
*
* This variable can be set to the following values:
* "0" - Don't add any graphics flags to the SDL_WindowFlags
* "1" - Add SDL_WINDOW_VULKAN to the SDL_WindowFlags
*
* By default SDL will not make the foreign window compatible with Vulkan.
*/
#define SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN "SDL_VIDEO_FOREIGN_WINDOW_VULKAN"
/**
* \brief A variable specifying which shader compiler to preload when using the Chrome ANGLE binaries
*
@ -1892,6 +1943,30 @@ extern "C" {
*/
#define SDL_HINT_X11_WINDOW_TYPE "SDL_X11_WINDOW_TYPE"
/**
* \brief A variable that decides whether to send SDL_QUIT when closing the final window.
*
* By default, SDL sends an SDL_QUIT event when there is only one window
* and it receives an SDL_WINDOWEVENT_CLOSE event, under the assumption most
* apps would also take the loss of this window as a signal to terminate the
* program.
*
* However, it's not unreasonable in some cases to have the program continue
* to live on, perhaps to create new windows later.
*
* Changing this hint to "0" will cause SDL to not send an SDL_QUIT event
* when the final window is requesting to close. Note that in this case,
* there are still other legitimate reasons one might get an SDL_QUIT
* event: choosing "Quit" from the macOS menu bar, sending a SIGINT (ctrl-c)
* on Unix, etc.
*
* The default value is "1". This hint can be changed at any time.
*
* This hint is available since SDL 2.0.22. Before then, you always get
* an SDL_QUIT event when closing the final window.
*/
#define SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE "SDL_QUIT_ON_LAST_WINDOW_CLOSE"
/**
* \brief An enumeration of hint priorities

View File

@ -54,8 +54,13 @@ typedef struct SDL_Point
/**
* The structure that defines a point (floating point)
*
* \sa SDL_EnclosePoints
* \sa SDL_PointInRect
* \sa SDL_FRectEmpty
* \sa SDL_FRectEquals
* \sa SDL_HasIntersectionF
* \sa SDL_IntersectFRect
* \sa SDL_UnionFRect
* \sa SDL_EncloseFPoints
* \sa SDL_PointInFRect
*/
typedef struct SDL_FPoint
{
@ -213,6 +218,131 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IntersectRectAndLine(const SDL_Rect *
int *Y1, int *X2,
int *Y2);
/* SDL_FRect versions... */
/**
* Returns true if point resides inside a rectangle.
*/
SDL_FORCE_INLINE SDL_bool SDL_PointInFRect(const SDL_FPoint *p, const SDL_FRect *r)
{
return ( (p->x >= r->x) && (p->x < (r->x + r->w)) &&
(p->y >= r->y) && (p->y < (r->y + r->h)) ) ? SDL_TRUE : SDL_FALSE;
}
/**
* Returns true if the rectangle has no area.
*/
SDL_FORCE_INLINE SDL_bool SDL_FRectEmpty(const SDL_FRect *r)
{
return ((!r) || (r->w <= 0.0f) || (r->h <= 0.0f)) ? SDL_TRUE : SDL_FALSE;
}
/**
* Returns true if the two rectangles are equal.
*/
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;
}
/**
* Determine whether two rectangles intersect with float precision.
*
* If either pointer is NULL the function will return SDL_FALSE.
*
* \param A an SDL_FRect structure representing the first rectangle
* \param B an SDL_FRect structure representing the second rectangle
* \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
*
* \since This function is available since SDL 2.0.22.
*
* \sa SDL_IntersectRect
*/
extern DECLSPEC SDL_bool SDLCALL SDL_HasIntersectionF(const SDL_FRect * A,
const SDL_FRect * B);
/**
* Calculate the intersection of two rectangles with float precision.
*
* If `result` is NULL then this function will return SDL_FALSE.
*
* \param A an SDL_FRect structure representing the first rectangle
* \param B an SDL_FRect structure representing the second rectangle
* \param result an SDL_FRect structure filled in with the intersection of
* rectangles `A` and `B`
* \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
*
* \since This function is available since SDL 2.0.22.
*
* \sa SDL_HasIntersectionF
*/
extern DECLSPEC SDL_bool SDLCALL SDL_IntersectFRect(const SDL_FRect * A,
const SDL_FRect * B,
SDL_FRect * result);
/**
* Calculate the union of two rectangles with float precision.
*
* \param A an SDL_FRect structure representing the first rectangle
* \param B an SDL_FRect structure representing the second rectangle
* \param result an SDL_FRect structure filled in with the union of rectangles
* `A` and `B`
*
* \since This function is available since SDL 2.0.22.
*/
extern DECLSPEC void SDLCALL SDL_UnionFRect(const SDL_FRect * A,
const SDL_FRect * B,
SDL_FRect * result);
/**
* Calculate a minimal rectangle enclosing a set of points with float
* precision.
*
* If `clip` is not NULL then only points inside of the clipping rectangle are
* considered.
*
* \param points an array of SDL_FPoint structures representing points to be
* enclosed
* \param count the number of structures in the `points` array
* \param clip an SDL_FRect used for clipping or NULL to enclose all points
* \param result an SDL_FRect structure filled in with the minimal enclosing
* rectangle
* \returns SDL_TRUE if any points were enclosed or SDL_FALSE if all the
* points were outside of the clipping rectangle.
*
* \since This function is available since SDL 2.0.22.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_EncloseFPoints(const SDL_FPoint * points,
int count,
const SDL_FRect * clip,
SDL_FRect * result);
/**
* Calculate the intersection of a rectangle and line segment with float
* precision.
*
* This function is used to clip a line segment to a rectangle. A line segment
* contained entirely within the rectangle or that does not intersect will
* remain unchanged. A line segment that crosses the rectangle at either or
* both ends will be clipped to the boundary of the rectangle and the new
* coordinates saved in `X1`, `Y1`, `X2`, and/or `Y2` as necessary.
*
* \param rect an SDL_FRect structure representing the rectangle to intersect
* \param X1 a pointer to the starting X-coordinate of the line
* \param Y1 a pointer to the starting Y-coordinate of the line
* \param X2 a pointer to the ending X-coordinate of the line
* \param Y2 a pointer to the ending Y-coordinate of the line
* \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise.
*
* \since This function is available since SDL 2.0.22.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_IntersectFRectAndLine(const SDL_FRect *
rect, float *X1,
float *Y1, float *X2,
float *Y2);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}

View File

@ -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.
*
@ -1662,7 +1673,8 @@ extern DECLSPEC int SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer,
* Read pixels from the current rendering target to an array of pixels.
*
* **WARNING**: This is a very slow operation, and should not be used
* frequently.
* frequently. If you're using this on the main rendering target, it should be
* called after rendering and before SDL_RenderPresent().
*
* `pitch` specifies the number of bytes between rows in the destination
* `pixels` data. This allows you to write to a subrectangle or have padded

View File

@ -354,8 +354,14 @@ typedef uint64_t Uint64;
#endif
#endif /* SDL_DISABLE_ANALYZE_MACROS */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
#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);
#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]
#endif
/** \cond */
#ifndef DOXYGEN_SHOULD_IGNORE_THIS
SDL_COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1);

View File

@ -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:

View File

@ -369,11 +369,11 @@ SDL_Convert71To51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
const float surround_left_distributed = src[6] * 0.5f;
const float surround_right_distributed = src[7] * 0.5f;
dst[0] = (src[0] + surround_left_distributed) * two_thirds; /* FL */
dst[1] = (src[1] + surround_right_distributed) * two_thirds; /* FR */
dst[1] = (src[1] + surround_right_distributed) * two_thirds; /* FR */
dst[2] = src[2] * two_thirds; /* CC */
dst[3] = src[3] * two_thirds; /* LFE */
dst[4] = (src[4] + surround_left_distributed) * two_thirds; /* BL */
dst[5] = (src[5] + surround_right_distributed) * two_thirds; /* BR */
dst[5] = (src[5] + surround_right_distributed) * two_thirds; /* BR */
}
cvt->len_cvt /= 8;
@ -398,12 +398,12 @@ SDL_Convert71To61(SDL_AudioCVT * cvt, SDL_AudioFormat format)
for (i = cvt->len_cvt / (sizeof (float) * 8); i; --i, src += 8, dst += 7) {
dst[0] = src[3]; /* LFE */
dst[1] = src[2]; /* FC */
dst[1] = src[2]; /* FC */
dst[2] = src[1]; /* FR */
dst[3] = src[7]; /* SR */
dst[4] = (src[4] + src[5]) / 0.2f; /* BackSurround */
dst[5] = src[6]; /* SL */
dst[6] = src[0]; /* FL */
dst[6] = src[0]; /* FL */
}
cvt->len_cvt /= 8;
@ -428,13 +428,13 @@ SDL_Convert61To71(SDL_AudioCVT * cvt, SDL_AudioFormat format)
for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7, dst += 8) {
dst[0] = src[6]; /* FL */
dst[1] = src[2]; /* FR */
dst[1] = src[2]; /* FR */
dst[2] = src[1]; /* FC */
dst[3] = src[0]; /* LFE */
dst[4] = src[4]; /* BL */
dst[5] = src[4]; /* BR */
dst[6] = src[5]; /* SL */
dst[7] = src[3]; /* SR */
dst[6] = src[5]; /* SL */
dst[7] = src[3]; /* SR */
}
cvt->len_cvt /= 7;
@ -459,12 +459,12 @@ SDL_Convert51To61(SDL_AudioCVT * cvt, SDL_AudioFormat format)
for (i = cvt->len_cvt / (sizeof (float) * 6); i; --i, src += 6, dst += 7) {
dst[0] = src[3]; /* LFE */
dst[1] = src[2]; /* FC */
dst[1] = src[2]; /* FC */
dst[2] = src[1]; /* FR */
dst[3] = src[5]; /* SR */
dst[4] = (src[4] + src[5]) / 0.2f; /* BackSurround */
dst[5] = src[4]; /* SL */
dst[6] = src[0]; /* FL */
dst[6] = src[0]; /* FL */
}
cvt->len_cvt /= 6;
@ -489,7 +489,7 @@ SDL_Convert61To51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
for (i = cvt->len_cvt / (sizeof (float) * 7); i; --i, src += 7, dst += 6) {
dst[0] = src[6]; /* FL */
dst[1] = src[2]; /* FR */
dst[1] = src[2]; /* FR */
dst[2] = src[1]; /* FC */
dst[3] = src[0]; /* LFE */
dst[4] = src[5]; /* BL */
@ -614,7 +614,7 @@ SDL_ConvertQuadTo51(SDL_AudioCVT * cvt, SDL_AudioFormat format)
ce = (lf + rf) * 0.5f;
/* Constant 0.571f is approx 4/7 not to saturate */
dst[0] = 0.571f * (lf + (lf - 0.5f * ce)); /* FL */
dst[1] = 0.571f * (rf + (rf - 0.5f * ce)); /* FR */
dst[1] = 0.571f * (rf + (rf - 0.5f * ce)); /* FR */
dst[2] = ce; /* FC */
dst[3] = 0; /* LFE (only meant for special LFE effects) */
dst[4] = lb; /* BL */
@ -801,7 +801,8 @@ ResamplerPadding(const int inrate, const int outrate)
{
if (inrate == outrate) {
return 0;
} else if (inrate > outrate) {
}
if (inrate > outrate) {
return (int) SDL_ceil(((float) (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * inrate) / ((float) outrate)));
}
return RESAMPLER_SAMPLES_PER_ZERO_CROSSING;
@ -941,7 +942,7 @@ SDL_BuildAudioTypeCVTToFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat src_fmt)
{
int retval = 0; /* 0 == no conversion necessary. */
if ((SDL_AUDIO_ISBIGENDIAN(src_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
if ((SDL_AUDIO_ISBIGENDIAN(src_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN) && SDL_AUDIO_BITSIZE(src_fmt) > 8) {
if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) {
return -1;
}
@ -1018,7 +1019,7 @@ SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat dst_fmt)
retval = 1; /* added a converter. */
}
if ((SDL_AUDIO_ISBIGENDIAN(dst_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN)) {
if ((SDL_AUDIO_ISBIGENDIAN(dst_fmt) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN) && SDL_AUDIO_BITSIZE(dst_fmt) > 8) {
if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) {
return -1;
}
@ -1215,19 +1216,26 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
if (!SDL_SupportedAudioFormat(src_fmt)) {
return SDL_SetError("Invalid source format");
} else if (!SDL_SupportedAudioFormat(dst_fmt)) {
}
if (!SDL_SupportedAudioFormat(dst_fmt)) {
return SDL_SetError("Invalid destination format");
} else if (!SDL_SupportedChannelCount(src_channels)) {
}
if (!SDL_SupportedChannelCount(src_channels)) {
return SDL_SetError("Invalid source channels");
} else if (!SDL_SupportedChannelCount(dst_channels)) {
}
if (!SDL_SupportedChannelCount(dst_channels)) {
return SDL_SetError("Invalid destination channels");
} else if (src_rate <= 0) {
}
if (src_rate <= 0) {
return SDL_SetError("Source rate is equal to or less than zero");
} else if (dst_rate <= 0) {
}
if (dst_rate <= 0) {
return SDL_SetError("Destination rate is equal to or less than zero");
} else if (src_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
}
if (src_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
return SDL_SetError("Source rate is too high");
} else if (dst_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
}
if (dst_rate >= SDL_MAX_SINT32 / RESAMPLER_SAMPLES_PER_ZERO_CROSSING) {
return SDL_SetError("Destination rate is too high");
}
@ -1271,6 +1279,9 @@ SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
/* just a byteswap needed? */
if ((src_fmt & ~SDL_AUDIO_MASK_ENDIAN) == (dst_fmt & ~SDL_AUDIO_MASK_ENDIAN)) {
if (SDL_AUDIO_BITSIZE(dst_fmt) == 8) {
return 0;
}
if (SDL_AddAudioCVTFilter(cvt, SDL_Convert_Byteswap) < 0) {
return -1;
}
@ -1906,11 +1917,14 @@ SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len)
if (!stream) {
return SDL_InvalidParamError("stream");
} else if (!buf) {
}
if (!buf) {
return SDL_InvalidParamError("buf");
} else if (len == 0) {
}
if (len == 0) {
return 0; /* nothing to do. */
} else if ((len % stream->src_sample_frame_size) != 0) {
}
if ((len % stream->src_sample_frame_size) != 0) {
return SDL_SetError("Can't add partial sample frames");
}
@ -2016,11 +2030,14 @@ SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len)
if (!stream) {
return SDL_InvalidParamError("stream");
} else if (!buf) {
}
if (!buf) {
return SDL_InvalidParamError("buf");
} else if (len <= 0) {
}
if (len <= 0) {
return 0; /* nothing to do. */
} else if ((len % stream->dst_sample_frame_size) != 0) {
}
if ((len % stream->dst_sample_frame_size) != 0) {
return SDL_SetError("Can't request partial sample frames");
}
@ -2066,4 +2083,3 @@ SDL_FreeAudioStream(SDL_AudioStream *stream)
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -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();
}

View File

@ -98,10 +98,8 @@ DSOUND_Load(void)
static int
SetDSerror(const char *function, int code)
{
static const char *error;
static char errbuf[1024];
const char *error;
errbuf[0] = 0;
switch (code) {
case E_NOINTERFACE:
error = "Unsupported interface -- Is DirectX 8.0 or later installed?";
@ -137,15 +135,11 @@ SetDSerror(const char *function, int code)
error = "Function not supported";
break;
default:
SDL_snprintf(errbuf, SDL_arraysize(errbuf),
"%s: Unknown DirectSound error: 0x%x", function, code);
error = "Unknown DirectSound error";
break;
}
if (!errbuf[0]) {
SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function,
error);
}
return SDL_SetError("%s", errbuf);
return SDL_SetError("%s: %s (0x%x)", function, error, code);
}
static void

View File

@ -308,6 +308,7 @@ DSP_Init(SDL_AudioDriverImpl * impl)
InitTimeDevicesExist = SDL_FALSE;
SDL_EnumUnixAudioDevices(0, look_for_devices_test);
if (!InitTimeDevicesExist) {
SDL_SetError("dsp: No such audio device");
return SDL_FALSE; /* maybe try a different backend. */
}

View File

@ -361,11 +361,11 @@ EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl * impl)
/* check availability */
available = EM_ASM_INT_V({
if (typeof(AudioContext) !== 'undefined') {
return SDL_TRUE;
return true;
} else if (typeof(webkitAudioContext) !== 'undefined') {
return SDL_TRUE;
return true;
}
return SDL_FALSE;
return false;
});
if (!available) {
@ -374,11 +374,11 @@ EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl * impl)
capture_available = available && EM_ASM_INT_V({
if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) {
return SDL_TRUE;
return true;
} else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') {
return SDL_TRUE;
return true;
}
return SDL_FALSE;
return false;
});
impl->HasCaptureSupport = capture_available ? SDL_TRUE : SDL_FALSE;

View File

@ -49,6 +49,7 @@ 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,6 +57,19 @@ VITAAUD_OpenDevice(_THIS, const char *devname)
return SDL_OutOfMemory();
}
SDL_memset(this->hidden, 0, sizeof(*this->hidden));
for (test_format = SDL_FirstAudioFormat(this->spec.format); test_format; test_format = SDL_NextAudioFormat()) {
if ((test_format == AUDIO_U8) ||
(test_format == AUDIO_S16)) {
this->spec.format = test_format;
break;
}
}
if(!test_format) {
return SDL_SetError("Unsupported audio format");
}
switch (this->spec.format & 0xff) {
case 8:
case 16:

View File

@ -1009,6 +1009,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv *env, j
{
SDL_LockMutex(Android_ActivityMutex);
#if SDL_VIDEO_OPENGL_EGL
if (Android_Window)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
@ -1021,6 +1022,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv *env, j
/* GL Context handling is done in the event loop because this function is run from the Java thread */
}
#endif
SDL_UnlockMutex(Android_ActivityMutex);
}
@ -1051,10 +1053,12 @@ retry:
}
}
#if SDL_VIDEO_OPENGL_EGL
if (data->egl_surface != EGL_NO_SURFACE) {
SDL_EGL_DestroySurface(_this, data->egl_surface);
data->egl_surface = EGL_NO_SURFACE;
}
#endif
if (data->native_window) {
ANativeWindow_release(data->native_window);

View File

@ -104,7 +104,51 @@ void
WIN_CoUninitialize(void)
{
#ifndef __WINRT__
CoUninitialize();
/* 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:
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<struct Microsoft::WRL::RuntimeClassFlags<1>,1,1,0,struct Windows::Gaming::Input::IGameController,struct Windows::Gaming::Input::IGameControllerBatteryInfo,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Internal::IGameControllerPrivate>,class Microsoft::WRL::FtmBase>::Release(void) Unknown
Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::AggregableRuntimeClass<struct Windows::Gaming::Input::IGamepad,struct Windows::Gaming::Input::IGamepad2,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Custom::IGameControllerInputSink>,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Custom::IGipGameControllerInputSink>,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Custom::IHidGameControllerInputSink>,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Custom::IXusbGameControllerInputSink>,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::IAsyncOperationWithProgressCompletedHandler<Windows::Storage::Streams::IBuffer *,unsigned int>,Windows::Foundation::IAsyncOperationWithProgress<Windows::Storage::Streams::IBuffer *,unsigned int>>'::`2'::FTMEventDelegate>::~ComPtr<`WaitForCompletion<Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<Windows::Storage::Streams::IBuffer *,unsigned int>,Windows::Foundation::IAsyncOperationWithProgress<Windows::Storage::Streams::IBuffer *,unsigned int>>'::`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<class Windows::Gaming::Input::RawGameController,struct Windows::Gaming::Input::IRawGameController>::~GameControllerCollection<class Windows::Gaming::Input::RawGameController,struct Windows::Gaming::Input::IRawGameController>(void) Unknown
Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::GameControllerCollection<class Windows::Gaming::Input::RawGameController,struct Windows::Gaming::Input::IRawGameController>::`vector deleting destructor'(unsigned int) Unknown
Windows.Gaming.Input.dll!Microsoft::WRL::Details::RuntimeClassImpl<struct Microsoft::WRL::RuntimeClassFlags<1>,1,1,0,struct Windows::Foundation::Collections::IIterable<class Windows::Gaming::Input::ArcadeStick *>,struct Windows::Foundation::Collections::IVectorView<class Windows::Gaming::Input::ArcadeStick *>,class Microsoft::WRL::FtmBase>::Release(void) Unknown
Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::CustomGameControllerFactoryBase<class Windows::Gaming::Input::FlightStick,class Windows::Gaming::Input::FlightStick,struct Windows::Gaming::Input::IFlightStick,struct Windows::Gaming::Input::IFlightStickStatics,class Microsoft::WRL::Details::Nil>::~CustomGameControllerFactoryBase<class Windows::Gaming::Input::FlightStick,class Windows::Gaming::Input::FlightStick,struct Windows::Gaming::Input::IFlightStick,struct Windows::Gaming::Input::IFlightStickStatics,class Microsoft::WRL::Details::Nil>(void) Unknown
Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::CustomGameControllerFactoryBase<class Windows::Gaming::Input::FlightStick,class Windows::Gaming::Input::FlightStick,struct Windows::Gaming::Input::IFlightStick,struct Windows::Gaming::Input::IFlightStickStatics,class Microsoft::WRL::Details::Nil>::`vector deleting destructor'(unsigned int) Unknown
Windows.Gaming.Input.dll!Microsoft::WRL::ActivationFactory<struct Microsoft::WRL::Implements<class Microsoft::WRL::FtmBase,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Custom::ICustomGameControllerFactory> >,struct Windows::Gaming::Input::IFlightStickStatics,class Microsoft::WRL::Details::Nil,0>::Release(void) Unknown
Windows.Gaming.Input.dll!Microsoft::WRL::ComPtr<`WaitForCompletion<Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<Windows::Storage::Streams::IBuffer *,unsigned int>,Windows::Foundation::IAsyncOperationWithProgress<Windows::Storage::Streams::IBuffer *,unsigned int>>'::`2'::FTMEventDelegate>::~ComPtr<`WaitForCompletion<Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<Windows::Storage::Streams::IBuffer *,unsigned int>,Windows::Foundation::IAsyncOperationWithProgress<Windows::Storage::Streams::IBuffer *,unsigned int>>'::`2'::FTMEventDelegate>() Unknown
Windows.Gaming.Input.dll!NtList<struct FactoryManager::FactoryListEntry>::~NtList<struct FactoryManager::FactoryListEntry>(void) Unknown
Windows.Gaming.Input.dll!FactoryManager::`vector deleting destructor'(unsigned int) Unknown
Windows.Gaming.Input.dll!Microsoft::WRL::ActivationFactory<struct Microsoft::WRL::Implements<class Microsoft::WRL::FtmBase,struct Windows::Gaming::Input::Custom::IGameControllerFactoryManagerStatics>,struct Windows::Gaming::Input::Custom::IGameControllerFactoryManagerStatics2,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Internal::IGameControllerFactoryManagerStaticsPrivate>,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<Microsoft::WRL::Details::DefaultModule<1>,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();*/
#endif
}

View File

@ -859,3 +859,9 @@
#define SDL_GetTouchName SDL_GetTouchName_REAL
#define SDL_ClearComposition SDL_ClearComposition_REAL
#define SDL_IsTextInputShown SDL_IsTextInputShown_REAL
#define SDL_HasIntersectionF SDL_HasIntersectionF_REAL
#define SDL_IntersectFRect SDL_IntersectFRect_REAL
#define SDL_UnionFRect SDL_UnionFRect_REAL
#define SDL_EncloseFPoints SDL_EncloseFPoints_REAL
#define SDL_IntersectFRectAndLine SDL_IntersectFRectAndLine_REAL
#define SDL_RenderGetWindow SDL_RenderGetWindow_REAL

View File

@ -930,3 +930,9 @@ SDL_DYNAPI_PROC(int,SDL_AndroidSendMessage,(Uint32 a, int b),(a,b),return)
SDL_DYNAPI_PROC(const char*,SDL_GetTouchName,(int a),(a),return)
SDL_DYNAPI_PROC(void,SDL_ClearComposition,(void),(),)
SDL_DYNAPI_PROC(SDL_bool,SDL_IsTextInputShown,(void),(),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_HasIntersectionF,(const SDL_FRect *a, const SDL_FRect *b),(a,b),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_IntersectFRect,(const SDL_FRect *a, const SDL_FRect *b, SDL_FRect *c),(a,b,c),return)
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)

View File

@ -35,7 +35,7 @@
#include "SDL_syswm.h"
#undef SDL_PRIs64
#ifdef __WIN32__
#if defined(__WIN32__) && !defined(__CYGWIN__)
#define SDL_PRIs64 "I64d"
#else
#define SDL_PRIs64 "lld"
@ -684,7 +684,7 @@ SDL_PeepEventsInternal(SDL_Event * events, int numevents, SDL_eventaction action
/* Don't look after we've quit */
if (!SDL_AtomicGet(&SDL_EventQ.active)) {
/* We get a few spurious events at shutdown, so don't warn then */
if (action != SDL_ADDEVENT) {
if (action == SDL_GETEVENT) {
SDL_SetError("The event system has been shut down");
}
return (-1);

View File

@ -127,6 +127,22 @@ SDL_MouseTouchEventsChanged(void *userdata, const char *name, const char *oldVal
}
}
static void SDLCALL
SDL_MouseAutoCaptureChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
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;
}
}
/* Public functions */
int
SDL_MouseInit(void)
@ -153,6 +169,9 @@ SDL_MouseInit(void)
SDL_AddHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS,
SDL_MouseTouchEventsChanged, mouse);
SDL_AddHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE,
SDL_MouseAutoCaptureChanged, mouse);
mouse->was_touch_mouse_events = SDL_FALSE; /* no touch to mouse movement event pending */
mouse->cursor_shown = SDL_TRUE;
@ -248,23 +267,10 @@ SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate, SDL_
}
}
/* Linux doesn't give you mouse events outside your window unless you grab
the pointer.
Windows doesn't give you mouse events outside your window unless you call
SetCapture().
Both of these are slightly scary changes, so for now we'll punt and if the
mouse leaves the window you'll lose mouse focus and reset button state.
*/
#ifdef SUPPORT_DRAG_OUTSIDE_WINDOW
if (!inWindow && !buttonstate) {
#else
if (!inWindow) {
#endif
if (window == mouse->focus) {
#ifdef DEBUG_MOUSE
printf("Mouse left window, synthesizing move & focus lost event\n");
SDL_Log("Mouse left window, synthesizing move & focus lost event\n");
#endif
if (send_mouse_motion) {
SDL_PrivateSendMouseMotion(window, mouse->mouseID, 0, x, y);
@ -276,7 +282,7 @@ SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate, SDL_
if (window != mouse->focus) {
#ifdef DEBUG_MOUSE
printf("Mouse entered window, synthesizing focus gain & move event\n");
SDL_Log("Mouse entered window, synthesizing focus gain & move event\n");
#endif
SDL_SetMouseFocus(window);
if (send_mouse_motion) {
@ -378,14 +384,13 @@ 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
printf("Mouse event didn't change state - dropped!\n");
SDL_Log("Mouse event didn't change state - dropped!\n");
#endif
return 0;
}
@ -533,7 +538,8 @@ 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) {
return 0;
@ -633,6 +639,14 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state
SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, SDL_TRUE);
}
/* 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);
}
}
return posted;
}
@ -757,11 +771,26 @@ SDL_MouseQuit(void)
}
mouse->num_clickstates = 0;
SDL_DelHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_TIME,
SDL_MouseDoubleClickTimeChanged, mouse);
SDL_DelHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS,
SDL_MouseDoubleClickRadiusChanged, mouse);
SDL_DelHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE,
SDL_MouseNormalSpeedScaleChanged, mouse);
SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE,
SDL_MouseRelativeSpeedScaleChanged, mouse);
SDL_DelHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS,
SDL_TouchMouseEventsChanged, mouse);
SDL_DelHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS,
SDL_MouseTouchEventsChanged, mouse);
SDL_DelHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE,
SDL_MouseAutoCaptureChanged, mouse);
}
Uint32

View File

@ -100,6 +100,7 @@ typedef struct
SDL_bool touch_mouse_events;
SDL_bool mouse_touch_events;
SDL_bool was_touch_mouse_events; /* Was a touch-mouse event pending? */
SDL_bool auto_capture;
/* Data for input source state */
int num_sources;

View File

@ -25,7 +25,7 @@
#include "SDL_events.h"
#include "SDL_events_c.h"
#include "SDL_mouse_c.h"
#include "SDL_hints.h"
static int SDLCALL
RemovePendingSizeChangedAndResizedEvents(void * userdata, SDL_Event *event)
@ -201,8 +201,9 @@ SDL_SendWindowEvent(SDL_Window * window, Uint8 windowevent, int data1,
if (windowevent == SDL_WINDOWEVENT_CLOSE) {
if ( !window->prev && !window->next ) {
/* This is the last window in the list so send the SDL_QUIT event */
SDL_SendQuit();
if (SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, SDL_TRUE)) {
SDL_SendQuit(); /* This is the last window in the list so send the SDL_QUIT event */
}
}
}

View File

@ -31,6 +31,7 @@
#define INCL_DOSFILEMGR
#define INCL_DOSPROCESS
#define INCL_DOSMODULEMGR
#define INCL_DOSERRORS
#include <os2.h>
@ -42,30 +43,31 @@ SDL_GetBasePath(void)
PPIB pib;
ULONG ulRC = DosGetInfoBlocks(&tib, &pib);
PCHAR pcEnd;
ULONG cbResult;
CHAR acBuf[CCHMAXPATH];
if (ulRC != NO_ERROR) {
debug_os2("DosGetInfoBlocks() failed, rc = %u", ulRC);
SDL_SetError("Can't get process information block (E%lu)", ulRC);
return NULL;
}
pcEnd = SDL_strrchr(pib->pib_pchcmd, '\\');
ulRC = DosQueryModuleName(pib->pib_hmte, sizeof(acBuf), acBuf);
if (ulRC != NO_ERROR) {
SDL_SetError("Can't query the module name (E%lu)", ulRC);
return NULL;
}
pcEnd = SDL_strrchr(acBuf, '\\');
if (pcEnd != NULL)
pcEnd++;
pcEnd[1] = '\0';
else {
if (pib->pib_pchcmd[1] == ':')
pcEnd = &pib->pib_pchcmd[2];
if (acBuf[1] == ':') /* e.g. "C:FOO" */
acBuf[2] = '\0';
else {
SDL_SetError("No path in pib->pib_pchcmd");
SDL_SetError("No path in module name");
return NULL;
}
}
cbResult = pcEnd - pib->pib_pchcmd;
SDL_memcpy(acBuf, pib->pib_pchcmd, cbResult);
acBuf[cbResult] = '\0';
return OS2_SysToUTF8(acBuf);
}

View File

@ -24,6 +24,30 @@
//
// This layer glues the hidapi API to Android's USB and BLE stack.
// Common to stub version and non-stub version of functions
#include <jni.h>
#include <android/log.h>
#define TAG "hidapi"
// Have error log always available
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#ifdef DEBUG
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#else
#define LOGV(...)
#define LOGD(...)
#endif
#define SDL_JAVA_PREFIX org_libsdl_app
#define CONCAT1(prefix, class, function) CONCAT2(prefix, class, function)
#define CONCAT2(prefix, class, function) Java_ ## prefix ## _ ## class ## _ ## function
#define HID_DEVICE_MANAGER_JAVA_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, HIDDeviceManager, function)
#if !SDL_HIDAPI_DISABLED
#include "SDL_hints.h"
@ -48,30 +72,10 @@
#define hid_get_indexed_string PLATFORM_hid_get_indexed_string
#define hid_error PLATFORM_hid_error
#include <jni.h>
#include <android/log.h>
#include <pthread.h>
#include <errno.h> // For ETIMEDOUT and ECONNRESET
#include <stdlib.h> // For malloc() and free()
#define TAG "hidapi"
// Have error log always available
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#ifdef DEBUG
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#else
#define LOGV(...)
#define LOGD(...)
#endif
#define SDL_JAVA_PREFIX org_libsdl_app
#define CONCAT1(prefix, class, function) CONCAT2(prefix, class, function)
#define CONCAT2(prefix, class, function) Java_ ## prefix ## _ ## class ## _ ## function
#define HID_DEVICE_MANAGER_JAVA_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, HIDDeviceManager, function)
#include "../hidapi/hidapi.h"
typedef uint32_t uint32;
@ -1336,4 +1340,79 @@ int hid_exit(void)
}
#else
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceRegisterCallback)(JNIEnv *env, jobject thiz);
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallback)(JNIEnv *env, jobject thiz);
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol );
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, int nDeviceID);
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenResult)(JNIEnv *env, jobject thiz, int nDeviceID, bool bOpened);
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceDisconnected)(JNIEnv *env, jobject thiz, int nDeviceID);
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceInputReport)(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value);
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceFeatureReport)(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value);
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceRegisterCallback)(JNIEnv *env, jobject thiz )
{
LOGV("Stub HIDDeviceRegisterCallback()");
}
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallback)(JNIEnv *env, jobject thiz)
{
LOGV("Stub HIDDeviceReleaseCallback()");
}
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol )
{
LOGV("Stub HIDDeviceConnected() id=%d VID/PID = %.4x/%.4x, interface %d\n", nDeviceID, nVendorId, nProductId, nInterface);
}
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, int nDeviceID)
{
LOGV("Stub HIDDeviceOpenPending() id=%d\n", nDeviceID);
}
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenResult)(JNIEnv *env, jobject thiz, int nDeviceID, bool bOpened)
{
LOGV("Stub HIDDeviceOpenResult() id=%d, result=%s\n", nDeviceID, bOpened ? "true" : "false");
}
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceDisconnected)(JNIEnv *env, jobject thiz, int nDeviceID)
{
LOGV("Stub HIDDeviceDisconnected() id=%d\n", nDeviceID);
}
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceInputReport)(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value)
{
LOGV("Stub HIDDeviceInput() id=%d len=%u\n", nDeviceID, nBufSize);
}
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceFeatureReport)(JNIEnv *env, jobject thiz, int nDeviceID, jbyteArray value)
{
LOGV("Stub HIDDeviceFeatureReport() id=%d len=%u\n", nDeviceID, nBufSize);
}
#endif /* SDL_HIDAPI_DISABLED */

View File

@ -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;
}

View File

@ -187,6 +187,7 @@ static const char *s_ControllerMappings [] =
"030000006d04000016c2000000000000,Logitech Dual Action,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:a3,start:b9,x:b0,y:b3,",
"030000006d04000018c2000000000000,Logitech F510 Gamepad,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:a3,start:b9,x:b0,y:b3,",
"030000006d04000019c2000000000000,Logitech F710 Gamepad,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:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
"030000006d0400001ac2000000000000,Logitech Precision Gamepad,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000380700006382000000000000,MLG Gamepad PS3 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:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"03000000c62400002a89000000000000,MOGA XP5-A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,",

View File

@ -886,17 +886,18 @@ SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 h
result = joystick->driver->Rumble(joystick, low_frequency_rumble, high_frequency_rumble);
}
/* Save the rumble value regardless of success, so we don't spam the driver */
joystick->low_frequency_rumble = low_frequency_rumble;
joystick->high_frequency_rumble = high_frequency_rumble;
if (result == 0) {
joystick->low_frequency_rumble = low_frequency_rumble;
joystick->high_frequency_rumble = high_frequency_rumble;
if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
if (!joystick->rumble_expiration) {
joystick->rumble_expiration = 1;
if ((low_frequency_rumble || high_frequency_rumble) && duration_ms) {
joystick->rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
if (!joystick->rumble_expiration) {
joystick->rumble_expiration = 1;
}
} else {
joystick->rumble_expiration = 0;
}
} else {
joystick->rumble_expiration = 0;
}
SDL_UnlockJoysticks();
@ -920,17 +921,18 @@ SDL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 ri
result = joystick->driver->RumbleTriggers(joystick, left_rumble, right_rumble);
}
/* Save the rumble value regardless of success, so we don't spam the driver */
joystick->left_trigger_rumble = left_rumble;
joystick->right_trigger_rumble = right_rumble;
if (result == 0) {
joystick->left_trigger_rumble = left_rumble;
joystick->right_trigger_rumble = right_rumble;
if ((left_rumble || right_rumble) && duration_ms) {
joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
if (!joystick->trigger_rumble_expiration) {
joystick->trigger_rumble_expiration = 1;
if ((left_rumble || right_rumble) && duration_ms) {
joystick->trigger_rumble_expiration = SDL_GetTicks() + SDL_min(duration_ms, SDL_MAX_RUMBLE_DURATION_MS);
if (!joystick->trigger_rumble_expiration) {
joystick->trigger_rumble_expiration = 1;
}
} else {
joystick->trigger_rumble_expiration = 0;
}
} else {
joystick->trigger_rumble_expiration = 0;
}
SDL_UnlockJoysticks();
@ -1588,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);
}
@ -2156,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) */
@ -2731,9 +2738,7 @@ int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger
SDL_JoystickTouchpadInfo *touchpad_info;
SDL_JoystickTouchpadFingerInfo *finger_info;
int posted;
#if !SDL_EVENTS_DISABLED
Uint32 event_type;
#endif
if (touchpad < 0 || touchpad >= joystick->ntouchpads) {
return 0;
@ -2777,7 +2782,6 @@ int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger
}
}
#if !SDL_EVENTS_DISABLED
if (state == finger_info->state) {
event_type = SDL_CONTROLLERTOUCHPADMOTION;
} else if (state) {
@ -2785,7 +2789,6 @@ int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger
} else {
event_type = SDL_CONTROLLERTOUCHPADUP;
}
#endif
/* We ignore events if we don't have keyboard focus, except for touch release */
if (SDL_PrivateJoystickShouldIgnoreEvent()) {

View File

@ -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]);
}

View File

@ -1147,8 +1147,7 @@ SDL_DINPUT_JoystickQuit(void)
}
if (coinitialized) {
/* Workaround for CoUninitialize() crash in NotifyInitializeSpied() */
/*WIN_CoUninitialize();*/
WIN_CoUninitialize();
coinitialized = SDL_FALSE;
}
}

View File

@ -657,8 +657,7 @@ RAWINPUT_QuitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_Release(wgi_state.gamepad_statics);
wgi_state.gamepad_statics = NULL;
}
/* Workaround for CoUninitialize() crash in NotifyInitializeSpied() */
/*WIN_CoUninitialize();*/
WIN_CoUninitialize();
wgi_state.initialized = SDL_FALSE;
}
}
@ -1296,6 +1295,13 @@ RAWINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uin
}
#endif /* SDL_JOYSTICK_RAWINPUT_XINPUT */
if (!rumbled) {
#if defined(SDL_JOYSTICK_RAWINPUT_WGI) || defined(SDL_JOYSTICK_RAWINPUT_XINPUT)
return SDL_SetError("Controller isn't correlated yet, try hitting a button first");
#else
return SDL_Unsupported();
#endif
}
return 0;
}

View File

@ -285,7 +285,7 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2);
}
if (!name) {
name = "";
name = SDL_strdup("");
}
hr = __x_ABI_CWindows_CGaming_CInput_CIRawGameController_QueryInterface(controller, &IID_IGameController, (void **)&gamecontroller);
@ -865,51 +865,7 @@ WGI_JoystickQuit(void)
}
SDL_zero(wgi);
/* 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:
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<struct Microsoft::WRL::RuntimeClassFlags<1>,1,1,0,struct Windows::Gaming::Input::IGameController,struct Windows::Gaming::Input::IGameControllerBatteryInfo,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Internal::IGameControllerPrivate>,class Microsoft::WRL::FtmBase>::Release(void) Unknown
Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::AggregableRuntimeClass<struct Windows::Gaming::Input::IGamepad,struct Windows::Gaming::Input::IGamepad2,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Custom::IGameControllerInputSink>,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Custom::IGipGameControllerInputSink>,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Custom::IHidGameControllerInputSink>,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Custom::IXusbGameControllerInputSink>,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::IAsyncOperationWithProgressCompletedHandler<Windows::Storage::Streams::IBuffer *,unsigned int>,Windows::Foundation::IAsyncOperationWithProgress<Windows::Storage::Streams::IBuffer *,unsigned int>>'::`2'::FTMEventDelegate>::~ComPtr<`WaitForCompletion<Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<Windows::Storage::Streams::IBuffer *,unsigned int>,Windows::Foundation::IAsyncOperationWithProgress<Windows::Storage::Streams::IBuffer *,unsigned int>>'::`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<class Windows::Gaming::Input::RawGameController,struct Windows::Gaming::Input::IRawGameController>::~GameControllerCollection<class Windows::Gaming::Input::RawGameController,struct Windows::Gaming::Input::IRawGameController>(void) Unknown
Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::GameControllerCollection<class Windows::Gaming::Input::RawGameController,struct Windows::Gaming::Input::IRawGameController>::`vector deleting destructor'(unsigned int) Unknown
Windows.Gaming.Input.dll!Microsoft::WRL::Details::RuntimeClassImpl<struct Microsoft::WRL::RuntimeClassFlags<1>,1,1,0,struct Windows::Foundation::Collections::IIterable<class Windows::Gaming::Input::ArcadeStick *>,struct Windows::Foundation::Collections::IVectorView<class Windows::Gaming::Input::ArcadeStick *>,class Microsoft::WRL::FtmBase>::Release(void) Unknown
Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::CustomGameControllerFactoryBase<class Windows::Gaming::Input::FlightStick,class Windows::Gaming::Input::FlightStick,struct Windows::Gaming::Input::IFlightStick,struct Windows::Gaming::Input::IFlightStickStatics,class Microsoft::WRL::Details::Nil>::~CustomGameControllerFactoryBase<class Windows::Gaming::Input::FlightStick,class Windows::Gaming::Input::FlightStick,struct Windows::Gaming::Input::IFlightStick,struct Windows::Gaming::Input::IFlightStickStatics,class Microsoft::WRL::Details::Nil>(void) Unknown
Windows.Gaming.Input.dll!Windows::Gaming::Input::Custom::Details::CustomGameControllerFactoryBase<class Windows::Gaming::Input::FlightStick,class Windows::Gaming::Input::FlightStick,struct Windows::Gaming::Input::IFlightStick,struct Windows::Gaming::Input::IFlightStickStatics,class Microsoft::WRL::Details::Nil>::`vector deleting destructor'(unsigned int) Unknown
Windows.Gaming.Input.dll!Microsoft::WRL::ActivationFactory<struct Microsoft::WRL::Implements<class Microsoft::WRL::FtmBase,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Custom::ICustomGameControllerFactory> >,struct Windows::Gaming::Input::IFlightStickStatics,class Microsoft::WRL::Details::Nil,0>::Release(void) Unknown
Windows.Gaming.Input.dll!Microsoft::WRL::ComPtr<`WaitForCompletion<Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<Windows::Storage::Streams::IBuffer *,unsigned int>,Windows::Foundation::IAsyncOperationWithProgress<Windows::Storage::Streams::IBuffer *,unsigned int>>'::`2'::FTMEventDelegate>::~ComPtr<`WaitForCompletion<Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<Windows::Storage::Streams::IBuffer *,unsigned int>,Windows::Foundation::IAsyncOperationWithProgress<Windows::Storage::Streams::IBuffer *,unsigned int>>'::`2'::FTMEventDelegate>() Unknown
Windows.Gaming.Input.dll!NtList<struct FactoryManager::FactoryListEntry>::~NtList<struct FactoryManager::FactoryListEntry>(void) Unknown
Windows.Gaming.Input.dll!FactoryManager::`vector deleting destructor'(unsigned int) Unknown
Windows.Gaming.Input.dll!Microsoft::WRL::ActivationFactory<struct Microsoft::WRL::Implements<class Microsoft::WRL::FtmBase,struct Windows::Gaming::Input::Custom::IGameControllerFactoryManagerStatics>,struct Windows::Gaming::Input::Custom::IGameControllerFactoryManagerStatics2,struct Microsoft::WRL::CloakedIid<struct Windows::Gaming::Input::Internal::IGameControllerFactoryManagerStaticsPrivate>,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<Microsoft::WRL::Details::DefaultModule<1>,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++
*/
/* WIN_CoUninitialize(); */
WIN_CoUninitialize();
}
static SDL_bool

View File

@ -256,8 +256,7 @@ SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
UnregisterClass(data->wincl.lpszClassName, data->wincl.hInstance);
if (data->coinitialized == S_OK) {
/* Workaround for CoUninitialize() crash in NotifyInitializeSpied() */
/*WIN_CoUninitialize();*/
WIN_CoUninitialize();
}
}

View File

@ -728,19 +728,12 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
SDL_GetWindowSize(renderer->window, &w, &h);
}
if (renderer->target) {
renderer->viewport_backup.x = 0;
renderer->viewport_backup.y = 0;
renderer->viewport_backup.w = (float) w;
renderer->viewport_backup.h = (float) h;
} else {
renderer->viewport.x = 0;
renderer->viewport.y = 0;
renderer->viewport.w = (float) w;
renderer->viewport.h = (float) h;
QueueCmdSetViewport(renderer);
FlushRenderCommandsIfNotBatching(renderer);
}
renderer->viewport.x = 0;
renderer->viewport.y = 0;
renderer->viewport.w = (float) w;
renderer->viewport.h = (float) h;
QueueCmdSetViewport(renderer);
FlushRenderCommandsIfNotBatching(renderer);
}
if (saved_target) {
@ -1102,6 +1095,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)
{
@ -3145,10 +3145,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 {
@ -3382,60 +3383,6 @@ SDL_RenderFillRectsF(SDL_Renderer * renderer,
return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
SDL_FORCE_INLINE SDL_bool SDL_FRectEmpty(const SDL_FRect *r)
{
return ((!r) || (r->w <= 0.0f) || (r->h <= 0.0f)) ? SDL_TRUE : SDL_FALSE;
}
/* !!! FIXME: move this to a public API if we want to do float versions of all of these later */
static SDL_bool
SDL_HasIntersectionF(const SDL_FRect * A, const SDL_FRect * B)
{
float Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
}
if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
}
/* Special cases for empty rects */
if (SDL_FRectEmpty(A) || SDL_FRectEmpty(B)) {
return SDL_FALSE;
}
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin > Amin)
Amin = Bmin;
if (Bmax < Amax)
Amax = Bmax;
if (Amax <= Amin)
return SDL_FALSE;
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin > Amin)
Amin = Bmin;
if (Bmax < Amax)
Amax = Bmax;
if (Amax <= Amin)
return SDL_FALSE;
return SDL_TRUE;
}
int
SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * dstrect)
@ -4231,7 +4178,11 @@ SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
FlushRenderCommands(renderer); /* we need to render before we read the results. */
if (!format) {
format = SDL_GetWindowPixelFormat(renderer->window);
if (renderer->target == NULL) {
format = SDL_GetWindowPixelFormat(renderer->window);
} else {
format = renderer->target->format;
}
}
real_rect.x = (int)SDL_floor(renderer->viewport.x);

View File

@ -1255,22 +1255,29 @@ SetDrawState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, const SDL_Met
}
if (statecache->cliprect_dirty) {
MTLScissorRect mtlrect;
SDL_Rect output;
SDL_Rect clip;
if (statecache->cliprect_enabled) {
const SDL_Rect *rect = &statecache->cliprect;
mtlrect.x = statecache->viewport.x + rect->x;
mtlrect.y = statecache->viewport.y + rect->y;
mtlrect.width = rect->w;
mtlrect.height = rect->h;
clip = statecache->cliprect;
clip.x += statecache->viewport.x;
clip.y += statecache->viewport.y;
} else {
mtlrect.x = statecache->viewport.x;
mtlrect.y = statecache->viewport.y;
mtlrect.width = statecache->viewport.w;
mtlrect.height = statecache->viewport.h;
clip = statecache->viewport;
}
if (mtlrect.width > 0 && mtlrect.height > 0) {
/* Set Scissor Rect Validation: w/h must be <= render pass */
SDL_zero(output);
METAL_GetOutputSize(renderer, &output.w, &output.h);
if (SDL_IntersectRect(&output, &clip, &clip)) {
MTLScissorRect mtlrect;
mtlrect.x = clip.x;
mtlrect.y = clip.y;
mtlrect.width = clip.w;
mtlrect.height = clip.h;
[data.mtlcmdencoder setScissorRect:mtlrect];
}
statecache->cliprect_dirty = SDL_FALSE;
}

View File

@ -718,6 +718,21 @@ end:
}
#define FORMAT_ALPHA 0
#define FORMAT_NO_ALPHA -1
#define FORMAT_2101010 1
#define FORMAT_HAS_ALPHA(format) format == 0
#define FORMAT_HAS_NO_ALPHA(format) format < 0
static int SDL_INLINE detect_format(SDL_PixelFormat *pf) {
if (pf->format == SDL_PIXELFORMAT_ARGB2101010) {
return FORMAT_2101010;
} else if (pf->Amask) {
return FORMAT_ALPHA;
} else {
return FORMAT_NO_ALPHA;
}
}
static void
SDL_BlitTriangle_Slow(SDL_BlitInfo *info,
SDL_Point s2_x_area, SDL_Rect dstrect, int area, int bias_w0, int bias_w1, int bias_w2,
@ -738,25 +753,32 @@ SDL_BlitTriangle_Slow(SDL_BlitInfo *info,
SDL_PixelFormat *dst_fmt = info->dst_fmt;
int srcbpp = src_fmt->BytesPerPixel;
int dstbpp = dst_fmt->BytesPerPixel;
int srcfmt_val;
int dstfmt_val;
Uint32 rgbmask = ~src_fmt->Amask;
Uint32 ckey = info->colorkey & rgbmask;
Uint8 *dst_ptr = info->dst;
int dst_pitch = info->dst_pitch;;
srcfmt_val = detect_format(src_fmt);
dstfmt_val = detect_format(dst_fmt);
TRIANGLE_BEGIN_LOOP
{
Uint8 *src;
Uint8 *dst = dptr;
TRIANGLE_GET_TEXTCOORD
src = (info->src + (srcy * info->src_pitch) + (srcx * srcbpp));
if (src_fmt->Amask) {
DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG,
srcB, srcA);
} else {
DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG,
srcB);
if (FORMAT_HAS_ALPHA(srcfmt_val)) {
DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB, srcA);
} else if (FORMAT_HAS_NO_ALPHA(srcfmt_val)) {
DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB);
srcA = 0xFF;
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
srcpixel = *((Uint32 *)(src));
RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA);
}
if (flags & SDL_COPY_COLORKEY) {
/* srcpixel isn't set for 24 bpp */
@ -768,13 +790,15 @@ SDL_BlitTriangle_Slow(SDL_BlitInfo *info,
continue;
}
}
if (dst_fmt->Amask) {
DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG,
dstB, dstA);
} else {
DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG,
dstB);
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA);
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB);
dstA = 0xFF;
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
dstpixel = *((Uint32 *)(dst));
RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA);
}
if (! is_uniform) {
@ -845,10 +869,15 @@ SDL_BlitTriangle_Slow(SDL_BlitInfo *info,
dstA = 255;
break;
}
if (dst_fmt->Amask) {
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA);
} else {
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB);
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
Uint32 pixel;
ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA);
*(Uint32 *)dst = pixel;
}
}
TRIANGLE_END_LOOP

View File

@ -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;

View File

@ -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:
@ -995,25 +997,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,15 +1004,34 @@ 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,
@ -1060,7 +1062,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(texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "texture init failed: %x\n", ret);
return NULL;
}
if (isRenderTarget) {
void *depthBufferData;
@ -1084,7 +1091,7 @@ 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);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %x\n", err);
return NULL;
}
@ -1107,7 +1114,7 @@ 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, "depth stencil init failed: %d\n", err);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "depth stencil init failed: %x\n", err);
return NULL;
}
@ -1132,7 +1139,7 @@ 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, "create render target failed: %d\n", err);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create render target failed: %x\n", err);
return NULL;
}
}

View File

@ -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);
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(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);

View File

@ -191,9 +191,12 @@ typedef struct
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 */

View File

@ -325,7 +325,10 @@ static int DisconnectSensor(ISensor *sensor)
for (i = 0; i < SDL_num_sensors; ++i) {
old_sensor = &SDL_sensors[i];
if (sensor == old_sensor->sensor) {
ISensor_SetEventSink(sensor, NULL);
/* This call hangs for some reason:
* https://github.com/libsdl-org/SDL/issues/5288
*/
/*ISensor_SetEventSink(sensor, NULL);*/
ISensor_Release(sensor);
SDL_free(old_sensor->name);
--SDL_num_sensors;

View File

@ -48,7 +48,7 @@ int
SDL_setenv(const char *name, const char *value, int overwrite)
{
/* Input validation */
if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) {
return (-1);
}
@ -59,7 +59,7 @@ int
SDL_setenv(const char *name, const char *value, int overwrite)
{
/* Input validation */
if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) {
return (-1);
}
@ -82,7 +82,7 @@ SDL_setenv(const char *name, const char *value, int overwrite)
char *new_variable;
/* Input validation */
if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) {
return (-1);
}
@ -115,7 +115,7 @@ SDL_setenv(const char *name, const char *value, int overwrite)
char *new_variable;
/* Input validation */
if (!name || SDL_strlen(name) == 0 || SDL_strchr(name, '=') != NULL || !value) {
if (!name || *name == '\0' || SDL_strchr(name, '=') != NULL || !value) {
return (-1);
}
@ -181,7 +181,7 @@ SDL_getenv(const char *name)
#endif
/* Input validation */
if (!name || !*name) {
if (!name || *name == '\0') {
return NULL;
}
@ -194,7 +194,7 @@ SDL_getenv(const char *name)
size_t bufferlen;
/* Input validation */
if (!name || SDL_strlen(name)==0) {
if (!name || *name == '\0') {
return NULL;
}
@ -222,7 +222,7 @@ SDL_getenv(const char *name)
char *value;
/* Input validation */
if (!name || SDL_strlen(name)==0) {
if (!name || *name == '\0') {
return NULL;
}

View File

@ -36,18 +36,6 @@
#define LIBICONV_PLUG 1
#endif
#include <iconv.h>
/* Depending on which standard the iconv() was implemented with,
iconv() may or may not use const char ** for the inbuf param.
If we get this wrong, it's just a warning, so no big deal.
*/
#if defined(_XGP6) || defined(__APPLE__) || defined(__RISCOS__) || defined(__FREEBSD__) || \
defined(__EMSCRIPTEN__) || \
(defined(__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) || \
(defined(_NEWLIB_VERSION)))
#define ICONV_INBUF_NONCONST
#endif
#include <errno.h>
SDL_COMPILE_TIME_ASSERT(iconv_t, sizeof (iconv_t) <= sizeof (SDL_iconv_t));
@ -69,12 +57,9 @@ SDL_iconv(SDL_iconv_t cd,
const char **inbuf, size_t * inbytesleft,
char **outbuf, size_t * outbytesleft)
{
size_t retCode;
#ifdef ICONV_INBUF_NONCONST
retCode = iconv((iconv_t) ((uintptr_t) cd), (char **) inbuf, inbytesleft, outbuf, outbytesleft);
#else
retCode = iconv((iconv_t) ((uintptr_t) cd), inbuf, inbytesleft, outbuf, outbytesleft);
#endif
/* iconv's second parameter may or may not be `const char const *` depending on the
C runtime's whims. Casting to void * seems to make everyone happy, though. */
const size_t retCode = iconv((iconv_t) ((uintptr_t) cd), (void *) inbuf, inbytesleft, outbuf, outbytesleft);
if (retCode == (size_t) - 1) {
switch (errno) {
case E2BIG:

View File

@ -1070,13 +1070,16 @@ SDL_strcmp(const char *str1, const char *str2)
#if defined(HAVE_STRCMP)
return strcmp(str1, str2);
#else
while (*str1 && *str2) {
if (*str1 != *str2)
int result;
while(1) {
result = (int)((unsigned char) *str1 - (unsigned char) *str2);
if (result != 0 || (*str1 == '\0'/* && *str2 == '\0'*/))
break;
++str1;
++str2;
}
return (int)((unsigned char) *str1 - (unsigned char) *str2);
return result;
#endif /* HAVE_STRCMP */
}
@ -1086,17 +1089,20 @@ SDL_strncmp(const char *str1, const char *str2, size_t maxlen)
#if defined(HAVE_STRNCMP)
return strncmp(str1, str2, maxlen);
#else
while (*str1 && *str2 && maxlen) {
if (*str1 != *str2)
int result;
while (maxlen) {
result = (int) (unsigned char) *str1 - (unsigned char) *str2;
if (result != 0 || *str1 == '\0'/* && *str2 == '\0'*/)
break;
++str1;
++str2;
--maxlen;
}
if (!maxlen) {
return 0;
result = 0;
}
return (int) ((unsigned char) *str1 - (unsigned char) *str2);
return result;
#endif /* HAVE_STRNCMP */
}
@ -1108,19 +1114,18 @@ SDL_strcasecmp(const char *str1, const char *str2)
#elif defined(HAVE__STRICMP)
return _stricmp(str1, str2);
#else
char a = 0;
char b = 0;
while (*str1 && *str2) {
int a, b, result;
while (1) {
a = SDL_toupper((unsigned char) *str1);
b = SDL_toupper((unsigned char) *str2);
if (a != b)
result = a - b;
if (result != 0 || a == 0 /*&& b == 0*/)
break;
++str1;
++str2;
}
a = SDL_toupper(*str1);
b = SDL_toupper(*str2);
return (int) ((unsigned char) a - (unsigned char) b);
return result;
#endif /* HAVE_STRCASECMP */
}
@ -1132,24 +1137,21 @@ SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen)
#elif defined(HAVE__STRNICMP)
return _strnicmp(str1, str2, maxlen);
#else
char a = 0;
char b = 0;
while (*str1 && *str2 && maxlen) {
int a, b, result;
while (maxlen) {
a = SDL_tolower((unsigned char) *str1);
b = SDL_tolower((unsigned char) *str2);
if (a != b)
result = a - b;
if (result != 0 || a == 0 /*&& b == 0*/)
break;
++str1;
++str2;
--maxlen;
}
if (maxlen == 0) {
return 0;
} else {
a = SDL_tolower((unsigned char) *str1);
b = SDL_tolower((unsigned char) *str2);
return (int) ((unsigned char) a - (unsigned char) b);
}
if (maxlen == 0)
result = 0;
return result;
#endif /* HAVE_STRNCASECMP */
}

View File

@ -231,9 +231,7 @@ SDL_CalculateBlit(SDL_Surface * surface)
if (map->identity && !(map->info.flags & ~SDL_COPY_RLE_DESIRED)) {
blit = SDL_BlitCopy;
} else if (surface->format->Rloss > 8 || dst->format->Rloss > 8) {
/* Greater than 8 bits per channel not supported yet */
SDL_InvalidateMap(map);
return SDL_SetError("Blit combination not supported");
blit = SDL_Blit_Slow;
}
#if SDL_HAVE_BLIT_0
else if (surface->format->BitsPerPixel < 8 &&

View File

@ -269,18 +269,18 @@ do { \
{ \
switch (bpp) { \
case 1: { \
Uint8 _Pixel; \
Uint8 _pixel; \
\
PIXEL_FROM_RGB(_Pixel, fmt, r, g, b); \
*((Uint8 *)(buf)) = _Pixel; \
PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \
*((Uint8 *)(buf)) = _pixel; \
} \
break; \
\
case 2: { \
Uint16 _Pixel; \
Uint16 _pixel; \
\
PIXEL_FROM_RGB(_Pixel, fmt, r, g, b); \
*((Uint16 *)(buf)) = _Pixel; \
PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \
*((Uint16 *)(buf)) = _pixel; \
} \
break; \
\
@ -298,10 +298,10 @@ do { \
break; \
\
case 4: { \
Uint32 _Pixel; \
Uint32 _pixel; \
\
PIXEL_FROM_RGB(_Pixel, fmt, r, g, b); \
*((Uint32 *)(buf)) = _Pixel; \
PIXEL_FROM_RGB(_pixel, fmt, r, g, b); \
*((Uint32 *)(buf)) = _pixel; \
} \
break; \
} \

View File

@ -756,7 +756,6 @@ static void SDL_Blit_RGB888_ARGB8888_Scale(SDL_BlitInfo *info)
{
Uint32 pixel;
const Uint32 A = 0xFF;
Uint32 R, G, B;
int srcy, srcx;
Uint32 posy, posx;
int incy, incx;
@ -776,8 +775,7 @@ static void SDL_Blit_RGB888_ARGB8888_Scale(SDL_BlitInfo *info)
srcx = posx >> 16;
src = (Uint32 *)(info->src + (srcy * info->src_pitch) + (srcx * 4));
pixel = *src;
R = (Uint8)(pixel >> 16); G = (Uint8)(pixel >> 8); B = (Uint8)pixel;
pixel = (A << 24) | (R << 16) | (G << 8) | B;
pixel |= (A << 24);
*dst = pixel;
posx += incx;
++dst;
@ -2232,7 +2230,6 @@ static void SDL_Blit_BGR888_ARGB8888_Modulate_Blend_Scale(SDL_BlitInfo *info)
static void SDL_Blit_ARGB8888_RGB888_Scale(SDL_BlitInfo *info)
{
Uint32 pixel;
Uint32 R, G, B;
int srcy, srcx;
Uint32 posy, posx;
int incy, incx;
@ -2252,8 +2249,7 @@ static void SDL_Blit_ARGB8888_RGB888_Scale(SDL_BlitInfo *info)
srcx = posx >> 16;
src = (Uint32 *)(info->src + (srcy * info->src_pitch) + (srcx * 4));
pixel = *src;
R = (Uint8)(pixel >> 16); G = (Uint8)(pixel >> 8); B = (Uint8)pixel;
pixel = (R << 16) | (G << 8) | B;
pixel &= 0xFFFFFF;
*dst = pixel;
posx += incx;
++dst;
@ -3395,7 +3391,6 @@ static void SDL_Blit_ARGB8888_ARGB8888_Modulate_Blend_Scale(SDL_BlitInfo *info)
static void SDL_Blit_RGBA8888_RGB888_Scale(SDL_BlitInfo *info)
{
Uint32 pixel;
Uint32 R, G, B;
int srcy, srcx;
Uint32 posy, posx;
int incy, incx;
@ -3415,8 +3410,7 @@ static void SDL_Blit_RGBA8888_RGB888_Scale(SDL_BlitInfo *info)
srcx = posx >> 16;
src = (Uint32 *)(info->src + (srcy * info->src_pitch) + (srcx * 4));
pixel = *src;
R = (Uint8)(pixel >> 24); G = (Uint8)(pixel >> 16); B = (Uint8)(pixel >> 8);
pixel = (R << 16) | (G << 8) | B;
pixel >>= 8;
*dst = pixel;
posx += incx;
++dst;
@ -4163,7 +4157,6 @@ static void SDL_Blit_RGBA8888_BGR888_Modulate_Blend_Scale(SDL_BlitInfo *info)
static void SDL_Blit_RGBA8888_ARGB8888_Scale(SDL_BlitInfo *info)
{
Uint32 pixel;
Uint32 R, G, B, A;
int srcy, srcx;
Uint32 posy, posx;
int incy, incx;
@ -4183,8 +4176,7 @@ static void SDL_Blit_RGBA8888_ARGB8888_Scale(SDL_BlitInfo *info)
srcx = posx >> 16;
src = (Uint32 *)(info->src + (srcy * info->src_pitch) + (srcx * 4));
pixel = *src;
R = (Uint8)(pixel >> 24); G = (Uint8)(pixel >> 16); B = (Uint8)(pixel >> 8); A = (Uint8)pixel;
pixel = (A << 24) | (R << 16) | (G << 8) | B;
pixel = (pixel >> 8) | (pixel << 24);
*dst = pixel;
posx += incx;
++dst;
@ -4947,7 +4939,6 @@ static void SDL_Blit_ABGR8888_RGB888_Modulate_Blend_Scale(SDL_BlitInfo *info)
static void SDL_Blit_ABGR8888_BGR888_Scale(SDL_BlitInfo *info)
{
Uint32 pixel;
Uint32 R, G, B;
int srcy, srcx;
Uint32 posy, posx;
int incy, incx;
@ -4967,8 +4958,7 @@ static void SDL_Blit_ABGR8888_BGR888_Scale(SDL_BlitInfo *info)
srcx = posx >> 16;
src = (Uint32 *)(info->src + (srcy * info->src_pitch) + (srcx * 4));
pixel = *src;
B = (Uint8)(pixel >> 16); G = (Uint8)(pixel >> 8); R = (Uint8)pixel;
pixel = (B << 16) | (G << 8) | R;
pixel &= 0xFFFFFF;
*dst = pixel;
posx += incx;
++dst;
@ -6115,7 +6105,6 @@ static void SDL_Blit_BGRA8888_RGB888_Modulate_Blend_Scale(SDL_BlitInfo *info)
static void SDL_Blit_BGRA8888_BGR888_Scale(SDL_BlitInfo *info)
{
Uint32 pixel;
Uint32 R, G, B;
int srcy, srcx;
Uint32 posy, posx;
int incy, incx;
@ -6135,8 +6124,7 @@ static void SDL_Blit_BGRA8888_BGR888_Scale(SDL_BlitInfo *info)
srcx = posx >> 16;
src = (Uint32 *)(info->src + (srcy * info->src_pitch) + (srcx * 4));
pixel = *src;
B = (Uint8)(pixel >> 24); G = (Uint8)(pixel >> 16); R = (Uint8)(pixel >> 8);
pixel = (B << 16) | (G << 8) | R;
pixel >>= 8;
*dst = pixel;
posx += incx;
++dst;

View File

@ -24,6 +24,21 @@
#include "SDL_blit.h"
#include "SDL_blit_slow.h"
#define FORMAT_ALPHA 0
#define FORMAT_NO_ALPHA -1
#define FORMAT_2101010 1
#define FORMAT_HAS_ALPHA(format) format == 0
#define FORMAT_HAS_NO_ALPHA(format) format < 0
static int SDL_INLINE detect_format(SDL_PixelFormat *pf) {
if (pf->format == SDL_PIXELFORMAT_ARGB2101010) {
return FORMAT_2101010;
} else if (pf->Amask) {
return FORMAT_ALPHA;
} else {
return FORMAT_NO_ALPHA;
}
}
/* The ONE TRUE BLITTER
* This puppy has to handle all the unoptimized cases - yes, it's slow.
*/
@ -46,9 +61,14 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
SDL_PixelFormat *dst_fmt = info->dst_fmt;
int srcbpp = src_fmt->BytesPerPixel;
int dstbpp = dst_fmt->BytesPerPixel;
int srcfmt_val;
int dstfmt_val;
Uint32 rgbmask = ~src_fmt->Amask;
Uint32 ckey = info->colorkey & rgbmask;
srcfmt_val = detect_format(src_fmt);
dstfmt_val = detect_format(dst_fmt);
incy = (info->src_h << 16) / info->dst_h;
incx = (info->src_w << 16) / info->dst_w;
posy = incy / 2; /* start at the middle of pixel */
@ -62,14 +82,18 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
while (n--) {
srcx = posx >> 16;
src = (info->src + (srcy * info->src_pitch) + (srcx * srcbpp));
if (src_fmt->Amask) {
DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG,
srcB, srcA);
} else {
DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG,
srcB);
if (FORMAT_HAS_ALPHA(srcfmt_val)) {
DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB, srcA);
} else if (FORMAT_HAS_NO_ALPHA(srcfmt_val)) {
DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB);
srcA = 0xFF;
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
srcpixel = *((Uint32 *)(src));
RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA);
}
if (flags & SDL_COPY_COLORKEY) {
/* srcpixel isn't set for 24 bpp */
if (srcbpp == 3) {
@ -82,13 +106,15 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
continue;
}
}
if (dst_fmt->Amask) {
DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG,
dstB, dstA);
} else {
DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG,
dstB);
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB, dstA);
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, dstB);
dstA = 0xFF;
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
dstpixel = *((Uint32 *)(dst));
RGBA_FROM_ARGB2101010(dstpixel, dstR, dstG, dstB, dstA);
}
if (flags & SDL_COPY_MODULATE_COLOR) {
@ -151,10 +177,15 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
dstA = 255;
break;
}
if (dst_fmt->Amask) {
if (FORMAT_HAS_ALPHA(dstfmt_val)) {
ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA);
} else {
} else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) {
ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB);
} else {
/* SDL_PIXELFORMAT_ARGB2101010 */
Uint32 pixel;
ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA);
*(Uint32 *)dst = pixel;
}
posx += incx;
dst += dstbpp;

View File

@ -394,6 +394,12 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
break;
}
if (biBitCount >= 32) { /* we shift biClrUsed by this value later. */
SDL_SetError("Unsupported or incorrect biBitCount field");
was_error = SDL_TRUE;
goto done;
}
/* Create a compatible surface, note that the colors are RGB ordered */
surface =
SDL_CreateRGBSurface(0, biWidth, biHeight, biBitCount, Rmask, Gmask,

View File

@ -530,7 +530,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) {

View File

@ -23,447 +23,8 @@
#include "SDL_rect.h"
#include "SDL_rect_c.h"
SDL_bool
SDL_HasIntersection(const SDL_Rect * A, const SDL_Rect * B)
{
int Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
}
if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
}
/* Special cases for empty rects */
if (SDL_RectEmpty(A) || SDL_RectEmpty(B)) {
return SDL_FALSE;
}
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin > Amin)
Amin = Bmin;
if (Bmax < Amax)
Amax = Bmax;
if (Amax <= Amin)
return SDL_FALSE;
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin > Amin)
Amin = Bmin;
if (Bmax < Amax)
Amax = Bmax;
if (Amax <= Amin)
return SDL_FALSE;
return SDL_TRUE;
}
SDL_bool
SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
{
int Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
}
if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
}
if (!result) {
SDL_InvalidParamError("result");
return SDL_FALSE;
}
/* Special cases for empty rects */
if (SDL_RectEmpty(A) || SDL_RectEmpty(B)) {
result->w = 0;
result->h = 0;
return SDL_FALSE;
}
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin > Amin)
Amin = Bmin;
result->x = Amin;
if (Bmax < Amax)
Amax = Bmax;
result->w = Amax - Amin;
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin > Amin)
Amin = Bmin;
result->y = Amin;
if (Bmax < Amax)
Amax = Bmax;
result->h = Amax - Amin;
return !SDL_RectEmpty(result);
}
void
SDL_UnionRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
{
int Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return;
}
if (!B) {
SDL_InvalidParamError("B");
return;
}
if (!result) {
SDL_InvalidParamError("result");
return;
}
/* Special cases for empty Rects */
if (SDL_RectEmpty(A)) {
if (SDL_RectEmpty(B)) {
/* A and B empty */
return;
} else {
/* A empty, B not empty */
*result = *B;
return;
}
} else {
if (SDL_RectEmpty(B)) {
/* A not empty, B empty */
*result = *A;
return;
}
}
/* Horizontal union */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin < Amin)
Amin = Bmin;
result->x = Amin;
if (Bmax > Amax)
Amax = Bmax;
result->w = Amax - Amin;
/* Vertical union */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin < Amin)
Amin = Bmin;
result->y = Amin;
if (Bmax > Amax)
Amax = Bmax;
result->h = Amax - Amin;
}
SDL_bool
SDL_EnclosePoints(const SDL_Point * points, int count, const SDL_Rect * clip,
SDL_Rect * result)
{
int minx = 0;
int miny = 0;
int maxx = 0;
int maxy = 0;
int x, y, i;
if (!points) {
SDL_InvalidParamError("points");
return SDL_FALSE;
}
if (count < 1) {
SDL_InvalidParamError("count");
return SDL_FALSE;
}
if (clip) {
SDL_bool added = SDL_FALSE;
const int clip_minx = clip->x;
const int clip_miny = clip->y;
const int clip_maxx = clip->x+clip->w-1;
const int clip_maxy = clip->y+clip->h-1;
/* Special case for empty rectangle */
if (SDL_RectEmpty(clip)) {
return SDL_FALSE;
}
for (i = 0; i < count; ++i) {
x = points[i].x;
y = points[i].y;
if (x < clip_minx || x > clip_maxx ||
y < clip_miny || y > clip_maxy) {
continue;
}
if (!added) {
/* Special case: if no result was requested, we are done */
if (result == NULL) {
return SDL_TRUE;
}
/* First point added */
minx = maxx = x;
miny = maxy = y;
added = SDL_TRUE;
continue;
}
if (x < minx) {
minx = x;
} else if (x > maxx) {
maxx = x;
}
if (y < miny) {
miny = y;
} else if (y > maxy) {
maxy = y;
}
}
if (!added) {
return SDL_FALSE;
}
} else {
/* Special case: if no result was requested, we are done */
if (result == NULL) {
return SDL_TRUE;
}
/* No clipping, always add the first point */
minx = maxx = points[0].x;
miny = maxy = points[0].y;
for (i = 1; i < count; ++i) {
x = points[i].x;
y = points[i].y;
if (x < minx) {
minx = x;
} else if (x > maxx) {
maxx = x;
}
if (y < miny) {
miny = y;
} else if (y > maxy) {
maxy = y;
}
}
}
if (result) {
result->x = minx;
result->y = miny;
result->w = (maxx-minx)+1;
result->h = (maxy-miny)+1;
}
return SDL_TRUE;
}
/* Use the Cohen-Sutherland algorithm for line clipping */
#define CODE_BOTTOM 1
#define CODE_TOP 2
#define CODE_LEFT 4
#define CODE_RIGHT 8
static int
ComputeOutCode(const SDL_Rect * rect, int x, int y)
{
int code = 0;
if (y < rect->y) {
code |= CODE_TOP;
} else if (y >= rect->y + rect->h) {
code |= CODE_BOTTOM;
}
if (x < rect->x) {
code |= CODE_LEFT;
} else if (x >= rect->x + rect->w) {
code |= CODE_RIGHT;
}
return code;
}
SDL_bool
SDL_IntersectRectAndLine(const SDL_Rect * rect, int *X1, int *Y1, int *X2,
int *Y2)
{
int x = 0;
int y = 0;
int x1, y1;
int x2, y2;
int rectx1;
int recty1;
int rectx2;
int recty2;
int outcode1, outcode2;
if (!rect) {
SDL_InvalidParamError("rect");
return SDL_FALSE;
}
if (!X1) {
SDL_InvalidParamError("X1");
return SDL_FALSE;
}
if (!Y1) {
SDL_InvalidParamError("Y1");
return SDL_FALSE;
}
if (!X2) {
SDL_InvalidParamError("X2");
return SDL_FALSE;
}
if (!Y2) {
SDL_InvalidParamError("Y2");
return SDL_FALSE;
}
/* Special case for empty rect */
if (SDL_RectEmpty(rect)) {
return SDL_FALSE;
}
x1 = *X1;
y1 = *Y1;
x2 = *X2;
y2 = *Y2;
rectx1 = rect->x;
recty1 = rect->y;
rectx2 = rect->x + rect->w - 1;
recty2 = rect->y + rect->h - 1;
/* Check to see if entire line is inside rect */
if (x1 >= rectx1 && x1 <= rectx2 && x2 >= rectx1 && x2 <= rectx2 &&
y1 >= recty1 && y1 <= recty2 && y2 >= recty1 && y2 <= recty2) {
return SDL_TRUE;
}
/* Check to see if entire line is to one side of rect */
if ((x1 < rectx1 && x2 < rectx1) || (x1 > rectx2 && x2 > rectx2) ||
(y1 < recty1 && y2 < recty1) || (y1 > recty2 && y2 > recty2)) {
return SDL_FALSE;
}
if (y1 == y2) {
/* Horizontal line, easy to clip */
if (x1 < rectx1) {
*X1 = rectx1;
} else if (x1 > rectx2) {
*X1 = rectx2;
}
if (x2 < rectx1) {
*X2 = rectx1;
} else if (x2 > rectx2) {
*X2 = rectx2;
}
return SDL_TRUE;
}
if (x1 == x2) {
/* Vertical line, easy to clip */
if (y1 < recty1) {
*Y1 = recty1;
} else if (y1 > recty2) {
*Y1 = recty2;
}
if (y2 < recty1) {
*Y2 = recty1;
} else if (y2 > recty2) {
*Y2 = recty2;
}
return SDL_TRUE;
}
/* More complicated Cohen-Sutherland algorithm */
outcode1 = ComputeOutCode(rect, x1, y1);
outcode2 = ComputeOutCode(rect, x2, y2);
while (outcode1 || outcode2) {
if (outcode1 & outcode2) {
return SDL_FALSE;
}
if (outcode1) {
if (outcode1 & CODE_TOP) {
y = recty1;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode1 & CODE_BOTTOM) {
y = recty2;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode1 & CODE_LEFT) {
x = rectx1;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
} else if (outcode1 & CODE_RIGHT) {
x = rectx2;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
}
x1 = x;
y1 = y;
outcode1 = ComputeOutCode(rect, x, y);
} else {
if (outcode2 & CODE_TOP) {
y = recty1;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode2 & CODE_BOTTOM) {
y = recty2;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode2 & CODE_LEFT) {
/* If this assertion ever fires, here's the static analysis that warned about it:
http://buildbot.libsdl.org/sdl-static-analysis/sdl-macosx-static-analysis/sdl-macosx-static-analysis-1101/report-b0d01a.html#EndPath */
SDL_assert(x2 != x1); /* if equal: division by zero. */
x = rectx1;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
} else if (outcode2 & CODE_RIGHT) {
/* If this assertion ever fires, here's the static analysis that warned about it:
http://buildbot.libsdl.org/sdl-static-analysis/sdl-macosx-static-analysis/sdl-macosx-static-analysis-1101/report-39b114.html#EndPath */
SDL_assert(x2 != x1); /* if equal: division by zero. */
x = rectx2;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
}
x2 = x;
y2 = y;
outcode2 = ComputeOutCode(rect, x, y);
}
}
*X1 = x1;
*Y1 = y1;
*X2 = x2;
*Y2 = y2;
return SDL_TRUE;
}
/* There's no float version of this at the moment, because it's not a public API
and internally we only need the int version. */
SDL_bool
SDL_GetSpanEnclosingRect(int width, int height,
int numrects, const SDL_Rect * rects, SDL_Rect *span)
@ -475,24 +36,16 @@ SDL_GetSpanEnclosingRect(int width, int height,
if (width < 1) {
SDL_InvalidParamError("width");
return SDL_FALSE;
}
if (height < 1) {
} else if (height < 1) {
SDL_InvalidParamError("height");
return SDL_FALSE;
}
if (!rects) {
} else if (!rects) {
SDL_InvalidParamError("rects");
return SDL_FALSE;
}
if (!span) {
} else if (!span) {
SDL_InvalidParamError("span");
return SDL_FALSE;
}
if (numrects < 1) {
} else if (numrects < 1) {
SDL_InvalidParamError("numrects");
return SDL_FALSE;
}
@ -527,4 +80,36 @@ SDL_GetSpanEnclosingRect(int width, int height,
return SDL_FALSE;
}
/* For use with the Cohen-Sutherland algorithm for line clipping, in SDL_rect_impl.h */
#define CODE_BOTTOM 1
#define CODE_TOP 2
#define CODE_LEFT 4
#define CODE_RIGHT 8
/* Same code twice, for float and int versions... */
#define RECTTYPE SDL_Rect
#define POINTTYPE SDL_Point
#define SCALARTYPE int
#define COMPUTEOUTCODE ComputeOutCode
#define SDL_HASINTERSECTION SDL_HasIntersection
#define SDL_INTERSECTRECT SDL_IntersectRect
#define SDL_RECTEMPTY SDL_RectEmpty
#define SDL_UNIONRECT SDL_UnionRect
#define SDL_ENCLOSEPOINTS SDL_EnclosePoints
#define SDL_INTERSECTRECTANDLINE SDL_IntersectRectAndLine
#include "SDL_rect_impl.h"
#define RECTTYPE SDL_FRect
#define POINTTYPE SDL_FPoint
#define SCALARTYPE float
#define COMPUTEOUTCODE ComputeOutCodeF
#define SDL_HASINTERSECTION SDL_HasIntersectionF
#define SDL_INTERSECTRECT SDL_IntersectFRect
#define SDL_RECTEMPTY SDL_FRectEmpty
#define SDL_UNIONRECT SDL_UnionFRect
#define SDL_ENCLOSEPOINTS SDL_EncloseFPoints
#define SDL_INTERSECTRECTANDLINE SDL_IntersectFRectAndLine
#include "SDL_rect_impl.h"
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -0,0 +1,444 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
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.
*/
/* This file is #included twice to support int and float versions with the same code. */
SDL_bool
SDL_HASINTERSECTION(const RECTTYPE * A, const RECTTYPE * B)
{
SCALARTYPE Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
} else if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
} else if (SDL_RECTEMPTY(A) || SDL_RECTEMPTY(B)) {
return SDL_FALSE; /* Special cases for empty rects */
}
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin > Amin) {
Amin = Bmin;
}
if (Bmax < Amax) {
Amax = Bmax;
}
if (Amax <= Amin) {
return SDL_FALSE;
}
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin > Amin) {
Amin = Bmin;
}
if (Bmax < Amax) {
Amax = Bmax;
}
if (Amax <= Amin) {
return SDL_FALSE;
}
return SDL_TRUE;
}
SDL_bool
SDL_INTERSECTRECT(const RECTTYPE * A, const RECTTYPE * B, RECTTYPE * result)
{
SCALARTYPE Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return SDL_FALSE;
} else if (!B) {
SDL_InvalidParamError("B");
return SDL_FALSE;
} else if (!result) {
SDL_InvalidParamError("result");
return SDL_FALSE;
} else if (SDL_RECTEMPTY(A) || SDL_RECTEMPTY(B)) { /* Special cases for empty rects */
result->w = 0;
result->h = 0;
return SDL_FALSE;
}
/* Horizontal intersection */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin > Amin) {
Amin = Bmin;
}
result->x = Amin;
if (Bmax < Amax) {
Amax = Bmax;
}
result->w = Amax - Amin;
/* Vertical intersection */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin > Amin) {
Amin = Bmin;
}
result->y = Amin;
if (Bmax < Amax) {
Amax = Bmax;
}
result->h = Amax - Amin;
return !SDL_RECTEMPTY(result);
}
void
SDL_UNIONRECT(const RECTTYPE * A, const RECTTYPE * B, RECTTYPE * result)
{
SCALARTYPE Amin, Amax, Bmin, Bmax;
if (!A) {
SDL_InvalidParamError("A");
return;
} else if (!B) {
SDL_InvalidParamError("B");
return;
} else if (!result) {
SDL_InvalidParamError("result");
return;
} else if (SDL_RECTEMPTY(A)) { /* Special cases for empty Rects */
if (SDL_RECTEMPTY(B)) { /* A and B empty */
SDL_zerop(result);
} else { /* A empty, B not empty */
*result = *B;
}
return;
} else if (SDL_RECTEMPTY(B)) { /* A not empty, B empty */
*result = *A;
return;
}
/* Horizontal union */
Amin = A->x;
Amax = Amin + A->w;
Bmin = B->x;
Bmax = Bmin + B->w;
if (Bmin < Amin) {
Amin = Bmin;
}
result->x = Amin;
if (Bmax > Amax) {
Amax = Bmax;
}
result->w = Amax - Amin;
/* Vertical union */
Amin = A->y;
Amax = Amin + A->h;
Bmin = B->y;
Bmax = Bmin + B->h;
if (Bmin < Amin) {
Amin = Bmin;
}
result->y = Amin;
if (Bmax > Amax) {
Amax = Bmax;
}
result->h = Amax - Amin;
}
SDL_bool SDL_ENCLOSEPOINTS(const POINTTYPE * points, int count, const RECTTYPE * clip,
RECTTYPE * result)
{
SCALARTYPE minx = 0;
SCALARTYPE miny = 0;
SCALARTYPE maxx = 0;
SCALARTYPE maxy = 0;
SCALARTYPE x, y;
int i;
if (!points) {
SDL_InvalidParamError("points");
return SDL_FALSE;
} else if (count < 1) {
SDL_InvalidParamError("count");
return SDL_FALSE;
}
if (clip) {
SDL_bool added = SDL_FALSE;
const SCALARTYPE clip_minx = clip->x;
const SCALARTYPE clip_miny = clip->y;
const SCALARTYPE clip_maxx = clip->x+clip->w-1;
const SCALARTYPE clip_maxy = clip->y+clip->h-1;
/* Special case for empty rectangle */
if (SDL_RECTEMPTY(clip)) {
return SDL_FALSE;
}
for (i = 0; i < count; ++i) {
x = points[i].x;
y = points[i].y;
if (x < clip_minx || x > clip_maxx ||
y < clip_miny || y > clip_maxy) {
continue;
}
if (!added) {
/* Special case: if no result was requested, we are done */
if (result == NULL) {
return SDL_TRUE;
}
/* First point added */
minx = maxx = x;
miny = maxy = y;
added = SDL_TRUE;
continue;
}
if (x < minx) {
minx = x;
} else if (x > maxx) {
maxx = x;
}
if (y < miny) {
miny = y;
} else if (y > maxy) {
maxy = y;
}
}
if (!added) {
return SDL_FALSE;
}
} else {
/* Special case: if no result was requested, we are done */
if (result == NULL) {
return SDL_TRUE;
}
/* No clipping, always add the first point */
minx = maxx = points[0].x;
miny = maxy = points[0].y;
for (i = 1; i < count; ++i) {
x = points[i].x;
y = points[i].y;
if (x < minx) {
minx = x;
} else if (x > maxx) {
maxx = x;
}
if (y < miny) {
miny = y;
} else if (y > maxy) {
maxy = y;
}
}
}
if (result) {
result->x = minx;
result->y = miny;
result->w = (maxx-minx)+1;
result->h = (maxy-miny)+1;
}
return SDL_TRUE;
}
/* Use the Cohen-Sutherland algorithm for line clipping */
static int
COMPUTEOUTCODE(const RECTTYPE * rect, SCALARTYPE x, SCALARTYPE y)
{
int code = 0;
if (y < rect->y) {
code |= CODE_TOP;
} else if (y >= rect->y + rect->h) {
code |= CODE_BOTTOM;
}
if (x < rect->x) {
code |= CODE_LEFT;
} else if (x >= rect->x + rect->w) {
code |= CODE_RIGHT;
}
return code;
}
SDL_bool
SDL_INTERSECTRECTANDLINE(const RECTTYPE * rect, SCALARTYPE *X1, SCALARTYPE *Y1, SCALARTYPE *X2,
SCALARTYPE *Y2)
{
SCALARTYPE x = 0;
SCALARTYPE y = 0;
SCALARTYPE x1, y1;
SCALARTYPE x2, y2;
SCALARTYPE rectx1;
SCALARTYPE recty1;
SCALARTYPE rectx2;
SCALARTYPE recty2;
int outcode1, outcode2;
if (!rect) {
SDL_InvalidParamError("rect");
return SDL_FALSE;
} else if (!X1) {
SDL_InvalidParamError("X1");
return SDL_FALSE;
} else if (!Y1) {
SDL_InvalidParamError("Y1");
return SDL_FALSE;
} else if (!X2) {
SDL_InvalidParamError("X2");
return SDL_FALSE;
} else if (!Y2) {
SDL_InvalidParamError("Y2");
return SDL_FALSE;
} else if (SDL_RECTEMPTY(rect)) {
return SDL_FALSE; /* Special case for empty rect */
}
x1 = *X1;
y1 = *Y1;
x2 = *X2;
y2 = *Y2;
rectx1 = rect->x;
recty1 = rect->y;
rectx2 = rect->x + rect->w - 1;
recty2 = rect->y + rect->h - 1;
/* Check to see if entire line is inside rect */
if (x1 >= rectx1 && x1 <= rectx2 && x2 >= rectx1 && x2 <= rectx2 &&
y1 >= recty1 && y1 <= recty2 && y2 >= recty1 && y2 <= recty2) {
return SDL_TRUE;
}
/* Check to see if entire line is to one side of rect */
if ((x1 < rectx1 && x2 < rectx1) || (x1 > rectx2 && x2 > rectx2) ||
(y1 < recty1 && y2 < recty1) || (y1 > recty2 && y2 > recty2)) {
return SDL_FALSE;
}
if (y1 == y2) { /* Horizontal line, easy to clip */
if (x1 < rectx1) {
*X1 = rectx1;
} else if (x1 > rectx2) {
*X1 = rectx2;
}
if (x2 < rectx1) {
*X2 = rectx1;
} else if (x2 > rectx2) {
*X2 = rectx2;
}
return SDL_TRUE;
}
if (x1 == x2) { /* Vertical line, easy to clip */
if (y1 < recty1) {
*Y1 = recty1;
} else if (y1 > recty2) {
*Y1 = recty2;
}
if (y2 < recty1) {
*Y2 = recty1;
} else if (y2 > recty2) {
*Y2 = recty2;
}
return SDL_TRUE;
}
/* More complicated Cohen-Sutherland algorithm */
outcode1 = COMPUTEOUTCODE(rect, x1, y1);
outcode2 = COMPUTEOUTCODE(rect, x2, y2);
while (outcode1 || outcode2) {
if (outcode1 & outcode2) {
return SDL_FALSE;
}
if (outcode1) {
if (outcode1 & CODE_TOP) {
y = recty1;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode1 & CODE_BOTTOM) {
y = recty2;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode1 & CODE_LEFT) {
x = rectx1;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
} else if (outcode1 & CODE_RIGHT) {
x = rectx2;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
}
x1 = x;
y1 = y;
outcode1 = COMPUTEOUTCODE(rect, x, y);
} else {
if (outcode2 & CODE_TOP) {
y = recty1;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode2 & CODE_BOTTOM) {
y = recty2;
x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
} else if (outcode2 & CODE_LEFT) {
/* If this assertion ever fires, here's the static analysis that warned about it:
http://buildbot.libsdl.org/sdl-static-analysis/sdl-macosx-static-analysis/sdl-macosx-static-analysis-1101/report-b0d01a.html#EndPath */
SDL_assert(x2 != x1); /* if equal: division by zero. */
x = rectx1;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
} else if (outcode2 & CODE_RIGHT) {
/* If this assertion ever fires, here's the static analysis that warned about it:
http://buildbot.libsdl.org/sdl-static-analysis/sdl-macosx-static-analysis/sdl-macosx-static-analysis-1101/report-39b114.html#EndPath */
SDL_assert(x2 != x1); /* if equal: division by zero. */
x = rectx2;
y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
}
x2 = x;
y2 = y;
outcode2 = COMPUTEOUTCODE(rect, x, y);
}
}
*X1 = x1;
*Y1 = y1;
*X2 = x2;
*Y2 = y2;
return SDL_TRUE;
}
#undef RECTTYPE
#undef POINTTYPE
#undef SCALARTYPE
#undef COMPUTEOUTCODE
#undef SDL_HASINTERSECTION
#undef SDL_INTERSECTRECT
#undef SDL_RECTEMPTY
#undef SDL_UNIONRECT
#undef SDL_ENCLOSEPOINTS
#undef SDL_INTERSECTRECTANDLINE
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -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;
}
@ -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");
}
@ -1676,6 +1678,7 @@ SDL_Window *
SDL_CreateWindowFrom(const void *data)
{
SDL_Window *window;
Uint32 flags = SDL_WINDOW_FOREIGN;
if (!_this) {
SDL_UninitializedVideo();
@ -1685,6 +1688,37 @@ SDL_CreateWindowFrom(const void *data)
SDL_Unsupported();
return NULL;
}
if (SDL_GetHintBoolean(SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL, SDL_FALSE)) {
if (!_this->GL_CreateContext) {
SDL_SetError("OpenGL support is either not configured in SDL "
"or not available in current SDL video driver "
"(%s) or platform", _this->name);
return NULL;
}
if (SDL_GL_LoadLibrary(NULL) < 0) {
return NULL;
}
flags |= SDL_WINDOW_OPENGL;
}
if (SDL_GetHintBoolean(SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN, SDL_FALSE)) {
if (!_this->Vulkan_CreateSurface) {
SDL_SetError("Vulkan support is either not configured in SDL "
"or not available in current SDL video driver "
"(%s) or platform", _this->name);
return NULL;
}
if (flags & SDL_WINDOW_OPENGL) {
SDL_SetError("Vulkan and OpenGL not supported on same window");
return NULL;
}
if (SDL_Vulkan_LoadLibrary(NULL) < 0) {
return NULL;
}
flags |= SDL_WINDOW_VULKAN;
}
window = (SDL_Window *)SDL_calloc(1, sizeof(*window));
if (!window) {
SDL_OutOfMemory();
@ -1692,7 +1726,7 @@ SDL_CreateWindowFrom(const void *data)
}
window->magic = &_this->window_magic;
window->id = _this->next_object_id++;
window->flags = SDL_WINDOW_FOREIGN;
window->flags = flags;
window->last_fullscreen_flags = window->flags;
window->is_destroying = SDL_FALSE;
window->opacity = 1.0f;
@ -1738,7 +1772,9 @@ SDL_RecreateWindow(SDL_Window * window, Uint32 flags)
}
/* Restore video mode, etc. */
SDL_HideWindow(window);
if (!(window->flags & SDL_WINDOW_FOREIGN)) {
SDL_HideWindow(window);
}
/* Tear down the old native window */
if (window->surface) {
@ -2473,6 +2509,11 @@ SDL_CreateWindowFramebuffer(SDL_Window * window)
attempt_texture_framebuffer = SDL_FALSE;
}
#endif
#if defined(__EMSCRIPTEN__)
else {
attempt_texture_framebuffer = SDL_FALSE;
}
#endif
if (attempt_texture_framebuffer) {
if (SDL_CreateWindowTexture(_this, window, &format, &pixels, &pitch) == -1) {
@ -3067,7 +3108,9 @@ SDL_DestroyWindow(SDL_Window * window)
window->is_destroying = SDL_TRUE;
/* Restore video mode, etc. */
SDL_HideWindow(window);
if (!(window->flags & SDL_WINDOW_FOREIGN)) {
SDL_HideWindow(window);
}
/* Make sure this window no longer has focus */
if (SDL_GetKeyboardFocus() == window) {

View File

@ -67,6 +67,7 @@ SDL_NumberOfEvents(Uint32 type)
return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type);
}
#if SDL_VIDEO_OPENGL_EGL
static void
android_egl_context_restore(SDL_Window *window)
{
@ -96,7 +97,7 @@ android_egl_context_backup(SDL_Window *window)
data->backup_done = 1;
}
}
#endif
/*
* Android_ResumeSem and Android_PauseSem are signaled from Java_org_libsdl_app_SDLActivity_nativePause and Java_org_libsdl_app_SDLActivity_nativeResume
@ -113,12 +114,14 @@ Android_PumpEvents_Blocking(_THIS)
if (videodata->isPaused) {
SDL_bool isContextExternal = SDL_IsVideoContextExternal();
#if SDL_VIDEO_OPENGL_EGL
/* Make sure this is the last thing we do before pausing */
if (!isContextExternal) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_backup(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
}
#endif
ANDROIDAUDIO_PauseDevices();
openslES_PauseDevices();
@ -138,11 +141,13 @@ Android_PumpEvents_Blocking(_THIS)
aaudio_ResumeDevices();
/* Restore the GL Context from here, as this operation is thread dependent */
#if SDL_VIDEO_OPENGL_EGL
if (!isContextExternal && !SDL_HasEvent(SDL_QUIT)) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_restore(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
}
#endif
/* Make sure SW Keyboard is restored when an app becomes foreground */
if (SDL_IsTextInputActive()) {
@ -188,11 +193,13 @@ Android_PumpEvents_NonBlocking(_THIS)
SDL_bool isContextExternal = SDL_IsVideoContextExternal();
if (backup_context) {
#if SDL_VIDEO_OPENGL_EGL
if (!isContextExternal) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_backup(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
}
#endif
if (videodata->pauseAudio) {
ANDROIDAUDIO_PauseDevices();
@ -219,12 +226,14 @@ Android_PumpEvents_NonBlocking(_THIS)
aaudio_ResumeDevices();
}
#if SDL_VIDEO_OPENGL_EGL
/* Restore the GL Context from here, as this operation is thread dependent */
if (!isContextExternal && !SDL_HasEvent(SDL_QUIT)) {
SDL_LockMutex(Android_ActivityMutex);
android_egl_context_restore(Android_Window);
SDL_UnlockMutex(Android_ActivityMutex);
}
#endif
/* Make sure SW Keyboard is restored when an app becomes foreground */
if (SDL_IsTextInputActive()) {

View File

@ -20,7 +20,7 @@
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_ANDROID
#if SDL_VIDEO_DRIVER_ANDROID && SDL_VIDEO_OPENGL_EGL
/* Android SDL video driver implementation */

View File

@ -122,12 +122,14 @@ 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;
device->free = Android_DeleteDevice;
/* GL pointers */
#if SDL_VIDEO_OPENGL_EGL
device->GL_LoadLibrary = Android_GLES_LoadLibrary;
device->GL_GetProcAddress = Android_GLES_GetProcAddress;
device->GL_UnloadLibrary = Android_GLES_UnloadLibrary;
@ -137,6 +139,7 @@ Android_CreateDevice(int devindex)
device->GL_GetSwapInterval = Android_GLES_GetSwapInterval;
device->GL_SwapWindow = Android_GLES_SwapWindow;
device->GL_DeleteContext = Android_GLES_DeleteContext;
#endif
#if SDL_VIDEO_VULKAN
device->Vulkan_LoadLibrary = Android_Vulkan_LoadLibrary;

View File

@ -81,6 +81,7 @@ Android_CreateWindow(_THIS, SDL_Window * window)
/* Do not create EGLSurface for Vulkan window since it will then make the window
incompatible with vkCreateAndroidSurfaceKHR */
#if SDL_VIDEO_OPENGL_EGL
if ((window->flags & SDL_WINDOW_OPENGL) != 0) {
data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
@ -91,6 +92,7 @@ Android_CreateWindow(_THIS, SDL_Window * window)
goto endfunction;
}
}
#endif
window->driverdata = data;
Android_Window = window;
@ -165,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)
{
@ -175,9 +183,13 @@ Android_DestroyWindow(_THIS, SDL_Window *window)
if (window->driverdata) {
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
#if SDL_VIDEO_OPENGL_EGL
if (data->egl_surface != EGL_NO_SURFACE) {
SDL_EGL_DestroySurface(_this, data->egl_surface);
}
#endif
if (data->native_window) {
ANativeWindow_release(data->native_window);
}
@ -198,7 +210,11 @@ Android_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
info->version.minor == SDL_MINOR_VERSION) {
info->subsystem = SDL_SYSWM_ANDROID;
info->info.android.window = data->native_window;
#if SDL_VIDEO_OPENGL_EGL
info->info.android.surface = data->egl_surface;
#endif
return SDL_TRUE;
} else {
SDL_SetError("Application not compiled with SDL %d.%d",

View File

@ -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);
@ -37,8 +38,10 @@ extern SDL_Window *Android_Window;
typedef struct
{
#if SDL_VIDEO_OPENGL_EGL
EGLSurface egl_surface;
EGLContext egl_context; /* We use this to preserve the context when losing focus */
#endif
SDL_bool backup_done;
ANativeWindow *native_window;

View File

@ -253,7 +253,7 @@ Cocoa_WarpMouseGlobal(int x, int y)
static void
Cocoa_WarpMouse(SDL_Window * window, int x, int y)
{
Cocoa_WarpMouseGlobal(x + window->x, y + window->y);
Cocoa_WarpMouseGlobal(window->x + x, window->y + y);
}
static int
@ -262,9 +262,9 @@ Cocoa_SetRelativeMouseMode(SDL_bool enabled)
/* We will re-apply the relative mode when the window gets focus, if it
* doesn't have focus right now.
*/
SDL_Window *window = SDL_GetMouseFocus();
SDL_Window *window = SDL_GetKeyboardFocus();
if (!window) {
return 0;
return 0;
}
/* We will re-apply the relative mode when the window finishes being moved,

View File

@ -2020,9 +2020,19 @@ Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
*/
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Cocoa_WindowListener *listener = data->listener;
NSWindow *nswindow = data->nswindow;
SDL_VideoData *videodata = ((SDL_WindowData *) window->driverdata)->videodata;
if (![listener isInFullscreenSpace]) {
SetWindowStyle(window, GetWindowStyle(window));
}
if (videodata->allow_spaces) {
if (resizable) {
/* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */
[nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
} else {
[nswindow setCollectionBehavior:NSWindowCollectionBehaviorManaged];
}
}
}}
void

View File

@ -220,16 +220,82 @@ sub output_copycore
my $A_is_const_FF = shift;
my $s = "";
my $d = "";
my $dst_has_alpha = ($dst =~ /A/) ? 1 : 0;
my $src_has_alpha = ($src =~ /A/) ? 1 : 0;
my $sa = "";
my $da = "";
# Nice and easy...
if ( $src eq $dst && !$modulate && !$blend ) {
print FILE <<__EOF__;
if (!$modulate && !$blend) {
# Nice and easy...
if ( $src eq $dst ) {
print FILE <<__EOF__;
*dst = *src;
__EOF__
return;
return;
}
# Matching color-order
$sa = $src;
$sa =~ s/[A8]//g;
$da = $dst;
$da =~ s/[A8]//g;
if ($sa eq $da) {
if ($dst_has_alpha && $src_has_alpha) {
$da = substr $dst, 0, 1;
if ($da eq "A") {
# RGBA -> ARGB
print FILE <<__EOF__;
pixel = *src;
pixel = (pixel >> 8) | (pixel << 24);
*dst = pixel;
__EOF__
} else {
# ARGB -> RGBA -- unused
print FILE <<__EOF__;
pixel = *src;
pixel = (pixel << 8) | A;
*dst = pixel;
__EOF__
}
} elsif ($dst_has_alpha) {
$da = substr $dst, 0, 1;
if ($da eq "A") {
# RGB -> ARGB
print FILE <<__EOF__;
pixel = *src;
pixel |= (A << 24);
*dst = pixel;
__EOF__
} else {
# RGB -> RGBA -- unused
print FILE <<__EOF__;
pixel = *src;
pixel = (pixel << 8) | A;
*dst = pixel;
__EOF__
}
} else {
$sa = substr $src, 0, 1;
if ($sa eq "A") {
# ARGB -> RGB
print FILE <<__EOF__;
pixel = *src;
pixel &= 0xFFFFFF;
*dst = pixel;
__EOF__
} else {
# RGBA -> RGB
print FILE <<__EOF__;
pixel = *src;
pixel >>= 8;
*dst = pixel;
__EOF__
}
}
return;
}
}
my $dst_has_alpha = ($dst =~ /A/) ? 1 : 0;
my $ignore_dst_alpha = !$dst_has_alpha && !$blend;
if ( $blend ) {
@ -366,6 +432,14 @@ sub output_copyfunc
my $is_modulateA_done = 0;
my $A_is_const_FF = 0;
my $sa = $src;
my $da = $dst;
my $matching_colors = 0;
$sa =~ s/[A8]//g;
$da =~ s/[A8]//g;
$matching_colors = (!$modulate && !$blend && ($sa eq $da)) ? 1 : 0;
output_copyfuncname("static void", $src, $dst, $modulate, $blend, $scale, 1, "\n");
print FILE <<__EOF__;
{
@ -424,8 +498,8 @@ __EOF__
print FILE <<__EOF__;
Uint32 pixel;
__EOF__
if (!$ignore_dst_alpha && !$src_has_alpha) {
if ($modulate){
if ( !$ignore_dst_alpha && !$src_has_alpha ) {
if ( $modulate ) {
$is_modulateA_done = 1;
print FILE <<__EOF__;
const Uint32 A = (flags & SDL_COPY_MODULATE_ALPHA) ? modulateA : 0xFF;
@ -436,14 +510,18 @@ __EOF__
const Uint32 A = 0xFF;
__EOF__
}
print FILE <<__EOF__;
if ( !$matching_colors ) {
print FILE <<__EOF__;
Uint32 R, G, B;
__EOF__
} elsif (!$ignore_dst_alpha) {
print FILE <<__EOF__;
}
} elsif ( !$ignore_dst_alpha ) {
if ( !$matching_colors ) {
print FILE <<__EOF__;
Uint32 R, G, B, A;
__EOF__
} else {
}
} elsif ( !$matching_colors ) {
print FILE <<__EOF__;
Uint32 R, G, B;
__EOF__

View File

@ -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)

View File

@ -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 <libdecor.h>
@ -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 {
@ -815,6 +817,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 +841,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);
@ -1054,10 +1070,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 +1676,361 @@ 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 int sx = wl_fixed_to_int(sx_w);
const int sy = wl_fixed_to_int(sy_w);
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 +2044,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 +2057,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 +2101,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);

View File

@ -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: */

View File

@ -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)

View File

@ -52,6 +52,8 @@
#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"
#ifdef HAVE_LIBDECOR_H
#include <libdecor.h>
@ -59,6 +61,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 +138,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
@ -291,6 +286,60 @@ 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;
}
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;
driverdata->width = width;
driverdata->height = height;
}
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
display_handle_geometry(void *data,
struct wl_output *output,
@ -307,7 +356,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 +367,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->xdg_output) {
driverdata->x = x;
driverdata->y = y;
}
driverdata->physical_width = physical_width;
driverdata->physical_height = physical_height;
if (driverdata->index == -1) {
@ -372,9 +424,15 @@ display_handle_mode(void *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;
/*
* Don't rotate this yet, wl-output coordinates are transformed in
* handle_done and xdg-output coordinates are pre-transformed.
*/
if (!driverdata->xdg_output) {
driverdata->width = width;
driverdata->height = height;
}
driverdata->refresh = refresh;
}
@ -410,17 +468,37 @@ display_handle_done(void *data,
SDL_DisplayMode mode;
SDL_VideoDisplay *dpy;
if (driverdata->done)
return;
/*
* 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->done = SDL_TRUE;
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;
}
SDL_zero(mode);
mode.format = SDL_PIXELFORMAT_RGB888;
if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
if (driverdata->xdg_output) {
/* xdg-output dimensions are already transformed, so no need to rotate. */
mode.w = driverdata->width;
mode.h = driverdata->height;
} else if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
mode.w = driverdata->height / driverdata->scale_factor;
mode.h = driverdata->width / driverdata->scale_factor;
} else {
mode.w = driverdata->width / driverdata->scale_factor;
mode.h = driverdata->height / driverdata->scale_factor;
}
/* 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 +510,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,6 +521,7 @@ 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;
@ -509,6 +585,24 @@ Wayland_add_display(SDL_VideoData *d, uint32_t id)
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 +618,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 +637,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,
@ -620,6 +727,15 @@ 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);
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
} else if (SDL_strcmp(interface, "qt_touch_extension") == 0) {
@ -737,6 +853,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 +899,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 +921,10 @@ Wayland_VideoQuit(_THIS)
}
#endif
if (data->xdg_output_manager) {
zxdg_output_manager_v1_destroy(data->xdg_output_manager);
}
if (data->compositor)
wl_compositor_destroy(data->compositor);

View File

@ -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,7 @@ 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;
EGLDisplay edpy;
EGLContext context;
@ -77,6 +81,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,9 +95,10 @@ 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 x, y, width, height, refresh, transform;
@ -100,8 +107,9 @@ typedef struct {
float ddpi, hdpi, vdpi;
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"

View File

@ -1325,7 +1325,7 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
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
}

View File

@ -374,7 +374,7 @@ WIN_CheckAsyncMouseRelease(SDL_WindowData *data)
if (!(keyState & 0x8000)) {
WIN_CheckWParamMouseButton(SDL_FALSE, mouseFlags, swapButtons, data, SDL_BUTTON_X2, 0);
}
data->mouse_button_flags = 0;
data->mouse_button_flags = (WPARAM)-1;
}
static void
@ -1167,10 +1167,12 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
SDL_SendWindowEvent(data->window,
SDL_WINDOWEVENT_MINIMIZED, 0, 0);
break;
default:
case SIZE_RESTORED:
SDL_SendWindowEvent(data->window,
SDL_WINDOWEVENT_RESTORED, 0, 0);
break;
default:
break;
}
}
break;

View File

@ -276,27 +276,18 @@ WIN_SetTextInputRect(_THIS, SDL_Rect *rect)
}
}
#ifdef SDL_DISABLE_WINDOWS_IME
void WIN_ClearComposition(_THIS)
{
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
IME_ClearComposition(videodata);
}
SDL_bool WIN_IsTextInputShown(_THIS)
{
SDL_VideoData* videodata = (SDL_VideoData*)_this->driverdata;
return IME_IsTextInputShown(videodata);
return SDL_FALSE;
}
static SDL_bool
WIN_ShouldShowNativeUI()
{
return SDL_GetHintBoolean(SDL_HINT_IME_SHOW_UI, SDL_FALSE);
}
#ifdef SDL_DISABLE_WINDOWS_IME
SDL_bool
IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata)
{
@ -378,6 +369,12 @@ static void UILess_ReleaseSinks(SDL_VideoData *videodata);
static void UILess_EnableUIUpdates(SDL_VideoData *videodata);
static void UILess_DisableUIUpdates(SDL_VideoData *videodata);
static SDL_bool
WIN_ShouldShowNativeUI()
{
return SDL_GetHintBoolean(SDL_HINT_IME_SHOW_UI, SDL_FALSE);
}
static void
IME_Init(SDL_VideoData *videodata, HWND hwnd)
{
@ -796,10 +793,10 @@ IME_GetCompositionString(SDL_VideoData *videodata, HIMC himc, DWORD string)
videodata->ime_cursor = LOWORD(ImmGetCompositionStringW(himc, GCS_CURSORPOS, 0, 0));
if ((dwLang == LANG_CHT || dwLang == LANG_CHS) &&
videodata->ime_cursor > 0 &&
videodata->ime_cursor < videodata->ime_composition_length / sizeof(WCHAR) &&
videodata->ime_cursor < (int)(videodata->ime_composition_length / sizeof(WCHAR)) &&
(videodata->ime_composition[0] == 0x3000 || videodata->ime_composition[0] == 0x0020)) {
// Traditional Chinese IMEs add a placeholder U+3000
// Simplified Chinese IMEs seem to add a placholder U+0020 sometimes
// Simplified Chinese IMEs seem to add a placeholder U+0020 sometimes
int i;
for (i = videodata->ime_cursor + 1; i < length; ++i)
videodata->ime_composition[i - 1] = videodata->ime_composition[i];
@ -1714,6 +1711,18 @@ void IME_Present(SDL_VideoData *videodata)
/* FIXME: Need to show the IME bitmap */
}
SDL_bool WIN_IsTextInputShown(_THIS)
{
SDL_VideoData* videodata = (SDL_VideoData*)_this->driverdata;
return IME_IsTextInputShown(videodata);
}
void WIN_ClearComposition(_THIS)
{
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
IME_ClearComposition(videodata);
}
#endif /* SDL_DISABLE_WINDOWS_IME */
#endif /* SDL_VIDEO_DRIVER_WINDOWS */

View File

@ -175,11 +175,13 @@ WIN_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
static SDL_Cursor *
WIN_CreateBlankCursor()
{
SDL_Cursor *cursor = NULL;
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, 32, 32, 32, SDL_PIXELFORMAT_ARGB8888);
if (surface) {
return WIN_CreateCursor(surface, 0, 0);
cursor = WIN_CreateCursor(surface, 0, 0);
SDL_FreeSurface(surface);
}
return NULL;
return cursor;
}
static SDL_Cursor *
@ -370,7 +372,8 @@ WIN_QuitMouse(_THIS)
}
if (SDL_blank_cursor) {
SDL_FreeCursor(SDL_blank_cursor);
WIN_FreeCursor(SDL_blank_cursor);
SDL_blank_cursor = NULL;
}
}

View File

@ -28,6 +28,7 @@
#include "../SDL_pixels_c.h"
#include "../../events/SDL_keyboard_c.h"
#include "../../events/SDL_mouse_c.h"
#include "../../SDL_hints_c.h"
#include "SDL_windowsvideo.h"
#include "SDL_windowswindow.h"
@ -170,6 +171,13 @@ WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
data->expected_resize = SDL_FALSE;
}
static void SDLCALL
WIN_MouseRelativeModeCenterChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_WindowData *data = (SDL_WindowData *)userdata;
data->mouse_relative_mode_center = SDL_GetStringBoolean(hint, SDL_TRUE);
}
static int
SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool created)
{
@ -188,11 +196,13 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool cre
data->hinstance = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
data->created = created;
data->high_surrogate = 0;
data->mouse_button_flags = 0;
data->mouse_button_flags = (WPARAM)-1;
data->last_pointer_update = (LPARAM)-1;
data->videodata = videodata;
data->initializing = SDL_TRUE;
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, WIN_MouseRelativeModeCenterChanged, data);
window->driverdata = data;
/* Associate the data with the window */
@ -297,7 +307,39 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool cre
return 0;
}
static void CleanupWindowData(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (data) {
SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, WIN_MouseRelativeModeCenterChanged, data);
if (data->keyboard_hook) {
UnhookWindowsHookEx(data->keyboard_hook);
}
ReleaseDC(data->hwnd, data->hdc);
RemoveProp(data->hwnd, TEXT("SDL_WindowData"));
if (data->created) {
DestroyWindow(data->hwnd);
if (data->parent) {
DestroyWindow(data->parent);
}
} else {
/* Restore any original event handler... */
if (data->wndproc != NULL) {
#ifdef GWLP_WNDPROC
SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
(LONG_PTR) data->wndproc);
#else
SetWindowLong(data->hwnd, GWL_WNDPROC,
(LONG_PTR) data->wndproc);
#endif
}
}
SDL_free(data);
}
window->driverdata = NULL;
}
int
WIN_CreateWindow(_THIS, SDL_Window * window)
@ -422,6 +464,9 @@ WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
}
}
}
} else if (window->flags & SDL_WINDOW_OPENGL) {
/* Try to set up the pixel format, if it hasn't been set by the application */
WIN_GL_SetupWindow(_this, window);
}
}
#endif
@ -855,15 +900,6 @@ void
WIN_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
{
WIN_UpdateClipCursor(window);
if (window->flags & SDL_WINDOW_FULLSCREEN) {
UINT flags = SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE;
if (!(window->flags & SDL_WINDOW_SHOWN)) {
flags |= SWP_NOACTIVATE;
}
WIN_SetWindowPositionInternal(_this, window, flags);
}
}
void
@ -879,34 +915,7 @@ WIN_SetWindowKeyboardGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
void
WIN_DestroyWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
if (data) {
if (data->keyboard_hook) {
UnhookWindowsHookEx(data->keyboard_hook);
}
ReleaseDC(data->hwnd, data->hdc);
RemoveProp(data->hwnd, TEXT("SDL_WindowData"));
if (data->created) {
DestroyWindow(data->hwnd);
if (data->parent) {
DestroyWindow(data->parent);
}
} else {
/* Restore any original event handler... */
if (data->wndproc != NULL) {
#ifdef GWLP_WNDPROC
SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
(LONG_PTR) data->wndproc);
#else
SetWindowLong(data->hwnd, GWL_WNDPROC,
(LONG_PTR) data->wndproc);
#endif
}
}
SDL_free(data);
}
window->driverdata = NULL;
CleanupWindowData(_this, window);
}
SDL_bool
@ -1038,7 +1047,7 @@ WIN_UpdateClipCursor(SDL_Window *window)
if ((mouse->relative_mode || (window->flags & SDL_WINDOW_MOUSE_GRABBED) ||
(window->mouse_rect.w > 0 && window->mouse_rect.h > 0)) &&
(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
if (mouse->relative_mode && !mouse->relative_mode_warp) {
if (mouse->relative_mode && !mouse->relative_mode_warp && data->mouse_relative_mode_center) {
if (GetWindowRect(data->hwnd, &rect)) {
LONG cx, cy;

View File

@ -49,6 +49,7 @@ typedef struct
Uint8 focus_click_pending;
SDL_bool skip_update_clipcursor;
Uint32 last_updated_clipcursor;
SDL_bool mouse_relative_mode_center;
SDL_bool windowed_mode_was_maximized;
SDL_bool in_window_deactivation;
RECT cursor_clipped_rect;

View File

@ -380,7 +380,7 @@ X11_GetScrollLockModifierMask(_THIS)
return num_mask;
}
static void
void
X11_ReconcileKeyboardState(_THIS)
{
SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;

View File

@ -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_ */

View File

@ -409,6 +409,8 @@ X11_InitKeyboard(_THIS)
SDL_IME_Init();
#endif
X11_ReconcileKeyboardState(_this);
return 0;
}

View File

@ -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;

View File

@ -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))
{

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,220 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="xdg_output_unstable_v1">
<copyright>
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.
</copyright>
<description summary="Protocol to describe output regions">
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.
</description>
<interface name="zxdg_output_manager_v1" version="3">
<description summary="manage xdg_output objects">
A global factory interface for xdg_output objects.
</description>
<request name="destroy" type="destructor">
<description summary="destroy the xdg_output_manager object">
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.
</description>
</request>
<request name="get_xdg_output">
<description summary="create an xdg output from a wl_output">
This creates a new xdg_output object for the given wl_output.
</description>
<arg name="id" type="new_id" interface="zxdg_output_v1"/>
<arg name="output" type="object" interface="wl_output"/>
</request>
</interface>
<interface name="zxdg_output_v1" version="3">
<description summary="compositor logical output region">
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.
</description>
<request name="destroy" type="destructor">
<description summary="destroy the xdg_output object">
Using this request a client can tell the server that it is not
going to use the xdg_output object anymore.
</description>
</request>
<event name="logical_position">
<description summary="position of the output within the global compositor space">
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.
</description>
<arg name="x" type="int"
summary="x position within the global compositor space"/>
<arg name="y" type="int"
summary="y position within the global compositor space"/>
</event>
<event name="logical_size">
<description summary="size of the output in 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).
</description>
<arg name="width" type="int"
summary="width in global compositor space"/>
<arg name="height" type="int"
summary="height in global compositor space"/>
</event>
<event name="done">
<description summary="all information about the output have been sent">
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.
</description>
</event>
<!-- Version 2 additions -->
<event name="name" since="2">
<description summary="name of this output">
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.
</description>
<arg name="name" type="string" summary="output name"/>
</event>
<event name="description" since="2">
<description summary="human-readable description of this output">
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.
</description>
<arg name="description" type="string" summary="output description"/>
</event>
</interface>
</protocol>