Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
switch/video: port implementation
  • Loading branch information
vs49688 committed May 17, 2025
commit 9986e2a79d5e489a5198e7c434ae106cb16c5da4
16 changes: 16 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2927,6 +2927,22 @@ elseif(N3DS)
elseif(NINTENDO_SWITCH)
sdl_link_dependency(nx LIBS nx)

if(SDL_VIDEO)
set(SDL_VIDEO_DRIVER_SWITCH 1)
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/switch/*.c")
set(HAVE_SDL_VIDEO TRUE)

CheckEGL()
if(HAVE_OPENGL_EGL)
sdl_link_dependency(opengl LIBS EGL glapi drm_nouveau)
endif()

CheckOpenGLES()
CheckOpenGL()

sdl_compile_options(PRIVATE -DSDL_VIDEO_STATIC_ANGLE)
endif()

CheckPTHREAD()

if(SDL_CLOCK_GETTIME)
Expand Down
1 change: 1 addition & 0 deletions include/build_config/SDL_build_config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@
#cmakedefine SDL_VIDEO_DRIVER_X11_XSHAPE 1
#cmakedefine SDL_VIDEO_DRIVER_X11_XSYNC 1
#cmakedefine SDL_VIDEO_DRIVER_QNX 1
#cmakedefine SDL_VIDEO_DRIVER_SWITCH 1

#cmakedefine SDL_VIDEO_RENDER_D3D 1
#cmakedefine SDL_VIDEO_RENDER_D3D11 1
Expand Down
1 change: 1 addition & 0 deletions src/video/SDL_sysvideo.h
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ extern VideoBootStrap PSP_bootstrap;
extern VideoBootStrap VITA_bootstrap;
extern VideoBootStrap RISCOS_bootstrap;
extern VideoBootStrap N3DS_bootstrap;
extern VideoBootStrap SWITCH_bootstrap;
extern VideoBootStrap RPI_bootstrap;
extern VideoBootStrap KMSDRM_bootstrap;
extern VideoBootStrap DUMMY_bootstrap;
Expand Down
3 changes: 3 additions & 0 deletions src/video/SDL_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ static VideoBootStrap *bootstrap[] = {
#ifdef SDL_VIDEO_DRIVER_N3DS
&N3DS_bootstrap,
#endif
#ifdef SDL_VIDEO_DRIVER_SWITCH
&SWITCH_bootstrap,
#endif
#ifdef SDL_VIDEO_DRIVER_KMSDRM
&KMSDRM_bootstrap,
#endif
Expand Down
16 changes: 7 additions & 9 deletions src/video/switch/SDL_switchkeyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,50 +18,48 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"

#if SDL_VIDEO_DRIVER_SWITCH

#include <switch.h>

#include "../../events/SDL_keyboard_c.h"
#include "SDL_events.h"
#include "SDL_log.h"
#include "SDL_switchkeyboard.h"
#include "SDL_switchvideo.h"

static bool keys[SDL_NUM_SCANCODES] = { 0 };
static bool keys[SDL_SCANCODE_COUNT] = { 0 };
static SDL_KeyboardID keyboard_id = 1;

void SWITCH_InitKeyboard(void)
{
hidInitializeKeyboard();
SDL_AddKeyboard(keyboard_id, NULL, false);
}

void SWITCH_PollKeyboard(void)
void SWITCH_PollKeyboard(Uint64 timestamp)
{
HidKeyboardState state;
SDL_Scancode scancode;

if (SDL_GetFocusWindow() == NULL) {
if (SDL_GetKeyboardFocus() == NULL) {
return;
}

if (hidGetKeyboardStates(&state, 1)) {
for (scancode = SDL_SCANCODE_UNKNOWN; scancode < (SDL_Scancode)HidKeyboardKey_RightGui; scancode++) {
bool pressed = hidKeyboardStateGetKey(&state, (int)scancode);
if (pressed && !keys[scancode]) {
SDL_SendKeyboardKey(pressed, scancode);
keys[scancode] = true;
} else if (!pressed && keys[scancode]) {
SDL_SendKeyboardKey(pressed, scancode);
keys[scancode] = false;
}
SDL_SendKeyboardKey(timestamp, keyboard_id, pressed, scancode, keys[scancode]);
}
}
}

void SWITCH_QuitKeyboard(void)
{
SDL_RemoveKeyboard(keyboard_id, false);
}

#endif /* SDL_VIDEO_DRIVER_SWITCH */
Expand Down
4 changes: 2 additions & 2 deletions src/video/switch/SDL_switchkeyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
#ifndef _SDL_switchkeyboard_h
#define _SDL_switchkeyboard_h

