LIBS: updated sdl2

master
Martin Gerhardy 2022-04-14 18:58:41 +02:00
parent f425c549f7
commit ef09d67d80
82 changed files with 2169 additions and 600 deletions

View File

@ -71,12 +71,12 @@ include(cmake/sdlchecks.cmake)
# set SDL_BINARY_AGE and SDL_INTERFACE_AGE to 0.
set(SDL_MAJOR_VERSION 2)
set(SDL_MINOR_VERSION 0)
set(SDL_MICRO_VERSION 21)
set(SDL_INTERFACE_AGE 3)
set(SDL_BINARY_AGE 21)
set(SDL_MICRO_VERSION 22)
set(SDL_INTERFACE_AGE 0)
set(SDL_BINARY_AGE 22)
set(SDL_VERSION "${SDL_MAJOR_VERSION}.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}")
# the following should match the versions in Xcode project file:
set(DYLIB_CURRENT_VERSION 19.3.0)
set(DYLIB_CURRENT_VERSION 23.0.0)
set(DYLIB_COMPATIBILITY_VERSION 1.0.0)
# Calculate a libtool-like version number
@ -1604,6 +1604,7 @@ elseif(WINDOWS)
# headers needed elsewhere
check_include_file(tpcshrd.h HAVE_TPCSHRD_H)
check_include_file(roapi.h HAVE_ROAPI_H)
check_include_file(mmdeviceapi.h HAVE_MMDEVICEAPI_H)
check_include_file(audioclient.h HAVE_AUDIOCLIENT_H)
check_include_file(sensorsapi.h HAVE_SENSORSAPI_H)
@ -2283,6 +2284,11 @@ elseif(VITA)
${SDL2_SOURCE_DIR}/src/thread/generic/SDL_systls.c)
set(HAVE_SDL_THREADS TRUE)
endif()
if(SDL_LOCALE)
file(GLOB LOCALE_SOURCES ${SDL2_SOURCE_DIR}/src/locale/vita/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${LOCALE_SOURCES})
set(HAVE_SDL_LOCALE TRUE)
endif()
if(SDL_TIMERS)
set(SDL_TIMER_VITA 1)
file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/vita/*.c)
@ -2309,10 +2315,10 @@ elseif(VITA)
list(APPEND EXTRA_LIBS
pib
)
set(HAVE_VITA_PIB ON)
set(HAVE_VIDEO_VITA_PIB ON)
set(SDL_VIDEO_VITA_PIB 1)
else()
set(HAVE_VITA_PIB OFF)
set(HAVE_VIDEO_VITA_PIB OFF)
endif()
endif()
@ -2320,6 +2326,7 @@ elseif(VITA)
check_include_file(gpu_es4/psp2_pvr_hint.h HAVE_PVR_H)
if(HAVE_PVR_H)
target_compile_definitions(sdl-build-options INTERFACE "-D__psp2__")
check_include_file(gl4esinit.h HAVE_GL4ES_H)
set(SDL_VIDEO_OPENGL_EGL 1)
set(HAVE_OPENGLES TRUE)
set(SDL_VIDEO_OPENGL_ES 1)
@ -2331,10 +2338,20 @@ elseif(VITA)
libgpu_es4_ext_stub_weak
libIMGEGL_stub_weak
)
set(HAVE_VITA_PVR ON)
set(HAVE_VIDEO_VITA_PVR ON)
set(SDL_VIDEO_VITA_PVR 1)
if(HAVE_GL4ES_H)
set(HAVE_OPENGL TRUE)
set(SDL_VIDEO_OPENGL 1)
set(SDL_VIDEO_RENDER_OGL 1)
list(APPEND EXTRA_LIBS libGL_stub)
set(SDL_VIDEO_VITA_PVR_OGL 1)
endif()
else()
set(HAVE_VITA_PVR OFF)
set(HAVE_VIDEO_VITA_PVR OFF)
endif()
endif()
@ -2346,6 +2363,7 @@ elseif(VITA)
SceCtrl_stub
SceAppMgr_stub
SceAudio_stub
SceAudioIn_stub
SceSysmodule_stub
SceDisplay_stub
SceCtrl_stub

View File

@ -67,9 +67,8 @@ typedef enum
SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */
SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D11 */
SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D11 */
SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D9, D3D11 */
SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D9, D3D11 */
} SDL_BlendOperation;
/**
@ -87,7 +86,6 @@ typedef enum
SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = 0x8, /**< 1-dstR, 1-dstG, 1-dstB, 1-dstA */
SDL_BLENDFACTOR_DST_ALPHA = 0x9, /**< dstA, dstA, dstA, dstA */
SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = 0xA /**< 1-dstA, 1-dstA, 1-dstA, 1-dstA */
} SDL_BlendFactor;
/**
@ -135,10 +133,10 @@ typedef enum
* SDL 2.0.6. All renderers support the four blend modes listed in the
* SDL_BlendMode enumeration.
*
* - **direct3d**: Supports `SDL_BLENDOPERATION_ADD` with all factors.
* - **direct3d11**: Supports all operations with all factors. However, some
* - **direct3d**: Supports all operations with all factors. However, some
* factors produce unexpected results with `SDL_BLENDOPERATION_MINIMUM` and
* `SDL_BLENDOPERATION_MAXIMUM`.
* - **direct3d11**: Same as Direct3D 9.
* - **opengl**: Supports the `SDL_BLENDOPERATION_ADD` operation with all
* factors. OpenGL versions 1.1, 1.2, and 1.3 do not work correctly with SDL
* 2.0.6.

View File

@ -253,6 +253,7 @@
#cmakedefine HAVE_AUDIOCLIENT_H @HAVE_AUDIOCLIENT_H@
#cmakedefine HAVE_TPCSHRD_H @HAVE_TPCSHRD_H@
#cmakedefine HAVE_SENSORSAPI_H @HAVE_SENSORSAPI_H@
#cmakedefine HAVE_ROAPI_H @HAVE_ROAPI_H@
#cmakedefine HAVE_XINPUT_GAMEPAD_EX @HAVE_XINPUT_GAMEPAD_EX@
#cmakedefine HAVE_XINPUT_STATE_EX @HAVE_XINPUT_STATE_EX@
@ -520,6 +521,7 @@
#cmakedefine SDL_VIDEO_VITA_PIB @SDL_VIDEO_VITA_PIB@
#cmakedefine SDL_VIDEO_VITA_PVR @SDL_VIDEO_VITA_PVR@
#cmakedefine SDL_VIDEO_VITA_PVR_OGL @SDL_VIDEO_VITA_PVR_OGL@
#if !defined(__WIN32__) && !defined(__WINRT__)
# if !defined(_STDINT_H_) && !defined(_STDINT_H) && !defined(HAVE_STDINT_H) && !defined(_HAVE_STDINT_H)

View File

@ -242,6 +242,7 @@
#undef HAVE_AUDIOCLIENT_H
#undef HAVE_TPCSHRD_H
#undef HAVE_SENSORSAPI_H
#undef HAVE_ROAPI_H
/* SDL internal assertion support */
#undef SDL_DEFAULT_ASSERT_LEVEL

View File

@ -185,6 +185,7 @@
/* Enable various threading systems */
#ifdef __EMSCRIPTEN_PTHREADS__
#define SDL_THREAD_PTHREAD 1
#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
#endif
/* Enable various timer systems */

View File

@ -104,6 +104,7 @@ typedef unsigned int uintptr_t;
#endif
#if defined(_WIN32_MAXVER) && _WIN32_MAXVER >= 0x0602 /* Windows 8 SDK */
#define HAVE_D3D11_H 1
#define HAVE_ROAPI_H 1
#endif
#define HAVE_MMDEVICEAPI_H 1
#define HAVE_AUDIOCLIENT_H 1

View File

@ -195,6 +195,8 @@ typedef unsigned int uintptr_t;
#define HAVE_TRUNCF 1
#define HAVE__FSEEKI64 1
#define HAVE_ROAPI_H 1
/* Enable various audio drivers */
#define SDL_AUDIO_DRIVER_WASAPI 1
#define SDL_AUDIO_DRIVER_DISK 1

View File

