mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2026-04-21 15:40:18 +00:00
WIP SDL3 compatibility
This commit is contained in:
@@ -174,7 +174,7 @@ void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength)
|
||||
// of other threads due to severely restricted CPU time available,
|
||||
// so we will skip it on that platform.
|
||||
if (s_ActiveSession->m_AudioSampleCount == 0) {
|
||||
if (SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH) < 0) {
|
||||
if (SDLC_FAILURE(SDL_SetCurrentThreadPriority(SDL_THREAD_PRIORITY_HIGH))) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unable to set audio thread to high priority: %s",
|
||||
SDL_GetError());
|
||||
|
||||
@@ -22,7 +22,7 @@ bool SdlAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION*
|
||||
|
||||
SDL_zero(want);
|
||||
want.freq = opusConfig->sampleRate;
|
||||
want.format = AUDIO_F32SYS;
|
||||
want.format = SDL_AUDIO_F32;
|
||||
want.channels = opusConfig->channelCount;
|
||||
|
||||
// On PulseAudio systems, setting a value too small can cause underruns for other
|
||||
@@ -73,7 +73,7 @@ bool SdlAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION*
|
||||
SDL_GetCurrentAudioDriver());
|
||||
|
||||
// Start playback
|
||||
SDL_PauseAudioDevice(m_AudioDevice, 0);
|
||||
SDL_ResumeAudioDevice(m_AudioDevice);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -82,13 +82,13 @@ void SdlInputHandler::handleAbsoluteFingerEvent(SDL_TouchFingerEvent* event)
|
||||
|
||||
uint8_t eventType;
|
||||
switch (event->type) {
|
||||
case SDL_FINGERDOWN:
|
||||
case SDL_EVENT_FINGER_DOWN :
|
||||
eventType = LI_TOUCH_EVENT_DOWN;
|
||||
break;
|
||||
case SDL_FINGERMOTION:
|
||||
case SDL_EVENT_FINGER_MOTION :
|
||||
eventType = LI_TOUCH_EVENT_MOVE;
|
||||
break;
|
||||
case SDL_FINGERUP:
|
||||
case SDL_EVENT_FINGER_UP :
|
||||
eventType = LI_TOUCH_EVENT_UP;
|
||||
break;
|
||||
default:
|
||||
@@ -98,16 +98,16 @@ void SdlInputHandler::handleAbsoluteFingerEvent(SDL_TouchFingerEvent* event)
|
||||
uint32_t pointerId;
|
||||
|
||||
// If the pointer ID is larger than we can fit, just CRC it and use that as the ID.
|
||||
if ((uint64_t)event->fingerId > UINT32_MAX) {
|
||||
if ((uint64_t) event->fingerID > UINT32_MAX) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||
QByteArrayView bav((char*)&event->fingerId, sizeof(event->fingerId));
|
||||
QByteArrayView bav((char*)&event->fingerID, sizeof(event->fingerID));
|
||||
pointerId = qChecksum(bav);
|
||||
#else
|
||||
pointerId = qChecksum((char*)&event->fingerId, sizeof(event->fingerId));
|
||||
pointerId = qChecksum((char*)&event->fingerID, sizeof(event->fingerID));
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
pointerId = (uint32_t)event->fingerId;
|
||||
pointerId = (uint32_t) event->fingerID;
|
||||
}
|
||||
|
||||
// Try to send it as a native pen/touch event, otherwise fall back to our touch emulation
|
||||
@@ -117,7 +117,7 @@ void SdlInputHandler::handleAbsoluteFingerEvent(SDL_TouchFingerEvent* event)
|
||||
|
||||
int numTouchDevices = SDL_GetNumTouchDevices();
|
||||
for (int i = 0; i < numTouchDevices; i++) {
|
||||
if (event->touchId == SDL_GetTouchDevice(i)) {
|
||||
if (event->touchID == SDL_GetTouchDevice(i)) {
|
||||
const char* touchName = SDL_GetTouchName(i);
|
||||
|
||||
// SDL will report "pen" as the name of pen input devices on Windows.
|
||||
@@ -158,12 +158,12 @@ void SdlInputHandler::emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event)
|
||||
// dx and dy are deltas from the last touch event, not the first touch down.
|
||||
|
||||
// Ignore touch down events with more than one finger
|
||||
if (event->type == SDL_FINGERDOWN && SDL_GetNumTouchFingers(event->touchId) > 1) {
|
||||
if (event->type == SDL_EVENT_FINGER_DOWN && SDL_GetNumTouchFingers(event->touchID) > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore touch move and touch up events from the non-primary finger
|
||||
if (event->type != SDL_FINGERDOWN && event->fingerId != m_LastTouchDownEvent.fingerId) {
|
||||
if (event->type != SDL_EVENT_FINGER_DOWN && event->fingerID != m_LastTouchDownEvent.fingerID) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ void SdlInputHandler::emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event)
|
||||
}
|
||||
|
||||
// Don't reposition for finger down events within the deadzone. This makes double-clicking easier.
|
||||
if (event->type != SDL_FINGERDOWN ||
|
||||
if (event->type != SDL_EVENT_FINGER_DOWN ||
|
||||
event->timestamp - m_LastTouchUpEvent.timestamp > DOUBLE_TAP_DEAD_ZONE_DELAY ||
|
||||
qSqrt(qPow(event->x - m_LastTouchUpEvent.x, 2) + qPow(event->y - m_LastTouchUpEvent.y, 2)) > DOUBLE_TAP_DEAD_ZONE_DELTA) {
|
||||
// Scale window-relative events to be video-relative and clamp to video region
|
||||
@@ -201,7 +201,7 @@ void SdlInputHandler::emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event)
|
||||
LiSendMousePositionEvent(x - dst.x, y - dst.y, dst.w, dst.h);
|
||||
}
|
||||
|
||||
if (event->type == SDL_FINGERDOWN) {
|
||||
if (event->type == SDL_EVENT_FINGER_DOWN) {
|
||||
m_LastTouchDownEvent = *event;
|
||||
|
||||
// Start/restart the long press timer
|
||||
@@ -213,7 +213,7 @@ void SdlInputHandler::emulateAbsoluteFingerEvent(SDL_TouchFingerEvent* event)
|
||||
// Left button down on finger down
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||
}
|
||||
else if (event->type == SDL_FINGERUP) {
|
||||
else if (event->type == SDL_EVENT_FINGER_UP) {
|
||||
m_LastTouchUpEvent = *event;
|
||||
|
||||
// Cancel the long press timer
|
||||
|
||||
@@ -188,7 +188,7 @@ Uint32 SdlInputHandler::mouseEmulationTimerCallback(Uint32 interval, void *param
|
||||
return interval;
|
||||
}
|
||||
|
||||
void SdlInputHandler::handleControllerAxisEvent(SDL_ControllerAxisEvent* event)
|
||||
void SdlInputHandler::handleControllerAxisEvent(SDL_GamepadAxisEvent * event)
|
||||
{
|
||||
SDL_JoystickID gameControllerId = event->which;
|
||||
GamepadState* state = findStateForGamepad(gameControllerId);
|
||||
@@ -201,10 +201,10 @@ void SdlInputHandler::handleControllerAxisEvent(SDL_ControllerAxisEvent* event)
|
||||
for (;;) {
|
||||
switch (event->axis)
|
||||
{
|
||||
case SDL_CONTROLLER_AXIS_LEFTX:
|
||||
case SDL_GAMEPAD_AXIS_LEFTX :
|
||||
state->lsX = event->value;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_LEFTY:
|
||||
case SDL_GAMEPAD_AXIS_LEFTY :
|
||||
// Signed values have one more negative value than
|
||||
// positive value, so inverting the sign on -32768
|
||||
// could actually cause the value to overflow and
|
||||
@@ -212,16 +212,16 @@ void SdlInputHandler::handleControllerAxisEvent(SDL_ControllerAxisEvent* event)
|
||||
// capping the value at 32767.
|
||||
state->lsY = -qMax(event->value, (short)-32767);
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX:
|
||||
case SDL_GAMEPAD_AXIS_RIGHTX :
|
||||
state->rsX = event->value;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY:
|
||||
case SDL_GAMEPAD_AXIS_RIGHTY :
|
||||
state->rsY = -qMax(event->value, (short)-32767);
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
|
||||
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER :
|
||||
state->lt = (unsigned char)(event->value * 255UL / 32767);
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
|
||||
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER :
|
||||
state->rt = (unsigned char)(event->value * 255UL / 32767);
|
||||
break;
|
||||
default:
|
||||
@@ -232,18 +232,18 @@ void SdlInputHandler::handleControllerAxisEvent(SDL_ControllerAxisEvent* event)
|
||||
}
|
||||
|
||||
// Check for another event to batch with
|
||||
if (SDL_PeepEvents(&nextEvent, 1, SDL_PEEKEVENT, SDL_CONTROLLERAXISMOTION, SDL_CONTROLLERAXISMOTION) <= 0) {
|
||||
if (SDL_PeepEvents(&nextEvent, 1, SDL_PEEKEVENT, SDL_EVENT_GAMEPAD_AXIS_MOTION, SDL_EVENT_GAMEPAD_AXIS_MOTION) <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
event = &nextEvent.caxis;
|
||||
event = &nextEvent.gaxis;
|
||||
if (event->which != gameControllerId) {
|
||||
// Stop batching if a different gamepad interrupts us
|
||||
break;
|
||||
}
|
||||
|
||||
// Remove the next event to batch
|
||||
SDL_PeepEvents(&nextEvent, 1, SDL_GETEVENT, SDL_CONTROLLERAXISMOTION, SDL_CONTROLLERAXISMOTION);
|
||||
SDL_PeepEvents(&nextEvent, 1, SDL_GETEVENT, SDL_EVENT_GAMEPAD_AXIS_MOTION, SDL_EVENT_GAMEPAD_AXIS_MOTION);
|
||||
}
|
||||
|
||||
// Only send the gamepad state to the host if it's not in mouse emulation mode
|
||||
@@ -252,7 +252,7 @@ void SdlInputHandler::handleControllerAxisEvent(SDL_ControllerAxisEvent* event)
|
||||
}
|
||||
}
|
||||
|
||||
void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* event)
|
||||
void SdlInputHandler::handleControllerButtonEvent(SDL_GamepadButtonEvent * event)
|
||||
{
|
||||
if (event->button >= SDL_arraysize(k_ButtonMap)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
@@ -268,53 +268,53 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
|
||||
|
||||
if (m_SwapFaceButtons) {
|
||||
switch (event->button) {
|
||||
case SDL_CONTROLLER_BUTTON_A:
|
||||
event->button = SDL_CONTROLLER_BUTTON_B;
|
||||
case SDL_GAMEPAD_BUTTON_SOUTH :
|
||||
event->button = SDL_GAMEPAD_BUTTON_EAST;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_B:
|
||||
event->button = SDL_CONTROLLER_BUTTON_A;
|
||||
case SDL_GAMEPAD_BUTTON_EAST :
|
||||
event->button = SDL_GAMEPAD_BUTTON_SOUTH;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_X:
|
||||
event->button = SDL_CONTROLLER_BUTTON_Y;
|
||||
case SDL_GAMEPAD_BUTTON_WEST :
|
||||
event->button = SDL_GAMEPAD_BUTTON_NORTH;
|
||||
break;
|
||||
case SDL_CONTROLLER_BUTTON_Y:
|
||||
event->button = SDL_CONTROLLER_BUTTON_X;
|
||||
case SDL_GAMEPAD_BUTTON_NORTH :
|
||||
event->button = SDL_GAMEPAD_BUTTON_WEST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (event->state == SDL_PRESSED) {
|
||||
if (event->state == true) {
|
||||
state->buttons |= k_ButtonMap[event->button];
|
||||
|
||||
if (event->button == SDL_CONTROLLER_BUTTON_START) {
|
||||
if (event->button == SDL_GAMEPAD_BUTTON_START) {
|
||||
state->lastStartDownTime = SDL_GetTicks();
|
||||
}
|
||||
else if (state->mouseEmulationTimer != 0) {
|
||||
if (event->button == SDL_CONTROLLER_BUTTON_A) {
|
||||
if (event->button == SDL_GAMEPAD_BUTTON_SOUTH) {
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_B) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_EAST) {
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_X) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_WEST) {
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_MIDDLE);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_LEFT_SHOULDER) {
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_X1);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER) {
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_X2);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_UP) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_DPAD_UP) {
|
||||
LiSendScrollEvent(1);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_DOWN) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_DPAD_DOWN) {
|
||||
LiSendScrollEvent(-1);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_RIGHT) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_DPAD_RIGHT) {
|
||||
LiSendHScrollEvent(1);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_DPAD_LEFT) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_DPAD_LEFT) {
|
||||
LiSendHScrollEvent(-1);
|
||||
}
|
||||
}
|
||||
@@ -322,7 +322,7 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
|
||||
else {
|
||||
state->buttons &= ~k_ButtonMap[event->button];
|
||||
|
||||
if (event->button == SDL_CONTROLLER_BUTTON_START) {
|
||||
if (event->button == SDL_GAMEPAD_BUTTON_START) {
|
||||
if (SDL_GetTicks() - state->lastStartDownTime > MOUSE_EMULATION_LONG_PRESS_TIME) {
|
||||
if (state->mouseEmulationTimer != 0) {
|
||||
SDL_RemoveTimer(state->mouseEmulationTimer);
|
||||
@@ -345,19 +345,19 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
|
||||
}
|
||||
}
|
||||
else if (state->mouseEmulationTimer != 0) {
|
||||
if (event->button == SDL_CONTROLLER_BUTTON_A) {
|
||||
if (event->button == SDL_GAMEPAD_BUTTON_SOUTH) {
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_B) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_EAST) {
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_X) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_WEST) {
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_MIDDLE);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_LEFT_SHOULDER) {
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X1);
|
||||
}
|
||||
else if (event->button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) {
|
||||
else if (event->button == SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER) {
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_X2);
|
||||
}
|
||||
}
|
||||
@@ -370,7 +370,7 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
|
||||
|
||||
// Push a quit event to the main loop
|
||||
SDL_Event event;
|
||||
event.type = SDL_QUIT;
|
||||
event.type = SDL_EVENT_QUIT;
|
||||
event.quit.timestamp = SDL_GetTicks();
|
||||
SDL_PushEvent(&event);
|
||||
|
||||
@@ -403,7 +403,7 @@ void SdlInputHandler::handleControllerButtonEvent(SDL_ControllerButtonEvent* eve
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
|
||||
void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* event)
|
||||
void SdlInputHandler::handleControllerSensorEvent(SDL_GamepadSensorEvent * event)
|
||||
{
|
||||
GamepadState* state = findStateForGamepad(event->which);
|
||||
if (state == NULL) {
|
||||
@@ -438,7 +438,7 @@ void SdlInputHandler::handleControllerSensorEvent(SDL_ControllerSensorEvent* eve
|
||||
}
|
||||
}
|
||||
|
||||
void SdlInputHandler::handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* event)
|
||||
void SdlInputHandler::handleControllerTouchpadEvent(SDL_GamepadTouchpadEvent * event)
|
||||
{
|
||||
GamepadState* state = findStateForGamepad(event->which);
|
||||
if (state == NULL) {
|
||||
@@ -447,13 +447,13 @@ void SdlInputHandler::handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent*
|
||||
|
||||
uint8_t eventType;
|
||||
switch (event->type) {
|
||||
case SDL_CONTROLLERTOUCHPADDOWN:
|
||||
case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN :
|
||||
eventType = LI_TOUCH_EVENT_DOWN;
|
||||
break;
|
||||
case SDL_CONTROLLERTOUCHPADUP:
|
||||
case SDL_EVENT_GAMEPAD_TOUCHPAD_UP :
|
||||
eventType = LI_TOUCH_EVENT_UP;
|
||||
break;
|
||||
case SDL_CONTROLLERTOUCHPADMOTION:
|
||||
case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION :
|
||||
eventType = LI_TOUCH_EVENT_MOVE;
|
||||
break;
|
||||
default:
|
||||
@@ -479,18 +479,21 @@ void SdlInputHandler::handleJoystickBatteryEvent(SDL_JoyBatteryEvent* event)
|
||||
|
||||
#endif
|
||||
|
||||
void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* event)
|
||||
void SdlInputHandler::handleControllerDeviceEvent(SDL_GamepadDeviceEvent * event)
|
||||
{
|
||||
GamepadState* state;
|
||||
|
||||
if (event->type == SDL_CONTROLLERDEVICEADDED) {
|
||||
if (event->type == SDL_EVENT_GAMEPAD_ADDED) {
|
||||
int i;
|
||||
const char* name;
|
||||
SDL_GameController* controller;
|
||||
SDL_Gamepad * controller;
|
||||
const char* mapping;
|
||||
char guidStr[33];
|
||||
uint32_t hapticCaps;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
controller = SDL_OpenGamepad(event->which);
|
||||
#else
|
||||
controller = SDL_GameControllerOpen(event->which);
|
||||
if (controller == NULL) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
@@ -500,7 +503,7 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
}
|
||||
|
||||
// SDL_CONTROLLERDEVICEADDED can be reported multiple times for the same
|
||||
// gamepad in rare cases, because SDL doesn't fixup the device index in
|
||||
// gamepad in rare cases, because SDL2 doesn't fixup the device index in
|
||||
// the SDL_CONTROLLERDEVICEADDED event if an unopened gamepad disappears
|
||||
// before we've processed the add event.
|
||||
for (int i = 0; i < MAX_GAMEPADS; i++) {
|
||||
@@ -508,10 +511,11 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Received duplicate add event for controller index: %d",
|
||||
event->which);
|
||||
SDL_GameControllerClose(controller);
|
||||
SDL_CloseGamepad(controller);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// We used to use SDL_GameControllerGetPlayerIndex() here but that
|
||||
// can lead to strange issues due to bugs in Windows where an Xbox
|
||||
@@ -531,18 +535,18 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
if (i == MAX_GAMEPADS) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"No open gamepad slots found!");
|
||||
SDL_GameControllerClose(controller);
|
||||
SDL_CloseGamepad(controller);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(SDL_GameControllerGetJoystick(controller)),
|
||||
SDL_JoystickGetGUIDString(SDL_GetJoystickGUID(SDL_GetGamepadJoystick(controller)),
|
||||
guidStr, sizeof(guidStr));
|
||||
if (m_IgnoreDeviceGuids.contains(guidStr, Qt::CaseInsensitive))
|
||||
{
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Skipping ignored device with GUID: %s",
|
||||
guidStr);
|
||||
SDL_GameControllerClose(controller);
|
||||
SDL_CloseGamepad(controller);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -554,7 +558,7 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
// This will change indicators on the controller to show the assigned
|
||||
// player index. For Xbox 360 controllers, that means updating the LED
|
||||
// ring to light up the corresponding quadrant for this player.
|
||||
SDL_GameControllerSetPlayerIndex(controller, state->index);
|
||||
SDL_SetGamepadPlayerIndex(controller, state->index);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
@@ -563,7 +567,7 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
}
|
||||
|
||||
state->controller = controller;
|
||||
state->jsId = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(state->controller));
|
||||
state->jsId = SDL_GetJoystickID(SDL_GetGamepadJoystick(state->controller));
|
||||
|
||||
hapticCaps = 0;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
@@ -573,9 +577,9 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
// Perform a tiny rumbles to see if haptics are supported.
|
||||
// NB: We cannot use zeros for rumble intensity or SDL will not actually call the JS driver
|
||||
// and we'll get a (potentially false) success value returned.
|
||||
hapticCaps |= SDL_GameControllerRumble(controller, 1, 1, 1) == 0 ? ML_HAPTIC_GC_RUMBLE : 0;
|
||||
hapticCaps |= SDL_RumbleGamepad(controller, 1, 1, 1) ? ML_HAPTIC_GC_RUMBLE : 0;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
hapticCaps |= SDL_GameControllerRumbleTriggers(controller, 1, 1, 1) == 0 ? ML_HAPTIC_GC_TRIGGER_RUMBLE : 0;
|
||||
hapticCaps |= SDL_RumbleGamepadTriggers(controller, 1, 1, 1) ? ML_HAPTIC_GC_TRIGGER_RUMBLE : 0;
|
||||
#endif
|
||||
#else
|
||||
state->haptic = SDL_HapticOpenFromJoystick(SDL_GameControllerGetJoystick(state->controller));
|
||||
@@ -606,11 +610,11 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
}
|
||||
#endif
|
||||
|
||||
mapping = SDL_GameControllerMapping(state->controller);
|
||||
name = SDL_GameControllerName(state->controller);
|
||||
mapping = SDL_GetGamepadMapping(state->controller);
|
||||
name = SDL_GetGamepadName(state->controller);
|
||||
|
||||
uint16_t vendorId = SDL_GameControllerGetVendor(state->controller);
|
||||
uint16_t productId = SDL_GameControllerGetProduct(state->controller);
|
||||
uint16_t vendorId = SDL_GetGamepadVendor(state->controller);
|
||||
uint16_t productId = SDL_GetGamepadProduct(state->controller);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Gamepad %d (player %d) is: %s (VID/PID: 0x%.4x/0x%.4x) (haptic capabilities: 0x%x) (mapping: %s -> %s)",
|
||||
i,
|
||||
@@ -636,21 +640,21 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
SDL_assert(m_GamepadMask == 0x1);
|
||||
}
|
||||
|
||||
SDL_JoystickPowerLevel powerLevel = SDL_JoystickCurrentPowerLevel(SDL_GameControllerGetJoystick(state->controller));
|
||||
SDL_JoystickPowerLevel powerLevel = SDL_GetJoystickPowerLevel(SDL_GetGamepadJoystick(state->controller));
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
// On SDL 2.0.14 and later, we can provide enhanced controller information to the host PC
|
||||
// for it to use as a hint for the type of controller to emulate.
|
||||
uint32_t supportedButtonFlags = 0;
|
||||
for (int i = 0; i < (int)SDL_arraysize(k_ButtonMap); i++) {
|
||||
if (SDL_GameControllerHasButton(state->controller, (SDL_GameControllerButton)i)) {
|
||||
if (SDL_GamepadHasButton(state->controller, (SDL_GamepadButton)i)) {
|
||||
supportedButtonFlags |= k_ButtonMap[i];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t capabilities = 0;
|
||||
if (SDL_GameControllerGetBindForAxis(state->controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT).bindType == SDL_CONTROLLER_BINDTYPE_AXIS ||
|
||||
SDL_GameControllerGetBindForAxis(state->controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT).bindType == SDL_CONTROLLER_BINDTYPE_AXIS) {
|
||||
if (SDL_GameControllerGetBindForAxis(state->controller, SDL_GAMEPAD_AXIS_LEFT_TRIGGER).bindType == SDL_GAMEPAD_BINDTYPE_AXIS ||
|
||||
SDL_GameControllerGetBindForAxis(state->controller, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER).bindType == SDL_GAMEPAD_BINDTYPE_AXIS) {
|
||||
// We assume these are analog triggers if the binding is to an axis rather than a button
|
||||
capabilities |= LI_CCAP_ANALOG_TRIGGERS;
|
||||
}
|
||||
@@ -660,13 +664,13 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
if (hapticCaps & ML_HAPTIC_GC_TRIGGER_RUMBLE) {
|
||||
capabilities |= LI_CCAP_TRIGGER_RUMBLE;
|
||||
}
|
||||
if (SDL_GameControllerGetNumTouchpads(state->controller) > 0) {
|
||||
if (SDL_GetNumGamepadTouchpads(state->controller) > 0) {
|
||||
capabilities |= LI_CCAP_TOUCHPAD;
|
||||
}
|
||||
if (SDL_GameControllerHasSensor(state->controller, SDL_SENSOR_ACCEL)) {
|
||||
if (SDL_GamepadHasSensor(state->controller, SDL_SENSOR_ACCEL)) {
|
||||
capabilities |= LI_CCAP_ACCEL;
|
||||
}
|
||||
if (SDL_GameControllerHasSensor(state->controller, SDL_SENSOR_GYRO)) {
|
||||
if (SDL_GamepadHasSensor(state->controller, SDL_SENSOR_GYRO)) {
|
||||
capabilities |= LI_CCAP_GYRO;
|
||||
}
|
||||
if (powerLevel != SDL_JOYSTICK_POWER_UNKNOWN || SDL_VERSION_ATLEAST(2, 24, 0)) {
|
||||
@@ -677,21 +681,21 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
}
|
||||
|
||||
uint8_t type;
|
||||
switch (SDL_GameControllerGetType(state->controller)) {
|
||||
case SDL_CONTROLLER_TYPE_XBOX360:
|
||||
case SDL_CONTROLLER_TYPE_XBOXONE:
|
||||
switch (SDL_GetGamepadType(state->controller)) {
|
||||
case SDL_GAMEPAD_TYPE_XBOX360 :
|
||||
case SDL_GAMEPAD_TYPE_XBOXONE :
|
||||
type = LI_CTYPE_XBOX;
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_PS3:
|
||||
case SDL_CONTROLLER_TYPE_PS4:
|
||||
case SDL_CONTROLLER_TYPE_PS5:
|
||||
case SDL_GAMEPAD_TYPE_PS3 :
|
||||
case SDL_GAMEPAD_TYPE_PS4 :
|
||||
case SDL_GAMEPAD_TYPE_PS5 :
|
||||
type = LI_CTYPE_PS;
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
|
||||
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO :
|
||||
#if SDL_VERSION_ATLEAST(2, 24, 0)
|
||||
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT:
|
||||
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT:
|
||||
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR:
|
||||
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT :
|
||||
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT :
|
||||
case SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR :
|
||||
#endif
|
||||
type = LI_CTYPE_NINTENDO;
|
||||
break;
|
||||
@@ -704,7 +708,7 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
// we'll allow the Select+PS button combo to act as the touchpad.
|
||||
state->clickpadButtonEmulationEnabled =
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
SDL_GameControllerGetBindForButton(state->controller, SDL_CONTROLLER_BUTTON_TOUCHPAD).bindType == SDL_CONTROLLER_BINDTYPE_NONE &&
|
||||
SDL_GameControllerGetBindForButton(state->controller, SDL_GAMEPAD_BUTTON_TOUCHPAD).bindType == SDL_GAMEPAD_BINDTYPE_NONE &&
|
||||
#endif
|
||||
type == LI_CTYPE_PS;
|
||||
|
||||
@@ -720,7 +724,7 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
sendGamepadBatteryState(state, powerLevel);
|
||||
}
|
||||
}
|
||||
else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
|
||||
else if (event->type == SDL_EVENT_GAMEPAD_REMOVED) {
|
||||
state = findStateForGamepad(event->which);
|
||||
if (state != NULL) {
|
||||
if (state->mouseEmulationTimer != 0) {
|
||||
@@ -728,7 +732,7 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
SDL_RemoveTimer(state->mouseEmulationTimer);
|
||||
}
|
||||
|
||||
SDL_GameControllerClose(state->controller);
|
||||
SDL_CloseGamepad(state->controller);
|
||||
|
||||
#if !SDL_VERSION_ATLEAST(2, 0, 9)
|
||||
if (state->haptic != nullptr) {
|
||||
@@ -761,24 +765,23 @@ void SdlInputHandler::handleControllerDeviceEvent(SDL_ControllerDeviceEvent* eve
|
||||
|
||||
void SdlInputHandler::handleJoystickArrivalEvent(SDL_JoyDeviceEvent* event)
|
||||
{
|
||||
SDL_assert(event->type == SDL_JOYDEVICEADDED);
|
||||
SDL_assert(event->type == SDL_EVENT_JOYSTICK_ADDED);
|
||||
|
||||
if (!SDL_IsGameController(event->which)) {
|
||||
char guidStr[33];
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(event->which),
|
||||
guidStr, sizeof(guidStr));
|
||||
const char* name = SDL_JoystickNameForIndex(event->which);
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Joystick discovered with no mapping: %s %s",
|
||||
name ? name : "<UNKNOWN>",
|
||||
guidStr);
|
||||
SDL_Joystick* joy = SDL_JoystickOpen(event->which);
|
||||
if (!SDL_IsGamepad(event->which)) {
|
||||
SDL_Joystick* joy = SDL_OpenJoystick(event->which);
|
||||
if (joy != nullptr) {
|
||||
char guidStr[33];
|
||||
SDL_GUIDToString(SDL_JoystickGetGUID(joy), guidStr, sizeof(guidStr));
|
||||
const char* name = SDL_JoystickName(joy);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unmapped joystick: %s %s",
|
||||
name ? name : "<UNKNOWN>",
|
||||
guidStr);
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Number of axes: %d | Number of buttons: %d | Number of hats: %d",
|
||||
SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy),
|
||||
SDL_JoystickNumHats(joy));
|
||||
SDL_JoystickClose(joy);
|
||||
SDL_GetNumJoystickAxes(joy), SDL_GetNumJoystickButtons(joy),
|
||||
SDL_GetNumJoystickHats(joy));
|
||||
SDL_CloseJoystick(joy);
|
||||
}
|
||||
else {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
@@ -797,7 +800,7 @@ void SdlInputHandler::rumble(unsigned short controllerNumber, unsigned short low
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 9)
|
||||
if (m_GamepadState[controllerNumber].controller != nullptr) {
|
||||
SDL_GameControllerRumble(m_GamepadState[controllerNumber].controller, lowFreqMotor, highFreqMotor, 30000);
|
||||
SDL_RumbleGamepad(m_GamepadState[controllerNumber].controller, lowFreqMotor, highFreqMotor, 30000);
|
||||
}
|
||||
#else
|
||||
// Check if the controller supports haptics (and if the controller exists at all)
|
||||
@@ -855,7 +858,7 @@ void SdlInputHandler::rumbleTriggers(uint16_t controllerNumber, uint16_t leftTri
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
if (m_GamepadState[controllerNumber].controller != nullptr) {
|
||||
SDL_GameControllerRumbleTriggers(m_GamepadState[controllerNumber].controller, leftTrigger, rightTrigger, 30000);
|
||||
SDL_RumbleGamepadTriggers(m_GamepadState[controllerNumber].controller, leftTrigger, rightTrigger, 30000);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -874,12 +877,12 @@ void SdlInputHandler::setMotionEventState(uint16_t controllerNumber, uint8_t mot
|
||||
switch (motionType) {
|
||||
case LI_MOTION_TYPE_ACCEL:
|
||||
m_GamepadState[controllerNumber].accelReportPeriodMs = reportPeriodMs;
|
||||
SDL_GameControllerSetSensorEnabled(m_GamepadState[controllerNumber].controller, SDL_SENSOR_ACCEL, reportRateHz ? SDL_TRUE : SDL_FALSE);
|
||||
SDL_SetGamepadSensorEnabled(m_GamepadState[controllerNumber].controller, SDL_SENSOR_ACCEL, reportRateHz ? SDL_TRUE : SDL_FALSE);
|
||||
break;
|
||||
|
||||
case LI_MOTION_TYPE_GYRO:
|
||||
m_GamepadState[controllerNumber].gyroReportPeriodMs = reportPeriodMs;
|
||||
SDL_GameControllerSetSensorEnabled(m_GamepadState[controllerNumber].controller, SDL_SENSOR_GYRO, reportRateHz ? SDL_TRUE : SDL_FALSE);
|
||||
SDL_SetGamepadSensorEnabled(m_GamepadState[controllerNumber].controller, SDL_SENSOR_GYRO, reportRateHz ? SDL_TRUE : SDL_FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -895,7 +898,7 @@ void SdlInputHandler::setControllerLED(uint16_t controllerNumber, uint8_t r, uin
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
if (m_GamepadState[controllerNumber].controller != nullptr) {
|
||||
SDL_GameControllerSetLED(m_GamepadState[controllerNumber].controller, r, g, b);
|
||||
SDL_SetGamepadLED(m_GamepadState[controllerNumber].controller, r, g, b);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -904,31 +907,32 @@ QString SdlInputHandler::getUnmappedGamepads()
|
||||
{
|
||||
QString ret;
|
||||
|
||||
if (SDLC_FAILURE(SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER))) {
|
||||
if (SDLC_FAILURE(SDL_InitSubSystem(SDL_INIT_GAMEPAD))) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) failed: %s",
|
||||
"SDL_InitSubSystem(SDL_INIT_GAMEPAD) failed: %s",
|
||||
SDL_GetError());
|
||||
}
|
||||
|
||||
MappingManager mappingManager;
|
||||
mappingManager.applyMappings();
|
||||
|
||||
int numJoysticks = SDL_NumJoysticks();
|
||||
int numJoysticks = 0;
|
||||
SDL_JoystickID* joysticks = SDL_GetJoysticks(&numJoysticks);
|
||||
for (int i = 0; i < numJoysticks; i++) {
|
||||
if (!SDL_IsGameController(i)) {
|
||||
char guidStr[33];
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i),
|
||||
guidStr, sizeof(guidStr));
|
||||
const char* name = SDL_JoystickNameForIndex(i);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unmapped joystick: %s %s",
|
||||
name ? name : "<UNKNOWN>",
|
||||
guidStr);
|
||||
SDL_Joystick* joy = SDL_JoystickOpen(i);
|
||||
if (!SDL_IsGamepad(joysticks[i])) {
|
||||
SDL_Joystick* joy = SDL_OpenJoystick(joysticks[i]);
|
||||
if (joy != nullptr) {
|
||||
int numButtons = SDL_JoystickNumButtons(joy);
|
||||
int numHats = SDL_JoystickNumHats(joy);
|
||||
int numAxes = SDL_JoystickNumAxes(joy);
|
||||
char guidStr[33];
|
||||
SDL_GUIDToString(SDL_JoystickGetGUID(joy), guidStr, sizeof(guidStr));
|
||||
const char* name = SDL_JoystickName(joy);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unmapped joystick: %s %s",
|
||||
name ? name : "<UNKNOWN>",
|
||||
guidStr);
|
||||
|
||||
int numButtons = SDL_GetNumJoystickButtons(joy);
|
||||
int numHats = SDL_GetNumJoystickHats(joy);
|
||||
int numAxes = SDL_GetNumJoystickAxes(joy);
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Number of axes: %d | Number of buttons: %d | Number of hats: %d",
|
||||
@@ -944,7 +948,7 @@ QString SdlInputHandler::getUnmappedGamepads()
|
||||
ret += name;
|
||||
}
|
||||
|
||||
SDL_JoystickClose(joy);
|
||||
SDL_CloseJoystick(joy);
|
||||
}
|
||||
else {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
@@ -953,12 +957,13 @@ QString SdlInputHandler::getUnmappedGamepads()
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_free(joysticks);
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMEPAD);
|
||||
|
||||
// Flush stale events so they aren't processed by the main session event loop
|
||||
SDL_FlushEvents(SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED);
|
||||
SDL_FlushEvents(SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEREMAPPED);
|
||||
SDL_FlushEvents(SDL_EVENT_JOYSTICK_ADDED, SDL_EVENT_JOYSTICK_REMOVED);
|
||||
SDL_FlushEvents(SDL_EVENT_GAMEPAD_ADDED, SDL_EVENT_GAMEPAD_REMAPPED);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -974,19 +979,17 @@ int SdlInputHandler::getAttachedGamepadMask()
|
||||
}
|
||||
|
||||
count = mask = 0;
|
||||
int numJoysticks = SDL_NumJoysticks();
|
||||
for (int i = 0; i < numJoysticks; i++) {
|
||||
if (SDL_IsGameController(i)) {
|
||||
char guidStr[33];
|
||||
SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(i),
|
||||
guidStr, sizeof(guidStr));
|
||||
int numGamepads = 0;
|
||||
SDL_JoystickID *gamepads = SDL_GetGamepads(&numGamepads);
|
||||
for (int i = 0; i < numGamepads; i++) {
|
||||
char guidStr[33];
|
||||
SDL_GUIDToString(SDL_GetJoystickGUIDForID(i), guidStr, sizeof(guidStr));
|
||||
|
||||
if (!m_IgnoreDeviceGuids.contains(guidStr, Qt::CaseInsensitive))
|
||||
{
|
||||
mask |= (1 << count++);
|
||||
}
|
||||
if (!m_IgnoreDeviceGuids.contains(guidStr, Qt::CaseInsensitive)) {
|
||||
mask |= (1 << count++);
|
||||
}
|
||||
}
|
||||
SDL_free(gamepads);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
@@ -165,10 +165,10 @@ SdlInputHandler::SdlInputHandler(StreamingPreferences& prefs, int streamWidth, i
|
||||
|
||||
// We need to reinit this each time, since you only get
|
||||
// an initial set of gamepad arrival events once per init.
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_GAMECONTROLLER));
|
||||
if (SDLC_FAILURE(SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER))) {
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_GAMEPAD));
|
||||
if (SDLC_FAILURE(SDL_InitSubSystem(SDL_INIT_GAMEPAD))) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) failed: %s",
|
||||
"SDL_InitSubSystem(SDL_INIT_GAMEPAD) failed: %s",
|
||||
SDL_GetError());
|
||||
}
|
||||
|
||||
@@ -219,8 +219,8 @@ SdlInputHandler::~SdlInputHandler()
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_HAPTIC));
|
||||
#endif
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_GAMECONTROLLER));
|
||||
SDL_QuitSubSystem(SDL_INIT_GAMEPAD);
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_GAMEPAD));
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
SDL_assert(!SDL_WasInit(SDL_INIT_JOYSTICK));
|
||||
@@ -275,7 +275,7 @@ void SdlInputHandler::notifyMouseLeave()
|
||||
// NB: Not using SDL_GetGlobalMouseState() because we want our state not the system's
|
||||
Uint32 mouseState = SDL_GetMouseState(nullptr, nullptr);
|
||||
for (Uint32 button = SDL_BUTTON_LEFT; button <= SDL_BUTTON_X2; button++) {
|
||||
if (mouseState & SDL_BUTTON(button)) {
|
||||
if (mouseState & SDL_BUTTON_MASK(button)) {
|
||||
SDL_CaptureMouse(SDL_TRUE);
|
||||
break;
|
||||
}
|
||||
@@ -388,7 +388,7 @@ void SdlInputHandler::setCaptureActive(bool active)
|
||||
if (isMouseInVideoRegion(mouseX, mouseY)) {
|
||||
// Synthesize a mouse event to synchronize the cursor
|
||||
SDL_MouseMotionEvent motionEvent = {};
|
||||
motionEvent.type = SDL_MOUSEMOTION;
|
||||
motionEvent.type = SDL_EVENT_MOUSE_MOTION;
|
||||
motionEvent.timestamp = SDL_GetTicks();
|
||||
motionEvent.windowID = SDL_GetWindowID(m_Window);
|
||||
motionEvent.x = mouseX;
|
||||
@@ -418,7 +418,7 @@ void SdlInputHandler::setCaptureActive(bool active)
|
||||
void SdlInputHandler::handleTouchFingerEvent(SDL_TouchFingerEvent* event)
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 10)
|
||||
if (SDL_GetTouchDeviceType(event->touchId) != SDL_TOUCH_DEVICE_DIRECT) {
|
||||
if (SDL_GetTouchDeviceType(event->touchID) != SDL_TOUCH_DEVICE_DIRECT) {
|
||||
// Ignore anything that isn't a touchscreen. We may get callbacks
|
||||
// for trackpads, but we want to handle those in the mouse path.
|
||||
return;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "SDL_compat.h"
|
||||
|
||||
struct GamepadState {
|
||||
SDL_GameController* controller;
|
||||
SDL_Gamepad * controller;
|
||||
SDL_JoystickID jsId;
|
||||
short index;
|
||||
|
||||
@@ -24,11 +24,11 @@ struct GamepadState {
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
uint8_t gyroReportPeriodMs;
|
||||
float lastGyroEventData[SDL_arraysize(SDL_ControllerSensorEvent::data)];
|
||||
float lastGyroEventData[SDL_arraysize(SDL_GamepadSensorEvent::data)];
|
||||
uint32_t lastGyroEventTime;
|
||||
|
||||
uint8_t accelReportPeriodMs;
|
||||
float lastAccelEventData[SDL_arraysize(SDL_ControllerSensorEvent::data)];
|
||||
float lastAccelEventData[SDL_arraysize(SDL_GamepadSensorEvent::data)];
|
||||
uint32_t lastAccelEventTime;
|
||||
#endif
|
||||
|
||||
@@ -67,16 +67,16 @@ public:
|
||||
|
||||
void handleMouseWheelEvent(SDL_MouseWheelEvent* event);
|
||||
|
||||
void handleControllerAxisEvent(SDL_ControllerAxisEvent* event);
|
||||
void handleControllerAxisEvent(SDL_GamepadAxisEvent* event);
|
||||
|
||||
void handleControllerButtonEvent(SDL_ControllerButtonEvent* event);
|
||||
void handleControllerButtonEvent(SDL_GamepadButtonEvent* event);
|
||||
|
||||
void handleControllerDeviceEvent(SDL_ControllerDeviceEvent* event);
|
||||
void handleControllerDeviceEvent(SDL_GamepadDeviceEvent* event);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
void handleControllerSensorEvent(SDL_ControllerSensorEvent* event);
|
||||
void handleControllerSensorEvent(SDL_GamepadSensorEvent* event);
|
||||
|
||||
void handleControllerTouchpadEvent(SDL_ControllerTouchpadEvent* event);
|
||||
void handleControllerTouchpadEvent(SDL_GamepadTouchpadEvent* event);
|
||||
#endif
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 24, 0)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "streaming/session.h"
|
||||
|
||||
#include <Limelight.h>
|
||||
|
||||
#include "SDL_compat.h"
|
||||
|
||||
#define VK_0 0x30
|
||||
@@ -22,7 +23,7 @@ void SdlInputHandler::performSpecialKeyCombo(KeyCombo combo)
|
||||
|
||||
// Push a quit event to the main loop
|
||||
SDL_Event event;
|
||||
event.type = SDL_QUIT;
|
||||
event.type = SDL_EVENT_QUIT;
|
||||
event.quit.timestamp = SDL_GetTicks();
|
||||
SDL_PushEvent(&event);
|
||||
break;
|
||||
@@ -151,15 +152,15 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
|
||||
|
||||
if (event->repeat) {
|
||||
// Ignore repeat key down events
|
||||
SDL_assert(event->state == SDL_PRESSED);
|
||||
SDL_assert(event->state == true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for our special key combos
|
||||
if ((event->state == SDL_PRESSED) &&
|
||||
(event->keysym.mod & KMOD_CTRL) &&
|
||||
(event->keysym.mod & KMOD_ALT) &&
|
||||
(event->keysym.mod & KMOD_SHIFT)) {
|
||||
if ((event->state == true) &&
|
||||
(KEY_MOD(event) & SDL_KMOD_CTRL) &&
|
||||
(KEY_MOD(event) & SDL_KMOD_ALT) &&
|
||||
(KEY_MOD(event) & SDL_KMOD_SHIFT)) {
|
||||
// First we test the SDLK combos for matches,
|
||||
// that way we ensure that latin keyboard users
|
||||
// can match to the key they see on their keyboards.
|
||||
@@ -172,14 +173,14 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
|
||||
// the scancode of another.
|
||||
|
||||
for (int i = 0; i < KeyComboMax; i++) {
|
||||
if (m_SpecialKeyCombos[i].enabled && event->keysym.sym == m_SpecialKeyCombos[i].keyCode) {
|
||||
if (m_SpecialKeyCombos[i].enabled && KEY_KEY(event) == m_SpecialKeyCombos[i].keyCode) {
|
||||
performSpecialKeyCombo(m_SpecialKeyCombos[i].keyCombo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < KeyComboMax; i++) {
|
||||
if (m_SpecialKeyCombos[i].enabled && event->keysym.scancode == m_SpecialKeyCombos[i].scanCode) {
|
||||
if (m_SpecialKeyCombos[i].enabled && KEY_SCANCODE(event) == m_SpecialKeyCombos[i].scanCode) {
|
||||
performSpecialKeyCombo(m_SpecialKeyCombos[i].keyCombo);
|
||||
return;
|
||||
}
|
||||
@@ -188,16 +189,16 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
|
||||
|
||||
// Set modifier flags
|
||||
modifiers = 0;
|
||||
if (event->keysym.mod & KMOD_CTRL) {
|
||||
if (KEY_MOD(event) & SDL_KMOD_CTRL) {
|
||||
modifiers |= MODIFIER_CTRL;
|
||||
}
|
||||
if (event->keysym.mod & KMOD_ALT) {
|
||||
if (KEY_MOD(event) & SDL_KMOD_ALT) {
|
||||
modifiers |= MODIFIER_ALT;
|
||||
}
|
||||
if (event->keysym.mod & KMOD_SHIFT) {
|
||||
if (KEY_MOD(event) & SDL_KMOD_SHIFT) {
|
||||
modifiers |= MODIFIER_SHIFT;
|
||||
}
|
||||
if (event->keysym.mod & KMOD_GUI) {
|
||||
if (KEY_MOD(event) & SDL_KMOD_GUI) {
|
||||
if (isSystemKeyCaptureActive()) {
|
||||
modifiers |= MODIFIER_META;
|
||||
}
|
||||
@@ -206,25 +207,25 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
|
||||
// Set keycode. We explicitly use scancode here because GFE will try to correct
|
||||
// for AZERTY layouts on the host but it depends on receiving VK_ values matching
|
||||
// a QWERTY layout to work.
|
||||
if (event->keysym.scancode >= SDL_SCANCODE_1 && event->keysym.scancode <= SDL_SCANCODE_9) {
|
||||
if (KEY_SCANCODE(event) >= SDL_SCANCODE_1 && KEY_SCANCODE(event) <= SDL_SCANCODE_9) {
|
||||
// SDL defines SDL_SCANCODE_0 > SDL_SCANCODE_9, so we need to handle that manually
|
||||
keyCode = (event->keysym.scancode - SDL_SCANCODE_1) + VK_0 + 1;
|
||||
keyCode = (KEY_SCANCODE(event) - SDL_SCANCODE_1) + VK_0 + 1;
|
||||
}
|
||||
else if (event->keysym.scancode >= SDL_SCANCODE_A && event->keysym.scancode <= SDL_SCANCODE_Z) {
|
||||
keyCode = (event->keysym.scancode - SDL_SCANCODE_A) + VK_A;
|
||||
else if (KEY_SCANCODE(event) >= SDL_SCANCODE_A && KEY_SCANCODE(event) <= SDL_SCANCODE_Z) {
|
||||
keyCode = (KEY_SCANCODE(event) - SDL_SCANCODE_A) + VK_A;
|
||||
}
|
||||
else if (event->keysym.scancode >= SDL_SCANCODE_F1 && event->keysym.scancode <= SDL_SCANCODE_F12) {
|
||||
keyCode = (event->keysym.scancode - SDL_SCANCODE_F1) + VK_F1;
|
||||
else if (KEY_SCANCODE(event) >= SDL_SCANCODE_F1 && KEY_SCANCODE(event) <= SDL_SCANCODE_F12) {
|
||||
keyCode = (KEY_SCANCODE(event) - SDL_SCANCODE_F1) + VK_F1;
|
||||
}
|
||||
else if (event->keysym.scancode >= SDL_SCANCODE_F13 && event->keysym.scancode <= SDL_SCANCODE_F24) {
|
||||
keyCode = (event->keysym.scancode - SDL_SCANCODE_F13) + VK_F13;
|
||||
else if (KEY_SCANCODE(event) >= SDL_SCANCODE_F13 && KEY_SCANCODE(event) <= SDL_SCANCODE_F24) {
|
||||
keyCode = (KEY_SCANCODE(event) - SDL_SCANCODE_F13) + VK_F13;
|
||||
}
|
||||
else if (event->keysym.scancode >= SDL_SCANCODE_KP_1 && event->keysym.scancode <= SDL_SCANCODE_KP_9) {
|
||||
else if (KEY_SCANCODE(event) >= SDL_SCANCODE_KP_1 && KEY_SCANCODE(event) <= SDL_SCANCODE_KP_9) {
|
||||
// SDL defines SDL_SCANCODE_KP_0 > SDL_SCANCODE_KP_9, so we need to handle that manually
|
||||
keyCode = (event->keysym.scancode - SDL_SCANCODE_KP_1) + VK_NUMPAD0 + 1;
|
||||
keyCode = (KEY_SCANCODE(event) - SDL_SCANCODE_KP_1) + VK_NUMPAD0 + 1;
|
||||
}
|
||||
else {
|
||||
switch (event->keysym.scancode) {
|
||||
switch (KEY_SCANCODE(event)) {
|
||||
case SDL_SCANCODE_BACKSPACE:
|
||||
keyCode = 0x08;
|
||||
break;
|
||||
@@ -417,13 +418,13 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
|
||||
default:
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unhandled button event: %d",
|
||||
event->keysym.scancode);
|
||||
KEY_SCANCODE(event));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Track the key state so we always know which keys are down
|
||||
if (event->state == SDL_PRESSED) {
|
||||
if (event->state == true) {
|
||||
m_KeysDown.insert(keyCode);
|
||||
}
|
||||
else {
|
||||
@@ -431,7 +432,7 @@ void SdlInputHandler::handleKeyEvent(SDL_KeyboardEvent* event)
|
||||
}
|
||||
|
||||
LiSendKeyboardEvent(0x8000 | keyCode,
|
||||
event->state == SDL_PRESSED ?
|
||||
KEY_ACTION_DOWN : KEY_ACTION_UP,
|
||||
event->state == true ?
|
||||
KEY_ACTION_DOWN : KEY_ACTION_UP,
|
||||
modifiers);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ void SdlInputHandler::handleMouseButtonEvent(SDL_MouseButtonEvent* event)
|
||||
return;
|
||||
}
|
||||
else if (!isCaptureActive()) {
|
||||
if (event->button == SDL_BUTTON_LEFT && event->state == SDL_RELEASED &&
|
||||
if (event->button == SDL_BUTTON_LEFT && event->state == false &&
|
||||
isMouseInVideoRegion(event->x, event->y)) {
|
||||
// Capture the mouse again if clicked when unbound.
|
||||
// We start capture on left button released instead of
|
||||
@@ -26,7 +26,7 @@ void SdlInputHandler::handleMouseButtonEvent(SDL_MouseButtonEvent* event)
|
||||
// Not capturing
|
||||
return;
|
||||
}
|
||||
else if (m_AbsoluteMouseMode && !isMouseInVideoRegion(event->x, event->y) && event->state == SDL_PRESSED) {
|
||||
else if (m_AbsoluteMouseMode && !isMouseInVideoRegion(event->x, event->y) && event->state == true) {
|
||||
// Ignore button presses outside the video region, but allow button releases
|
||||
return;
|
||||
}
|
||||
@@ -62,7 +62,7 @@ void SdlInputHandler::handleMouseButtonEvent(SDL_MouseButtonEvent* event)
|
||||
button = BUTTON_RIGHT;
|
||||
}
|
||||
|
||||
LiSendMouseButtonEvent(event->state == SDL_PRESSED ?
|
||||
LiSendMouseButtonEvent(event->state == true ?
|
||||
BUTTON_ACTION_PRESS :
|
||||
BUTTON_ACTION_RELEASE,
|
||||
button);
|
||||
@@ -82,7 +82,7 @@ void SdlInputHandler::handleMouseMotionEvent(SDL_MouseMotionEvent* event)
|
||||
// Batch all pending mouse motion events to save CPU time
|
||||
Sint32 x = event->x, y = event->y, xrel = event->xrel, yrel = event->yrel;
|
||||
SDL_Event nextEvent;
|
||||
while (SDL_PeepEvents(&nextEvent, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION) > 0) {
|
||||
while (SDL_PeepEvents(&nextEvent, 1, SDL_GETEVENT, SDL_EVENT_MOUSE_MOTION, SDL_EVENT_MOUSE_MOTION) > 0) {
|
||||
event = &nextEvent.motion;
|
||||
|
||||
// Ignore synthetic mouse events
|
||||
@@ -175,34 +175,34 @@ void SdlInputHandler::handleMouseWheelEvent(SDL_MouseWheelEvent* event)
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
if (event->preciseY != 0.0f) {
|
||||
if (event->y != 0.0f) {
|
||||
// Invert the scroll direction if needed
|
||||
if (m_ReverseScrollDirection) {
|
||||
event->preciseY = -event->preciseY;
|
||||
event->y = -event->y;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
// HACK: Clamp the scroll values on macOS to prevent OS scroll acceleration
|
||||
// from generating wild scroll deltas when scrolling quickly.
|
||||
event->preciseY = SDL_clamp(event->preciseY, -1.0f, 1.0f);
|
||||
event->y = SDL_clamp(event->y, -1.0f, 1.0f);
|
||||
#endif
|
||||
|
||||
LiSendHighResScrollEvent((short)(event->preciseY * 120)); // WHEEL_DELTA
|
||||
LiSendHighResScrollEvent((short)(event->y * 120)); // WHEEL_DELTA
|
||||
}
|
||||
|
||||
if (event->preciseX != 0.0f) {
|
||||
if (event->x != 0.0f) {
|
||||
// Invert the scroll direction if needed
|
||||
if (m_ReverseScrollDirection) {
|
||||
event->preciseX = -event->preciseY;
|
||||
event->x = -event->y;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
// HACK: Clamp the scroll values on macOS to prevent OS scroll acceleration
|
||||
// from generating wild scroll deltas when scrolling quickly.
|
||||
event->preciseX = SDL_clamp(event->preciseX, -1.0f, 1.0f);
|
||||
event->x = SDL_clamp(event->x, -1.0f, 1.0f);
|
||||
#endif
|
||||
|
||||
LiSendHighResHScrollEvent((short)(event->preciseX * 120)); // WHEEL_DELTA
|
||||
LiSendHighResHScrollEvent((short)(event->x * 120)); // WHEEL_DELTA
|
||||
}
|
||||
#else
|
||||
if (event->y != 0) {
|
||||
|
||||
@@ -59,9 +59,9 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event)
|
||||
// This is also required to handle finger up which
|
||||
// where the finger will not be in SDL_GetTouchFinger()
|
||||
// anymore.
|
||||
if (event->type != SDL_FINGERDOWN) {
|
||||
if (event->type != SDL_EVENT_FINGER_DOWN) {
|
||||
for (int i = 0; i < MAX_FINGERS; i++) {
|
||||
if (event->fingerId == m_TouchDownEvent[i].fingerId) {
|
||||
if (event->fingerID == m_TouchDownEvent[i].fingerID) {
|
||||
fingerIndex = i;
|
||||
break;
|
||||
}
|
||||
@@ -70,12 +70,12 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event)
|
||||
else {
|
||||
// Resolve the new finger by determining the ID of each
|
||||
// finger on the display.
|
||||
int numTouchFingers = SDL_GetNumTouchFingers(event->touchId);
|
||||
int numTouchFingers = SDL_GetNumTouchFingers(event->touchID);
|
||||
for (int i = 0; i < numTouchFingers; i++) {
|
||||
SDL_Finger* finger = SDL_GetTouchFinger(event->touchId, i);
|
||||
SDL_Finger* finger = SDL_GetTouchFinger(event->touchID, i);
|
||||
SDL_assert(finger != nullptr);
|
||||
if (finger != nullptr) {
|
||||
if (finger->id == event->fingerId) {
|
||||
if (finger->id == event->fingerID) {
|
||||
fingerIndex = i;
|
||||
break;
|
||||
}
|
||||
@@ -106,7 +106,7 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event)
|
||||
|
||||
// Start a drag timer when primary or secondary
|
||||
// fingers go down
|
||||
if (event->type == SDL_FINGERDOWN &&
|
||||
if (event->type == SDL_EVENT_FINGER_DOWN &&
|
||||
(fingerIndex == 0 || fingerIndex == 1)) {
|
||||
SDL_RemoveTimer(m_DragTimer);
|
||||
m_DragTimer = SDL_AddTimer(DRAG_ACTIVATION_DELAY,
|
||||
@@ -114,7 +114,7 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event)
|
||||
this);
|
||||
}
|
||||
|
||||
if (event->type == SDL_FINGERMOTION) {
|
||||
if (event->type == SDL_EVENT_FINGER_MOTION) {
|
||||
// If it's outside the deadzone delta, cancel drags and taps
|
||||
if (qSqrt(qPow(event->x - m_TouchDownEvent[fingerIndex].x, 2) +
|
||||
qPow(event->y - m_TouchDownEvent[fingerIndex].y, 2)) > DEAD_ZONE_DELTA) {
|
||||
@@ -126,7 +126,7 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event)
|
||||
}
|
||||
}
|
||||
|
||||
if (event->type == SDL_FINGERUP) {
|
||||
if (event->type == SDL_EVENT_FINGER_UP) {
|
||||
// Cancel the drag timer on finger up
|
||||
SDL_RemoveTimer(m_DragTimer);
|
||||
m_DragTimer = 0;
|
||||
@@ -164,12 +164,12 @@ void SdlInputHandler::handleRelativeFingerEvent(SDL_TouchFingerEvent* event)
|
||||
}
|
||||
}
|
||||
|
||||
m_NumFingersDown = SDL_GetNumTouchFingers(event->touchId);
|
||||
m_NumFingersDown = SDL_GetNumTouchFingers(event->touchID);
|
||||
|
||||
if (event->type == SDL_FINGERDOWN) {
|
||||
if (event->type == SDL_EVENT_FINGER_DOWN) {
|
||||
m_TouchDownEvent[fingerIndex] = *event;
|
||||
}
|
||||
else if (event->type == SDL_FINGERUP) {
|
||||
else if (event->type == SDL_EVENT_FINGER_UP) {
|
||||
m_TouchDownEvent[fingerIndex] = {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ void Session::clRumble(unsigned short controllerNumber, unsigned short lowFreqMo
|
||||
// with the removal of game controllers that could result in our game controller
|
||||
// going away during this callback.
|
||||
SDL_Event rumbleEvent = {};
|
||||
rumbleEvent.type = SDL_USEREVENT;
|
||||
rumbleEvent.type = SDL_EVENT_USER;
|
||||
rumbleEvent.user.code = SDL_CODE_GAMECONTROLLER_RUMBLE;
|
||||
rumbleEvent.user.data1 = (void*)(uintptr_t)controllerNumber;
|
||||
rumbleEvent.user.data2 = (void*)(uintptr_t)((lowFreqMotor << 16) | highFreqMotor);
|
||||
@@ -210,12 +210,12 @@ void Session::clSetHdrMode(bool enabled)
|
||||
// If we're in the process of recreating our decoder when we get
|
||||
// this callback, we'll drop it. The main thread will make the
|
||||
// callback when it finishes creating the new decoder.
|
||||
if (SDL_AtomicTryLock(&s_ActiveSession->m_DecoderLock)) {
|
||||
if (SDL_TryLockSpinlock(&s_ActiveSession->m_DecoderLock)) {
|
||||
IVideoDecoder* decoder = s_ActiveSession->m_VideoDecoder;
|
||||
if (decoder != nullptr) {
|
||||
decoder->setHdrMode(enabled);
|
||||
}
|
||||
SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock);
|
||||
SDL_UnlockSpinlock(&s_ActiveSession->m_DecoderLock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ void Session::clRumbleTriggers(uint16_t controllerNumber, uint16_t leftTrigger,
|
||||
// with the removal of game controllers that could result in our game controller
|
||||
// going away during this callback.
|
||||
SDL_Event rumbleEvent = {};
|
||||
rumbleEvent.type = SDL_USEREVENT;
|
||||
rumbleEvent.type = SDL_EVENT_USER;
|
||||
rumbleEvent.user.code = SDL_CODE_GAMECONTROLLER_RUMBLE_TRIGGERS;
|
||||
rumbleEvent.user.data1 = (void*)(uintptr_t)controllerNumber;
|
||||
rumbleEvent.user.data2 = (void*)(uintptr_t)((leftTrigger << 16) | rightTrigger);
|
||||
@@ -238,7 +238,7 @@ void Session::clSetMotionEventState(uint16_t controllerNumber, uint8_t motionTyp
|
||||
// with the removal of game controllers that could result in our game controller
|
||||
// going away during this callback.
|
||||
SDL_Event setMotionEventStateEvent = {};
|
||||
setMotionEventStateEvent.type = SDL_USEREVENT;
|
||||
setMotionEventStateEvent.type = SDL_EVENT_USER;
|
||||
setMotionEventStateEvent.user.code = SDL_CODE_GAMECONTROLLER_SET_MOTION_EVENT_STATE;
|
||||
setMotionEventStateEvent.user.data1 = (void*)(uintptr_t)controllerNumber;
|
||||
setMotionEventStateEvent.user.data2 = (void*)(uintptr_t)((motionType << 16) | reportRateHz);
|
||||
@@ -251,7 +251,7 @@ void Session::clSetControllerLED(uint16_t controllerNumber, uint8_t r, uint8_t g
|
||||
// with the removal of game controllers that could result in our game controller
|
||||
// going away during this callback.
|
||||
SDL_Event setControllerLEDEvent = {};
|
||||
setControllerLEDEvent.type = SDL_USEREVENT;
|
||||
setControllerLEDEvent.type = SDL_EVENT_USER;
|
||||
setControllerLEDEvent.user.code = SDL_CODE_GAMECONTROLLER_SET_CONTROLLER_LED;
|
||||
setControllerLEDEvent.user.data1 = (void*)(uintptr_t)controllerNumber;
|
||||
setControllerLEDEvent.user.data2 = (void*)(uintptr_t)(r << 16 | g << 8 | b);
|
||||
@@ -348,15 +348,15 @@ int Session::drSubmitDecodeUnit(PDECODE_UNIT du)
|
||||
// safely return DR_OK and wait for the IDR frame request by
|
||||
// the decoder reinitialization code.
|
||||
|
||||
if (SDL_AtomicTryLock(&s_ActiveSession->m_DecoderLock)) {
|
||||
if (SDL_TryLockSpinlock(&s_ActiveSession->m_DecoderLock)) {
|
||||
IVideoDecoder* decoder = s_ActiveSession->m_VideoDecoder;
|
||||
if (decoder != nullptr) {
|
||||
int ret = decoder->submitDecodeUnit(du);
|
||||
SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock);
|
||||
SDL_UnlockSpinlock(&s_ActiveSession->m_DecoderLock);
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock);
|
||||
SDL_UnlockSpinlock(&s_ActiveSession->m_DecoderLock);
|
||||
return DR_OK;
|
||||
}
|
||||
}
|
||||
@@ -550,7 +550,7 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere
|
||||
m_InputHandler(nullptr),
|
||||
m_MouseEmulationRefCount(0),
|
||||
m_FlushingWindowEventsRef(0),
|
||||
m_CurrentDisplayIndex(-1),
|
||||
m_CurrentDisplay(-1),
|
||||
m_NeedsFirstEnterCapture(false),
|
||||
m_NeedsPostDecoderCreationCapture(false),
|
||||
m_AsyncConnectionSuccess(false),
|
||||
@@ -1261,11 +1261,10 @@ private:
|
||||
void Session::getWindowDimensions(int& x, int& y,
|
||||
int& width, int& height)
|
||||
{
|
||||
int displayIndex = 0;
|
||||
SDL_DisplayID display = SDL_GetPrimaryDisplay();
|
||||
|
||||
if (m_Window != nullptr) {
|
||||
displayIndex = SDL_GetWindowDisplayIndex(m_Window);
|
||||
SDL_assert(displayIndex >= 0);
|
||||
display = SDL_GetDisplayForWindow(m_Window);
|
||||
}
|
||||
// Create our window on the same display that Qt's UI
|
||||
// was being displayed on.
|
||||
@@ -1279,25 +1278,28 @@ void Session::getWindowDimensions(int& x, int& y,
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Qt UI screen is at (%d,%d)",
|
||||
displayRect.x(), displayRect.y());
|
||||
for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
|
||||
int numDisplays = 0;
|
||||
SDL_DisplayID* displays = SDL_GetDisplays(&numDisplays);
|
||||
for (int i = 0; i < numDisplays; i++) {
|
||||
SDL_Rect displayBounds;
|
||||
|
||||
if (SDLC_SUCCESS(SDL_GetDisplayBounds(i, &displayBounds))) {
|
||||
if (SDLC_SUCCESS(SDL_GetDisplayBounds(displays[i], &displayBounds))) {
|
||||
if (displayBounds.x == displayRect.x() &&
|
||||
displayBounds.y == displayRect.y()) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL found matching display %d",
|
||||
i);
|
||||
displayIndex = i;
|
||||
displays[i]);
|
||||
display = displays[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetDisplayBounds(%d) failed: %s",
|
||||
i, SDL_GetError());
|
||||
displays[i], SDL_GetError());
|
||||
}
|
||||
}
|
||||
SDL_free(displays);
|
||||
}
|
||||
else {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
@@ -1307,7 +1309,7 @@ void Session::getWindowDimensions(int& x, int& y,
|
||||
}
|
||||
|
||||
SDL_Rect usableBounds;
|
||||
if (SDLC_SUCCESS(SDL_GetDisplayUsableBounds(displayIndex, &usableBounds))) {
|
||||
if (SDLC_SUCCESS(SDL_GetDisplayUsableBounds(display, &usableBounds))) {
|
||||
// Don't use more than 80% of the display to leave room for system UI
|
||||
// and ensure the target size is not odd (otherwise one of the sides
|
||||
// of the image will have a one-pixel black bar next to it).
|
||||
@@ -1341,7 +1343,7 @@ void Session::getWindowDimensions(int& x, int& y,
|
||||
height = m_StreamConfig.height;
|
||||
}
|
||||
|
||||
x = y = SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex);
|
||||
x = y = SDL_WINDOWPOS_CENTERED_DISPLAY(display);
|
||||
}
|
||||
|
||||
void Session::updateOptimalWindowDisplayMode()
|
||||
@@ -1355,13 +1357,13 @@ void Session::updateOptimalWindowDisplayMode()
|
||||
|
||||
// Try the current display mode first. On macOS, this will be the normal
|
||||
// scaled desktop resolution setting.
|
||||
int displayIndex = SDL_GetWindowDisplayIndex(m_Window);
|
||||
if (SDL_GetDesktopDisplayMode(displayIndex, &desktopMode) == 0) {
|
||||
SDL_DisplayID display = SDL_GetDisplayForWindow(m_Window);
|
||||
if (SDL_GetDesktopDisplayMode(display, &desktopMode) == 0) {
|
||||
// If this doesn't fit the selected resolution, use the native
|
||||
// resolution of the panel (unscaled).
|
||||
if (desktopMode.w < m_ActiveVideoWidth || desktopMode.h < m_ActiveVideoHeight) {
|
||||
SDL_Rect safeArea;
|
||||
if (!StreamUtils::getNativeDesktopMode(displayIndex, &desktopMode, &safeArea)) {
|
||||
if (!StreamUtils::getNativeDesktopMode(display, &desktopMode, &safeArea)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1377,15 +1379,18 @@ void Session::updateOptimalWindowDisplayMode()
|
||||
// the highest refresh rate that our stream FPS evenly divides.
|
||||
bestMode = desktopMode;
|
||||
bestMode.refresh_rate = 0;
|
||||
for (int i = 0; i < SDL_GetNumDisplayModes(displayIndex); i++) {
|
||||
if (SDL_GetDisplayMode(displayIndex, i, &mode) == 0) {
|
||||
if (mode.w == desktopMode.w && mode.h == desktopMode.h &&
|
||||
{
|
||||
int numDisplayModes = SDL_GetNumDisplayModes(display);
|
||||
for (int i = 0; i < numDisplayModes; i++) {
|
||||
if (SDL_GetDisplayMode(display, i, &mode) == 0) {
|
||||
if (mode.w == desktopMode.w && mode.h == desktopMode.h &&
|
||||
mode.refresh_rate % m_StreamConfig.fps == 0) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Found display mode with desktop resolution: %dx%dx%d",
|
||||
mode.w, mode.h, mode.refresh_rate);
|
||||
if (mode.refresh_rate > bestMode.refresh_rate) {
|
||||
bestMode = mode;
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Found display mode with desktop resolution: %dx%dx%d",
|
||||
mode.w, mode.h, mode.refresh_rate);
|
||||
if (mode.refresh_rate > bestMode.refresh_rate) {
|
||||
bestMode = mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1399,8 +1404,9 @@ void Session::updateOptimalWindowDisplayMode()
|
||||
if (bestMode.refresh_rate == 0) {
|
||||
float bestModeAspectRatio = 0;
|
||||
float videoAspectRatio = (float)m_ActiveVideoWidth / (float)m_ActiveVideoHeight;
|
||||
for (int i = 0; i < SDL_GetNumDisplayModes(displayIndex); i++) {
|
||||
if (SDL_GetDisplayMode(displayIndex, i, &mode) == 0) {
|
||||
int numDisplayModes = SDL_GetNumDisplayModes(display);
|
||||
for (int i = 0; i < numDisplayModes; i++) {
|
||||
if (SDL_GetDisplayMode(display, i, &mode) == 0) {
|
||||
float modeAspectRatio = (float)mode.w / (float)mode.h;
|
||||
if (mode.w >= m_ActiveVideoWidth && mode.h >= m_ActiveVideoHeight &&
|
||||
mode.refresh_rate % m_StreamConfig.fps == 0) {
|
||||
@@ -1435,7 +1441,7 @@ void Session::updateOptimalWindowDisplayMode()
|
||||
bestMode.w, bestMode.h, bestMode.refresh_rate);
|
||||
}
|
||||
|
||||
SDL_SetWindowDisplayMode(m_Window, &bestMode);
|
||||
SDL_SetWindowFullscreenMode(m_Window, &bestMode);
|
||||
}
|
||||
|
||||
void Session::toggleFullscreen()
|
||||
@@ -1451,10 +1457,10 @@ void Session::toggleFullscreen()
|
||||
// On Apple Silicon Macs, the AVSampleBufferDisplayLayer may cause WindowServer
|
||||
// to deadlock when transitioning out of fullscreen. Destroy the decoder before
|
||||
// exiting fullscreen as a workaround. See issue #973.
|
||||
SDL_AtomicLock(&m_DecoderLock);
|
||||
SDL_LockSpinlock(&m_DecoderLock);
|
||||
delete m_VideoDecoder;
|
||||
m_VideoDecoder = nullptr;
|
||||
SDL_AtomicUnlock(&m_DecoderLock);
|
||||
SDL_UnlockSpinlock(&m_DecoderLock);
|
||||
#endif
|
||||
|
||||
// Actually enter/leave fullscreen
|
||||
@@ -1673,7 +1679,7 @@ void Session::flushWindowEvents()
|
||||
|
||||
// This event will cause us to set m_FlushingWindowEvents back to false.
|
||||
SDL_Event flushEvent = {};
|
||||
flushEvent.type = SDL_USEREVENT;
|
||||
flushEvent.type = SDL_EVENT_USER;
|
||||
flushEvent.user.code = SDL_CODE_FLUSH_WINDOW_EVENT_BARRIER;
|
||||
SDL_PushEvent(&flushEvent);
|
||||
}
|
||||
@@ -1682,24 +1688,24 @@ bool Session::handleWindowEvent(SDL_WindowEvent* event)
|
||||
{
|
||||
// Early handling of some events
|
||||
switch (event->event) {
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST :
|
||||
if (m_Preferences->muteOnFocusLoss) {
|
||||
m_AudioMuted = true;
|
||||
}
|
||||
m_InputHandler->notifyFocusLost();
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED :
|
||||
if (m_Preferences->muteOnFocusLoss) {
|
||||
m_AudioMuted = false;
|
||||
}
|
||||
break;
|
||||
case SDL_WINDOWEVENT_LEAVE:
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE :
|
||||
m_InputHandler->notifyMouseLeave();
|
||||
break;
|
||||
}
|
||||
|
||||
// Capture the mouse on SDL_WINDOWEVENT_ENTER if needed
|
||||
if (m_NeedsFirstEnterCapture && event->event == SDL_WINDOWEVENT_ENTER) {
|
||||
if (m_NeedsFirstEnterCapture && event->event == SDL_EVENT_WINDOW_MOUSE_ENTER) {
|
||||
m_InputHandler->setCaptureActive(true);
|
||||
m_NeedsFirstEnterCapture = false;
|
||||
}
|
||||
@@ -1707,19 +1713,19 @@ bool Session::handleWindowEvent(SDL_WindowEvent* event)
|
||||
// We want to recreate the decoder for resizes (full-screen toggles) and the initial shown event.
|
||||
// We use SDL_WINDOWEVENT_SIZE_CHANGED rather than SDL_WINDOWEVENT_RESIZED because the latter doesn't
|
||||
// seem to fire when switching from windowed to full-screen on X11.
|
||||
if (event->event != SDL_WINDOWEVENT_SIZE_CHANGED &&
|
||||
(event->event != SDL_WINDOWEVENT_SHOWN || m_VideoDecoder != nullptr)) {
|
||||
if (event->event != SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED &&
|
||||
(event->event != SDL_EVENT_WINDOW_SHOWN || m_VideoDecoder != nullptr)) {
|
||||
// Check that the window display hasn't changed. If it has, we want
|
||||
// to recreate the decoder to allow it to adapt to the new display.
|
||||
// This will allow Pacer to pull the new display refresh rate.
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
// On SDL 2.0.18+, there's an event for this specific situation
|
||||
if (event->event != SDL_WINDOWEVENT_DISPLAY_CHANGED) {
|
||||
if (event->event != SDL_EVENT_WINDOW_DISPLAY_CHANGED) {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
// Prior to SDL 2.0.18, we must check the display index for each window event
|
||||
if (SDL_GetWindowDisplayIndex(m_Window) == currentDisplayIndex) {
|
||||
if (SDL_GetDisplayForWindow(m_Window) == m_CurrentDisplay) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -1751,26 +1757,26 @@ bool Session::handleWindowEvent(SDL_WindowEvent* event)
|
||||
WINDOW_STATE_CHANGE_INFO windowChangeInfo = {};
|
||||
windowChangeInfo.window = m_Window;
|
||||
|
||||
if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
if (event->event == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) {
|
||||
windowChangeInfo.stateChangeFlags |= WINDOW_STATE_CHANGE_SIZE;
|
||||
|
||||
windowChangeInfo.width = event->data1;
|
||||
windowChangeInfo.height = event->data2;
|
||||
}
|
||||
|
||||
int newDisplayIndex = SDL_GetWindowDisplayIndex(m_Window);
|
||||
if (newDisplayIndex != m_CurrentDisplayIndex) {
|
||||
SDL_DisplayID newDisplay = SDL_GetDisplayForWindow(m_Window);
|
||||
if (newDisplay != m_CurrentDisplay) {
|
||||
windowChangeInfo.stateChangeFlags |= WINDOW_STATE_CHANGE_DISPLAY;
|
||||
|
||||
windowChangeInfo.displayIndex = newDisplayIndex;
|
||||
windowChangeInfo.displayIndex = newDisplay;
|
||||
|
||||
// If the refresh rates have changed, we will need to go through the full
|
||||
// decoder recreation path to ensure Pacer is switched to the new display
|
||||
// and that we apply any V-Sync disablement rules that may be needed for
|
||||
// this display.
|
||||
SDL_DisplayMode oldMode, newMode;
|
||||
if (SDL_GetCurrentDisplayMode(m_CurrentDisplayIndex, &oldMode) < 0 ||
|
||||
SDL_GetCurrentDisplayMode(newDisplayIndex, &newMode) < 0 ||
|
||||
if (SDL_GetCurrentDisplayMode(m_CurrentDisplay, &oldMode) < 0 ||
|
||||
SDL_GetCurrentDisplayMode(newDisplay, &newMode) < 0 ||
|
||||
oldMode.refresh_rate != newMode.refresh_rate) {
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Forcing renderer recreation due to refresh rate change between displays");
|
||||
@@ -1781,8 +1787,8 @@ bool Session::handleWindowEvent(SDL_WindowEvent* event)
|
||||
if (!forceRecreation && m_VideoDecoder->notifyWindowChanged(&windowChangeInfo)) {
|
||||
// Update the window display mode based on our current monitor
|
||||
// NB: Avoid a useless modeset by only doing this if it changed.
|
||||
if (newDisplayIndex != m_CurrentDisplayIndex) {
|
||||
m_CurrentDisplayIndex = newDisplayIndex;
|
||||
if (newDisplay != m_CurrentDisplay) {
|
||||
m_CurrentDisplay = newDisplay;
|
||||
updateOptimalWindowDisplayMode();
|
||||
}
|
||||
|
||||
@@ -1807,7 +1813,7 @@ bool Session::handleWindowEvent(SDL_WindowEvent* event)
|
||||
|
||||
bool Session::recreateRenderer()
|
||||
{
|
||||
SDL_AtomicLock(&m_DecoderLock);
|
||||
SDL_LockSpinlock(&m_DecoderLock);
|
||||
|
||||
// Destroy the old decoder
|
||||
delete m_VideoDecoder;
|
||||
@@ -1820,8 +1826,8 @@ bool Session::recreateRenderer()
|
||||
|
||||
// Update the window display mode based on our current monitor
|
||||
// NB: Avoid a useless modeset by only doing this if it changed.
|
||||
if (m_CurrentDisplayIndex != SDL_GetWindowDisplayIndex(m_Window)) {
|
||||
m_CurrentDisplayIndex = SDL_GetWindowDisplayIndex(m_Window);
|
||||
if (m_CurrentDisplay != SDL_GetDisplayForWindow(m_Window)) {
|
||||
m_CurrentDisplay = SDL_GetDisplayForWindow(m_Window);
|
||||
updateOptimalWindowDisplayMode();
|
||||
}
|
||||
|
||||
@@ -1829,8 +1835,8 @@ bool Session::recreateRenderer()
|
||||
// have queued to reset itself (if this reset was the result
|
||||
// of state loss).
|
||||
SDL_PumpEvents();
|
||||
SDL_FlushEvent(SDL_RENDER_DEVICE_RESET);
|
||||
SDL_FlushEvent(SDL_RENDER_TARGETS_RESET);
|
||||
SDL_FlushEvent(SDL_EVENT_RENDER_DEVICE_RESET);
|
||||
SDL_FlushEvent(SDL_EVENT_RENDER_TARGETS_RESET);
|
||||
|
||||
{
|
||||
// If the stream exceeds the display refresh rate (plus some slack),
|
||||
@@ -1853,7 +1859,7 @@ bool Session::recreateRenderer()
|
||||
enableVsync && m_Preferences->framePacing,
|
||||
false,
|
||||
s_ActiveSession->m_VideoDecoder)) {
|
||||
SDL_AtomicUnlock(&m_DecoderLock);
|
||||
SDL_UnlockSpinlock(&m_DecoderLock);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1876,7 +1882,7 @@ bool Session::recreateRenderer()
|
||||
// After a window resize, we need to reset the pointer lock region
|
||||
m_InputHandler->updatePointerRegionLock();
|
||||
|
||||
SDL_AtomicUnlock(&m_DecoderLock);
|
||||
SDL_UnlockSpinlock(&m_DecoderLock);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2002,7 +2008,7 @@ void Session::execInternal()
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||
|
||||
// We always want a resizable window with High DPI enabled
|
||||
Uint32 defaultWindowFlags = SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
|
||||
Uint32 defaultWindowFlags = SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_RESIZABLE;
|
||||
|
||||
// If we're starting in windowed mode and the Moonlight GUI is maximized or
|
||||
// minimized, match that with the streaming window.
|
||||
@@ -2090,12 +2096,7 @@ void Session::execInternal()
|
||||
|
||||
QPainter svgPainter(&svgImage);
|
||||
svgIconRenderer.render(&svgPainter);
|
||||
SDL_Surface* iconSurface = SDL_CreateRGBSurfaceWithFormatFrom((void*)svgImage.constBits(),
|
||||
svgImage.width(),
|
||||
svgImage.height(),
|
||||
32,
|
||||
4 * svgImage.width(),
|
||||
SDL_PIXELFORMAT_RGBA32);
|
||||
SDL_Surface* iconSurface = SDL_CreateSurfaceFrom(svgImage.width(), svgImage.height(), SDL_PIXELFORMAT_RGBA32, (void *)svgImage.constBits(), 4 * svgImage.width());
|
||||
#ifndef Q_OS_DARWIN
|
||||
// Other platforms seem to preserve our Qt icon when creating a new window.
|
||||
if (iconSurface != nullptr) {
|
||||
@@ -2147,7 +2148,7 @@ void Session::execInternal()
|
||||
// sleep precision and more accurate callback timing.
|
||||
SDL_SetHint(SDL_HINT_TIMER_RESOLUTION, "1");
|
||||
|
||||
m_CurrentDisplayIndex = SDL_GetWindowDisplayIndex(m_Window);
|
||||
m_CurrentDisplay = SDL_GetDisplayForWindow(m_Window);
|
||||
|
||||
// Now that we're about to stream, any SDL_QUIT event is expected
|
||||
// unless it comes from the connection termination callback where
|
||||
@@ -2205,12 +2206,12 @@ void Session::execInternal()
|
||||
}
|
||||
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
case SDL_EVENT_QUIT :
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Quit event received");
|
||||
goto DispatchDeferredCleanup;
|
||||
|
||||
case SDL_USEREVENT:
|
||||
case SDL_EVENT_USER :
|
||||
switch (event.user.code) {
|
||||
case SDL_CODE_FRAME_READY:
|
||||
if (m_VideoDecoder != nullptr) {
|
||||
@@ -2245,8 +2246,8 @@ void Session::execInternal()
|
||||
SDL_assert(false);
|
||||
}
|
||||
break;
|
||||
case SDL_RENDER_DEVICE_RESET:
|
||||
case SDL_RENDER_TARGETS_RESET:
|
||||
case SDL_EVENT_RENDER_DEVICE_RESET :
|
||||
case SDL_EVENT_RENDER_TARGETS_RESET :
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Recreating renderer by internal request: %d",
|
||||
event.type);
|
||||
@@ -2259,55 +2260,55 @@ void Session::execInternal()
|
||||
}
|
||||
break;
|
||||
|
||||
case SDL_KEYUP:
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_EVENT_KEY_UP :
|
||||
case SDL_EVENT_KEY_DOWN :
|
||||
presence.runCallbacks();
|
||||
m_InputHandler->handleKeyEvent(&event.key);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN :
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP :
|
||||
presence.runCallbacks();
|
||||
m_InputHandler->handleMouseButtonEvent(&event.button);
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
case SDL_EVENT_MOUSE_MOTION :
|
||||
m_InputHandler->handleMouseMotionEvent(&event.motion);
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
case SDL_EVENT_MOUSE_WHEEL :
|
||||
m_InputHandler->handleMouseWheelEvent(&event.wheel);
|
||||
break;
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
m_InputHandler->handleControllerAxisEvent(&event.caxis);
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION :
|
||||
m_InputHandler->handleControllerAxisEvent(&event.gaxis);
|
||||
break;
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN :
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP :
|
||||
presence.runCallbacks();
|
||||
m_InputHandler->handleControllerButtonEvent(&event.cbutton);
|
||||
m_InputHandler->handleControllerButtonEvent(&event.gbutton);
|
||||
break;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 14)
|
||||
case SDL_CONTROLLERSENSORUPDATE:
|
||||
m_InputHandler->handleControllerSensorEvent(&event.csensor);
|
||||
case SDL_EVENT_GAMEPAD_SENSOR_UPDATE :
|
||||
m_InputHandler->handleControllerSensorEvent(&event.gsensor);
|
||||
break;
|
||||
case SDL_CONTROLLERTOUCHPADDOWN:
|
||||
case SDL_CONTROLLERTOUCHPADUP:
|
||||
case SDL_CONTROLLERTOUCHPADMOTION:
|
||||
m_InputHandler->handleControllerTouchpadEvent(&event.ctouchpad);
|
||||
case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN :
|
||||
case SDL_EVENT_GAMEPAD_TOUCHPAD_UP :
|
||||
case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION :
|
||||
m_InputHandler->handleControllerTouchpadEvent(&event.gtouchpad);
|
||||
break;
|
||||
#endif
|
||||
#if SDL_VERSION_ATLEAST(2, 24, 0)
|
||||
case SDL_JOYBATTERYUPDATED:
|
||||
case SDL_EVENT_JOYSTICK_BATTERY_UPDATED :
|
||||
m_InputHandler->handleJoystickBatteryEvent(&event.jbattery);
|
||||
break;
|
||||
#endif
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
m_InputHandler->handleControllerDeviceEvent(&event.cdevice);
|
||||
case SDL_EVENT_GAMEPAD_ADDED :
|
||||
case SDL_EVENT_GAMEPAD_REMOVED :
|
||||
m_InputHandler->handleControllerDeviceEvent(&event.gdevice);
|
||||
break;
|
||||
case SDL_JOYDEVICEADDED:
|
||||
case SDL_EVENT_JOYSTICK_ADDED :
|
||||
m_InputHandler->handleJoystickArrivalEvent(&event.jdevice);
|
||||
break;
|
||||
case SDL_FINGERDOWN:
|
||||
case SDL_FINGERMOTION:
|
||||
case SDL_FINGERUP:
|
||||
case SDL_EVENT_FINGER_DOWN :
|
||||
case SDL_EVENT_FINGER_MOTION :
|
||||
case SDL_EVENT_FINGER_UP :
|
||||
m_InputHandler->handleTouchFingerEvent(&event.tfinger);
|
||||
break;
|
||||
}
|
||||
@@ -2335,10 +2336,10 @@ DispatchDeferredCleanup:
|
||||
// Destroy the decoder, since this must be done on the main thread
|
||||
// NB: This must happen before LiStopConnection() for pull-based
|
||||
// decoders.
|
||||
SDL_AtomicLock(&m_DecoderLock);
|
||||
SDL_LockSpinlock(&m_DecoderLock);
|
||||
delete m_VideoDecoder;
|
||||
m_VideoDecoder = nullptr;
|
||||
SDL_AtomicUnlock(&m_DecoderLock);
|
||||
SDL_UnlockSpinlock(&m_DecoderLock);
|
||||
|
||||
// Propagate state changes from the SDL window back to the Qt window
|
||||
//
|
||||
@@ -2370,7 +2371,7 @@ DispatchDeferredCleanup:
|
||||
SDL_DestroyWindow(m_Window);
|
||||
|
||||
if (iconSurface != nullptr) {
|
||||
SDL_FreeSurface(iconSurface);
|
||||
SDL_DestroySurface(iconSurface);
|
||||
}
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
|
||||
@@ -266,7 +266,7 @@ private:
|
||||
int m_FlushingWindowEventsRef;
|
||||
QList<QString> m_LaunchWarnings;
|
||||
|
||||
int m_CurrentDisplayIndex;
|
||||
SDL_DisplayID m_CurrentDisplay;
|
||||
bool m_NeedsFirstEnterCapture;
|
||||
bool m_NeedsPostDecoderCreationCapture;
|
||||
|
||||
|
||||
@@ -111,31 +111,22 @@ void StreamUtils::screenSpaceToNormalizedDeviceCoords(SDL_Rect* src, SDL_FRect*
|
||||
|
||||
int StreamUtils::getDisplayRefreshRate(SDL_Window* window)
|
||||
{
|
||||
int displayIndex = SDL_GetWindowDisplayIndex(window);
|
||||
if (displayIndex < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to get current display: %s",
|
||||
SDL_GetError());
|
||||
|
||||
// Assume display 0 if it fails
|
||||
displayIndex = 0;
|
||||
}
|
||||
|
||||
SDL_DisplayMode mode;
|
||||
if (SDLC_IsFullscreenExclusive(window)) {
|
||||
// Use the window display mode for full-screen exclusive mode
|
||||
if (SDL_GetWindowDisplayMode(window, &mode) != 0) {
|
||||
const SDL_DisplayMode *fsMode = SDL_GetWindowFullscreenMode(window);
|
||||
if (fsMode) {
|
||||
mode = *fsMode;
|
||||
}
|
||||
else {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetWindowDisplayMode() failed: %s",
|
||||
"SDL_GetWindowFullscreenMode() failed: %s",
|
||||
SDL_GetError());
|
||||
|
||||
// Assume 60 Hz
|
||||
return 60;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Use the current display mode for windowed and borderless
|
||||
if (SDL_GetCurrentDisplayMode(displayIndex, &mode) != 0) {
|
||||
if (SDL_GetCurrentDisplayMode(SDL_GetDisplayForWindow(window), &mode) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetCurrentDisplayMode() failed: %s",
|
||||
SDL_GetError());
|
||||
@@ -199,7 +190,7 @@ bool StreamUtils::hasFastAes()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool StreamUtils::getNativeDesktopMode(int displayIndex, SDL_DisplayMode* mode, SDL_Rect* safeArea)
|
||||
bool StreamUtils::getNativeDesktopMode(SDL_DisplayID display, SDL_DisplayMode* mode, SDL_Rect* safeArea)
|
||||
{
|
||||
#ifdef Q_OS_DARWIN
|
||||
#define MAX_DISPLAYS 16
|
||||
@@ -277,17 +268,13 @@ bool StreamUtils::getNativeDesktopMode(int displayIndex, SDL_DisplayMode* mode,
|
||||
#else
|
||||
SDL_assert(SDL_WasInit(SDL_INIT_VIDEO));
|
||||
|
||||
if (displayIndex >= SDL_GetNumVideoDisplays()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need to get the true display resolution without DPI scaling (since we use High DPI).
|
||||
// Windows returns the real display resolution here, even if DPI scaling is enabled.
|
||||
// macOS and Wayland report a resolution that includes the DPI scaling factor. Picking
|
||||
// the first mode on Wayland will get the native resolution without the scaling factor
|
||||
// (and macOS is handled in the #ifdef above).
|
||||
if (!strcmp(SDL_GetCurrentVideoDriver(), "wayland")) {
|
||||
if (SDL_GetDisplayMode(displayIndex, 0, mode) != 0) {
|
||||
if (SDL_GetDisplayMode(display, 0, mode) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetDisplayMode() failed: %s",
|
||||
SDL_GetError());
|
||||
@@ -295,7 +282,7 @@ bool StreamUtils::getNativeDesktopMode(int displayIndex, SDL_DisplayMode* mode,
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (SDL_GetDesktopDisplayMode(displayIndex, mode) != 0) {
|
||||
if (SDL_GetDesktopDisplayMode(display, mode) != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_GetDesktopDisplayMode() failed: %s",
|
||||
SDL_GetError());
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
void screenSpaceToNormalizedDeviceCoords(SDL_Rect* src, SDL_FRect* dst, int viewportWidth, int viewportHeight);
|
||||
|
||||
static
|
||||
bool getNativeDesktopMode(int displayIndex, SDL_DisplayMode* mode, SDL_Rect* safeArea);
|
||||
bool getNativeDesktopMode(SDL_DisplayID display, SDL_DisplayMode* mode, SDL_Rect* safeArea);
|
||||
|
||||
static
|
||||
int getDisplayRefreshRate(SDL_Window* window);
|
||||
|
||||
@@ -666,7 +666,7 @@ void D3D11VARenderer::renderFrame(AVFrame* frame)
|
||||
|
||||
// The card may have been removed or crashed. Reset the decoder.
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_TARGETS_RESET;
|
||||
event.type = SDL_EVENT_RENDER_TARGETS_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ void DrmRenderer::prepareToRender()
|
||||
// operation that the KMSDRM backend keeps pending until the next
|
||||
// time we swap buffers. We have to do this before we enumerate
|
||||
// CRTC modes below.
|
||||
SDL_Renderer* renderer = SDL_CreateRenderer(m_Window, -1, SDL_RENDERER_SOFTWARE);
|
||||
SDL_Renderer* renderer = SDL_CreateRenderer(m_Window, SDLC_DEFAULT_RENDER_DRIVER, SDL_RENDERER_SOFTWARE);
|
||||
if (renderer != nullptr) {
|
||||
// SDL_CreateRenderer() can end up having to recreate our window (SDL_RecreateWindow())
|
||||
// to ensure it's compatible with the renderer's OpenGL context. If that happens, we
|
||||
|
||||
@@ -1112,7 +1112,7 @@ void DXVA2Renderer::renderFrame(AVFrame *frame)
|
||||
"Clear() failed: %x",
|
||||
hr);
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_TARGETS_RESET;
|
||||
event.type = SDL_EVENT_RENDER_TARGETS_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
return;
|
||||
}
|
||||
@@ -1123,7 +1123,7 @@ void DXVA2Renderer::renderFrame(AVFrame *frame)
|
||||
"BeginScene() failed: %x",
|
||||
hr);
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_TARGETS_RESET;
|
||||
event.type = SDL_EVENT_RENDER_TARGETS_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
return;
|
||||
}
|
||||
@@ -1149,7 +1149,7 @@ void DXVA2Renderer::renderFrame(AVFrame *frame)
|
||||
"StretchRect() failed: %x",
|
||||
hr);
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_TARGETS_RESET;
|
||||
event.type = SDL_EVENT_RENDER_TARGETS_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
return;
|
||||
}
|
||||
@@ -1166,7 +1166,7 @@ void DXVA2Renderer::renderFrame(AVFrame *frame)
|
||||
"EndScene() failed: %x",
|
||||
hr);
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_TARGETS_RESET;
|
||||
event.type = SDL_EVENT_RENDER_TARGETS_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
return;
|
||||
}
|
||||
@@ -1184,7 +1184,7 @@ void DXVA2Renderer::renderFrame(AVFrame *frame)
|
||||
"PresentEx() failed: %x",
|
||||
hr);
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_TARGETS_RESET;
|
||||
event.type = SDL_EVENT_RENDER_TARGETS_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ void EGLRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
|
||||
if (!Session::get()->getOverlayManager().isOverlayEnabled(type)) {
|
||||
// If the overlay has been disabled, mark the data as invalid/stale.
|
||||
SDL_AtomicSet(&m_OverlayHasValidData[type], 0);
|
||||
SDL_SetAtomicInt(&m_OverlayHasValidData[type], 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -211,7 +211,7 @@ void EGLRenderer::renderOverlay(Overlay::OverlayType type, int viewportWidth, in
|
||||
// we must allocate a tightly packed buffer and copy our pixels there.
|
||||
packedPixelData = malloc(newSurface->w * newSurface->h * newSurface->format->BytesPerPixel);
|
||||
if (!packedPixelData) {
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ void EGLRenderer::renderOverlay(Overlay::OverlayType type, int viewportWidth, in
|
||||
overlayRect.w = newSurface->w;
|
||||
overlayRect.h = newSurface->h;
|
||||
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
|
||||
// Convert screen space to normalized device coordinates
|
||||
StreamUtils::screenSpaceToNormalizedDeviceCoords(&overlayRect, viewportWidth, viewportHeight);
|
||||
@@ -265,10 +265,10 @@ void EGLRenderer::renderOverlay(Overlay::OverlayType type, int viewportWidth, in
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_OverlayVbos[type]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
|
||||
|
||||
SDL_AtomicSet(&m_OverlayHasValidData[type], 1);
|
||||
SDL_SetAtomicInt(&m_OverlayHasValidData[type], 1);
|
||||
}
|
||||
|
||||
if (!SDL_AtomicGet(&m_OverlayHasValidData[type])) {
|
||||
if (!SDL_GetAtomicInt(&m_OverlayHasValidData[type])) {
|
||||
// If the overlay is not populated yet or is stale, don't render it.
|
||||
return;
|
||||
}
|
||||
@@ -435,6 +435,9 @@ bool EGLRenderer::initialize(PDECODER_PARAMETERS params)
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
m_DummyRenderer = SDL_CreateRenderer(m_Window, "opengles2", SDL_RENDERER_ACCELERATED);
|
||||
#else
|
||||
int renderIndex;
|
||||
int maxRenderers = SDL_GetNumRenderDrivers();
|
||||
SDL_assert(maxRenderers >= 0);
|
||||
@@ -454,6 +457,7 @@ bool EGLRenderer::initialize(PDECODER_PARAMETERS params)
|
||||
}
|
||||
|
||||
m_DummyRenderer = SDL_CreateRenderer(m_Window, renderIndex, SDL_RENDERER_ACCELERATED);
|
||||
#endif
|
||||
if (!m_DummyRenderer) {
|
||||
// Print the error here (before it gets clobbered), but ensure that we flush window
|
||||
// events just in case SDL re-created the window before eventually failing.
|
||||
@@ -638,7 +642,7 @@ bool EGLRenderer::initialize(PDECODER_PARAMETERS params)
|
||||
// If we got a working GL implementation via EGL, avoid using GLX from now on.
|
||||
// GLX will cause problems if we later want to use EGL again on this window.
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "EGL passed preflight checks. Using EGL for GL context creation.");
|
||||
SDL_SetHint(SDL_HINT_VIDEO_X11_FORCE_EGL, "1");
|
||||
SDL_SetHint(SDL_HINT_VIDEO_FORCE_EGL, "1");
|
||||
}
|
||||
|
||||
return err == GL_NO_ERROR;
|
||||
@@ -822,7 +826,7 @@ void EGLRenderer::renderFrame(AVFrame* frame)
|
||||
// XWayland. Other strategies like calling glGetError() don't seem
|
||||
// to be able to detect this situation for some reason.
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_TARGETS_RESET;
|
||||
event.type = SDL_EVENT_RENDER_TARGETS_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
|
||||
return;
|
||||
@@ -841,7 +845,11 @@ void EGLRenderer::renderFrame(AVFrame* frame)
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
int drawableWidth, drawableHeight;
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_GetWindowSizeInPixels(m_Window, &drawableWidth, &drawableHeight);
|
||||
#else
|
||||
SDL_GL_GetDrawableSize(m_Window, &drawableWidth, &drawableHeight);
|
||||
#endif
|
||||
|
||||
// Set the viewport to the size of the aspect-ratio-scaled video
|
||||
SDL_Rect src, dst;
|
||||
|
||||
@@ -56,7 +56,7 @@ void MmalRenderer::prepareToRender()
|
||||
{
|
||||
// Create a renderer and draw a black background for the area not covered by the MMAL overlay.
|
||||
// On the KMSDRM backend, this triggers the modeset that puts the CRTC into the mode we selected.
|
||||
m_BackgroundRenderer = SDL_CreateRenderer(m_Window, -1, SDL_RENDERER_SOFTWARE);
|
||||
m_BackgroundRenderer = SDL_CreateRenderer(m_Window, SDLC_DEFAULT_RENDER_DRIVER, SDL_RENDERER_SOFTWARE);
|
||||
if (m_BackgroundRenderer == nullptr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_CreateRenderer() failed: %s",
|
||||
|
||||
@@ -98,11 +98,7 @@ int Pacer::vsyncThread(void *context)
|
||||
{
|
||||
Pacer* me = reinterpret_cast<Pacer*>(context);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 9)
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_TIME_CRITICAL);
|
||||
#else
|
||||
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
|
||||
#endif
|
||||
SDL_SetCurrentThreadPriority(SDL_THREAD_PRIORITY_TIME_CRITICAL);
|
||||
|
||||
bool async = me->m_VsyncSource->isAsync();
|
||||
while (!me->m_Stopping) {
|
||||
@@ -131,7 +127,7 @@ int Pacer::renderThread(void* context)
|
||||
{
|
||||
Pacer* me = reinterpret_cast<Pacer*>(context);
|
||||
|
||||
if (SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH) < 0) {
|
||||
if (!SDL_SetCurrentThreadPriority(SDL_THREAD_PRIORITY_HIGH)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unable to set render thread to high priority: %s",
|
||||
SDL_GetError());
|
||||
@@ -183,7 +179,7 @@ void Pacer::enqueueFrameForRenderingAndUnlock(AVFrame *frame)
|
||||
SDL_Event event;
|
||||
|
||||
// For main thread rendering, we'll push an event to trigger a callback
|
||||
event.type = SDL_USEREVENT;
|
||||
event.type = SDL_EVENT_USER;
|
||||
event.user.code = SDL_CODE_FRAME_READY;
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ void PlVkRenderer::unlockQueue(struct AVHWDeviceContext *dev_ctx, uint32_t queue
|
||||
|
||||
void PlVkRenderer::overlayUploadComplete(void* opaque)
|
||||
{
|
||||
SDL_FreeSurface((SDL_Surface*)opaque);
|
||||
SDL_DestroySurface((SDL_Surface*)opaque);
|
||||
}
|
||||
|
||||
PlVkRenderer::PlVkRenderer(bool hwaccel, IFFmpegRenderer *backendRenderer) :
|
||||
@@ -362,7 +362,11 @@ bool PlVkRenderer::initialize(PDECODER_PARAMETERS params)
|
||||
m_Window = params->window;
|
||||
|
||||
unsigned int instanceExtensionCount = 0;
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if (!SDL_Vulkan_GetInstanceExtensions(&instanceExtensionCount, nullptr)) {
|
||||
#else
|
||||
if (!SDL_Vulkan_GetInstanceExtensions(params->window, &instanceExtensionCount, nullptr)) {
|
||||
#endif
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_Vulkan_GetInstanceExtensions() #1 failed: %s",
|
||||
SDL_GetError());
|
||||
@@ -370,7 +374,11 @@ bool PlVkRenderer::initialize(PDECODER_PARAMETERS params)
|
||||
}
|
||||
|
||||
std::vector<const char*> instanceExtensions(instanceExtensionCount);
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if (!SDL_Vulkan_GetInstanceExtensions(&instanceExtensionCount, instanceExtensions.data())) {
|
||||
#else
|
||||
if (!SDL_Vulkan_GetInstanceExtensions(params->window, &instanceExtensionCount, instanceExtensions.data())) {
|
||||
#endif
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_Vulkan_GetInstanceExtensions() #2 failed: %s",
|
||||
SDL_GetError());
|
||||
@@ -402,7 +410,11 @@ bool PlVkRenderer::initialize(PDECODER_PARAMETERS params)
|
||||
POPULATE_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR);
|
||||
POPULATE_FUNCTION(vkEnumerateDeviceExtensionProperties);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
if (!SDL_Vulkan_CreateSurface(params->window, m_PlVkInstance->instance, NULL, &m_VkSurface)) {
|
||||
#else
|
||||
if (!SDL_Vulkan_CreateSurface(params->window, m_PlVkInstance->instance, &m_VkSurface)) {
|
||||
#endif
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_Vulkan_CreateSurface() failed: %s",
|
||||
SDL_GetError());
|
||||
@@ -703,7 +715,7 @@ void PlVkRenderer::waitToRender()
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"GPU is in failed state. Recreating renderer.");
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_DEVICE_RESET;
|
||||
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
return;
|
||||
}
|
||||
@@ -721,7 +733,11 @@ void PlVkRenderer::waitToRender()
|
||||
|
||||
// Handle the swapchain being resized
|
||||
int vkDrawableW, vkDrawableH;
|
||||
#if SDL_VERSION_ATLEAST(3, 0, 0)
|
||||
SDL_GetWindowSizeInPixels(m_Window, &vkDrawableW, &vkDrawableH);
|
||||
#else
|
||||
SDL_Vulkan_GetDrawableSize(m_Window, &vkDrawableW, &vkDrawableH);
|
||||
#endif
|
||||
if (!pl_swapchain_resize(m_Swapchain, &vkDrawableW, &vkDrawableH)) {
|
||||
// Swapchain (re)creation can fail if the window is occluded
|
||||
return;
|
||||
@@ -905,12 +921,12 @@ void PlVkRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_AtomicLock(&m_OverlayLock);
|
||||
SDL_LockSpinlock(&m_OverlayLock);
|
||||
// We want to clear the staging overlay flag even if a staging overlay is still present,
|
||||
// since this ensures the render thread will not read from a partially initialized pl_tex
|
||||
// as we modify or recreate the staging overlay texture outside the overlay lock.
|
||||
m_Overlays[type].hasStagingOverlay = false;
|
||||
SDL_AtomicUnlock(&m_OverlayLock);
|
||||
SDL_UnlockSpinlock(&m_OverlayLock);
|
||||
|
||||
// If there's no new staging overlay, free the old staging overlay texture.
|
||||
// NB: This is safe to do outside the overlay lock because we're guaranteed
|
||||
@@ -925,7 +941,7 @@ void PlVkRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
SDL_assert(newSurface->format->format == SDL_PIXELFORMAT_ARGB8888);
|
||||
pl_fmt texFormat = pl_find_named_fmt(m_Vulkan->gpu, "bgra8");
|
||||
if (!texFormat) {
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"pl_find_named_fmt(bgra8) failed");
|
||||
return;
|
||||
@@ -945,7 +961,7 @@ void PlVkRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
if (!pl_tex_recreate(m_Vulkan->gpu, &m_Overlays[type].stagingOverlay.tex, &texParams)) {
|
||||
pl_tex_destroy(m_Vulkan->gpu, &m_Overlays[type].stagingOverlay.tex);
|
||||
SDL_zero(m_Overlays[type].stagingOverlay);
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"pl_tex_recreate() failed");
|
||||
return;
|
||||
@@ -962,7 +978,7 @@ void PlVkRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
if (!pl_tex_upload(m_Vulkan->gpu, &xferParams)) {
|
||||
pl_tex_destroy(m_Vulkan->gpu, &m_Overlays[type].stagingOverlay.tex);
|
||||
SDL_zero(m_Overlays[type].stagingOverlay);
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"pl_tex_upload() failed");
|
||||
return;
|
||||
@@ -978,10 +994,10 @@ void PlVkRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
m_Overlays[type].stagingOverlay.color = pl_color_space_srgb;
|
||||
|
||||
// Make this staging overlay visible to the render thread
|
||||
SDL_AtomicLock(&m_OverlayLock);
|
||||
SDL_LockSpinlock(&m_OverlayLock);
|
||||
SDL_assert(!m_Overlays[type].hasStagingOverlay);
|
||||
m_Overlays[type].hasStagingOverlay = true;
|
||||
SDL_AtomicUnlock(&m_OverlayLock);
|
||||
SDL_UnlockSpinlock(&m_OverlayLock);
|
||||
}
|
||||
|
||||
bool PlVkRenderer::notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO info)
|
||||
|
||||
@@ -169,7 +169,7 @@ bool SdlRenderer::initialize(PDECODER_PARAMETERS params)
|
||||
SDL_SetHintWithPriority(SDL_HINT_RENDER_DIRECT3D_THREADSAFE, "1", SDL_HINT_OVERRIDE);
|
||||
#endif
|
||||
|
||||
m_Renderer = SDL_CreateRenderer(params->window, -1, rendererFlags);
|
||||
m_Renderer = SDL_CreateRenderer(params->window, SDLC_DEFAULT_RENDER_DRIVER, rendererFlags);
|
||||
if (!m_Renderer) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SDL_CreateRenderer() failed: %s",
|
||||
@@ -221,7 +221,7 @@ void SdlRenderer::renderOverlay(Overlay::OverlayType type)
|
||||
if (type == Overlay::OverlayStatusUpdate) {
|
||||
// Bottom Left
|
||||
SDL_Rect viewportRect;
|
||||
SDL_RenderGetViewport(m_Renderer, &viewportRect);
|
||||
SDL_GetRenderViewport(m_Renderer, &viewportRect);
|
||||
m_OverlayRects[type].x = 0;
|
||||
m_OverlayRects[type].y = viewportRect.h - newSurface->h;
|
||||
}
|
||||
@@ -235,12 +235,12 @@ void SdlRenderer::renderOverlay(Overlay::OverlayType type)
|
||||
m_OverlayRects[type].h = newSurface->h;
|
||||
|
||||
m_OverlayTextures[type] = SDL_CreateTextureFromSurface(m_Renderer, newSurface);
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
}
|
||||
|
||||
// If we have an overlay texture, render it too
|
||||
if (m_OverlayTextures[type] != nullptr) {
|
||||
SDL_RenderCopy(m_Renderer, m_OverlayTextures[type], nullptr, &m_OverlayRects[type]);
|
||||
SDL_RenderTexture(m_Renderer, m_OverlayTextures[type], nullptr, &m_OverlayRects[type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,7 +659,7 @@ void VAAPIRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
}
|
||||
|
||||
if (!overlayEnabled) {
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -673,7 +673,7 @@ void VAAPIRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"vaCreateImage() failed: %d",
|
||||
status);
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -683,7 +683,7 @@ void VAAPIRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"vaMapBuffer() failed: %d",
|
||||
status);
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
vaDestroyImage(vaDeviceContext->display, newImage.image_id);
|
||||
return;
|
||||
}
|
||||
@@ -698,7 +698,7 @@ void VAAPIRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"vaUnmapBuffer() failed: %d",
|
||||
status);
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
vaDestroyImage(vaDeviceContext->display, newImage.image_id);
|
||||
return;
|
||||
}
|
||||
@@ -720,7 +720,7 @@ void VAAPIRenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
overlayRect.h = newSurface->h;
|
||||
|
||||
// Surface data is no longer needed
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
|
||||
VASubpictureID newSubpicture;
|
||||
status = vaCreateSubpicture(vaDeviceContext->display, newImage.image_id, &newSubpicture);
|
||||
|
||||
@@ -374,7 +374,7 @@ void VDPAURenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
}
|
||||
|
||||
if (!overlayEnabled) {
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -393,7 +393,7 @@ void VDPAURenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"VdpBitmapSurfaceCreate() failed: %s",
|
||||
m_VdpGetErrorString(status));
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -406,7 +406,7 @@ void VDPAURenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
"VdpBitmapSurfacePutBitsNative() failed: %s",
|
||||
m_VdpGetErrorString(status));
|
||||
m_VdpBitmapSurfaceDestroy(newBitmapSurface);
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -427,7 +427,7 @@ void VDPAURenderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
overlayRect.y1 = overlayRect.y0 + newSurface->h;
|
||||
|
||||
// Surface data is no longer needed
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
|
||||
SDL_LockMutex(m_OverlayMutex);
|
||||
m_OverlaySurface[type] = newBitmapSurface;
|
||||
@@ -467,7 +467,7 @@ void VDPAURenderer::renderOverlay(VdpOutputSurface destination, Overlay::Overlay
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDL_TryLockMutex(m_OverlayMutex) != 0) {
|
||||
if (!SDL_TryLockMutex(m_OverlayMutex)) {
|
||||
// If the overlay is currently being updated, skip rendering it this frame.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ int FFmpegVideoDecoder::getDecoderCapabilities()
|
||||
|
||||
if (!isHardwareAccelerated()) {
|
||||
// Slice up to 4 times for parallel CPU decoding, once slice per core
|
||||
int slices = qMin(MAX_SLICES, SDL_GetCPUCount());
|
||||
int slices = qMin(MAX_SLICES, SDL_GetNumLogicalCPUCores());
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Encoder configured for %d slices per frame",
|
||||
slices);
|
||||
@@ -269,10 +269,10 @@ void FFmpegVideoDecoder::reset()
|
||||
// Terminate the decoder thread before doing anything else.
|
||||
// It might be touching things we're about to free.
|
||||
if (m_DecoderThread != nullptr) {
|
||||
SDL_AtomicSet(&m_DecoderThreadShouldQuit, 1);
|
||||
SDL_SetAtomicInt(&m_DecoderThreadShouldQuit, 1);
|
||||
LiWakeWaitForVideoFrame();
|
||||
SDL_WaitThread(m_DecoderThread, NULL);
|
||||
SDL_AtomicSet(&m_DecoderThreadShouldQuit, 0);
|
||||
SDL_SetAtomicInt(&m_DecoderThreadShouldQuit, 0);
|
||||
m_DecoderThread = nullptr;
|
||||
}
|
||||
|
||||
@@ -484,7 +484,7 @@ bool FFmpegVideoDecoder::completeInitialization(const AVCodec* decoder, enum AVP
|
||||
// Enable slice multi-threading for software decoding
|
||||
if (!isHardwareAccelerated()) {
|
||||
m_VideoDecoderCtx->thread_type = FF_THREAD_SLICE;
|
||||
m_VideoDecoderCtx->thread_count = qMin(MAX_SLICES, SDL_GetCPUCount());
|
||||
m_VideoDecoderCtx->thread_count = qMin(MAX_SLICES, SDL_GetNumLogicalCPUCores());
|
||||
}
|
||||
else {
|
||||
// No threading for HW decode
|
||||
@@ -1608,7 +1608,7 @@ int FFmpegVideoDecoder::decoderThreadProcThunk(void *context)
|
||||
|
||||
void FFmpegVideoDecoder::decoderThreadProc()
|
||||
{
|
||||
while (!SDL_AtomicGet(&m_DecoderThreadShouldQuit)) {
|
||||
while (!SDL_GetAtomicInt(&m_DecoderThreadShouldQuit)) {
|
||||
if (m_FramesIn == m_FramesOut) {
|
||||
VIDEO_FRAME_HANDLE handle;
|
||||
PDECODE_UNIT du;
|
||||
@@ -1736,18 +1736,18 @@ void FFmpegVideoDecoder::decoderThreadProc()
|
||||
"Resetting decoder due to consistent failure");
|
||||
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_DEVICE_RESET;
|
||||
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
|
||||
// Don't consume any additional data
|
||||
SDL_AtomicSet(&m_DecoderThreadShouldQuit, 1);
|
||||
SDL_SetAtomicInt(&m_DecoderThreadShouldQuit, 1);
|
||||
}
|
||||
|
||||
// Just in case the error resulted in the loss of the frame,
|
||||
// request an IDR frame to reset our decoder state.
|
||||
LiRequestIdrFrame();
|
||||
}
|
||||
} while (err == AVERROR(EAGAIN) && !SDL_AtomicGet(&m_DecoderThreadShouldQuit));
|
||||
} while (err == AVERROR(EAGAIN) && !SDL_GetAtomicInt(&m_DecoderThreadShouldQuit));
|
||||
|
||||
if (err != 0) {
|
||||
// Free the frame if we failed to submit it
|
||||
@@ -1862,11 +1862,11 @@ int FFmpegVideoDecoder::submitDecodeUnit(PDECODE_UNIT du)
|
||||
"Resetting decoder due to consistent failure");
|
||||
|
||||
SDL_Event event;
|
||||
event.type = SDL_RENDER_DEVICE_RESET;
|
||||
event.type = SDL_EVENT_RENDER_DEVICE_RESET;
|
||||
SDL_PushEvent(&event);
|
||||
|
||||
// Don't consume any additional data
|
||||
SDL_AtomicSet(&m_DecoderThreadShouldQuit, 1);
|
||||
SDL_SetAtomicInt(&m_DecoderThreadShouldQuit, 1);
|
||||
}
|
||||
|
||||
return DR_NEED_IDR;
|
||||
|
||||
@@ -133,7 +133,7 @@ void OverlayManager::notifyOverlayUpdated(OverlayType type)
|
||||
}
|
||||
|
||||
// m_FontData must stay around until the font is closed
|
||||
m_Overlays[type].font = TTF_OpenFontRW(SDL_RWFromConstMem(m_FontData.constData(), m_FontData.size()),
|
||||
m_Overlays[type].font = TTF_OpenFontRW(SDL_IOFromConstMem(m_FontData.constData(), m_FontData.size()),
|
||||
1,
|
||||
m_Overlays[type].fontSize);
|
||||
if (m_Overlays[type].font == nullptr) {
|
||||
@@ -146,11 +146,11 @@ void OverlayManager::notifyOverlayUpdated(OverlayType type)
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface* oldSurface = (SDL_Surface*)SDL_AtomicSetPtr((void**)&m_Overlays[type].surface, nullptr);
|
||||
SDL_Surface* oldSurface = (SDL_Surface*) SDL_SetAtomicPointer((void**)&m_Overlays[type].surface, nullptr);
|
||||
|
||||
// Free the old surface
|
||||
if (oldSurface != nullptr) {
|
||||
SDL_FreeSurface(oldSurface);
|
||||
SDL_DestroySurface(oldSurface);
|
||||
}
|
||||
|
||||
if (m_Overlays[type].enabled) {
|
||||
@@ -159,7 +159,7 @@ void OverlayManager::notifyOverlayUpdated(OverlayType type)
|
||||
m_Overlays[type].text,
|
||||
m_Overlays[type].color,
|
||||
1024);
|
||||
SDL_AtomicSetPtr((void**)&m_Overlays[type].surface, surface);
|
||||
SDL_SetAtomicPointer((void**)&m_Overlays[type].surface, surface);
|
||||
}
|
||||
|
||||
// Notify the renderer
|
||||
|
||||
@@ -195,7 +195,7 @@ void SLVideoDecoder::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
}
|
||||
|
||||
if (!overlayEnabled) {
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ void SLVideoDecoder::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
if (m_Overlay == nullptr) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"SLVideo_CreateOverlay() failed");
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ void SLVideoDecoder::notifyOverlayUpdated(Overlay::OverlayType type)
|
||||
SLVideo_SetOverlayDisplayArea(m_Overlay, 0.0f, 1.0f - flHeight, flWidth, flHeight);
|
||||
|
||||
// We're done with the surface now
|
||||
SDL_FreeSurface(newSurface);
|
||||
SDL_DestroySurface(newSurface);
|
||||
|
||||
// Show the overlay
|
||||
SLVideo_ShowOverlay(m_Overlay);
|
||||
|
||||
Reference in New Issue
Block a user