#include "../../SDL_internal.h"
#include "SDL_internal.h"

/* Keyboard functions */
extern void SWITCH_InitKeyboard(void);
extern void SWITCH_PollKeyboard(void);
extern void SWITCH_PollKeyboard(Uint64 timestamp);
extern void SWITCH_QuitKeyboard(void);

#endif /* _SDL_switchkeyboard_h */
Expand Down
55 changes: 27 additions & 28 deletions src/video/switch/SDL_switchmouse.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,84 +18,82 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"

#if SDL_VIDEO_DRIVER_SWITCH

#include <switch.h>

#include "../../events/SDL_mouse_c.h"
#include "SDL_events.h"
#include "SDL_log.h"
#include "SDL_mouse.h"
#include "SDL_switchmouse_c.h"
#include "SDL_switchvideo.h"
#include "SDL_timer.h"

static uint64_t prev_buttons = 0;
static uint64_t last_timestamp = 0;
const uint64_t mouse_read_interval = 15; // in ms
static SDL_MouseID mouse_id = 1;

static int SWITCH_SetRelativeMouseMode(SDL_bool enabled)
static bool SWITCH_SetRelativeMouseMode(bool enabled)
{
return 0;
return true;
}

void SWITCH_InitMouse(void)
{
SDL_Mouse *mouse = SDL_GetMouse();
mouse->SetRelativeMouseMode = SWITCH_SetRelativeMouseMode;
hidInitializeMouse();

SDL_AddMouse(1, NULL, false);
}