@ -1354,6 +1354,18 @@ extern "C" {
*/
#define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS"
/**
* \brief A variable controlling which touchpad should generate synthetic mouse events
*
* This variable can be set to the following values:
* "0" - Only front touchpad should generate mouse events. Default
* "1" - Only back touchpad should generate mouse events.
* "2" - Both touchpads should generate mouse events.
*
* By default SDL will generate mouse events for all touch devices
*/
#define SDL_HINT_VITA_TOUCH_MOUSE_DEVICE "SDL_HINT_VITA_TOUCH_MOUSE_DEVICE"
/**
* \brief A variable controlling whether the Android / tvOS remotes
* should be listed as joystick devices, instead of sending keyboard events.
@ -1463,6 +1475,20 @@ extern "C" {
*/
#define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR"
/**
* \brief A variable controlling whether the libdecor Wayland backend is preferred over native decrations.
*
* When this hint is set, libdecor will be used to provide window decorations, even if xdg-decoration is
* available. (Note that, by default, libdecor will use xdg-decoration itself if available).
*
* This variable can be set to the following values:
* "0" - libdecor is enabled only if server-side decorations are unavailable.
* "1" - libdecor is always enabled if available.
*
* libdecor is used over xdg-shell when xdg-decoration protocol is unavailable.
*/
#define SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR "SDL_VIDEO_WAYLAND_PREFER_LIBDECOR"
/**
* \brief A variable that is the address of another SDL_Window* (as a hex string formatted with "%p").
*
@ -1938,8 +1964,7 @@ extern "C" {
* If not set or set to "", this hint is ignored. This hint must be set
* before the SDL_CreateWindow() call that it is intended to affect.
*
* This hint is available since SDL 2.0.22. Before then, virtual devices are
* always ignored.
* This hint is available since SDL 2.0.22.
*/
#define SDL_HINT_X11_WINDOW_TYPE "SDL_X11_WINDOW_TYPE"

View File

@ -92,6 +92,7 @@ extern DECLSPEC void *SDLCALL SDL_Metal_GetLayer(SDL_MetalView view);
*
* \param window SDL_Window from which the drawable size should be queried
* \param w Pointer to variable for storing the width in pixels, may be NULL
* \param h Pointer to variable for storing the height in pixels, may be NULL
*
* \since This function is available since SDL 2.0.14.
*

View File

@ -1618,6 +1618,7 @@ extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer,
* vertex array Color and alpha modulation is done per vertex
* (SDL_SetTextureColorMod and SDL_SetTextureAlphaMod are ignored).
*
* \param renderer The rendering context.
* \param texture (optional) The SDL texture to use.
* \param vertices Vertices.
* \param num_vertices Number of vertices.
@ -1642,6 +1643,7 @@ extern DECLSPEC int SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer,
* vertex arrays Color and alpha modulation is done per vertex
* (SDL_SetTextureColorMod and SDL_SetTextureAlphaMod are ignored).
*
* \param renderer The rendering context.
* \param texture (optional) The SDL texture to use.
* \param xy Vertex positions
* \param xy_stride Byte size to move from one element to the next element

View File

@ -355,9 +355,9 @@ typedef uint64_t Uint64;
#endif /* SDL_DISABLE_ANALYZE_MACROS */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
#define SDL_COMPILE_TIME_ASSERT(name, x) _Static_assert(x, #x);
#define SDL_COMPILE_TIME_ASSERT(name, x) _Static_assert(x, #x)
#elif defined(__cplusplus) && (__cplusplus >= 201103L)
#define SDL_COMPILE_TIME_ASSERT(name, x) static_assert(x, #x);
#define SDL_COMPILE_TIME_ASSERT(name, x) static_assert(x, #x)
#else /* universal, but may trigger -Wunused-local-typedefs */
#define SDL_COMPILE_TIME_ASSERT(name, x) \
typedef int SDL_compile_time_assert_ ## name[(x) * 2 - 1]

View File

@ -59,7 +59,7 @@ typedef struct SDL_version
*/
#define SDL_MAJOR_VERSION 2
#define SDL_MINOR_VERSION 0
#define SDL_PATCHLEVEL 21
#define SDL_PATCHLEVEL 22
/**
* Macro to determine SDL version program was compiled against.

View File

@ -1337,6 +1337,7 @@ extern DECLSPEC void SDLCALL SDL_SetWindowKeyboardGrab(SDL_Window * window,
* Mouse grab confines the mouse cursor to the window.
*
* \param window The window for which the mouse grab mode should be set.
* \param grabbed This is SDL_TRUE to grab mouse, and SDL_FALSE to release.
*
* \since This function is available since SDL 2.0.16.
*

View File

@ -107,7 +107,7 @@
#ifdef __BORLANDC__
#pragma nopackwarning
#endif
#ifdef _M_X64
#ifdef _WIN64
/* Use 8-byte alignment on 64-bit architectures, so pointers are aligned */
#pragma pack(push,8)
#else

View File

@ -0,0 +1,93 @@
/*
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.
*/
#include "./SDL_internal.h"
#include "SDL.h"
#include "./SDL_list.h"
/* Push */
int
SDL_ListAdd(SDL_ListNode **head, void *ent)
{
SDL_ListNode *node = SDL_malloc(sizeof (*node));
if (node == NULL) {
return SDL_OutOfMemory();
}
node->entry = ent;
node->next = *head;
*head = node;
return 0;
}
/* Pop from end as a FIFO (if add with SDL_ListAdd) */
void
SDL_ListPop(SDL_ListNode **head, void **ent)
{
SDL_ListNode **ptr = head;
/* Invalid or empty */
if (head == NULL || *head == NULL) {
return;
}
while ((*ptr)->next) {
ptr = &(*ptr)->next;
}
if (ent) {
*ent = (*ptr)->entry;
}
SDL_free(*ptr);
*ptr = NULL;
}
void
SDL_ListRemove(SDL_ListNode **head, void *ent)
{
SDL_ListNode **ptr = head;
while (*ptr) {
if ((*ptr)->entry == ent) {
SDL_ListNode *tmp = *ptr;
*ptr = (*ptr)->next;
SDL_free(tmp);
return;
}
ptr = &(*ptr)->next;
}
}
void
SDL_ListClear(SDL_ListNode **head)
{
SDL_ListNode *l = *head;
*head = NULL;
while (l) {
SDL_ListNode *tmp = l;
l = l->next;
SDL_free(tmp);
}
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -0,0 +1,39 @@
/*
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.
*/
#ifndef SDL_list_h_
#define SDL_list_h_
typedef struct SDL_ListNode
{
void *entry;
struct SDL_ListNode *next;
} SDL_ListNode;
int SDL_ListAdd(SDL_ListNode **head, void *ent);
void SDL_ListPop(SDL_ListNode **head, void **ent);
void SDL_ListRemove(SDL_ListNode **head, void *ent);
void SDL_ListClear(SDL_ListNode **head);
#endif /* SDL_list_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -80,7 +80,7 @@ SDL_ConvertStereoToMono_SSE3(SDL_AudioCVT * cvt, SDL_AudioFormat format)
Just use unaligned load/stores, if the memory at runtime is
aligned it'll be just as fast on modern processors */
while (i >= 4) { /* 4 * float32 */
_mm_storeu_ps(dst, _mm_mul_ps(_mm_hadd_ps(_mm_load_ps(src), _mm_loadu_ps(src+4)), divby2));
_mm_storeu_ps(dst, _mm_mul_ps(_mm_hadd_ps(_mm_loadu_ps(src), _mm_loadu_ps(src+4)), divby2));
i -= 4; src += 8; dst += 4;
}

View File

@ -32,7 +32,7 @@ static void
FeedAudioDevice(_THIS, const void *buf, const int buflen)
{
const int framelen = (SDL_AUDIO_BITSIZE(this->spec.format) / 8) * this->spec.channels;
EM_ASM_ARGS({
MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
var numChannels = SDL2.audio.currentOutputBuffer['numberOfChannels'];
for (var c = 0; c < numChannels; ++c) {
@ -101,7 +101,7 @@ HandleCaptureProcess(_THIS)
return;
}
EM_ASM_ARGS({
MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels;
for (var c = 0; c < numChannels; ++c) {
@ -147,7 +147,7 @@ HandleCaptureProcess(_THIS)
static void
EMSCRIPTENAUDIO_CloseDevice(_THIS)
{
EM_ASM_({
MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
if ($0) {
if (SDL2.capture.silenceTimer !== undefined) {
@ -201,7 +201,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
/* based on parts of library_sdl.js */
/* create context */
result = EM_ASM_INT({
result = MAIN_THREAD_EM_ASM_INT({
if(typeof(Module['SDL2']) === 'undefined') {
Module['SDL2'] = {};
}
@ -280,7 +280,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
feels like it's a pretty inefficient tapdance in similar ways,
to be honest. */
EM_ASM_({
MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
var have_microphone = function(stream) {
//console.log('SDL audio capture: we have a microphone! Replacing silence callback.');
@ -323,7 +323,7 @@ EMSCRIPTENAUDIO_OpenDevice(_THIS, const char *devname)
}, this->spec.channels, this->spec.samples, HandleCaptureProcess, this);
} else {
/* setup a ScriptProcessorNode */
EM_ASM_ARGS({
MAIN_THREAD_EM_ASM({
var SDL2 = Module['SDL2'];
SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0);
SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
@ -359,7 +359,7 @@ EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->ProvidesOwnCallbackThread = SDL_TRUE;
/* check availability */
available = EM_ASM_INT_V({
available = MAIN_THREAD_EM_ASM_INT({
if (typeof(AudioContext) !== 'undefined') {
return true;
} else if (typeof(webkitAudioContext) !== 'undefined') {
@ -372,7 +372,7 @@ EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl * impl)
SDL_SetError("No audio context available");
}
capture_available = available && EM_ASM_INT_V({
capture_available = available && MAIN_THREAD_EM_ASM_INT({
if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) {
return true;
} else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') {

View File

@ -37,12 +37,28 @@
#include <psp2/kernel/threadmgr.h>
#include <psp2/audioout.h>
#include <psp2/audioin.h>
#define SCE_AUDIO_SAMPLE_ALIGN(s) (((s) + 63) & ~63)
#define SCE_AUDIO_MAX_VOLUME 0x8000
/* The tag name used by VITA audio */
#define VITAAUD_DRIVER_NAME "vita"
static int
VITAAUD_OpenCaptureDevice(_THIS)
{
this->spec.freq = 16000;
this->spec.samples = 512;
this->spec.channels = 1;
SDL_CalculateAudioSpec(&this->spec);
this->hidden->port = sceAudioInOpenPort(SCE_AUDIO_IN_PORT_TYPE_VOICE , 512, 16000, SCE_AUDIO_IN_PARAM_FORMAT_S16_MONO);
if (this->hidden->port < 0) {
return SDL_SetError("Couldn't open audio in port: %x", this->hidden->port);
}
return 0;
}
static int
VITAAUD_OpenDevice(_THIS, const char *devname)
@ -59,8 +75,7 @@ VITAAUD_OpenDevice(_THIS, const char *devname)
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)) {
if (test_format == AUDIO_S16LSB) {
this->spec.format = test_format;
break;
}
@ -70,13 +85,8 @@ VITAAUD_OpenDevice(_THIS, const char *devname)
return SDL_SetError("Unsupported audio format");
}
switch (this->spec.format & 0xff) {
case 8:
case 16:
this->spec.format = AUDIO_S16LSB;
break;
default:
return SDL_SetError("Unsupported audio format");
if (this->iscapture) {
return VITAAUD_OpenCaptureDevice(this);
}
/* The sample count must be a multiple of 64. */
@ -105,14 +115,14 @@ VITAAUD_OpenDevice(_THIS, const char *devname)
port = SCE_AUDIO_OUT_PORT_TYPE_BGM;
}
this->hidden->channel = sceAudioOutOpenPort(port, this->spec.samples, this->spec.freq, format);
if (this->hidden->channel < 0) {
this->hidden->port = sceAudioOutOpenPort(port, this->spec.samples, this->spec.freq, format);
if (this->hidden->port < 0) {
free(this->hidden->rawbuf);
this->hidden->rawbuf = NULL;
return SDL_SetError("Couldn't reserve hardware channel");
return SDL_SetError("Couldn't open audio out port: %x", this->hidden->port);
}
sceAudioOutSetVolume(this->hidden->channel, SCE_AUDIO_VOLUME_FLAG_L_CH|SCE_AUDIO_VOLUME_FLAG_R_CH, vols);
sceAudioOutSetVolume(this->hidden->port, SCE_AUDIO_VOLUME_FLAG_L_CH|SCE_AUDIO_VOLUME_FLAG_R_CH, vols);
SDL_memset(this->hidden->rawbuf, 0, mixlen);
for (i = 0; i < NUM_BUFFERS; i++) {
@ -127,7 +137,7 @@ static void VITAAUD_PlayDevice(_THIS)
{
Uint8 *mixbuf = this->hidden->mixbufs[this->hidden->next_buffer];
sceAudioOutOutput(this->hidden->channel, mixbuf);
sceAudioOutOutput(this->hidden->port, mixbuf);
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
}
@ -137,6 +147,7 @@ static void VITAAUD_WaitDevice(_THIS)
{
/* Because we block when sending audio, there's no need for this function to do anything. */
}
static Uint8 *VITAAUD_GetDeviceBuf(_THIS)
{
return this->hidden->mixbufs[this->hidden->next_buffer];
@ -144,17 +155,32 @@ static Uint8 *VITAAUD_GetDeviceBuf(_THIS)
static void VITAAUD_CloseDevice(_THIS)
{
if (this->hidden->channel >= 0) {
sceAudioOutReleasePort(this->hidden->channel);
this->hidden->channel = -1;
if (this->hidden->port >= 0) {
if (this->iscapture) {
sceAudioInReleasePort(this->hidden->port);
} else {
sceAudioOutReleasePort(this->hidden->port);
}
this->hidden->port = -1;
}
if (this->hidden->rawbuf != NULL) {
if (!this->iscapture && this->hidden->rawbuf != NULL) {
free(this->hidden->rawbuf); /* this uses memalign(), not SDL_malloc(). */
this->hidden->rawbuf = NULL;
}
}
static int VITAAUD_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
int ret;
SDL_assert(buflen == this->spec.size);
ret = sceAudioInInput(this->hidden->port, buffer);
if (ret < 0) {
return SDL_SetError("Failed to capture from device: %x", ret);
}
return this->spec.size;
}
static void VITAAUD_ThreadInit(_THIS)
{
/* Increase the priority of this audio thread by 1 to put it
@ -179,12 +205,13 @@ VITAAUD_Init(SDL_AudioDriverImpl * impl)
impl->CloseDevice = VITAAUD_CloseDevice;
impl->ThreadInit = VITAAUD_ThreadInit;
/* VITA audio device */
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
/*
impl->CaptureFromDevice = VITAAUD_CaptureFromDevice;
/* and the capabilities */
impl->HasCaptureSupport = SDL_TRUE;
impl->OnlyHasDefaultInputDevice = SDL_TRUE;
*/
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
impl->OnlyHasDefaultCaptureDevice = SDL_TRUE;
return SDL_TRUE; /* this audio target is available. */
}

View File

@ -30,8 +30,8 @@
#define NUM_BUFFERS 2
struct SDL_PrivateAudioData {
/* The hardware output channel. */
int channel;
/* The hardware input/output port. */
int port;
/* The raw allocated mixing buffer. */
Uint8 *rawbuf;
/* Individual mixing buffers. */

View File

@ -339,11 +339,11 @@ SDL_Fcitx_Reset(void)
}
SDL_bool
SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
{
Uint32 state = Fcitx_ModState();
Uint32 mod_state = Fcitx_ModState();
Uint32 handled = SDL_FALSE;
Uint32 is_release = SDL_FALSE;
Uint32 is_release = (state == SDL_RELEASED);
Uint32 event_time = 0;
if (!fcitx_client.ic_path) {
@ -351,7 +351,7 @@ SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
}
if (SDL_DBus_CallMethod(FCITX_DBUS_SERVICE, fcitx_client.ic_path, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent",
DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &state, DBUS_TYPE_BOOLEAN, &is_release, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &mod_state, DBUS_TYPE_BOOLEAN, &is_release, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID)) {
if (handled) {
SDL_Fcitx_UpdateTextRect(NULL);

View File

@ -31,7 +31,7 @@ extern SDL_bool SDL_Fcitx_Init(void);
extern void SDL_Fcitx_Quit(void);
extern void SDL_Fcitx_SetFocus(SDL_bool focused);
extern void SDL_Fcitx_Reset(void);
extern SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
extern SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
extern void SDL_Fcitx_UpdateTextRect(SDL_Rect *rect);
extern void SDL_Fcitx_PumpEvents(void);

View File

@ -503,15 +503,20 @@ SDL_IBus_Reset(void)
}
SDL_bool
SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
{
Uint32 result = 0;
SDL_DBusContext *dbus = SDL_DBus_GetContext();
if (IBus_CheckConnection(dbus)) {
Uint32 mods = IBus_ModState();
Uint32 ibus_keycode = keycode - 8;
if (state == SDL_RELEASED) {
mods |= (1 << 30); // IBUS_RELEASE_MASK
}
if (!SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &ibus_keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID)) {
result = 0;
}

View File

@ -41,7 +41,7 @@ extern void SDL_IBus_Reset(void);
/* Sends a keypress event to IBus, returns SDL_TRUE if IBus used this event to
update its candidate list or change input methods. PumpEvents should be
called some time after this, to recieve the TextInput / TextEditing event back. */
extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
/* Update the position of IBus' candidate list. If rect is NULL then this will
just reposition it relative to the focused window's new position. */

View File

@ -27,7 +27,7 @@ typedef SDL_bool (*_SDL_IME_Init)(void);
typedef void (*_SDL_IME_Quit)(void);
typedef void (*_SDL_IME_SetFocus)(SDL_bool);
typedef void (*_SDL_IME_Reset)(void);
typedef SDL_bool (*_SDL_IME_ProcessKeyEvent)(Uint32, Uint32);
typedef SDL_bool (*_SDL_IME_ProcessKeyEvent)(Uint32, Uint32, Uint8 state);
typedef void (*_SDL_IME_UpdateTextRect)(SDL_Rect *);
typedef void (*_SDL_IME_PumpEvents)(void);
@ -127,10 +127,10 @@ SDL_IME_Reset(void)
}
SDL_bool
SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
{
if (SDL_IME_ProcessKeyEvent_Real)
return SDL_IME_ProcessKeyEvent_Real(keysym, keycode);
return SDL_IME_ProcessKeyEvent_Real(keysym, keycode, state);
return SDL_FALSE;
}

View File

@ -31,7 +31,7 @@ extern SDL_bool SDL_IME_Init(void);
extern void SDL_IME_Quit(void);
extern void SDL_IME_SetFocus(SDL_bool focused);
extern void SDL_IME_Reset(void);
extern SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
extern SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
extern void SDL_IME_UpdateTextRect(SDL_Rect *rect);
extern void SDL_IME_PumpEvents(void);

View File

@ -25,7 +25,15 @@
#include "SDL_windows.h"
#include "SDL_error.h"
#include <objbase.h> /* for CoInitialize/CoUninitialize (Win32 only) */
#include <objbase.h> /* for CoInitialize/CoUninitialize (Win32 only) */
#if defined(HAVE_ROAPI_H)
#include <roapi.h> /* For RoInitialize/RoUninitialize (Win32 only) */
#else
typedef enum RO_INIT_TYPE {
RO_INIT_SINGLETHREADED = 0,
RO_INIT_MULTITHREADED = 1
} RO_INIT_TYPE;
#endif
#ifndef _WIN32_WINNT_VISTA
#define _WIN32_WINNT_VISTA 0x0600
@ -37,6 +45,10 @@
#define _WIN32_WINNT_WIN8 0x0602
#endif
#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
#endif
/* Sets an error message based on an HRESULT */
int
@ -104,51 +116,54 @@ void
WIN_CoUninitialize(void)
{
#ifndef __WINRT__
/* Don't uninitialize COM because of what appears to be a bug in Microsoft WGI reference counting.
*
* If you plug in a non-Xbox controller and let the application run for 30 seconds, then it crashes in CoUninitialize()
* with this stack trace:
CoUninitialize();
#endif
}
Windows.Gaming.Input.dll!GameController::~GameController(void) Unknown
Windows.Gaming.Input.dll!GameController::`vector deleting destructor'(unsigned int) Unknown
Windows.Gaming.Input.dll!Microsoft::WRL::Details::RuntimeClassImpl<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();*/
#ifndef __WINRT__
void *
WIN_LoadComBaseFunction(const char *name)
{
static SDL_bool s_bLoaded;
static HMODULE s_hComBase;
if (!s_bLoaded) {
s_hComBase = LoadLibraryEx(TEXT("combase.dll"), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
s_bLoaded = SDL_TRUE;
}
if (s_hComBase) {
return GetProcAddress(s_hComBase, name);
} else {
return NULL;
}
}
#endif
HRESULT
WIN_RoInitialize(void)
{
#ifdef __WINRT__
return S_OK;
#else
typedef HRESULT (*RoInitialize_t)(RO_INIT_TYPE initType);
RoInitialize_t RoInitializeFunc = (RoInitialize_t)WIN_LoadComBaseFunction("RoInitialize");
if (RoInitializeFunc) {
return RoInitializeFunc(RO_INIT_MULTITHREADED);
} else {
return E_NOINTERFACE;
}
#endif
}
void
WIN_RoUninitialize(void)
{
#ifndef __WINRT__
typedef void (*RoUninitialize_t)(void);
RoUninitialize_t RoUninitializeFunc = (RoUninitialize_t)WIN_LoadComBaseFunction("RoUninitialize");
if (RoUninitializeFunc) {
RoUninitializeFunc();
}
#endif
}

View File

@ -63,10 +63,19 @@ extern int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr);
/* Sets an error message based on GetLastError(). Always return -1. */
extern int WIN_SetError(const char *prefix);
#if !defined(__WINRT__)
/* Load a function from combase.dll */
void *WIN_LoadComBaseFunction(const char *name);
#endif
/* Wrap up the oddities of CoInitialize() into a common function. */
extern HRESULT WIN_CoInitialize(void);
extern void WIN_CoUninitialize(void);
/* Wrap up the oddities of RoInitialize() into a common function. */
extern HRESULT WIN_RoInitialize(void);
extern void WIN_RoUninitialize(void);
/* Returns SDL_TRUE if we're running on Windows Vista and newer */
extern BOOL WIN_IsWindowsVistaOrGreater(void);

View File

@ -638,6 +638,7 @@ SDL_SetKeyboardFocus(SDL_Window * window)
/* old window must lose an existing mouse capture. */
if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) {
SDL_CaptureMouse(SDL_FALSE); /* drop the capture. */
SDL_UpdateMouseCapture(SDL_TRUE);
SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE));
}

View File

@ -109,6 +109,28 @@ SDL_TouchMouseEventsChanged(void *userdata, const char *name, const char *oldVal
mouse->touch_mouse_events = SDL_GetStringBoolean(hint, SDL_TRUE);
}
#if defined(__vita__)
static void SDLCALL
SDL_VitaTouchMouseDeviceChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
if (hint) {
switch(*hint) {
default:
case '0':
mouse->vita_touch_mouse_device = 0;
break;
case '1':
mouse->vita_touch_mouse_device = 1;
break;
case '2':
mouse->vita_touch_mouse_device = 2;
break;
}
}
}
#endif
static void SDLCALL
SDL_MouseTouchEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
@ -134,12 +156,8 @@ SDL_MouseAutoCaptureChanged(void *userdata, const char *name, const char *oldVal
SDL_bool auto_capture = SDL_GetStringBoolean(hint, SDL_TRUE);
if (auto_capture != mouse->auto_capture) {
/* Turn off mouse capture if it's currently active because of button presses */
if (!auto_capture && SDL_GetMouseState(NULL, NULL) != 0) {
SDL_CaptureMouse(SDL_FALSE);
}
mouse->auto_capture = auto_capture;
SDL_UpdateMouseCapture(SDL_FALSE);
}
}
@ -166,6 +184,11 @@ SDL_MouseInit(void)
SDL_AddHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS,
SDL_TouchMouseEventsChanged, mouse);
#if defined(__vita__)
SDL_AddHintCallback(SDL_HINT_VITA_TOUCH_MOUSE_DEVICE,
SDL_VitaTouchMouseDeviceChanged, mouse);
#endif
SDL_AddHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS,
SDL_MouseTouchEventsChanged, mouse);
@ -538,7 +561,6 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state
Uint32 type;
Uint32 buttonstate;
SDL_MouseInputSource *source;
SDL_bool had_buttons_pressed = (SDL_GetMouseState(NULL, NULL) ? SDL_TRUE : SDL_FALSE);
source = GetMouseInputSource(mouse, mouseID);
if (!source) {
@ -641,10 +663,7 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state
/* Automatically capture the mouse while buttons are pressed */
if (mouse->auto_capture) {
SDL_bool has_buttons_pressed = (SDL_GetMouseState(NULL, NULL) ? SDL_TRUE : SDL_FALSE);
if (has_buttons_pressed != had_buttons_pressed) {
SDL_CaptureMouse(has_buttons_pressed);
}
SDL_UpdateMouseCapture(SDL_FALSE);
}
return posted;
@ -741,6 +760,7 @@ SDL_MouseQuit(void)
if (mouse->CaptureMouse) {
SDL_CaptureMouse(SDL_FALSE);
SDL_UpdateMouseCapture(SDL_TRUE);
}
SDL_SetRelativeMouseMode(SDL_FALSE);
SDL_ShowCursor(1);
@ -945,6 +965,8 @@ SDL_SetRelativeMouseMode(SDL_bool enabled)
if (!enabled) {
SDL_WarpMouseInWindow(focusWindow, mouse->x, mouse->y);
}
SDL_UpdateMouseCapture(SDL_FALSE);
}
if (!enabled) {
@ -966,39 +988,59 @@ SDL_GetRelativeMouseMode()
return mouse->relative_mode;
}
int
SDL_UpdateMouseCapture(SDL_bool force_release)
{
SDL_Mouse *mouse = SDL_GetMouse();
SDL_Window *capture_window = NULL;
if (!mouse->CaptureMouse) {
return 0;
}
if (!force_release) {
if (mouse->capture_desired || (mouse->auto_capture && SDL_GetMouseState(NULL, NULL) != 0)) {
if (!mouse->relative_mode) {
capture_window = SDL_GetKeyboardFocus();
}
}
}
if (capture_window != mouse->capture_window) {
if (mouse->capture_window) {
mouse->CaptureMouse(NULL);
mouse->capture_window->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
mouse->capture_window = NULL;
}
if (capture_window) {
if (mouse->CaptureMouse(capture_window) < 0) {
/* CaptureMouse() will have set an error */
return -1;
}
capture_window->flags |= SDL_WINDOW_MOUSE_CAPTURE;
}
mouse->capture_window = capture_window;
}
return 0;
}
int
SDL_CaptureMouse(SDL_bool enabled)
{
SDL_Mouse *mouse = SDL_GetMouse();
SDL_Window *focusWindow;
SDL_bool isCaptured;
if (!mouse->CaptureMouse) {
return SDL_Unsupported();
}
focusWindow = SDL_GetKeyboardFocus();
isCaptured = focusWindow && (focusWindow->flags & SDL_WINDOW_MOUSE_CAPTURE);
if (isCaptured == enabled) {
return 0; /* already done! */
if (enabled && SDL_GetKeyboardFocus() == NULL) {
return SDL_SetError("No window has focus");
}
mouse->capture_desired = enabled;
if (enabled) {
if (!focusWindow) {
return SDL_SetError("No window has focus");
} else if (mouse->CaptureMouse(focusWindow) == -1) {
return -1; /* CaptureMouse() should call SetError */
}
focusWindow->flags |= SDL_WINDOW_MOUSE_CAPTURE;
} else {
if (mouse->CaptureMouse(NULL) == -1) {
return -1; /* CaptureMouse() should call SetError */
}
focusWindow->flags &= ~SDL_WINDOW_MOUSE_CAPTURE;
}
return 0;
return SDL_UpdateMouseCapture(SDL_FALSE);
}
SDL_Cursor *

View File

@ -100,7 +100,12 @@ typedef struct
SDL_bool touch_mouse_events;
SDL_bool mouse_touch_events;
SDL_bool was_touch_mouse_events; /* Was a touch-mouse event pending? */
#if defined(__vita__)
Uint8 vita_touch_mouse_device;
#endif
SDL_bool auto_capture;
SDL_bool capture_desired;
SDL_Window *capture_window;
/* Data for input source state */
int num_sources;
@ -132,6 +137,9 @@ extern void SDL_SetDefaultCursor(SDL_Cursor * cursor);
/* Set the mouse focus window */
extern void SDL_SetMouseFocus(SDL_Window * window);
/* Update the mouse capture window */
extern int SDL_UpdateMouseCapture(SDL_bool force_release);
/* Send a mouse motion event */
extern int SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y);

View File

@ -265,8 +265,13 @@ SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window * window,
#if SYNTHESIZE_TOUCH_TO_MOUSE
/* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
/* SDL_HINT_VITA_TOUCH_MOUSE_DEVICE: controlling which touchpad should generate synthetic mouse events, PSVita-only */
{
#if defined(__vita__)
if (mouse->touch_mouse_events && ((mouse->vita_touch_mouse_device == id) || (mouse->vita_touch_mouse_device == 2)) ) {
#else
if (mouse->touch_mouse_events) {
#endif
/* FIXME: maybe we should only restrict to a few SDL_TouchDeviceType */
if (id != SDL_MOUSE_TOUCHID) {
if (window) {

View File

@ -1185,9 +1185,9 @@ struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned
#ifdef SDL_LIBUSB_DYNAMIC
if (libusb_ctx.libhandle) {
usb_devs = LIBUSB_hid_enumerate(vendor_id, product_id);
#ifdef DEBUG_HIDAPI
#ifdef DEBUG_HIDAPI
SDL_Log("libusb devices found:");
#endif
#endif
for (usb_dev = usb_devs; usb_dev; usb_dev = usb_dev->next) {
new_dev = (struct SDL_hid_device_info*) SDL_malloc(sizeof(struct SDL_hid_device_info));
if (!new_dev) {
@ -1197,11 +1197,11 @@ struct SDL_hid_device_info *SDL_hid_enumerate(unsigned short vendor_id, unsigned
return NULL;
}
CopyHIDDeviceInfo(usb_dev, new_dev);
#ifdef DEBUG_HIDAPI
#ifdef DEBUG_HIDAPI
SDL_Log(" - %ls %ls 0x%.4hx 0x%.4hx",
usb_dev->manufacturer_string, usb_dev->product_string,
usb_dev->vendor_id, usb_dev->product_id);
#endif
#endif
if (last != NULL) {
last->next = new_dev;

View File

@ -747,7 +747,11 @@ HIDAPI_DriverPS5_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joy
}
}
return SDL_HIDAPI_SendRumbleAndUnlock(device, data, report_size);
if (SDL_HIDAPI_SendRumbleAndUnlock(device, data, report_size) != report_size) {
return -1;
}
return 0;
}
static int

View File

@ -109,6 +109,7 @@ typedef struct SDL_joylist_item
/* Steam Controller support */
SDL_bool m_bSteamController;
SDL_bool checked_mapping;
SDL_GamepadMapping *mapping;
} SDL_joylist_item;
@ -605,6 +606,26 @@ LINUX_InotifyJoystickDetect(void)
}
#endif /* HAVE_INOTIFY */
static int get_event_joystick_index(int event)
{
int joystick_index = -1;
int i, count;
struct dirent **entries = NULL;
char path[PATH_MAX];
SDL_snprintf(path, SDL_arraysize(path), "/sys/class/input/event%d/device", event);
count = scandir(path, &entries, NULL, alphasort);
for (i = 0; i < count; ++i) {
if (SDL_strncmp(entries[i]->d_name, "js", 2) == 0) {
joystick_index = SDL_atoi(entries[i]->d_name+2);
}
free(entries[i]); /* This should NOT be SDL_free() */
}
free(entries); /* This should NOT be SDL_free() */
return joystick_index;
}
/* Detect devices by reading /dev/input. In the inotify code path we
* have to do this the first time, to detect devices that already existed
* before we started; in the non-inotify code path we do this repeatedly
@ -617,10 +638,35 @@ filter_entries(const struct dirent *entry)
static int
sort_entries(const struct dirent **a, const struct dirent **b)
{
int numA = SDL_atoi((*a)->d_name+5);
int numB = SDL_atoi((*b)->d_name+5);
int numA, numB;
int offset;
if (SDL_classic_joysticks) {
offset = 2; /* strlen("js") */
numA = SDL_atoi((*a)->d_name+offset);
numB = SDL_atoi((*b)->d_name+offset);
} else {
offset = 5; /* strlen("event") */
numA = SDL_atoi((*a)->d_name+offset);
numB = SDL_atoi((*b)->d_name+offset);
/* See if we can get the joystick ordering */
{
int jsA = get_event_joystick_index(numA);
int jsB = get_event_joystick_index(numB);
if (jsA >= 0 && jsB >= 0) {
numA = jsA;
numB = jsB;
} else if (jsA >= 0) {
return -1;
} else if (jsB >= 0) {
return 1;
}
}
}
return (numA - numB);
}
static void
LINUX_FallbackJoystickDetect(void)
{
@ -633,7 +679,7 @@ LINUX_FallbackJoystickDetect(void)
/* Opening input devices can generate synchronous device I/O, so avoid it if we can */
if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) {
int i, count;
struct dirent **entries;
struct dirent **entries = NULL;
char path[PATH_MAX];
count = scandir("/dev/input", &entries, filter_entries, sort_entries);
@ -683,29 +729,7 @@ LINUX_JoystickInit(void)
SDL_classic_joysticks = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_CLASSIC, SDL_FALSE);
#if SDL_USE_LIBUDEV
if (enumeration_method == ENUMERATION_UNSET) {
if (SDL_GetHintBoolean("SDL_JOYSTICK_DISABLE_UDEV", SDL_FALSE)) {
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
"udev disabled by SDL_JOYSTICK_DISABLE_UDEV");
enumeration_method = ENUMERATION_FALLBACK;
} else if (access("/.flatpak-info", F_OK) == 0
|| access("/run/host/container-manager", F_OK) == 0) {
/* Explicitly check `/.flatpak-info` because, for old versions of
* Flatpak, this was the only available way to tell if we were in
* a Flatpak container. */
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
"Container detected, disabling udev integration");
enumeration_method = ENUMERATION_FALLBACK;
} else {
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
"Using udev for joystick device discovery");
enumeration_method = ENUMERATION_LIBUDEV;
}
}
#endif
enumeration_method = ENUMERATION_UNSET;
/* First see if the user specified one or more joysticks to use */
if (devices != NULL) {
@ -734,6 +758,28 @@ LINUX_JoystickInit(void)
LINUX_JoystickDetect();
#if SDL_USE_LIBUDEV
if (enumeration_method == ENUMERATION_UNSET) {
if (SDL_GetHintBoolean("SDL_JOYSTICK_DISABLE_UDEV", SDL_FALSE)) {
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
"udev disabled by SDL_JOYSTICK_DISABLE_UDEV");
enumeration_method = ENUMERATION_FALLBACK;
} else if (access("/.flatpak-info", F_OK) == 0
|| access("/run/host/container-manager", F_OK) == 0) {
/* Explicitly check `/.flatpak-info` because, for old versions of
* Flatpak, this was the only available way to tell if we were in
* a Flatpak container. */
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
"Container detected, disabling udev integration");
enumeration_method = ENUMERATION_FALLBACK;
} else {
SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
"Using udev for joystick device discovery");
enumeration_method = ENUMERATION_LIBUDEV;
}
}
if (enumeration_method == ENUMERATION_LIBUDEV) {
if (SDL_UDEV_Init() < 0) {
return SDL_SetError("Could not initialize UDEV");
@ -1573,9 +1619,13 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
SDL_Joystick *joystick;
SDL_joylist_item *item = JoystickByDevIndex(device_index);
if (item->mapping) {
SDL_memcpy(out, item->mapping, sizeof(*out));
return SDL_TRUE;
if (item->checked_mapping) {
if (item->mapping) {
SDL_memcpy(out, item->mapping, sizeof(*out));
return SDL_TRUE;
} else {
return SDL_FALSE;
}
}
/* We temporarily open the device to check how it's configured. Make
@ -1595,6 +1645,8 @@ LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
return SDL_FALSE;
}
item->checked_mapping = SDL_TRUE;
if (PrepareJoystickHwdata(joystick, item) == -1) {
SDL_free(joystick->hwdata);
SDL_free(joystick);

View File

@ -62,6 +62,7 @@ typedef struct WindowsGamingInputGamepadState WindowsGamingInputGamepadState;
#define GamepadButtons_GUIDE 0x40000000
#define COBJMACROS
#include "windows.gaming.input.h"
#include <roapi.h>
#endif
#if defined(SDL_JOYSTICK_RAWINPUT_XINPUT) || defined(SDL_JOYSTICK_RAWINPUT_WGI)
@ -565,22 +566,24 @@ RAWINPUT_InitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
if (!wgi_state.initialized) {
static const IID SDL_IID_IGamepadStatics = { 0x8BBCE529, 0xD49C, 0x39E9, { 0x95, 0x60, 0xE4, 0x7D, 0xDE, 0x96, 0xB7, 0xC8 } };
HRESULT hr;
HMODULE hModule;
/* I think this takes care of RoInitialize() in a way that is compatible with the rest of SDL */
if (FAILED(WIN_CoInitialize())) {
if (FAILED(WIN_RoInitialize())) {
return;
}
wgi_state.initialized = SDL_TRUE;
wgi_state.dirty = SDL_TRUE;
hModule = LoadLibraryA("combase.dll");
if (hModule != NULL) {
{
typedef HRESULT (WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING* string);
typedef HRESULT (WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void** factory);
WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)GetProcAddress(hModule, "WindowsCreateStringReference");
RoGetActivationFactory_t RoGetActivationFactoryFunc = (RoGetActivationFactory_t)GetProcAddress(hModule, "RoGetActivationFactory");
#ifdef __WINRT__
WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = WindowsCreateStringReference;
RoGetActivationFactory_t RoGetActivationFactoryFunc = RoGetActivationFactory;
#else
WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
RoGetActivationFactory_t RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
#endif
if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) {
PCWSTR pNamespace = L"Windows.Gaming.Input.Gamepad";
HSTRING_HEADER hNamespaceStringHeader;
@ -591,7 +594,6 @@ RAWINPUT_InitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
RoGetActivationFactoryFunc(hNamespaceString, &SDL_IID_IGamepadStatics, (void **)&wgi_state.gamepad_statics);
}
}
FreeLibrary(hModule);
}
}
}
@ -657,7 +659,7 @@ RAWINPUT_QuitWindowsGamingInput(RAWINPUT_DeviceContext *ctx)
__x_ABI_CWindows_CGaming_CInput_CIGamepadStatics_Release(wgi_state.gamepad_statics);
wgi_state.gamepad_statics = NULL;
}
WIN_CoUninitialize();
WIN_RoUninitialize();
wgi_state.initialized = SDL_FALSE;
}
}

View File

@ -260,10 +260,9 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
WindowsGetStringRawBufferFunc = WindowsGetStringRawBuffer;
WindowsDeleteStringFunc = WindowsDeleteString;
#else
HMODULE hModule = LoadLibraryA("combase.dll");
if (hModule != NULL) {
WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)GetProcAddress(hModule, "WindowsGetStringRawBuffer");
WindowsDeleteStringFunc = (WindowsDeleteString_t)GetProcAddress(hModule, "WindowsDeleteString");
{
WindowsGetStringRawBufferFunc = (WindowsGetStringRawBuffer_t)WIN_LoadComBaseFunction("WindowsGetStringRawBuffer");
WindowsDeleteStringFunc = (WindowsDeleteString_t)WIN_LoadComBaseFunction("WindowsDeleteString");
}
#endif /* __WINRT__ */
if (WindowsGetStringRawBufferFunc && WindowsDeleteStringFunc) {
@ -277,11 +276,6 @@ static HRESULT STDMETHODCALLTYPE IEventHandler_CRawGameControllerVtbl_InvokeAdde
WindowsDeleteStringFunc(hString);
}
}
#ifndef __WINRT__
if (hModule != NULL) {
FreeLibrary(hModule);
}
#endif
__x_ABI_CWindows_CGaming_CInput_CIRawGameController2_Release(controller2);
}
if (!name) {
@ -444,23 +438,19 @@ WGI_JoystickInit(void)
WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = NULL;
RoGetActivationFactory_t RoGetActivationFactoryFunc = NULL;
#ifndef __WINRT__
HMODULE hModule;
#endif
HRESULT hr;
if (FAILED(WIN_CoInitialize())) {
return SDL_SetError("CoInitialize() failed");
if (FAILED(WIN_RoInitialize())) {
return SDL_SetError("RoInitialize() failed");
}
#ifdef __WINRT__
WindowsCreateStringReferenceFunc = WindowsCreateStringReference;
RoGetActivationFactoryFunc = RoGetActivationFactory;
#else
hModule = LoadLibraryA("combase.dll");
if (hModule != NULL) {
WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)GetProcAddress(hModule, "WindowsCreateStringReference");
RoGetActivationFactoryFunc = (RoGetActivationFactory_t)GetProcAddress(hModule, "RoGetActivationFactory");
{
WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
}
#endif /* __WINRT__ */
if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc) {
@ -519,11 +509,6 @@ WGI_JoystickInit(void)
}
}
}
#ifndef __WINRT__
if (hModule != NULL) {
FreeLibrary(hModule);
}
#endif
if (wgi.statics) {
__FIVectorView_1_Windows__CGaming__CInput__CRawGameController *controllers;
@ -865,7 +850,7 @@ WGI_JoystickQuit(void)
}
SDL_zero(wgi);
WIN_CoUninitialize();
WIN_RoUninitialize();
}
static SDL_bool

View File

@ -0,0 +1,71 @@
/*
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.
*/
#include "../../SDL_internal.h"
#include "../SDL_syslocale.h"
#include <psp2/apputil.h>
#include <psp2/system_param.h>
void
SDL_SYS_GetPreferredLocales(char *buf, size_t buflen)
{
const char *vita_locales[] = {
"ja_JP",
"en_US",
"fr_FR",
"es_ES",
"de_DE",
"it_IT",
"nl_NL",
"pt_PT",
"ru_RU",
"ko_KR",
"zh_TW",
"zh_CN",
"fi_FI",
"sv_SE",
"da_DK",
"no_NO",
"pl_PL",
"pt_BR",
"en_GB",
"tr_TR",
};
Sint32 language = SCE_SYSTEM_PARAM_LANG_ENGLISH_US;
SceAppUtilInitParam initParam;
SceAppUtilBootParam bootParam;
SDL_zero(initParam);
SDL_zero(bootParam);
sceAppUtilInit(&initParam, &bootParam);
sceAppUtilSystemParamGetInt(SCE_SYSTEM_PARAM_ID_LANG, &language);
if (language < 0 || language > SCE_SYSTEM_PARAM_LANG_TURKISH)
language = SCE_SYSTEM_PARAM_LANG_ENGLISH_US; // default to english
SDL_strlcpy(buf, vita_locales[language], buflen);
sceAppUtilShutdown();
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,21,0
PRODUCTVERSION 2,0,21,0
FILEVERSION 2,0,22,0
PRODUCTVERSION 2,0,22,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
@ -23,12 +23,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SDL\0"
VALUE "FileVersion", "2, 0, 21, 0\0"
VALUE "FileVersion", "2, 0, 22, 0\0"
VALUE "InternalName", "SDL\0"
VALUE "LegalCopyright", "Copyright (C) 2022 Sam Lantinga\0"
VALUE "OriginalFilename", "SDL2.dll\0"
VALUE "ProductName", "Simple DirectMedia Layer\0"
VALUE "ProductVersion", "2, 0, 21, 0\0"
VALUE "ProductVersion", "2, 0, 22, 0\0"
END
END
BLOCK "VarFileInfo"

View File

@ -580,10 +580,10 @@ QueueCmdFillRects(SDL_Renderer *renderer, const SDL_FRect * rects, const int cou
if (retval < 0) {
cmd->command = SDL_RENDERCMD_NO_OP;
}
SDL_small_free(xy, isstack1);
SDL_small_free(indices, isstack2);
}
SDL_small_free(xy, isstack1);
SDL_small_free(indices, isstack2);
} else {
retval = renderer->QueueFillRects(renderer, cmd, rects, count);
if (retval < 0) {
@ -698,7 +698,17 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
renderer->WindowEvent(renderer, &event->window);
}
if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
/* In addition to size changes, we also want to do this block for
* moves as well, for two reasons:
*
* 1. The window could be moved to a new display, which has a new
* DPI and therefore a new window/drawable ratio
* 2. For whatever reason, the viewport can get messed up during
* window movement (this has been observed on macOS), so this is
* also a good opportunity to force viewport updates
*/
if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED ||
event->window.event == SDL_WINDOWEVENT_MOVED) {
/* Make sure we're operating on the default render target */
SDL_Texture *saved_target = SDL_GetRenderTarget(renderer);
if (saved_target) {
@ -1592,10 +1602,11 @@ SDL_SetTextureScaleMode(SDL_Texture * texture, SDL_ScaleMode scaleMode)
CHECK_TEXTURE_MAGIC(texture, -1);
renderer = texture->renderer;
renderer->SetTextureScaleMode(renderer, texture, scaleMode);
texture->scaleMode = scaleMode;
if (texture->native) {
return SDL_SetTextureScaleMode(texture->native, scaleMode);
} else {
renderer->SetTextureScaleMode(renderer, texture, scaleMode);
}
return 0;
}

View File

@ -347,7 +347,8 @@ D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
}
}
static D3DBLEND GetBlendFunc(SDL_BlendFactor factor)
static D3DBLEND
GetBlendFunc(SDL_BlendFactor factor)
{
switch (factor) {
case SDL_BLENDFACTOR_ZERO:
@ -370,9 +371,28 @@ static D3DBLEND GetBlendFunc(SDL_BlendFactor factor)
return D3DBLEND_DESTALPHA;
case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
return D3DBLEND_INVDESTALPHA;
default:
return (D3DBLEND)0;
default: break;
}
return (D3DBLEND) 0;
}
static D3DBLENDOP
GetBlendEquation(SDL_BlendOperation operation)
{
switch (operation) {
case SDL_BLENDOPERATION_ADD:
return D3DBLENDOP_ADD;
case SDL_BLENDOPERATION_SUBTRACT:
return D3DBLENDOP_SUBTRACT;
case SDL_BLENDOPERATION_REV_SUBTRACT:
return D3DBLENDOP_REVSUBTRACT;
case SDL_BLENDOPERATION_MINIMUM:
return D3DBLENDOP_MIN;
case SDL_BLENDOPERATION_MAXIMUM:
return D3DBLENDOP_MAX;
default: break;
}
return (D3DBLENDOP) 0;
}
static SDL_bool
@ -387,14 +407,16 @@ D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
if (!GetBlendFunc(srcColorFactor) || !GetBlendFunc(srcAlphaFactor) ||
!GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor)) {
!GetBlendEquation(colorOperation) ||
!GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor) ||
!GetBlendEquation(alphaOperation)) {
return SDL_FALSE;
}
if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->enableSeparateAlphaBlend) {
return SDL_FALSE;
}
if (colorOperation != SDL_BLENDOPERATION_ADD || alphaOperation != SDL_BLENDOPERATION_ADD) {
return SDL_FALSE;
if (!data->enableSeparateAlphaBlend) {
if ((srcColorFactor != srcAlphaFactor) || (dstColorFactor != dstAlphaFactor) || (colorOperation != alphaOperation)) {
return SDL_FALSE;
}
}
return SDL_TRUE;
}
@ -1040,11 +1062,15 @@ SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd)
GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)));
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,
GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)));
IDirect3DDevice9_SetRenderState(data->device, D3DRS_BLENDOP,
GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
if (data->enableSeparateAlphaBlend) {
IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,
GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)));
IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,
GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
IDirect3DDevice9_SetRenderState(data->device, D3DRS_BLENDOPALPHA,
GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
}
}

View File

@ -998,6 +998,16 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
goto done;
}
/* Set the swap chain target immediately, so that a target is always set
* even before we get to SetDrawState. Without this it's possible to hit
* null references in places like ReadPixels!
*/
ID3D11DeviceContext_OMSetRenderTargets(data->d3dContext,
1,
&data->mainRenderTargetView,
NULL
);
data->viewportDirty = SDL_TRUE;
done:

View File

@ -30,6 +30,11 @@
#include <OpenGL/OpenGL.h>
#endif
#ifdef SDL_VIDEO_VITA_PVR_OGL
#include <GL/gl.h>
#include <GL/glext.h>
#endif
/* To prevent unnecessary window recreation,
* these should match the defaults selected in SDL_GL_ResetAttributes
*/
@ -319,6 +324,20 @@ GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h)
return result;
}
static void
GL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
{
/* If the window x/y/w/h changed at all, assume the viewport has been
* changed behind our backs. x/y changes might seem weird but viewport
* resets have been observed on macOS at minimum!
*/
if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
event->event == SDL_WINDOWEVENT_MOVED) {
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
data->drawstate.viewport_dirty = SDL_TRUE;
}
}
static int
GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
{
@ -1211,13 +1230,6 @@ GL_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
}
}
#ifdef __MACOSX__
// On macOS, moving the window seems to invalidate the OpenGL viewport state,
// so don't bother trying to persist it across frames; always reset it.
// Workaround for: https://github.com/libsdl-org/SDL/issues/1504
data->drawstate.viewport_dirty = SDL_TRUE;
#endif
while (cmd) {
switch (cmd->command) {
case SDL_RENDERCMD_SETDRAWCOLOR: {
@ -1733,6 +1745,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
#ifndef SDL_VIDEO_VITA_PVR_OGL
window_flags = SDL_GetWindowFlags(window);
if (!(window_flags & SDL_WINDOW_OPENGL) ||
profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
@ -1746,6 +1759,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
goto error;
}
}
#endif
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
@ -1760,6 +1774,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
goto error;
}
renderer->WindowEvent = GL_WindowEvent;
renderer->GetOutputSize = GL_GetOutputSize;
renderer->SupportsBlendMode = GL_SupportsBlendMode;
renderer->CreateTexture = GL_CreateTexture;

View File

@ -1246,7 +1246,7 @@ VITA_GXM_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
sceGxmFinish(data->gxm_context);
free_gxm_texture(vita_texture->tex);
free_gxm_texture(data, vita_texture->tex);
SDL_free(vita_texture);

View File

@ -26,7 +26,7 @@
#include "SDL_render_vita_gxm_memory.h"
void *
mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid)
vita_mem_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid)
{
void *mem;
@ -51,7 +51,7 @@ mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignm
}
void
mem_gpu_free(SceUID uid)
vita_mem_free(SceUID uid)
{
void *mem = NULL;
if (sceKernelGetMemBlockBase(uid, &mem) < 0)
@ -61,7 +61,71 @@ mem_gpu_free(SceUID uid)
}
void *
mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size)
{
void *mem;
if (data->texturePool == NULL) {
int poolsize;
int ret;
SceKernelFreeMemorySizeInfo info;
info.size = sizeof(SceKernelFreeMemorySizeInfo);
sceKernelGetFreeMemorySize(&info);
poolsize = ALIGN(info.size_cdram, 256*1024);
if (poolsize > info.size_cdram) {
poolsize = ALIGN(info.size_cdram - 256*1024, 256*1024);
}
data->texturePoolUID = sceKernelAllocMemBlock("gpu_texture_pool", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, poolsize, NULL);
if (data->texturePoolUID < 0) {
return NULL;
}
ret = sceKernelGetMemBlockBase(data->texturePoolUID, &mem);
if ( ret < 0)
{
return NULL;
}
data->texturePool = sceClibMspaceCreate(mem, poolsize);
if (data->texturePool == NULL) {
return NULL;
}
ret = sceGxmMapMemory(mem, poolsize, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE);
if (ret < 0)
{
return NULL;
}
}
return sceClibMspaceMemalign(data->texturePool, SCE_GXM_TEXTURE_ALIGNMENT, size);
}
void
vita_gpu_mem_free(VITA_GXM_RenderData *data, void* ptr)
{
if (data->texturePool != NULL)
{
sceClibMspaceFree(data->texturePool, ptr);
}
}
void
vita_gpu_mem_destroy(VITA_GXM_RenderData *data)
{
void *mem = NULL;
if (data->texturePool != NULL)
{
sceClibMspaceDestroy(data->texturePool);
data->texturePool = NULL;
if (sceKernelGetMemBlockBase(data->texturePoolUID, &mem) < 0)
return;
sceGxmUnmapMemory(mem);
sceKernelFreeMemBlock(data->texturePoolUID);
}
}
void *
vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
{
void *mem = NULL;
@ -77,7 +141,7 @@ mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
}
void
mem_vertex_usse_free(SceUID uid)
vita_mem_vertex_usse_free(SceUID uid)
{
void *mem = NULL;
if (sceKernelGetMemBlockBase(uid, &mem) < 0)
@ -87,7 +151,7 @@ mem_vertex_usse_free(SceUID uid)
}
void *
mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset)
{
void *mem = NULL;
@ -103,7 +167,7 @@ mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offse
}
void
mem_fragment_usse_free(SceUID uid)
vita_mem_fragment_usse_free(SceUID uid)
{
void *mem = NULL;
if (sceKernelGetMemBlockBase(uid, &mem) < 0)

View File

@ -25,15 +25,19 @@
#include <psp2/gxm.h>
#include <psp2/types.h>
#include <psp2/kernel/sysmem.h>
#include "SDL_render_vita_gxm_types.h"
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
void *mem_gpu_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid);
void mem_gpu_free(SceUID uid);
void *mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
void mem_vertex_usse_free(SceUID uid);
void *mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
void mem_fragment_usse_free(SceUID uid);
void *vita_mem_alloc(SceKernelMemBlockType type, unsigned int size, unsigned int alignment, unsigned int attribs, SceUID *uid);
void vita_mem_free(SceUID uid);
void *vita_gpu_mem_alloc(VITA_GXM_RenderData *data, unsigned int size);
void vita_gpu_mem_free(VITA_GXM_RenderData *data, void* ptr);
void vita_gpu_mem_destroy(VITA_GXM_RenderData *data);
void *vita_mem_vertex_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
void vita_mem_vertex_usse_free(SceUID uid);
void *vita_mem_fragment_usse_alloc(unsigned int size, SceUID *uid, unsigned int *usse_offset);
void vita_mem_fragment_usse_free(SceUID uid);
#endif /* SDL_RENDER_VITA_GXM_MEMORY_H */