void SWITCH_PollMouse(void)
void SWITCH_PollMouse(Uint64 timestamp)
{
SDL_Window *window = SDL_GetFocusWindow();
SDL_Window *window = SDL_GetKeyboardFocus();
HidMouseState mouse_state;
size_t state_count;
uint64_t changed_buttons;
uint64_t timestamp;
int dx, dy;

// We skip polling mouse if no window is created
if (window == NULL)
if (window == NULL) {
return;
}

state_count = hidGetMouseStates(&mouse_state, 1);
changed_buttons = mouse_state.buttons ^ prev_buttons;

if (changed_buttons & HidMouseButton_Left) {
if (prev_buttons & HidMouseButton_Left)
SDL_SendMouseButton(window, 0, SDL_RELEASED, SDL_BUTTON_LEFT);
else
SDL_SendMouseButton(window, 0, SDL_PRESSED, SDL_BUTTON_LEFT);
if (prev_buttons & HidMouseButton_Left) {
SDL_SendMouseButton(timestamp, window, mouse_id, SDL_BUTTON_LEFT, false);
} else {
SDL_SendMouseButton(timestamp, window, mouse_id, SDL_BUTTON_LEFT, true);
}
}
if (changed_buttons & HidMouseButton_Right) {
if (prev_buttons & HidMouseButton_Right)
SDL_SendMouseButton(window, 0, SDL_RELEASED, SDL_BUTTON_RIGHT);
else
SDL_SendMouseButton(window, 0, SDL_PRESSED, SDL_BUTTON_RIGHT);
if (prev_buttons & HidMouseButton_Right) {
SDL_SendMouseButton(timestamp, window, mouse_id, SDL_BUTTON_RIGHT, false);
} else {
SDL_SendMouseButton(timestamp, window, mouse_id, SDL_BUTTON_RIGHT, true);
}
}
if (changed_buttons & HidMouseButton_Middle) {
if (prev_buttons & HidMouseButton_Middle)
SDL_SendMouseButton(window, 0, SDL_RELEASED, SDL_BUTTON_MIDDLE);
else
SDL_SendMouseButton(window, 0, SDL_PRESSED, SDL_BUTTON_MIDDLE);
if (prev_buttons & HidMouseButton_Middle) {
SDL_SendMouseButton(timestamp, window, mouse_id, SDL_BUTTON_MIDDLE, false);
} else {
SDL_SendMouseButton(timestamp, window, mouse_id, SDL_BUTTON_MIDDLE, true);
}
}

prev_buttons = mouse_state.buttons;

timestamp = SDL_GetTicks();

if (SDL_TICKS_PASSED(timestamp, last_timestamp + mouse_read_interval)) {
if (timestamp > last_timestamp + mouse_read_interval) {
// if hidMouseRead is called once per frame, a factor two on the velocities
// results in approximately the same mouse motion as reported by mouse_pos.x and mouse_pos.y
// but without the clamping to 1280 x 720
if (state_count > 0) {
dx = mouse_state.delta_x * 2;
dy = mouse_state.delta_y * 2;
if (dx || dy) {
SDL_SendMouseMotion(window, 0, 1, dx, dy);
SDL_SendMouseMotion(timestamp, window, mouse_id, 1, dx, dy);
}
}
last_timestamp = timestamp;
Expand All @@ -104,6 +102,7 @@ void SWITCH_PollMouse(void)

void SWITCH_QuitMouse(void)
{
SDL_RemoveMouse(mouse_id, false);
}

#endif /* SDL_VIDEO_DRIVER_SWITCH */
Expand Down
4 changes: 2 additions & 2 deletions src/video/switch/SDL_switchmouse_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
#ifndef _SDL_switchmouse_h
#define _SDL_switchmouse_h

#include "../../SDL_internal.h"
#include "SDL_internal.h"

/* mouse functions */
extern void SWITCH_InitMouse(void);
extern void SWITCH_PollMouse(void);
extern void SWITCH_PollMouse(Uint64 timestamp);
extern void SWITCH_QuitMouse(void);

#endif /* _SDL_switchmouse_h */
Expand Down
17 changes: 9 additions & 8 deletions src/video/switch/SDL_switchopengles.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,34 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

#include "../../SDL_internal.h"
#include "SDL_log.h"
#include "../../SDL_log_c.h"

#if SDL_VIDEO_DRIVER_SWITCH

#include "SDL_switchopengles.h"
#include "SDL_switchvideo.h"
#include "SDL_video.h"

/* EGL implementation of SDL OpenGL support */

void SWITCH_GLES_DefaultProfileConfig(_THIS, int *mask, int *major, int *minor)
void SWITCH_GLES_DefaultProfileConfig(SDL_VideoDevice *_this, int *mask, int *major, int *minor)
{
(void)_this;

*mask = SDL_GL_CONTEXT_PROFILE_ES;
*major = 2;
*minor = 0;
}

int SWITCH_GLES_LoadLibrary(_THIS, const char *path)
bool SWITCH_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path)
{
return SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY, 0);
}

// clang-format off
SDL_EGL_CreateContext_impl(SWITCH)
SDL_EGL_MakeCurrent_impl(SWITCH)
SDL_EGL_SwapWindow_impl(SWITCH)
SDL_EGL_MakeCurrent_impl(SWITCH)
SDL_EGL_SwapWindow_impl(SWITCH)
// clang-format on

#endif /* SDL_VIDEO_DRIVER_SWITCH */

Expand Down
18 changes: 8 additions & 10 deletions src/video/switch/SDL_switchopengles.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,17 @@
#include "../SDL_sysvideo.h"

/* OpenGLES functions */
#define SWITCH_GLES_GetAttribute SDL_EGL_GetAttribute
#define SWITCH_GLES_GetProcAddress SDL_EGL_GetProcAddress
#define SWITCH_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal
#define SWITCH_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
#define SWITCH_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
#define SWITCH_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
#define SWITCH_GLES_DeleteContext SDL_EGL_DeleteContext

extern int SWITCH_GLES_LoadLibrary(_THIS, const char *path);
extern SDL_GLContext SWITCH_GLES_CreateContext(_THIS, SDL_Window *window);
extern int SWITCH_GLES_SwapWindow(_THIS, SDL_Window *window);
extern int SWITCH_GLES_MakeCurrent(_THIS, SDL_Window *window, SDL_GLContext context);
extern void SWITCH_GLES_DefaultProfileConfig(_THIS, int *mask, int *major, int *minor);
extern void SWITCH_GLES_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h);
#define SWITCH_GLES_DestroyContext SDL_EGL_DestroyContext

extern bool SWITCH_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path);
extern SDL_GLContext SWITCH_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window);
extern bool SWITCH_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern bool SWITCH_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context);
extern void SWITCH_GLES_DefaultProfileConfig(SDL_VideoDevice *_this, int *mask, int *major, int *minor);

#endif /* SDL_VIDEO_DRIVER_SWITCH */
#endif /* SDL_switchteopengles_h_ */
Expand Down
Loading