View File

@ -416,28 +416,28 @@ gxm_init(SDL_Renderer *renderer)
}
// allocate ring buffer memory using default sizes
vdmRingBuffer = mem_gpu_alloc(
vdmRingBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE,
4,
SCE_GXM_MEMORY_ATTRIB_READ,
&data->vdmRingBufferUid);
vertexRingBuffer = mem_gpu_alloc(
vertexRingBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE,
4,
SCE_GXM_MEMORY_ATTRIB_READ,
&data->vertexRingBufferUid);
fragmentRingBuffer = mem_gpu_alloc(
fragmentRingBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE,
4,
SCE_GXM_MEMORY_ATTRIB_READ,
&data->fragmentRingBufferUid);
fragmentUsseRingBuffer = mem_fragment_usse_alloc(
fragmentUsseRingBuffer = vita_mem_fragment_usse_alloc(
SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE,
&data->fragmentUsseRingBufferUid,
&fragmentUsseRingBufferOffset);
@ -482,7 +482,7 @@ gxm_init(SDL_Renderer *renderer)
for (i = 0; i < VITA_GXM_BUFFERS; i++) {
// allocate memory for display
data->displayBufferData[i] = mem_gpu_alloc(
data->displayBufferData[i] = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
@ -527,7 +527,7 @@ gxm_init(SDL_Renderer *renderer)
// allocate the depth buffer
data->depthBufferData = mem_gpu_alloc(
data->depthBufferData = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
4 * sampleCount,
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@ -535,7 +535,7 @@ gxm_init(SDL_Renderer *renderer)
&data->depthBufferUid);
// allocate the stencil buffer
data->stencilBufferData = mem_gpu_alloc(
data->stencilBufferData = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
4 * sampleCount,
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@ -567,19 +567,19 @@ gxm_init(SDL_Renderer *renderer)
// allocate memory for buffers and USSE code
patcherBuffer = mem_gpu_alloc(
patcherBuffer = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
patcherBufferSize,
4,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&data->patcherBufferUid);
patcherVertexUsse = mem_vertex_usse_alloc(
patcherVertexUsse = vita_mem_vertex_usse_alloc(
patcherVertexUsseSize,
&data->patcherVertexUsseUid,
&patcherVertexUsseOffset);
patcherFragmentUsse = mem_fragment_usse_alloc(
patcherFragmentUsse = vita_mem_fragment_usse_alloc(
patcherFragmentUsseSize,
&data->patcherFragmentUsseUid,
&patcherFragmentUsseOffset);
@ -730,7 +730,7 @@ gxm_init(SDL_Renderer *renderer)
}
// create the clear triangle vertex/index data
data->clearVertices = (clear_vertex *)mem_gpu_alloc(
data->clearVertices = (clear_vertex *)vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
3*sizeof(clear_vertex),
4,
@ -742,7 +742,7 @@ gxm_init(SDL_Renderer *renderer)
// Allocate a 64k * 2 bytes = 128 KiB buffer and store all possible
// 16-bit indices in linear ascending order, so we can use this for
// all drawing operations where we don't want to use indexing.
data->linearIndices = (uint16_t *)mem_gpu_alloc(
data->linearIndices = (uint16_t *)vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
UINT16_MAX*sizeof(uint16_t),
sizeof(uint16_t),
@ -873,7 +873,7 @@ gxm_init(SDL_Renderer *renderer)
data->textureWvpParam = (SceGxmProgramParameter *)sceGxmProgramFindParameterByName(textureVertexProgramGxp, "wvp");
// Allocate memory for the memory pool
data->pool_addr[0] = mem_gpu_alloc(
data->pool_addr[0] = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW,
VITA_GXM_POOL_SIZE,
sizeof(void *),
@ -881,7 +881,7 @@ gxm_init(SDL_Renderer *renderer)
&data->poolUid[0]
);
data->pool_addr[1] = mem_gpu_alloc(
data->pool_addr[1] = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW,
VITA_GXM_POOL_SIZE,
sizeof(void *),
@ -920,28 +920,28 @@ void gxm_finish(SDL_Renderer *renderer)
free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mod);
free_fragment_programs(data, &data->blendFragmentPrograms.blend_mode_mul);
mem_gpu_free(data->linearIndicesUid);
mem_gpu_free(data->clearVerticesUid);
vita_mem_free(data->linearIndicesUid);
vita_mem_free(data->clearVerticesUid);
// wait until display queue is finished before deallocating display buffers
sceGxmDisplayQueueFinish();
// clean up display queue
mem_gpu_free(data->depthBufferUid);
vita_mem_free(data->depthBufferUid);
for (size_t i = 0; i < VITA_GXM_BUFFERS; i++)
{
// clear the buffer then deallocate
SDL_memset(data->displayBufferData[i], 0, VITA_GXM_SCREEN_HEIGHT * VITA_GXM_SCREEN_STRIDE * 4);
mem_gpu_free(data->displayBufferUid[i]);
vita_mem_free(data->displayBufferUid[i]);
// destroy the sync object
sceGxmSyncObjectDestroy(data->displayBufferSync[i]);
}
// Free the depth and stencil buffer
mem_gpu_free(data->depthBufferUid);
mem_gpu_free(data->stencilBufferUid);
vita_mem_free(data->depthBufferUid);
vita_mem_free(data->stencilBufferUid);
// unregister programs and destroy shader patcher
sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->clearFragmentProgramId);
@ -952,23 +952,24 @@ void gxm_finish(SDL_Renderer *renderer)
sceGxmShaderPatcherUnregisterProgram(data->shaderPatcher, data->textureVertexProgramId);
sceGxmShaderPatcherDestroy(data->shaderPatcher);
mem_fragment_usse_free(data->patcherFragmentUsseUid);
mem_vertex_usse_free(data->patcherVertexUsseUid);
mem_gpu_free(data->patcherBufferUid);
vita_mem_fragment_usse_free(data->patcherFragmentUsseUid);
vita_mem_vertex_usse_free(data->patcherVertexUsseUid);
vita_mem_free(data->patcherBufferUid);
// destroy the render target
sceGxmDestroyRenderTarget(data->renderTarget);
// destroy the gxm context
sceGxmDestroyContext(data->gxm_context);
mem_fragment_usse_free(data->fragmentUsseRingBufferUid);
mem_gpu_free(data->fragmentRingBufferUid);
mem_gpu_free(data->vertexRingBufferUid);
mem_gpu_free(data->vdmRingBufferUid);
vita_mem_fragment_usse_free(data->fragmentUsseRingBufferUid);
vita_mem_free(data->fragmentRingBufferUid);
vita_mem_free(data->vertexRingBufferUid);
vita_mem_free(data->vdmRingBufferUid);
SDL_free(data->contextParams.hostMem);
mem_gpu_free(data->poolUid[0]);
mem_gpu_free(data->poolUid[1]);
vita_mem_free(data->poolUid[0]);
vita_mem_free(data->poolUid[1]);
vita_gpu_mem_destroy(data);
// terminate libgxm
sceGxmTerminate();
@ -977,16 +978,20 @@ void gxm_finish(SDL_Renderer *renderer)
// textures
void
free_gxm_texture(gxm_texture *texture)
free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture)
{
if (texture) {
if (texture->gxm_rendertarget) {
sceGxmDestroyRenderTarget(texture->gxm_rendertarget);
}
if (texture->depth_UID) {
mem_gpu_free(texture->depth_UID);
vita_mem_free(texture->depth_UID);
}
if (texture->cdram) {
vita_gpu_mem_free(data, sceGxmTextureGetData(&texture->gxm_tex));
} else {
vita_mem_free(texture->data_UID);
}
mem_gpu_free(texture->data_UID);
SDL_free(texture);
}
}
@ -1033,24 +1038,24 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
*return_pitch = aligned_w * tex_format_to_bytespp(format);
/* Allocate a GPU buffer for the texture */
texture_data = mem_gpu_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
tex_size,
SCE_GXM_TEXTURE_ALIGNMENT,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&texture->data_UID
texture_data = vita_gpu_mem_alloc(
data,
tex_size
);
/* Try SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE in case we're out of VRAM */
if (!texture_data) {
SDL_LogWarn(SDL_LOG_CATEGORY_RENDER, "CDRAM texture allocation failed\n");
texture_data = mem_gpu_alloc(
texture_data = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
tex_size,
SCE_GXM_TEXTURE_ALIGNMENT,
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
&texture->data_UID
);
texture->cdram = 0;
} else {
texture->cdram = 1;
}
if (!texture_data) {
@ -1064,7 +1069,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
/* Create the gxm texture */
ret = sceGxmTextureInitLinear( &texture->gxm_tex, texture_data, format, texture_w, h, 0);
if (ret < 0) {
free_gxm_texture(texture);
free_gxm_texture(data, texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "texture init failed: %x\n", ret);
return NULL;
}
@ -1090,13 +1095,13 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
);
if (err < 0) {
free_gxm_texture(texture);
free_gxm_texture(data, texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "color surface init failed: %x\n", err);
return NULL;
}
// allocate it
depthBufferData = mem_gpu_alloc(
depthBufferData = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
4*sampleCount,
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
@ -1113,7 +1118,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
NULL);
if (err < 0) {
free_gxm_texture(texture);
free_gxm_texture(data, texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "depth stencil init failed: %x\n", err);
return NULL;
}
@ -1138,7 +1143,7 @@ create_gxm_texture(VITA_GXM_RenderData *data, unsigned int w, unsigned int h, Sc
texture->gxm_rendertarget = tgt;
if (err < 0) {
free_gxm_texture(texture);
free_gxm_texture(data, texture);
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "create render target failed: %x\n", err);
return NULL;
}
@ -1188,7 +1193,7 @@ void gxm_init_for_common_dialog(void)
for (int i = 0; i < VITA_GXM_BUFFERS; i += 1)
{
buffer_for_common_dialog[i].displayData.wait_vblank = SDL_TRUE;
buffer_for_common_dialog[i].displayData.address = mem_gpu_alloc(
buffer_for_common_dialog[i].displayData.address = vita_mem_alloc(
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
@ -1236,7 +1241,7 @@ void gxm_term_for_common_dialog(void)
sceGxmDisplayQueueFinish();
for (int i = 0; i < VITA_GXM_BUFFERS; i += 1)
{
mem_gpu_free(buffer_for_common_dialog[i].uid);
vita_mem_free(buffer_for_common_dialog[i].uid);
sceGxmSyncObjectDestroy(buffer_for_common_dialog[i].sync);
}
}

View File

@ -49,7 +49,7 @@ 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, unsigned int *return_w, unsigned int *return_h, unsigned int *return_pitch, float *return_wscale);
void free_gxm_texture(gxm_texture *texture);
void free_gxm_texture(VITA_GXM_RenderData *data, gxm_texture *texture);
void gxm_texture_set_filters(gxm_texture *texture, SceGxmTextureFilter min_filter, SceGxmTextureFilter mag_filter);
SceGxmTextureFormat gxm_texture_get_format(const gxm_texture *texture);

View File

@ -33,6 +33,7 @@
#include <psp2/gxm.h>
#include <psp2/types.h>
#include <psp2/kernel/sysmem.h>
#include <psp2/kernel/clib.h>
#include <string.h>
@ -79,6 +80,7 @@ typedef struct gxm_texture {
SceGxmColorSurface gxm_colorsurface;
SceGxmDepthStencilSurface gxm_depthstencil;
SceUID depth_UID;
SDL_bool cdram;
} gxm_texture;
typedef struct fragment_programs {
@ -186,6 +188,8 @@ typedef struct
blend_fragment_programs blendFragmentPrograms;
gxm_drawstate_cache drawstate;
SceClibMspace texturePool;
SceUID texturePoolUID;
} VITA_GXM_RenderData;
typedef struct

View File

@ -1464,10 +1464,12 @@ default: return "???";
static void
SDLTest_PrintEvent(SDL_Event * event)
{
#ifndef VERBOSE_MOTION_EVENTS
if ((event->type == SDL_MOUSEMOTION) || (event->type == SDL_FINGERMOTION)) {
/* Mouse and finger motion are really spammy */
return;
}
#endif
switch (event->type) {
case SDL_DISPLAYEVENT:

View File

@ -39,6 +39,7 @@
typedef unsigned long long ULLONG;
static SDL_bool ticks_started = SDL_FALSE;
static ULONG ulTmrFreq = 0;
static ULLONG ullTmrStart = 0;
@ -46,7 +47,14 @@ void
SDL_TicksInit(void)
{
ULONG ulTmrStart; /* for 32-bit fallback. */
ULONG ulRC = DosTmrQueryFreq(&ulTmrFreq);
ULONG ulRC;
if (ticks_started) {
return;
}
ticks_started = SDL_TRUE;
ulRC = DosTmrQueryFreq(&ulTmrFreq);
if (ulRC != NO_ERROR) {
debug_os2("DosTmrQueryFreq() failed, rc = %u", ulRC);
} else {
@ -65,6 +73,7 @@ SDL_TicksInit(void)
void
SDL_TicksQuit(void)
{
ticks_started = SDL_FALSE;
}
Uint64
@ -73,7 +82,7 @@ SDL_GetTicks64(void)
Uint64 ui64Result;
ULLONG ullTmrNow;
if (ulTmrFreq == 0) { /* Was not initialized. */
if (!ticks_started) {
SDL_TicksInit();
}

View File

@ -394,12 +394,6 @@ 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,
@ -418,6 +412,12 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
goto done;
}
if (biBitCount >= 32) { /* we shift biClrUsed by this value later. */
SDL_SetError("Unsupported or incorrect biBitCount field");
was_error = SDL_TRUE;
goto done;
}
if (biClrUsed == 0) {
biClrUsed = 1 << biBitCount;
}

View File

@ -27,7 +27,6 @@
#endif
#if SDL_VIDEO_DRIVER_ANDROID
#include <android/native_window.h>
#include "../core/android/SDL_android.h"
#include "../video/android/SDL_androidvideo.h"
#endif
#if SDL_VIDEO_DRIVER_RPI
@ -99,7 +98,7 @@
#define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
#endif /* SDL_VIDEO_DRIVER_RPI */
#if SDL_VIDEO_OPENGL
#if SDL_VIDEO_OPENGL && !SDL_VIDEO_VITA_PVR_OGL
#include "SDL_opengl.h"
#endif
@ -1062,7 +1061,7 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
if (SDL_GL_ExtensionSupported("GL_OES_surfaceless_context")) {
_this->gl_allow_no_surface = SDL_TRUE;
}
#if SDL_VIDEO_OPENGL
#if SDL_VIDEO_OPENGL && !defined(SDL_VIDEO_DRIVER_VITA)
} else {
/* Desktop OpenGL supports it by default from version 3.0 on. */
void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params);

View File

@ -28,6 +28,7 @@
#include "SDL_blit.h"
#include "SDL_pixels_c.h"
#include "SDL_RLEaccel_c.h"
#include "../SDL_list.h"
/* Lookup tables to expand partial bytes to the full 0..255 range */
@ -1024,12 +1025,6 @@ SDL_AllocBlitMap(void)
}
typedef struct SDL_ListNode
{
void *entry;
struct SDL_ListNode *next;
} SDL_ListNode;
void
SDL_InvalidateAllBlitMap(SDL_Surface *surface)
{
@ -1045,40 +1040,6 @@ SDL_InvalidateAllBlitMap(SDL_Surface *surface)
}
}
static void SDL_ListAdd(SDL_ListNode **head, void *ent);
static void SDL_ListRemove(SDL_ListNode **head, void *ent);
void
SDL_ListAdd(SDL_ListNode **head, void *ent)
{
SDL_ListNode *node = SDL_malloc(sizeof (*node));
if (node == NULL) {
SDL_OutOfMemory();
return;
}
node->entry = ent;
node->next = *head;
*head = node;
}
void
SDL_ListRemove(SDL_ListNode **head, void *ent)
{
SDL_ListNode **ptr = head;
while (*ptr) {
if ((*ptr)->entry == ent) {
SDL_ListNode *tmp = *ptr;
*ptr = (*ptr)->next;
SDL_free(tmp);
return;
}
ptr = &(*ptr)->next;
}
}
void
SDL_InvalidateMap(SDL_BlitMap * map)
{

View File

@ -345,6 +345,7 @@ struct SDL_VideoDevice
Uint32 next_object_id;
char *clipboard_text;
SDL_bool setting_display_mode;
SDL_bool disable_display_mode_switching;
/* * * */
/* Data used by the GL drivers */

View File

@ -1339,14 +1339,17 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
resized = SDL_FALSE;
}
/* only do the mode change if we want exclusive fullscreen */
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) {
return -1;
}
} else {
if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) {
return -1;
/* Don't try to change the display mode if the driver doesn't want it. */
if (_this->disable_display_mode_switching == SDL_FALSE) {
/* only do the mode change if we want exclusive fullscreen */
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
if (SDL_SetDisplayModeForDisplay(display, &fullscreen_mode) < 0) {
return -1;
}
} else {
if (SDL_SetDisplayModeForDisplay(display, NULL) < 0) {
return -1;
}
}
}

View File

@ -26,6 +26,8 @@
#include "SDL_emscriptenframebuffer.h"
#include "SDL_hints.h"
#include <emscripten/threading.h>
int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
{
@ -57,18 +59,9 @@ int Emscripten_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * form
return 0;
}
int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
static void
Emscripten_UpdateWindowFramebufferWorker(SDL_Surface* surface)
{
SDL_Surface *surface;
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
surface = data->surface;
if (!surface) {
return SDL_SetError("Couldn't find framebuffer surface for window");
}
/* Send the data to the display */
EM_ASM_INT({
var w = $0;
var h = $1;
@ -156,6 +149,29 @@ int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rec
SDL2.ctx.putImageData(SDL2.image, 0, 0);
return 0;
}, surface->w, surface->h, surface->pixels);
}
int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
{
SDL_Surface *surface;
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
surface = data->surface;
if (!surface) {
return SDL_SetError("Couldn't find framebuffer surface for window");
}
/* Send the data to the display */
if (emscripten_is_main_runtime_thread()) {
Emscripten_UpdateWindowFramebufferWorker(surface);
} else {
emscripten_sync_run_in_main_runtime_thread(
EM_FUNC_SIG_VI,
Emscripten_UpdateWindowFramebufferWorker,
(uint32_t)surface
);
}
if (emscripten_has_asyncify() && SDL_GetHintBoolean(SDL_HINT_EMSCRIPTEN_ASYNCIFY, SDL_TRUE)) {
/* give back control to browser for screen refresh */

View File

@ -24,6 +24,7 @@
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
#include <emscripten/threading.h>
#include "SDL_emscriptenmouse.h"
#include "SDL_emscriptenvideo.h"
@ -62,19 +63,10 @@ Emscripten_CreateDefaultCursor()
return Emscripten_CreateCursorFromString("default", SDL_FALSE);
}
static SDL_Cursor*
Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
static const char*
Emscripten_GetCursorUrl(int w, int h, int hot_x, int hot_y, void* pixels)
{
const char *cursor_url = NULL;
SDL_Surface *conv_surf;
conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
if (!conv_surf) {
return NULL;
}
cursor_url = (const char *)EM_ASM_INT({
return (const char *)EM_ASM_INT({
var w = $0;
var h = $1;
var hot_x = $2;
@ -122,7 +114,40 @@ Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
stringToUTF8(url, urlBuf, url.length + 1);
return urlBuf;
}, surface->w, surface->h, hot_x, hot_y, conv_surf->pixels);
}, w, h, hot_x, hot_y, pixels);
}
static SDL_Cursor*
Emscripten_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
{
const char *cursor_url = NULL;
SDL_Surface *conv_surf;
conv_surf = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ABGR8888, 0);
if (!conv_surf) {
return NULL;
}
if (emscripten_is_main_runtime_thread()) {
cursor_url = Emscripten_GetCursorUrl(
surface->w,
surface->h,
hot_x,
hot_y,
conv_surf->pixels
);
} else {
cursor_url = (const char *)emscripten_sync_run_in_main_runtime_thread(
EM_FUNC_SIG_IIIIIII,
Emscripten_GetCursorUrl,
surface->w,
surface->h,
hot_x,
hot_y,
conv_surf->pixels
);
}
SDL_FreeSurface(conv_surf);
@ -206,16 +231,15 @@ Emscripten_ShowCursor(SDL_Cursor* cursor)
curdata = (Emscripten_CursorData *) cursor->driverdata;
if(curdata->system_cursor) {
EM_ASM_INT({
MAIN_THREAD_EM_ASM({
if (Module['canvas']) {
Module['canvas'].style['cursor'] = UTF8ToString($0);
}
return 0;
}, curdata->system_cursor);
}
}
else {
EM_ASM(
MAIN_THREAD_EM_ASM(
if (Module['canvas']) {
Module['canvas'].style['cursor'] = 'none';
}

View File

@ -174,10 +174,10 @@ Emscripten_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect *
if (rect) {
rect->x = 0;
rect->y = 0;
rect->w = EM_ASM_INT_V({
rect->w = MAIN_THREAD_EM_ASM_INT({
return window.innerWidth;
});
rect->h = EM_ASM_INT_V({
rect->h = MAIN_THREAD_EM_ASM_INT({
return window.innerHeight;
});
}

View File

@ -186,8 +186,8 @@ UIKit_ShowMessageBoxAlertView(const SDL_MessageBoxData *messageboxdata, int *but
#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED < 80000 */
}
int
UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
static void
UIKit_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid, int *returnValue)
{
BOOL success = NO;
@ -199,12 +199,26 @@ UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
}
if (!success) {
return SDL_SetError("Could not show message box.");
*returnValue = SDL_SetError("Could not show message box.");
} else {
*returnValue = 0;
}
return 0;
}
int
UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
{ @autoreleasepool
{
__block int returnValue = 0;
if ([NSThread isMainThread]) {
UIKit_ShowMessageBoxImpl(messageboxdata, buttonid, &returnValue);
} else {
dispatch_sync(dispatch_get_main_queue(), ^{ UIKit_ShowMessageBoxImpl(messageboxdata, buttonid, &returnValue); });
}
return returnValue;
}}
#endif /* SDL_VIDEO_DRIVER_UIKIT */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -20,11 +20,12 @@
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR
#if SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR && SDL_VIDEO_VITA_PVR_OGL
#include <stdlib.h>
#include <string.h>
#include <psp2/kernel/modulemgr.h>
#include <gpu_es4/psp2_pvr_hint.h>
#include <gl4esinit.h>
#include "SDL_error.h"
#include "SDL_log.h"
@ -34,6 +35,16 @@
#define MAX_PATH 256 // vita limits are somehow wrong
/* Defaults */
int FB_WIDTH = 960;
int FB_HEIGHT = 544;
void getFBSize(int *width, int *height)
{
*width = FB_WIDTH;
*height = FB_HEIGHT;
}
int
VITA_GL_LoadLibrary(_THIS, const char *path)
{
@ -53,6 +64,9 @@ VITA_GL_LoadLibrary(_THIS, const char *path)
sceKernelLoadStartModule("vs0:sys/external/libfios2.suprx", 0, NULL, 0, NULL, NULL);
sceKernelLoadStartModule("vs0:sys/external/libc.suprx", 0, NULL, 0, NULL, NULL);
SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libGL.suprx");
sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libgpu_es4_ext.suprx");
sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
@ -74,30 +88,45 @@ VITA_GL_LoadLibrary(_THIS, const char *path)
SDL_GLContext
VITA_GL_CreateContext(_THIS, SDL_Window * window)
{
return SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
}
char gl_version[3];
SDL_GLContext context = NULL;
int temp_major = _this->gl_config.major_version;
int temp_minor = _this->gl_config.minor_version;
int temp_profile = _this->gl_config.profile_mask;
int
VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
{
if (window && context) {
return SDL_EGL_MakeCurrent(_this, ((SDL_WindowData *) window->driverdata)->egl_surface, context);
} else {
return SDL_EGL_MakeCurrent(_this, NULL, NULL);
/* Set version to 2.0 and PROFILE to ES */
_this->gl_config.major_version = 2;
_this->gl_config.minor_version = 0;
_this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
context = SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
if (context != NULL)
{
FB_WIDTH = window->w;
FB_HEIGHT = window->h;
set_getprocaddress((void *(*)(const char *))eglGetProcAddress);
set_getmainfbsize(getFBSize);
SDL_snprintf(gl_version, 3, "%d%d", temp_major, temp_minor);
gl4es_setenv("LIBGL_NOTEXRECT", "1", 1); /* Currently broken in driver */
gl4es_setenv("LIBGL_GL", gl_version, 1);
initialize_gl4es();
}
/* Restore gl_config */
_this->gl_config.major_version = temp_major;
_this->gl_config.minor_version = temp_minor;
_this->gl_config.profile_mask = temp_profile;
return context;
}
int
VITA_GL_SwapWindow(_THIS, SDL_Window * window)
void *
VITA_GL_GetProcAddress(_THIS, const char *proc)
{
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
if (videodata->ime_active) {
sceImeUpdate();
}
return SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
return gl4es_GetProcAddress(proc);
}
#endif /* SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -19,17 +19,16 @@
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SDL_vitagl_c_h_
#define SDL_vitagl_c_h_
#ifndef SDL_vitagl_pvr_c_h_
#define SDL_vitagl_pvr_c_h_
#include "SDL_vitavideo.h"
extern int VITA_GL_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
extern int VITA_GL_SwapWindow(_THIS, SDL_Window * window);
extern SDL_GLContext VITA_GL_CreateContext(_THIS, SDL_Window * window);
extern int VITA_GL_LoadLibrary(_THIS, const char *path);
extern void *VITA_GL_GetProcAddress(_THIS, const char *proc);
#endif /* SDL_vitagl_c_h_ */
#endif /* SDL_vitagl_pvr_c_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -27,7 +27,7 @@
#include "SDL_error.h"
#include "SDL_log.h"
#include "SDL_vitavideo.h"
#include "SDL_vitagl_c.h"
#include "SDL_vitagles_c.h"
/*****************************************************************************/
/* SDL OpenGL/OpenGL ES functions */
@ -45,7 +45,7 @@
} while (0)
void
VITA_GL_KeyboardCallback(ScePigletPreSwapData *data)
VITA_GLES_KeyboardCallback(ScePigletPreSwapData *data)
{
SceCommonDialogUpdateParam commonDialogParam;
SDL_zero(commonDialogParam);
@ -62,20 +62,20 @@ VITA_GL_KeyboardCallback(ScePigletPreSwapData *data)
}
int
VITA_GL_LoadLibrary(_THIS, const char *path)
VITA_GLES_LoadLibrary(_THIS, const char *path)
{
pibInit(PIB_SHACCCG | PIB_GET_PROC_ADDR_CORE);
return 0;
}
void *
VITA_GL_GetProcAddress(_THIS, const char *proc)
VITA_GLES_GetProcAddress(_THIS, const char *proc)
{
return eglGetProcAddress(proc);
}
void
VITA_GL_UnloadLibrary(_THIS)
VITA_GLES_UnloadLibrary(_THIS)
{
eglTerminate(_this->gl_data->display);
}
@ -84,7 +84,7 @@ static EGLint width = 960;
static EGLint height = 544;
SDL_GLContext
VITA_GL_CreateContext(_THIS, SDL_Window * window)
VITA_GLES_CreateContext(_THIS, SDL_Window * window)
{
SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
@ -159,13 +159,13 @@ VITA_GL_CreateContext(_THIS, SDL_Window * window)
_this->gl_data->surface = surface;
preSwapCallback = (PFNEGLPIGLETVITASETPRESWAPCALLBACKSCEPROC) eglGetProcAddress("eglPigletVitaSetPreSwapCallbackSCE");
preSwapCallback(VITA_GL_KeyboardCallback);
preSwapCallback(VITA_GLES_KeyboardCallback);
return context;
}
int
VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
VITA_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
{
if (!eglMakeCurrent(_this->gl_data->display, _this->gl_data->surface,
_this->gl_data->surface, _this->gl_data->context))
@ -176,7 +176,7 @@ VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
}
int
VITA_GL_SetSwapInterval(_THIS, int interval)
VITA_GLES_SetSwapInterval(_THIS, int interval)
{
EGLBoolean status;
status = eglSwapInterval(_this->gl_data->display, interval);
@ -190,13 +190,13 @@ VITA_GL_SetSwapInterval(_THIS, int interval)
}
int
VITA_GL_GetSwapInterval(_THIS)
VITA_GLES_GetSwapInterval(_THIS)
{
return _this->gl_data->swapinterval;
}
int
VITA_GL_SwapWindow(_THIS, SDL_Window * window)
VITA_GLES_SwapWindow(_THIS, SDL_Window * window)
{
if (!eglSwapBuffers(_this->gl_data->display, _this->gl_data->surface)) {
return SDL_SetError("eglSwapBuffers() failed");
@ -205,7 +205,7 @@ VITA_GL_SwapWindow(_THIS, SDL_Window * window)
}
void
VITA_GL_DeleteContext(_THIS, SDL_GLContext context)
VITA_GLES_DeleteContext(_THIS, SDL_GLContext context)
{
SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
EGLBoolean status;

View File

@ -19,8 +19,8 @@
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef SDL_vitagl_c_h_
#define SDL_vitagl_c_h_
#ifndef SDL_vitagles_c_h_
#define SDL_vitagles_c_h_
#include <pib.h>
@ -39,19 +39,19 @@ typedef struct SDL_GLDriverData {
uint32_t swapinterval;
}SDL_GLDriverData;
extern void * VITA_GL_GetProcAddress(_THIS, const char *proc);
extern int VITA_GL_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
extern void VITA_GL_SwapBuffers(_THIS);
extern void * VITA_GLES_GetProcAddress(_THIS, const char *proc);
extern int VITA_GLES_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
extern void VITA_GLES_SwapBuffers(_THIS);
extern int VITA_GL_SwapWindow(_THIS, SDL_Window * window);
extern SDL_GLContext VITA_GL_CreateContext(_THIS, SDL_Window * window);
extern int VITA_GLES_SwapWindow(_THIS, SDL_Window * window);
extern SDL_GLContext VITA_GLES_CreateContext(_THIS, SDL_Window * window);
extern int VITA_GL_LoadLibrary(_THIS, const char *path);
extern void VITA_GL_UnloadLibrary(_THIS);
extern int VITA_GL_SetSwapInterval(_THIS, int interval);
extern int VITA_GL_GetSwapInterval(_THIS);
extern int VITA_GLES_LoadLibrary(_THIS, const char *path);
extern void VITA_GLES_UnloadLibrary(_THIS);
extern int VITA_GLES_SetSwapInterval(_THIS, int interval);
extern int VITA_GLES_GetSwapInterval(_THIS);
#endif /* SDL_vitagl_c_h_ */
#endif /* SDL_vitagles_c_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -0,0 +1,103 @@
/*
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.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR
#include <stdlib.h>
#include <string.h>
#include <psp2/kernel/modulemgr.h>
#include <gpu_es4/psp2_pvr_hint.h>
#include "SDL_error.h"
#include "SDL_log.h"
#include "SDL_vitavideo.h"
#include "../SDL_egl_c.h"
#include "SDL_vitagles_pvr_c.h"
#define MAX_PATH 256 // vita limits are somehow wrong
int
VITA_GLES_LoadLibrary(_THIS, const char *path)
{
PVRSRV_PSP2_APPHINT hint;
char* override = SDL_getenv("VITA_MODULE_PATH");
char* skip_init = SDL_getenv("VITA_PVR_SKIP_INIT");
char* default_path = "app0:module";
char target_path[MAX_PATH];
if (skip_init == NULL) // we don't care about actual value
{
if (override != NULL)
{
default_path = override;
}
sceKernelLoadStartModule("vs0:sys/external/libfios2.suprx", 0, NULL, 0, NULL, NULL);
sceKernelLoadStartModule("vs0:sys/external/libc.suprx", 0, NULL, 0, NULL, NULL);
SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libgpu_es4_ext.suprx");
sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
SDL_snprintf(target_path, MAX_PATH, "%s/%s", default_path, "libIMGEGL.suprx");
sceKernelLoadStartModule(target_path, 0, NULL, 0, NULL, NULL);
PVRSRVInitializeAppHint(&hint);
SDL_snprintf(hint.szGLES1, MAX_PATH, "%s/%s", default_path, "libGLESv1_CM.suprx");
SDL_snprintf(hint.szGLES2, MAX_PATH, "%s/%s", default_path, "libGLESv2.suprx");
SDL_snprintf(hint.szWindowSystem, MAX_PATH, "%s/%s", default_path, "libpvrPSP2_WSEGL.suprx");
PVRSRVCreateVirtualAppHint(&hint);
}
return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) 0, 0);
}
SDL_GLContext
VITA_GLES_CreateContext(_THIS, SDL_Window * window)
{
return SDL_EGL_CreateContext(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
}
int
VITA_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
{
if (window && context) {
return SDL_EGL_MakeCurrent(_this, ((SDL_WindowData *) window->driverdata)->egl_surface, context);
} else {
return SDL_EGL_MakeCurrent(_this, NULL, NULL);
}
}
int
VITA_GLES_SwapWindow(_THIS, SDL_Window * window)
{
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
if (videodata->ime_active) {
sceImeUpdate();
}
return SDL_EGL_SwapBuffers(_this, ((SDL_WindowData *) window->driverdata)->egl_surface);
}
#endif /* SDL_VIDEO_DRIVER_VITA && SDL_VIDEO_VITA_PVR */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -0,0 +1,35 @@
/*
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.
*/
#ifndef SDL_vitagles_pvr_c_h_
#define SDL_vitagles_pvr_c_h_
#include "SDL_vitavideo.h"
extern int VITA_GLES_MakeCurrent(_THIS,SDL_Window * window, SDL_GLContext context);
extern int VITA_GLES_SwapWindow(_THIS, SDL_Window * window);
extern SDL_GLContext VITA_GLES_CreateContext(_THIS, SDL_Window * window);
extern int VITA_GLES_LoadLibrary(_THIS, const char *path);
#endif /* SDL_vitagles_pvr_c_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -41,15 +41,17 @@
#include "SDL_vitaframebuffer.h"
#if defined(SDL_VIDEO_VITA_PIB)
#include "SDL_vitagl_c.h"
#include "SDL_vitagles_c.h"
#elif defined(SDL_VIDEO_VITA_PVR)
#include "SDL_vitagles_pvr_c.h"
#if defined(SDL_VIDEO_VITA_PVR_OGL)
#include "SDL_vitagl_pvr_c.h"
#include "../SDL_egl_c.h"
#define VITA_GL_GetProcAddress SDL_EGL_GetProcAddress
#define VITA_GL_UnloadLibrary SDL_EGL_UnloadLibrary
#define VITA_GL_SetSwapInterval SDL_EGL_SetSwapInterval
#define VITA_GL_GetSwapInterval SDL_EGL_GetSwapInterval
#define VITA_GL_DeleteContext SDL_EGL_DeleteContext
#endif
#define VITA_GLES_GetProcAddress SDL_EGL_GetProcAddress
#define VITA_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
#define VITA_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
#define VITA_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
#define VITA_GLES_DeleteContext SDL_EGL_DeleteContext
#endif
SDL_Window *Vita_Window;
@ -140,15 +142,26 @@ VITA_Create()
*/
#if defined(SDL_VIDEO_VITA_PIB) || defined(SDL_VIDEO_VITA_PVR)
#if defined(SDL_VIDEO_VITA_PVR_OGL)
if(SDL_getenv("VITA_PVR_OGL") != NULL) {
device->GL_LoadLibrary = VITA_GL_LoadLibrary;
device->GL_GetProcAddress = VITA_GL_GetProcAddress;
device->GL_UnloadLibrary = VITA_GL_UnloadLibrary;
device->GL_CreateContext = VITA_GL_CreateContext;
device->GL_MakeCurrent = VITA_GL_MakeCurrent;
device->GL_SetSwapInterval = VITA_GL_SetSwapInterval;
device->GL_GetSwapInterval = VITA_GL_GetSwapInterval;
device->GL_SwapWindow = VITA_GL_SwapWindow;
device->GL_DeleteContext = VITA_GL_DeleteContext;
device->GL_GetProcAddress = VITA_GL_GetProcAddress;
} else {
#endif
device->GL_LoadLibrary = VITA_GLES_LoadLibrary;
device->GL_CreateContext = VITA_GLES_CreateContext;
device->GL_GetProcAddress = VITA_GLES_GetProcAddress;
#if defined(SDL_VIDEO_VITA_PVR_OGL)
}
#endif
device->GL_UnloadLibrary = VITA_GLES_UnloadLibrary;
device->GL_MakeCurrent = VITA_GLES_MakeCurrent;
device->GL_SetSwapInterval = VITA_GLES_SetSwapInterval;
device->GL_GetSwapInterval = VITA_GLES_GetSwapInterval;
device->GL_SwapWindow = VITA_GLES_SwapWindow;
device->GL_DeleteContext = VITA_GLES_DeleteContext;
#endif
device->HasScreenKeyboardSupport = VITA_HasScreenKeyboardSupport;
@ -245,6 +258,9 @@ VITA_CreateWindow(_THIS, SDL_Window * window)
SDL_WindowData *wdata;
#if defined(SDL_VIDEO_VITA_PVR)
Psp2NativeWindow win;
int temp_major = 2;
int temp_minor = 1;
int temp_profile = 0;
#endif
/* Allocate window internal data */
@ -282,11 +298,26 @@ VITA_CreateWindow(_THIS, SDL_Window * window)
win.windowSize = PSP2_WINDOW_960X544;
}
if ((window->flags & SDL_WINDOW_OPENGL) != 0) {
wdata->egl_surface = SDL_EGL_CreateSurface(_this, &win);
if(SDL_getenv("VITA_PVR_OGL") != NULL) {
/* Set version to 2.1 and PROFILE to ES */
temp_major = _this->gl_config.major_version;
temp_minor = _this->gl_config.minor_version;
temp_profile = _this->gl_config.profile_mask;
_this->gl_config.major_version = 2;
_this->gl_config.minor_version = 1;
_this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES;
}
wdata->egl_surface = SDL_EGL_CreateSurface(_this, &win);
if (wdata->egl_surface == EGL_NO_SURFACE) {
return SDL_SetError("Could not create GLES window surface");
}
if(SDL_getenv("VITA_PVR_OGL") != NULL) {
/* Revert */
_this->gl_config.major_version = temp_major;
_this->gl_config.minor_version = temp_minor;
_this->gl_config.profile_mask = temp_profile;
}
}
#endif

View File

@ -90,16 +90,23 @@ SDL_bool VITA_GetWindowWMInfo(_THIS, SDL_Window * window,
struct SDL_SysWMinfo *info);
#if SDL_VIDEO_DRIVER_VITA
#if defined(SDL_VIDEO_VITA_PVR_OGL)
/* OpenGL functions */
int VITA_GL_LoadLibrary(_THIS, const char *path);
void *VITA_GL_GetProcAddress(_THIS, const char *proc);
void VITA_GL_UnloadLibrary(_THIS);
SDL_GLContext VITA_GL_CreateContext(_THIS, SDL_Window * window);
int VITA_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
int VITA_GL_SetSwapInterval(_THIS, int interval);
int VITA_GL_GetSwapInterval(_THIS);
int VITA_GL_SwapWindow(_THIS, SDL_Window * window);
void VITA_GL_DeleteContext(_THIS, SDL_GLContext context);
void *VITA_GL_GetProcAddress(_THIS, const char *proc);
#endif
/* OpenGLES functions */
int VITA_GLES_LoadLibrary(_THIS, const char *path);
void *VITA_GLES_GetProcAddress(_THIS, const char *proc);
void VITA_GLES_UnloadLibrary(_THIS);
SDL_GLContext VITA_GLES_CreateContext(_THIS, SDL_Window * window);
int VITA_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
int VITA_GLES_SetSwapInterval(_THIS, int interval);
int VITA_GLES_GetSwapInterval(_THIS);
int VITA_GLES_SwapWindow(_THIS, SDL_Window * window);
void VITA_GLES_DeleteContext(_THIS, SDL_GLContext context);
#endif
/* VITA on screen keyboard */

View File

@ -389,8 +389,10 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
input->sx_w = sx_w;
input->sy_w = sy_w;
if (input->pointer_focus) {
const int sx = wl_fixed_to_int(sx_w);
const int sy = wl_fixed_to_int(sy_w);
const float sx_f = (float)wl_fixed_to_double(sx_w);
const float sy_f = (float)wl_fixed_to_double(sy_w);
const int sx = (int)SDL_lroundf(sx_f * window->pointer_scale_x);
const int sy = (int)SDL_lroundf(sy_f * window->pointer_scale_y);
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
}
}
@ -717,8 +719,8 @@ touch_handler_down(void *data, struct wl_touch *touch, unsigned int serial,
int id, wl_fixed_t fx, wl_fixed_t fy)
{
SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(surface);
const double dblx = wl_fixed_to_double(fx);
const double dbly = wl_fixed_to_double(fy);
const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
const float x = dblx / window_data->sdlwindow->w;
const float y = dbly / window_data->sdlwindow->h;
@ -750,8 +752,8 @@ touch_handler_motion(void *data, struct wl_touch *touch, unsigned int timestamp,
int id, wl_fixed_t fx, wl_fixed_t fy)
{
SDL_WindowData *window_data = (SDL_WindowData *)wl_surface_get_user_data(touch_surface(id));
const double dblx = wl_fixed_to_double(fx);
const double dbly = wl_fixed_to_double(fy);
const double dblx = wl_fixed_to_double(fx) * window_data->pointer_scale_x;
const double dbly = wl_fixed_to_double(fy) * window_data->pointer_scale_y;
const float x = dblx / window_data->sdlwindow->w;
const float y = dbly / window_data->sdlwindow->h;
@ -919,7 +921,7 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
}
static SDL_bool
keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key, SDL_bool *handled_by_ime)
keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key, Uint8 state, SDL_bool *handled_by_ime)
{
SDL_WindowData *window = input->keyboard_focus;
const xkb_keysym_t *syms;
@ -936,12 +938,16 @@ keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint
sym = syms[0];
#ifdef SDL_USE_IME
if (SDL_IME_ProcessKeyEvent(sym, key + 8)) {
if (SDL_IME_ProcessKeyEvent(sym, key + 8, state)) {
*handled_by_ime = SDL_TRUE;
return SDL_TRUE;
}
#endif
if (state == SDL_RELEASED) {
return SDL_FALSE;
}
if (input->xkb.compose_state && WAYLAND_xkb_compose_state_feed(input->xkb.compose_state, sym) == XKB_COMPOSE_FEED_ACCEPTED) {
switch(WAYLAND_xkb_compose_state_get_status(input->xkb.compose_state)) {
case XKB_COMPOSE_COMPOSING:
@ -975,7 +981,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
SDL_bool handled_by_ime = SDL_FALSE;
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
has_text = keyboard_input_get_text(text, input, key, &handled_by_ime);
has_text = keyboard_input_get_text(text, input, key, SDL_PRESSED, &handled_by_ime);
} else {
if (keyboard_repeat_is_set(&input->keyboard_repeat)) {
// Send any due key repeat events before stopping the repeat and generating the key up event
@ -985,6 +991,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
keyboard_repeat_handle(&input->keyboard_repeat, time - input->keyboard_repeat.wl_press_time);
keyboard_repeat_clear(&input->keyboard_repeat);
}
keyboard_input_get_text(text, input, key, SDL_RELEASED, &handled_by_ime);
}
if (!handled_by_ime && key < SDL_arraysize(xfree86_scancode_table2)) {
@ -1817,8 +1824,10 @@ tablet_tool_handle_motion(void* data, struct zwp_tablet_tool_v2* tool, wl_fixed_
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);
const float sx_f = (float)wl_fixed_to_double(sx_w);
const float sy_f = (float)wl_fixed_to_double(sy_w);
const int sx = (int)SDL_lroundf(sx_f * window->pointer_scale_x);
const int sy = (int)SDL_lroundf(sy_f * window->pointer_scale_y);
SDL_SendMouseMotion(window->sdlwindow, 0, 0, sx, sy);
}
}
@ -2345,12 +2354,19 @@ int Wayland_input_confine_pointer(struct SDL_WaylandInput *input, SDL_Window *wi
if (SDL_RectEmpty(&window->mouse_rect)) {
confine_rect = NULL;
} else {
SDL_Rect scaled_mouse_rect;
scaled_mouse_rect.x = (int)SDL_floorf((float)window->mouse_rect.x / w->pointer_scale_x);
scaled_mouse_rect.y = (int)SDL_floorf((float)window->mouse_rect.y / w->pointer_scale_y);
scaled_mouse_rect.w = (int)SDL_ceilf((float)window->mouse_rect.w / w->pointer_scale_x);
scaled_mouse_rect.h = (int)SDL_ceilf((float)window->mouse_rect.h / w->pointer_scale_y);
confine_rect = wl_compositor_create_region(d->compositor);
wl_region_add(confine_rect,
window->mouse_rect.x,
window->mouse_rect.y,
window->mouse_rect.w,
window->mouse_rect.h);
scaled_mouse_rect.x,
scaled_mouse_rect.y,
scaled_mouse_rect.w,
scaled_mouse_rect.h);
}
confined_pointer =

View File

@ -205,11 +205,11 @@ Wayland_GLES_GetDrawableSize(_THIS, SDL_Window * window, int * w, int * h)
data = (SDL_WindowData *) window->driverdata;
if (w) {
*w = window->w * data->scale_factor;
*w = data->drawable_width;
}
if (h) {
*h = window->h * data->scale_factor;
*h = data->drawable_height;
}
}
}

View File

@ -54,6 +54,7 @@
#include "text-input-unstable-v3-client-protocol.h"
#include "tablet-unstable-v2-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
#include "viewporter-client-protocol.h"
#ifdef HAVE_LIBDECOR_H
#include <libdecor.h>
@ -278,6 +279,8 @@ Wayland_CreateDevice(int devindex)
device->free = Wayland_DeleteDevice;
device->disable_display_mode_switching = SDL_TRUE;
return device;
}
@ -294,6 +297,7 @@ xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output
driverdata->x = x;
driverdata->y = y;
driverdata->has_logical_position = SDL_TRUE;
}
static void
@ -302,8 +306,28 @@ xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output,
{
SDL_WaylandOutputData* driverdata = data;
if (driverdata->width != 0 && driverdata->height != 0) {
/* FIXME: GNOME has a bug where the logical size does not account for
* scale, resulting in bogus viewport sizes.
*
* Until this is fixed, validate that _some_ kind of scaling is being
* done (we can't match exactly because fractional scaling can't be
* detected otherwise), then override if necessary.
* -flibit
*/
const float scale = (float) driverdata->width / (float) width;
if ((scale == 1.0f) && (driverdata->scale_factor != 1.0f)) {
SDL_LogWarn(
SDL_LOG_CATEGORY_VIDEO,
"xdg_output scale did not match, overriding with wl_output scale"
);
return;
}
}
driverdata->width = width;
driverdata->height = height;
driverdata->has_logical_size = SDL_TRUE;
}
static void
@ -340,6 +364,80 @@ static const struct zxdg_output_v1_listener xdg_output_listener = {
xdg_output_handle_description,
};
static void
AddEmulatedModes(SDL_VideoDisplay *dpy, SDL_bool rot_90)
{
struct EmulatedMode
{
int w;
int h;
};
/* Resolution lists courtesy of XWayland */
const struct EmulatedMode mode_list[] = {
/* 16:9 (1.77) */
{ 7680, 4320 },
{ 6144, 3160 },
{ 5120, 2880 },
{ 4096, 2304 },
{ 3840, 2160 },
{ 3200, 1800 },
{ 2880, 1620 },
{ 2560, 1440 },
{ 2048, 1152 },
{ 1920, 1080 },
{ 1600, 900 },
{ 1368, 768 },
{ 1280, 720 },
{ 864, 486 },
/* 16:10 (1.6) */
{ 2560, 1600 },
{ 1920, 1200 },
{ 1680, 1050 },
{ 1440, 900 },
{ 1280, 800 },
/* 3:2 (1.5) */
{ 720, 480 },
/* 4:3 (1.33) */
{ 2048, 1536 },
{ 1920, 1440 },
{ 1600, 1200 },
{ 1440, 1080 },
{ 1400, 1050 },
{ 1280, 1024 },
{ 1280, 960 },
{ 1152, 864 },
{ 1024, 768 },
{ 800, 600 },
{ 640, 480 }
};
int i;
const int native_width = dpy->display_modes->w;
const int native_height = dpy->display_modes->h;
for (i = 0; i < SDL_arraysize(mode_list); ++i) {
/* Only add modes that are smaller than the native mode */
if ((mode_list[i].w < native_width && mode_list[i].h < native_height) ||
(mode_list[i].w < native_width && mode_list[i].h == native_height)) {
SDL_DisplayMode mode = *dpy->display_modes;
if (rot_90) {
mode.w = mode_list[i].h;
mode.h = mode_list[i].w;
} else {
mode.w = mode_list[i].w;
mode.h = mode_list[i].h;
}
SDL_AddDisplayMode(dpy, &mode);
}
}
}
static void
display_handle_geometry(void *data,
struct wl_output *output,
@ -371,7 +469,7 @@ display_handle_geometry(void *data,
}
/* Apply the change from wl-output only if xdg-output is not supported */
if (driverdata->xdg_output) {
if (!driverdata->has_logical_position) {
driverdata->x = x;
driverdata->y = y;
}
@ -421,43 +519,22 @@ display_handle_mode(void *data,
int refresh)
{
SDL_WaylandOutputData* driverdata = data;
SDL_DisplayMode mode;
if (flags & WL_OUTPUT_MODE_CURRENT) {
driverdata->native_width = width;
driverdata->native_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) {
if (!driverdata->has_logical_size) {
driverdata->width = width;
driverdata->height = height;
}
driverdata->refresh = refresh;
}
/* Note that the width/height are NOT multiplied by scale_factor!
* This is intentional and is designed to get the unscaled modes, which is
* important for high-DPI games intending to use the display mode as the
* target drawable size. The scaled desktop mode will be added at the end
* when display_handle_done is called (see below).
*/
SDL_zero(mode);
mode.format = SDL_PIXELFORMAT_RGB888;
if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
mode.w = height;
mode.h = width;
} else {
mode.w = width;
mode.h = height;
}
mode.refresh_rate = (int)SDL_round(refresh / 1000.0); /* mHz to Hz */
mode.driverdata = driverdata->output;
if (driverdata->index > -1) {
SDL_AddDisplayMode(SDL_GetDisplay(driverdata->index), &mode);
} else {
SDL_AddDisplayMode(&driverdata->placeholder, &mode);
}
}
static void
@ -465,7 +542,8 @@ display_handle_done(void *data,
struct wl_output *output)
{
SDL_WaylandOutputData* driverdata = data;
SDL_DisplayMode mode;
SDL_VideoData* video = driverdata->videodata;
SDL_DisplayMode native_mode, desktop_mode;
SDL_VideoDisplay *dpy;
/*
@ -482,19 +560,51 @@ display_handle_done(void *data,
return;
}
SDL_zero(mode);
mode.format = SDL_PIXELFORMAT_RGB888;
/* The native display resolution */
SDL_zero(native_mode);
native_mode.format = SDL_PIXELFORMAT_RGB888;
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;
if (driverdata->transform & WL_OUTPUT_TRANSFORM_90) {
native_mode.w = driverdata->native_height;
native_mode.h = driverdata->native_width;
} else {
mode.w = driverdata->width / driverdata->scale_factor;
mode.h = driverdata->height / driverdata->scale_factor;
native_mode.w = driverdata->native_width;
native_mode.h = driverdata->native_height;
}
native_mode.refresh_rate = (int)SDL_round(driverdata->refresh / 1000.0); /* mHz to Hz */
native_mode.driverdata = driverdata->output;
/* The scaled desktop mode */
SDL_zero(desktop_mode);
desktop_mode.format = SDL_PIXELFORMAT_RGB888;
/* Scale the desktop coordinates, if xdg-output isn't present */
if (!driverdata->has_logical_size) {
driverdata->width /= driverdata->scale_factor;
driverdata->height /= driverdata->scale_factor;
}
/* xdg-output dimensions are already transformed, so no need to rotate. */
if (driverdata->has_logical_size || !(driverdata->transform & WL_OUTPUT_TRANSFORM_90)) {
desktop_mode.w = driverdata->width;
desktop_mode.h = driverdata->height;
} else {
desktop_mode.w = driverdata->height;
desktop_mode.h = driverdata->width;
}
desktop_mode.refresh_rate = (int)SDL_round(driverdata->refresh / 1000.0); /* mHz to Hz */
desktop_mode.driverdata = driverdata->output;
/*
* The native display mode is only exposed separately from the desktop size if:
* the desktop is scaled and the wp_viewporter protocol is supported.
*/
if (driverdata->scale_factor > 1.0f && video->viewporter != NULL) {
if (driverdata->index > -1) {
SDL_AddDisplayMode(SDL_GetDisplay(driverdata->index), &native_mode);
} else {
SDL_AddDisplayMode(&driverdata->placeholder, &native_mode);
}
}
/* Calculate the display DPI */
@ -522,18 +632,20 @@ display_handle_done(void *data,
((float) driverdata->physical_height) / 25.4f);
}
mode.refresh_rate = (int)SDL_round(driverdata->refresh / 1000.0); /* mHz to Hz */
mode.driverdata = driverdata->output;
if (driverdata->index > -1) {
dpy = SDL_GetDisplay(driverdata->index);
} else {
dpy = &driverdata->placeholder;
}
SDL_AddDisplayMode(dpy, &mode);
SDL_SetCurrentDisplayMode(dpy, &mode);
SDL_SetDesktopDisplayMode(dpy, &mode);
SDL_AddDisplayMode(dpy, &desktop_mode);
SDL_SetCurrentDisplayMode(dpy, &desktop_mode);
SDL_SetDesktopDisplayMode(dpy, &desktop_mode);
/* Add emulated modes if wp_viewporter is supported. */
if (video->viewporter) {
AddEmulatedModes(dpy, (driverdata->transform & WL_OUTPUT_TRANSFORM_90) != 0);
}
if (driverdata->index == -1) {
/* First time getting display info, create the VideoDisplay */
@ -580,7 +692,7 @@ Wayland_add_display(SDL_VideoData *d, uint32_t id)
data->videodata = d;
data->output = output;
data->registry_id = id;
data->scale_factor = 1.0;
data->scale_factor = 1.0f;
data->index = -1;
wl_output_add_listener(output, &output_listener, data);
@ -736,6 +848,8 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
version = SDL_min(version, 3); /* Versions 1 through 3 are supported. */
d->xdg_output_manager = wl_registry_bind(d->registry, id, &zxdg_output_manager_v1_interface, version);
Wayland_init_xdg_output(d);
} else if (SDL_strcmp(interface, "wp_viewporter") == 0) {
d->viewporter = wl_registry_bind(d->registry, id, &wp_viewporter_interface, 1);
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
} else if (SDL_strcmp(interface, "qt_touch_extension") == 0) {
@ -762,6 +876,29 @@ static const struct wl_registry_listener registry_listener = {
display_handle_global,
display_remove_global
};
#ifdef HAVE_LIBDECOR_H
static SDL_bool should_use_libdecor(SDL_VideoData *data)
{
if (!SDL_WAYLAND_HAVE_WAYLAND_LIBDECOR) {
return SDL_FALSE;
}
if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR, SDL_TRUE)) {
return SDL_FALSE;
}
if (SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR, SDL_FALSE)) {
return SDL_TRUE;
}
if (data->decoration_manager) {
return SDL_FALSE;
}
return SDL_TRUE;
}
#endif
int
Wayland_VideoInit(_THIS)
@ -785,7 +922,7 @@ Wayland_VideoInit(_THIS)
#ifdef HAVE_LIBDECOR_H
/* Don't have server-side decorations? Try client-side instead. */
if (!data->decoration_manager && SDL_WAYLAND_HAVE_WAYLAND_LIBDECOR && SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR, SDL_TRUE)) {
if (should_use_libdecor(data)) {
data->shell.libdecor = libdecor_new(data->display, &libdecor_interface);
/* If libdecor works, we don't need xdg-shell anymore. */
@ -925,6 +1062,10 @@ Wayland_VideoQuit(_THIS)
zxdg_output_manager_v1_destroy(data->xdg_output_manager);
}
if (data->viewporter) {
wp_viewporter_destroy(data->viewporter);
}
if (data->compositor)
wl_compositor_destroy(data->compositor);

View File

@ -74,6 +74,7 @@ typedef struct {
struct xdg_activation_v1 *activation_manager;
struct zwp_text_input_manager_v3 *text_input_manager;
struct zxdg_output_manager_v1 *xdg_output_manager;
struct wp_viewporter *viewporter;
EGLDisplay edpy;
EGLContext context;
@ -101,10 +102,12 @@ struct SDL_WaylandOutputData {
struct zxdg_output_v1 *xdg_output;
uint32_t registry_id;
float scale_factor;
int native_width, native_height;
int x, y, width, height, refresh, transform;
SDL_DisplayOrientation orientation;
int physical_width, physical_height;
float ddpi, hdpi, vdpi;
SDL_bool has_logical_position, has_logical_size;
int index;
SDL_VideoDisplay placeholder;
int wl_output_done_count;

View File

@ -139,11 +139,11 @@ void Wayland_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
data = (SDL_WindowData *) window->driverdata;
if (w) {
*w = window->w * data->scale_factor;
*w = data->drawable_width;
}
if (h) {
*h = window->h * data->scale_factor;
*h = data->drawable_height;
}
}
}

View File

@ -36,11 +36,268 @@
#include "xdg-decoration-unstable-v1-client-protocol.h"
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "xdg-activation-v1-client-protocol.h"
#include "viewporter-client-protocol.h"
#ifdef HAVE_LIBDECOR_H
#include <libdecor.h>
#endif
static void
GetFullScreenDimensions(SDL_Window *window, int *width, int *height, int *drawable_width, int *drawable_height)
{
SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
int fs_width, fs_height;
int buf_width, buf_height;
/*
* Fullscreen desktop mandates a desktop sized window, so that's what applications will get.
* If the application is DPI aware, it will need to handle the transformations between the
* differently sized window and backbuffer spaces on its own.
*/
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) {
fs_width = output->width;
fs_height = output->height;
/* If the application is DPI aware, we can expose the true backbuffer size */
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
buf_width = output->native_width;
buf_height = output->native_height;
} else {
buf_width = fs_width;
buf_height = fs_height;
}
} else {
/*
* If a mode was set, use it, otherwise use the native resolution
* for DPI aware apps and the desktop size for legacy apps.
*/
if (window->fullscreen_mode.w != 0 && window->fullscreen_mode.h != 0) {
fs_width = window->fullscreen_mode.w;
fs_height = window->fullscreen_mode.h;
} else if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
fs_width = output->native_width;
fs_height = output->native_height;
} else {
fs_width = output->width;
fs_height = output->height;
}
buf_width = fs_width;
buf_height = fs_height;
}
if (width) {
*width = fs_width;
}
if (height) {
*height = fs_height;
}
if (drawable_width) {
*drawable_width = buf_width;
}
if (drawable_height) {
*drawable_height = buf_height;
}
}
static inline SDL_bool
DesktopIsScaled(SDL_Window *window)
{
SDL_WindowData *data = window->driverdata;
return data->scale_factor != 1.0f;
}
static inline SDL_bool
DesktopIsFractionalScaled(SDL_Window *window)
{
SDL_WindowData *data = window->driverdata;
SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
if ((output->native_width != (int)(output->width * data->scale_factor) ||
output->native_height != (int)(output->height * data->scale_factor))) {
return SDL_TRUE;
}
return SDL_FALSE;
}
static SDL_bool
NeedFullscreenViewport(SDL_Window *window)
{
SDL_WindowData *data = window->driverdata;
SDL_VideoData *video = data->waylandData;
SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
int fs_width, fs_height;
GetFullScreenDimensions(window, &fs_width, &fs_height, NULL, NULL);
/*
* Fullscreen needs a viewport:
* - If the desktop uses fractional scaling
* - Fullscreen desktop was not requested OR the window is DPI aware
*
* - The desktop uses non-fractional scaling
* - Fullscreen desktop was NOT requested
*
* - The desktop is not scaled
* - A non-native fullscreen mode was explicitly set by the client
*/
if (video->viewporter != NULL && (window->flags & SDL_WINDOW_FULLSCREEN)) {
if (DesktopIsFractionalScaled(window)) {
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP ||
(window->flags & SDL_WINDOW_ALLOW_HIGHDPI)) {
return SDL_TRUE;
}
} else if (DesktopIsScaled(window)) {
if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP) {
return SDL_TRUE;
}
} else if (fs_width != output->native_width && fs_height != output->native_height) {
return SDL_TRUE;
}
}
return SDL_FALSE;
}
static inline SDL_bool
NeedWindowedViewport(SDL_Window *window)
{
SDL_WindowData *data = window->driverdata;
SDL_VideoData *video = data->waylandData;
return !(window->flags & SDL_WINDOW_FULLSCREEN) && (video->viewporter != NULL) &&
DesktopIsFractionalScaled(window) && (window->flags & SDL_WINDOW_ALLOW_HIGHDPI);
}
static void
GetWindowBufferSize(SDL_Window *window, int *width, int *height)
{
SDL_WindowData *data = window->driverdata;
SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
int buf_width;
int buf_height;
if (NeedWindowedViewport(window)) {
const float frac_scale_x = (float)output->native_width / (float)output->width;
const float frac_scale_y = (float)output->native_height / (float)output->height;
buf_width = (int)SDL_lroundf(window->w * frac_scale_x);
buf_height = (int)SDL_lroundf(window->h * frac_scale_y);
} else { /* Windowed or fullscreen with no viewport */
buf_width = window->w * data->scale_factor;
buf_height = window->h * data->scale_factor;
}
if (width) {
*width = buf_width;
}
if (height) {
*height = buf_height;
}
}
static void
SetViewport(SDL_Window *window, int src_width, int src_height, int dst_width, int dst_height)
{
SDL_WindowData *wind = window->driverdata;
SDL_VideoData *video = wind->waylandData;
if (video->viewporter) {
if (wind->viewport == NULL) {
wind->viewport = wp_viewporter_get_viewport(video->viewporter, wind->surface);
}
wp_viewport_set_source(wind->viewport, wl_fixed_from_int(0), wl_fixed_from_int(0), wl_fixed_from_int(src_width), wl_fixed_from_int(src_height));
wp_viewport_set_destination(wind->viewport, dst_width, dst_height);
}
}
static void
UnsetViewport(SDL_Window *window)
{
SDL_WindowData *wind = window->driverdata;
if (wind->viewport) {
wp_viewport_destroy(wind->viewport);
wind->viewport = NULL;
}
}
static void
ConfigureViewport(SDL_Window *window)
{
SDL_WindowData *data = window->driverdata;
SDL_VideoData *viddata = data->waylandData;
SDL_WaylandOutputData *output = (SDL_WaylandOutputData *)SDL_GetDisplayForWindow(window)->driverdata;
if (NeedFullscreenViewport(window)) {
int fs_width, fs_height;
int src_width, src_height;
GetFullScreenDimensions(window, &fs_width, &fs_height, &src_width, &src_height);
SetViewport(window, src_width, src_height, output->width, output->height);
data->damage_region.x = 0;
data->damage_region.y = 0;
data->damage_region.w = output->width;
data->damage_region.h = output->height;
data->pointer_scale_x = (float)fs_width / (float)output->width;
data->pointer_scale_y = (float)fs_height / (float)output->height;
} else {
if (NeedWindowedViewport(window)) {
int src_width, src_height;
GetWindowBufferSize(window, &src_width, &src_height);
SetViewport(window, src_width, src_height, window->w, window->h);
} else {
UnsetViewport(window);
}
SDL_zero(data->damage_region);
data->pointer_scale_x = 1.0f;
data->pointer_scale_y = 1.0f;
}
/*
* If mouse_rect is not empty, re-create the confinement region with the new scale value.
* If the pointer is locked to the general surface with unspecified coordinates, it will
* be confined to the viewport region, so no update is required.
*/
if (!SDL_RectEmpty(&window->mouse_rect)) {
Wayland_input_confine_pointer(viddata->input, window);
}
}
static void
SetDrawScale(SDL_Window *window)
{
SDL_WindowData *data = window->driverdata;
if (NeedFullscreenViewport(window)) {
int fs_width, fs_height;
GetFullScreenDimensions(window, &fs_width, &fs_height, &data->drawable_width, &data->drawable_height);
/* Set the buffer scale to 1 since a viewport will be used. */
wl_surface_set_buffer_scale(data->surface, 1);
} else {
GetWindowBufferSize(window, &data->drawable_width, &data->drawable_height);
if (NeedWindowedViewport(window)) {
/* Set the buffer scale to 1 since a viewport will be used. */
wl_surface_set_buffer_scale(data->surface, 1);
} else {
wl_surface_set_buffer_scale(data->surface, (int32_t)data->scale_factor);
}
}
}
static void
SetMinMaxDimensions(SDL_Window *window, SDL_bool commit)
{
@ -150,6 +407,11 @@ handle_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time)
SDL_WindowData *wind = (SDL_WindowData *) data;
SDL_AtomicSet(&wind->swap_interval_ready, 1); /* mark window as ready to present again. */
if (!SDL_RectEmpty(&wind->damage_region)) {
wl_surface_damage(wind->surface, wind->damage_region.x, wind->damage_region.y,
wind->damage_region.w, wind->damage_region.h);
}
/* reset this callback to fire again once a new frame was presented and compositor wants the next one. */
wind->frame_callback = wl_surface_frame(wind->frame_surface_wrapper);
wl_callback_destroy(cb);
@ -303,9 +565,14 @@ handle_configure_xdg_toplevel(void *data,
* UPDATE: Nope, sure enough a compositor sends 0,0. This is a known bug:
* https://bugs.kde.org/show_bug.cgi?id=444962
*/
if (width != 0 && height != 0 && (window->w != width || window->h != height)) {
window->w = width;
window->h = height;
if (!NeedFullscreenViewport(window)) {
if (width != 0 && height != 0 && (window->w != width || window->h != height)) {
window->w = width;
window->h = height;
wind->needs_resize_event = SDL_TRUE;
}
} else {
GetFullScreenDimensions(window, &window->w, &window->h, NULL, NULL);
wind->needs_resize_event = SDL_TRUE;
}
@ -399,17 +666,23 @@ decoration_frame_configure(struct libdecor_frame *frame,
* Always assume the configure is wrong.
*/
if (fullscreen) {
/* FIXME: We have been explicitly told to respect the fullscreen size
* parameters here, even though they are known to be wrong on GNOME at
* bare minimum. If this is wrong, don't blame us, we were explicitly
* told to do this.
*/
if (!libdecor_configuration_get_content_size(configuration, frame,
&width, &height)) {
width = window->w;
height = window->h;
if (!NeedFullscreenViewport(window)) {
/* FIXME: We have been explicitly told to respect the fullscreen size
* parameters here, even though they are known to be wrong on GNOME at
* bare minimum. If this is wrong, don't blame us, we were explicitly
* told to do this.
*/
if (!libdecor_configuration_get_content_size(configuration, frame,
&width, &height)) {
width = window->w;
height = window->h;
}
} else {
GetFullScreenDimensions(window, &width, &height, NULL, NULL);
}
wind->needs_resize_event = SDL_TRUE;
/* This part is good though. */
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
scale_factor = driverdata->scale_factor;
@ -554,9 +827,28 @@ Wayland_move_window(SDL_Window *window,
int i, numdisplays = SDL_GetNumVideoDisplays();
for (i = 0; i < numdisplays; i += 1) {
if (SDL_GetDisplay(i)->driverdata == driverdata) {
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED,
SDL_WINDOWPOS_CENTERED_DISPLAY(i),
SDL_WINDOWPOS_CENTERED_DISPLAY(i));
/* We want to send a very very specific combination here:
*
* 1. A coordinate that tells the application what display we're on
* 2. Exactly (0, 0)
*
* Part 1 is useful information but is also really important for
* ensuring we end up on the right display for fullscreen, while
* part 2 is important because numerous applications use a specific
* combination of GetWindowPosition and GetGlobalMouseState, and of
* course neither are supported by Wayland. Since global mouse will
* fall back to just GetMouseState, we need the window position to
* be zero so the cursor math works without it going off in some
* random direction. See UE5 Editor for a notable example of this!
*
* This may be an issue some day if we're ever able to implement
* SDL_GetDisplayUsableBounds!
*
* -flibit
*/
SDL_Rect bounds;
SDL_GetDisplayBounds(i, &bounds);
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, bounds.x, bounds.y);
break;
}
}
@ -731,6 +1023,23 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
SDL_VideoData *c = _this->driverdata;
SDL_WindowData *data = window->driverdata;
/* Detach any previous buffers before resetting everything, otherwise when
* calling this a second time you'll get an annoying protocol error!
*
* FIXME: This was originally moved to HideWindow, which _should_ make
* sense, but for whatever reason UE5's popups require that this actually
* be in both places at once? Possibly from renderers making commits? I can't
* fully remember if this location caused crashes or if I was fixing a pair
* of Hide/Show calls. In any case, UE gives us a pretty good test and having
* both detach calls passes. This bug may be relevant if I'm wrong:
*
* https://bugs.kde.org/show_bug.cgi?id=448856
*
* -flibit
*/
wl_surface_attach(data->surface, NULL, 0, 0);
wl_surface_commit(data->surface);
/* Create the shell surface and map the toplevel */
#ifdef HAVE_LIBDECOR_H
if (c->shell.libdecor) {
@ -1269,7 +1578,9 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
data->waylandData = c;
data->sdlwindow = window;
data->scale_factor = 1.0;
data->scale_factor = 1.0f;
data->pointer_scale_x = 1.0f;
data->pointer_scale_y = 1.0f;
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
int i;
@ -1316,9 +1627,11 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
}
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
data->drawable_width = window->w * data->scale_factor;
data->drawable_height = window->h * data->scale_factor;
if (window->flags & SDL_WINDOW_OPENGL) {
data->egl_window = WAYLAND_wl_egl_window_create(data->surface,
window->w * data->scale_factor, window->h * data->scale_factor);
data->egl_window = WAYLAND_wl_egl_window_create(data->surface, data->drawable_width, data->drawable_height);
#if SDL_VIDEO_OPENGL_EGL
/* Create the GLES window surface */
@ -1375,12 +1688,13 @@ Wayland_HandleResize(SDL_Window *window, int width, int height, float scale)
data->needs_resize_event = SDL_FALSE;
}
wl_surface_set_buffer_scale(data->surface, data->scale_factor);
/* Configure the backbuffer size and scale factors */
SetDrawScale(window);
if (data->egl_window) {
WAYLAND_wl_egl_window_resize(data->egl_window,
window->w * data->scale_factor,
window->h * data->scale_factor,
data->drawable_width,
data->drawable_height,
0, 0);
}
@ -1397,6 +1711,9 @@ Wayland_HandleResize(SDL_Window *window, int width, int height, float scale)
if (viddata->shell.xdg && data->shell_surface.xdg.surface) {
xdg_surface_set_window_geometry(data->shell_surface.xdg.surface, 0, 0, window->w, window->h);
}
/* Update the viewport */
ConfigureViewport(window);
}
void
@ -1431,12 +1748,12 @@ void Wayland_SetWindowSize(_THIS, SDL_Window * window)
}
#endif
wl_surface_set_buffer_scale(wind->surface, wind->scale_factor);
SetDrawScale(window);
if (wind->egl_window) {
WAYLAND_wl_egl_window_resize(wind->egl_window,
window->w * wind->scale_factor,
window->h * wind->scale_factor,
wind->drawable_width,
wind->drawable_height,
0, 0);
}
@ -1549,6 +1866,10 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window)
xdg_activation_token_v1_destroy(wind->activation_token);
}
if (wind->viewport) {
wp_viewport_destroy(wind->viewport);
}
SDL_free(wind->outputs);
if (wind->frame_callback) {

View File

@ -72,6 +72,7 @@ typedef struct {
struct zwp_keyboard_shortcuts_inhibitor_v1 *key_inhibitor;
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
struct xdg_activation_token_v1 *activation_token;
struct wp_viewport *viewport;
/* floating dimensions for restoring from maximized and fullscreen */
int floating_width, floating_height;
@ -86,6 +87,10 @@ typedef struct {
int num_outputs;
float scale_factor;
float pointer_scale_x;
float pointer_scale_y;
int drawable_width, drawable_height;
SDL_Rect damage_region;
SDL_bool needs_resize_event;
SDL_bool floating_resize_pending;
} SDL_WindowData;
@ -112,6 +117,7 @@ extern int Wayland_SetWindowModalFor(_THIS, SDL_Window * modal_window, SDL_Windo
extern void Wayland_SetWindowTitle(_THIS, SDL_Window * window);
extern void Wayland_DestroyWindow(_THIS, SDL_Window *window);
extern void Wayland_SuspendScreenSaver(_THIS);
extern int Wayland_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
extern SDL_bool
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);

View File

@ -378,14 +378,14 @@ WIN_CheckAsyncMouseRelease(SDL_WindowData *data)
}
static void
WIN_UpdateFocus(SDL_Window *window)
WIN_UpdateFocus(SDL_Window *window, SDL_bool expect_focus)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
HWND hwnd = data->hwnd;
SDL_bool had_focus = (SDL_GetKeyboardFocus() == window) ? SDL_TRUE : SDL_FALSE;
SDL_bool has_focus = (GetForegroundWindow() == hwnd) ? SDL_TRUE : SDL_FALSE;
if (had_focus == has_focus) {
if (had_focus == has_focus || has_focus != expect_focus) {
return;
}
@ -686,7 +686,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
/* Update the focus here, since it's possible to get WM_ACTIVATE and WM_SETFOCUS without
actually being the foreground window, but this appears to get called in all cases where
the global foreground window changes to and from this window. */
WIN_UpdateFocus(data->window);
WIN_UpdateFocus(data->window, !!wParam);
WIN_CheckICMProfileChanged(data->window);
}
break;
@ -694,16 +694,22 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_ACTIVATE:
{
/* Update the focus in case we changed focus to a child window and then away from the application */
WIN_UpdateFocus(data->window);
WIN_UpdateFocus(data->window, !!LOWORD(wParam));
}
break;
case WM_SETFOCUS:
{
/* Update the focus in case it's changing between top-level windows in the same application */
WIN_UpdateFocus(data->window, SDL_TRUE);
}
break;
case WM_KILLFOCUS:
case WM_ENTERIDLE:
{
/* Update the focus in case it's changing between top-level windows in the same application */
WIN_UpdateFocus(data->window);
WIN_UpdateFocus(data->window, SDL_FALSE);
}
break;

View File

@ -734,6 +734,13 @@ WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display,
int x, y;
int w, h;
if (!fullscreen && (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_FULLSCREEN_DESKTOP)) != 0) {
/* Resizing the window on hide causes problems restoring it in Wine, and it's unnecessary.
* Also, Windows would preview the minimized window with the wrong size.
*/
return;
}
if (SDL_ShouldAllowTopmost() && ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS) || window->flags & SDL_WINDOW_ALWAYS_ON_TOP)) {
top = HWND_TOPMOST;
} else {

View File

@ -408,7 +408,22 @@ X11_ReconcileKeyboardState(_THIS)
SDL_bool sdlKeyPressed = keyboardState[scancode] == SDL_PRESSED;
if (x11KeyPressed && !sdlKeyPressed) {
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
/* Only update modifier state for keys that are pressed in another application */
switch (SDL_GetKeyFromScancode(scancode)) {
case SDLK_LCTRL:
case SDLK_RCTRL:
case SDLK_LSHIFT:
case SDLK_RSHIFT:
case SDLK_LALT:
case SDLK_RALT:
case SDLK_LGUI:
case SDLK_RGUI:
case SDLK_MODE:
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
break;
default:
break;
}
} else if (!x11KeyPressed && sdlKeyPressed) {
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
}
@ -996,8 +1011,9 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
}
break;
/* Key press? */
case KeyPress:{
/* Key press/release? */
case KeyPress:
case KeyRelease: {
KeyCode keycode = xevent->xkey.keycode;
KeySym keysym = NoSymbol;
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
@ -1005,7 +1021,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
SDL_bool handled_by_ime = SDL_FALSE;
#ifdef DEBUG_XEVENTS
printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode);
printf("window %p: %s (X11 keycode = 0x%X)\n" data, (xevent->type == KeyPress ? "KeyPress" : "KeyRelease"), xevent->xkey.keycode);
#endif
#if 1
if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
@ -1021,7 +1037,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
/* */
SDL_zeroa(text);
#ifdef X_HAVE_UTF8_STRING
if (data->ic) {
if (data->ic && xevent->type == KeyPress) {
X11_Xutf8LookupString(data->ic, &xevent->xkey, text, sizeof(text),
&keysym, &status);
} else {
@ -1033,35 +1049,30 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
#ifdef SDL_USE_IME
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode);
handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode, (xevent->type == KeyPress ? SDL_PRESSED : SDL_RELEASED));
}
#endif
if (!handled_by_ime) {
/* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */
if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) {
SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
}
if(*text) {
SDL_SendKeyboardText(text);
if (xevent->type == KeyPress) {
/* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */
if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) {
SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
}
if(*text) {
SDL_SendKeyboardText(text);
}
} else {
if (X11_KeyRepeat(display, xevent)) {
/* We're about to get a repeated key down, ignore the key up */
break;
}
SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
}
}
X11_UpdateUserTime(data, xevent->xkey.time);
}
break;
/* Key release? */
case KeyRelease:{
KeyCode keycode = xevent->xkey.keycode;
#ifdef DEBUG_XEVENTS
printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode);
#endif
if (X11_KeyRepeat(display, xevent)) {
/* We're about to get a repeated key down, ignore the key up */
break;
if (xevent->type == KeyPress) {
X11_UpdateUserTime(data, xevent->xkey.time);
}
SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
}
break;
@ -1438,6 +1449,13 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
}
}
if (changed & SDL_WINDOW_FULLSCREEN_DESKTOP) {
/* FULLSCREEN_DESKTOP encompasses two bits: SDL_WINDOW_FULLSCREEN, plus a bit to note it's FULLSCREEN_DESKTOP */
const Uint32 fsmasked = flags & SDL_WINDOW_FULLSCREEN_DESKTOP;
data->window->flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP;
data->window->flags |= fsmasked;
}
if (changed & SDL_WINDOW_MAXIMIZED) {
if (flags & SDL_WINDOW_MAXIMIZED) {
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);

View File

@ -1011,7 +1011,13 @@ static int (*PreXRRSetScreenSizeErrorHandler)(Display *, XErrorEvent *) = NULL;
static int
SDL_XRRSetScreenSizeErrHandler(Display *d, XErrorEvent *e)
{
return (e->error_code == BadMatch) ? 0 : PreXRRSetScreenSizeErrorHandler(d, e);
/* BadMatch: https://github.com/libsdl-org/SDL/issues/4561 */
/* BadValue: https://github.com/libsdl-org/SDL/issues/4840 */
if ((e->error_code == BadMatch) || (e->error_code == BadValue)) {
return 0;
}
return PreXRRSetScreenSizeErrorHandler(d, e);
}
int

View File

@ -247,11 +247,6 @@ X11_GL_LoadLibrary(_THIS, const char *path)
X11_GL_UseEGL(_this) ) {
#if SDL_VIDEO_OPENGL_EGL
X11_GL_UnloadLibrary(_this);
/* Better avoid conflicts! */
if (_this->gl_config.dll_handle != NULL ) {
GL_UnloadObject(_this->gl_config.dll_handle);
_this->gl_config.dll_handle = NULL;
}
_this->GL_LoadLibrary = X11_GLES_LoadLibrary;
_this->GL_GetProcAddress = X11_GLES_GetProcAddress;
_this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;

View File

@ -222,7 +222,7 @@ X11_GetNetWMState(_THIS, Window xwindow)
}
if (fullscreen == 1) {
flags |= SDL_WINDOW_FULLSCREEN;
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
}
/* If the window is unmapped, numItems will be zero and _NET_WM_STATE_HIDDEN
@ -782,11 +782,22 @@ X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
X11_XFlush(display);
}
static SDL_bool caught_x11_error = SDL_FALSE;
static int
X11_CatchAnyError(Display * d, XErrorEvent * e)
{
/* this may happen during tumultuous times when we are polling anyhow,
so just note we had an error and return control. */
caught_x11_error = SDL_TRUE;
return 0;
}
void
X11_SetWindowPosition(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
int (*prev_handler) (Display *, XErrorEvent *) = NULL;
unsigned int childCount;
Window childReturn, root, parent;
Window* children;
@ -805,20 +816,27 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
/* Wait a brief time to see if the window manager decided to let this move happen.
If the window changes at all, even to an unexpected value, we break out. */
X11_XSync(display, False);
prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
timeout = SDL_GetTicks() + 100;
while (SDL_TRUE) {
int x, y;
caught_x11_error = SDL_FALSE;
X11_XSync(display, False);
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
attrs.x, attrs.y, &x, &y, &childReturn);
if ((x != orig_x) || (y != orig_y)) {
window->x = x;
window->y = y;
break; /* window moved, time to go. */
} else if ((x == window->x) && (y == window->y)) {
break; /* we're at the place we wanted to be anyhow, drop out. */
if (!caught_x11_error) {
if ((x != orig_x) || (y != orig_y)) {
window->x = x;
window->y = y;
break; /* window moved, time to go. */
} else if ((x == window->x) && (y == window->y)) {
break; /* we're at the place we wanted to be anyhow, drop out. */
}
}
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
@ -827,6 +845,9 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
SDL_Delay(10);
}
X11_XSetErrorHandler(prev_handler);
caught_x11_error = SDL_FALSE;
}
void
@ -892,6 +913,7 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
int (*prev_handler) (Display *, XErrorEvent *) = NULL;
XWindowAttributes attrs;
int orig_w, orig_h;
Uint32 timeout;
@ -943,19 +965,25 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
}
X11_XSync(display, False);
prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
/* Wait a brief time to see if the window manager decided to let this resize happen.
If the window changes at all, even to an unexpected value, we break out. */
timeout = SDL_GetTicks() + 100;
while (SDL_TRUE) {
caught_x11_error = SDL_FALSE;
X11_XSync(display, False);
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
if ((attrs.width != orig_w) || (attrs.height != orig_h)) {
window->w = attrs.width;
window->h = attrs.height;
break; /* window changed, time to go. */
} else if ((attrs.width == window->w) && (attrs.height == window->h)) {
break; /* we're at the place we wanted to be anyhow, drop out. */
if (!caught_x11_error) {
if ((attrs.width != orig_w) || (attrs.height != orig_h)) {
window->w = attrs.width;
window->h = attrs.height;
break; /* window changed, time to go. */
} else if ((attrs.width == window->w) && (attrs.height == window->h)) {
break; /* we're at the place we wanted to be anyhow, drop out. */
}
}
if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
@ -964,6 +992,9 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
SDL_Delay(10);
}
X11_XSetErrorHandler(prev_handler);
caught_x11_error = SDL_FALSE;
}
int
@ -1281,6 +1312,22 @@ X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _dis
if (X11_IsWindowMapped(_this, window)) {
XEvent e;
/* !!! FIXME: most of this waiting code is copy/pasted from elsewhere. */
int (*prev_handler) (Display *, XErrorEvent *) = NULL;
unsigned int childCount;
Window childReturn, root, parent;
Window* children;
XWindowAttributes attrs;
int orig_w, orig_h, orig_x, orig_y;
Uint64 timeout;
X11_XSync(display, False);
X11_XQueryTree(display, data->xwindow, &root, &parent, &children, &childCount);
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
attrs.x, attrs.y, &orig_x, &orig_y, &childReturn);
orig_w = attrs.width;
orig_h = attrs.height;
if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
/* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we
@ -1330,6 +1377,41 @@ X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _dis
X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
SubstructureNotifyMask | SubstructureRedirectMask, &e);
}
/* Wait a brief time to see if the window manager decided to let this happen.
If the window changes at all, even to an unexpected value, we break out. */
X11_XSync(display, False);
prev_handler = X11_XSetErrorHandler(X11_CatchAnyError);
timeout = SDL_GetTicks64() + 100;
while (SDL_TRUE) {
int x, y;
caught_x11_error = SDL_FALSE;
X11_XSync(display, False);
X11_XGetWindowAttributes(display, data->xwindow, &attrs);
X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
attrs.x, attrs.y, &x, &y, &childReturn);
if (!caught_x11_error) {
if ((x != orig_x) || (y != orig_y) || (attrs.width != orig_w) || (attrs.height != orig_h)) {
window->x = x;
window->y = y;
window->w = attrs.width;
window->h = attrs.height;
break; /* window moved, time to go. */
}
}
if (SDL_GetTicks64() >= timeout) {
break;
}
SDL_Delay(10);
}
X11_XSetErrorHandler(prev_handler);
caught_x11_error = SDL_FALSE;
} else {
Uint32 flags;

View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="viewporter">
<copyright>
Copyright © 2013-2016 Collabora, Ltd.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
</copyright>
<interface name="wp_viewporter" version="1">
<description summary="surface cropping and scaling">
The global interface exposing surface cropping and scaling
capabilities is used to instantiate an interface extension for a
wl_surface object. This extended interface will then allow
cropping and scaling the surface contents, effectively
disconnecting the direct relationship between the buffer and the
surface size.
</description>
<request name="destroy" type="destructor">
<description summary="unbind from the cropping and scaling interface">
Informs the server that the client will not be using this
protocol object anymore. This does not affect any other objects,
wp_viewport objects included.
</description>
</request>
<enum name="error">
<entry name="viewport_exists" value="0"
summary="the surface already has a viewport object associated"/>
</enum>
<request name="get_viewport">
<description summary="extend surface interface for crop and scale">
Instantiate an interface extension for the given wl_surface to
crop and scale its content. If the given wl_surface already has
a wp_viewport object associated, the viewport_exists
protocol error is raised.
</description>
<arg name="id" type="new_id" interface="wp_viewport"
summary="the new viewport interface id"/>
<arg name="surface" type="object" interface="wl_surface"
summary="the surface"/>
</request>
</interface>
<interface name="wp_viewport" version="1">
<description summary="crop and scale interface to a wl_surface">
An additional interface to a wl_surface object, which allows the
client to specify the cropping and scaling of the surface
contents.
This interface works with two concepts: the source rectangle (src_x,
src_y, src_width, src_height), and the destination size (dst_width,
dst_height). The contents of the source rectangle are scaled to the
destination size, and content outside the source rectangle is ignored.
This state is double-buffered, and is applied on the next
wl_surface.commit.
The two parts of crop and scale state are independent: the source
rectangle, and the destination size. Initially both are unset, that
is, no scaling is applied. The whole of the current wl_buffer is
used as the source, and the surface size is as defined in
wl_surface.attach.
If the destination size is set, it causes the surface size to become
dst_width, dst_height. The source (rectangle) is scaled to exactly
this size. This overrides whatever the attached wl_buffer size is,
unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface
has no content and therefore no size. Otherwise, the size is always
at least 1x1 in surface local coordinates.
If the source rectangle is set, it defines what area of the wl_buffer is
taken as the source. If the source rectangle is set and the destination
size is not set, then src_width and src_height must be integers, and the
surface size becomes the source rectangle size. This results in cropping
without scaling. If src_width or src_height are not integers and
destination size is not set, the bad_size protocol error is raised when
the surface state is applied.
The coordinate transformations from buffer pixel coordinates up to
the surface-local coordinates happen in the following order:
1. buffer_transform (wl_surface.set_buffer_transform)
2. buffer_scale (wl_surface.set_buffer_scale)
3. crop and scale (wp_viewport.set*)
This means, that the source rectangle coordinates of crop and scale
are given in the coordinates after the buffer transform and scale,
i.e. in the coordinates that would be the surface-local coordinates
if the crop and scale was not applied.
If src_x or src_y are negative, the bad_value protocol error is raised.
Otherwise, if the source rectangle is partially or completely outside of
the non-NULL wl_buffer, then the out_of_buffer protocol error is raised
when the surface state is applied. A NULL wl_buffer does not raise the
out_of_buffer error.
The x, y arguments of wl_surface.attach are applied as normal to
the surface. They indicate how many pixels to remove from the
surface size from the left and the top. In other words, they are
still in the surface-local coordinate system, just like dst_width
and dst_height are.
If the wl_surface associated with the wp_viewport is destroyed,
all wp_viewport requests except 'destroy' raise the protocol error
no_surface.
If the wp_viewport object is destroyed, the crop and scale
state is removed from the wl_surface. The change will be applied
on the next wl_surface.commit.
</description>
<request name="destroy" type="destructor">
<description summary="remove scaling and cropping from the surface">
The associated wl_surface's crop and scale state is removed.
The change is applied on the next wl_surface.commit.
</description>
</request>
<enum name="error">
<entry name="bad_value" value="0"
summary="negative or zero values in width or height"/>
<entry name="bad_size" value="1"
summary="destination size is not integer"/>
<entry name="out_of_buffer" value="2"
summary="source rectangle extends outside of the content area"/>
<entry name="no_surface" value="3"
summary="the wl_surface was destroyed"/>
</enum>
<request name="set_source">
<description summary="set the source rectangle for cropping">
Set the source rectangle of the associated wl_surface. See
wp_viewport for the description, and relation to the wl_buffer
size.
If all of x, y, width and height are -1.0, the source rectangle is
unset instead. Any other set of values where width or height are zero
or negative, or x or y are negative, raise the bad_value protocol
error.
The crop and scale state is double-buffered state, and will be
applied on the next wl_surface.commit.
</description>
<arg name="x" type="fixed" summary="source rectangle x"/>
<arg name="y" type="fixed" summary="source rectangle y"/>
<arg name="width" type="fixed" summary="source rectangle width"/>
<arg name="height" type="fixed" summary="source rectangle height"/>
</request>
<request name="set_destination">
<description summary="set the surface size for scaling">
Set the destination size of the associated wl_surface. See
wp_viewport for the description, and relation to the wl_buffer
size.
If width is -1 and height is -1, the destination size is unset
instead. Any other pair of values for width and height that
contains zero or negative values raises the bad_value protocol
error.
The crop and scale state is double-buffered state, and will be
applied on the next wl_surface.commit.
</description>
<arg name="width" type="int" summary="surface width"/>
<arg name="height" type="int" summary="surface height"/>
</request>
</interface>
</protocol>