mirror of https://github.com/encounter/SDL.git
switch: move to opengles 2 renderer
* switch: move to opengles 2 rendering * switch: remove libglad dependecy * switch: minor cleanup * switch: minor cleanup 2 * switch: use SDL2 EGL video, fix inputs, major cleanup * switch: fix configure flags (static EGL funcs) * switch: update to latest mesa (remove SDL_egl.c hacks) * switch: restore vanilla SDL_egl.c (remove crap) * switch: use RGBA8888 display mode instead of ARGB888 * switch: add "multiple display" mode support
This commit is contained in:
parent
9e06af0445
commit
2776779715
|
@ -10,8 +10,8 @@ set(CMAKE_CXX_COMPILER "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-g++")
|
||||||
set(CMAKE_ASM_COMPILER "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-as")
|
set(CMAKE_ASM_COMPILER "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-as")
|
||||||
set(CMAKE_AR "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-gcc-ar" CACHE STRING "")
|
set(CMAKE_AR "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-gcc-ar" CACHE STRING "")
|
||||||
set(CMAKE_RANLIB "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-gcc-ranlib" CACHE STRING "")
|
set(CMAKE_RANLIB "${DEVKITPRO}/devkitA64/bin/aarch64-none-elf-gcc-ranlib" CACHE STRING "")
|
||||||
set(CMAKE_C_FLAGS "-O2 -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIC -ftls-model=local-exec -I${DEVKITPRO}/libnx/include -I${DEVKITPRO}/portlibs/switch/include" CACHE STRING "C flags")
|
set(CMAKE_C_FLAGS "-g -O2 -march=armv8-a -mtune=cortex-a57 -mtp=soft -ftls-model=local-exec -fPIC -I${DEVKITPRO}/libnx/include -I${DEVKITPRO}/portlibs/switch/include" CACHE STRING "C flags")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fpermissive -fno-rtti -fno-exceptions -std=gnu++11" CACHE STRING "C++ flags")
|
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions" CACHE STRING "C++ flags")
|
||||||
set(CMAKE_FIND_ROOT_PATH ${DEVKITPRO} ${DEVKITPRO}/devkitA64 ${DEVKITPRO}/libnx ${DEVKITPRO}/portlibs/switch)
|
set(CMAKE_FIND_ROOT_PATH ${DEVKITPRO} ${DEVKITPRO}/devkitA64 ${DEVKITPRO}/libnx ${DEVKITPRO}/portlibs/switch)
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||||
|
@ -39,6 +39,9 @@ set(SRC_DIRS
|
||||||
src/power
|
src/power
|
||||||
src/render
|
src/render
|
||||||
src/render/software
|
src/render/software
|
||||||
|
src/render/opengl
|
||||||
|
src/render/opengles
|
||||||
|
src/render/opengles2
|
||||||
src/stdlib
|
src/stdlib
|
||||||
src/thread
|
src/thread
|
||||||
src/thread/switch
|
src/thread/switch
|
||||||
|
@ -58,17 +61,19 @@ endforeach (DIR)
|
||||||
# SDL2 library
|
# SDL2 library
|
||||||
add_library(${PROJECT_NAME} STATIC ${SRC_FILES})
|
add_library(${PROJECT_NAME} STATIC ${SRC_FILES})
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${SRC_DIRS} include)
|
target_include_directories(${PROJECT_NAME} PUBLIC ${SRC_DIRS} include)
|
||||||
target_compile_options(${PROJECT_NAME} PUBLIC -O3 -D__SWITCH__)
|
target_compile_options(${PROJECT_NAME} PUBLIC -O3 -D__SWITCH__ -DSDL_VIDEO_STATIC_ANGLE)
|
||||||
|
|
||||||
# SDL2 test
|
# SDL2 test
|
||||||
add_executable(${PROJECT_NAME}.elf test/testswitch.c)
|
add_executable(${PROJECT_NAME}.elf test/testswitch.c)
|
||||||
target_include_directories(${PROJECT_NAME}.elf PRIVATE include)
|
target_include_directories(${PROJECT_NAME}.elf PRIVATE include)
|
||||||
#target_include_directories(${PROJECT_NAME}.elf PRIVATE ${DEVKITPRO}/portlibs/switch/include)
|
|
||||||
target_compile_options(${PROJECT_NAME}.elf PRIVATE -O3 -D__SWITCH__)
|
target_compile_options(${PROJECT_NAME}.elf PRIVATE -O3 -D__SWITCH__)
|
||||||
target_link_libraries(${PROJECT_NAME}.elf
|
target_link_libraries(${PROJECT_NAME}.elf
|
||||||
${PROJECT_NAME}
|
${PROJECT_NAME}
|
||||||
#${DEVKITPRO}/portlibs/switch/lib/libSDL2.a
|
${DEVKITPRO}/portlibs/switch/lib/libEGL.a
|
||||||
|
${DEVKITPRO}/portlibs/switch/lib/libglapi.a
|
||||||
|
${DEVKITPRO}/portlibs/switch/lib/libdrm_nouveau.a
|
||||||
${DEVKITPRO}/libnx/lib/libnx.a
|
${DEVKITPRO}/libnx/lib/libnx.a
|
||||||
|
stdc++
|
||||||
m
|
m
|
||||||
)
|
)
|
||||||
set_target_properties(${PROJECT_NAME}.elf PROPERTIES LINK_FLAGS "-specs=${DEVKITPRO}/libnx/switch.specs")
|
set_target_properties(${PROJECT_NAME}.elf PROPERTIES LINK_FLAGS "-specs=${DEVKITPRO}/libnx/switch.specs")
|
||||||
|
|
20
configure.ac
20
configure.ac
|
@ -4232,17 +4232,23 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
|
||||||
;;
|
;;
|
||||||
aarch64-none-elf*)
|
aarch64-none-elf*)
|
||||||
ARCH=switch
|
ARCH=switch
|
||||||
SDL_CFLAGS="$SDL_CFLAGS -isystem ${DEVKITPRO}/libnx/include -I${DEVKITPRO}/portlibs/switch/include -D__SWITCH__ -march=armv8-a -mtune=cortex-a57 -mtp=soft -ftls-model=local-exec"
|
SDL_CFLAGS="$SDL_CFLAGS -isystem ${DEVKITPRO}/libnx/include -I${DEVKITPRO}/portlibs/switch/include"
|
||||||
EXTRA_CFLAGS="$EXTRA_CFLAGS -g -O2 $SDL_CFLAGS -fPIC"
|
EXTRA_CFLAGS="$EXTRA_CFLAGS -D__SWITCH__ -march=armv8-a -mtune=cortex-a57 -mtp=soft -ftls-model=local-exec -fPIC"
|
||||||
EXTRA_LDFLAGS="-march=armv8-a -fPIE -L${DEVKITPRO}/libnx/lib -lnx"
|
EXTRA_CFLAGS="$EXTRA_CFLAGS $SDL_CFLAGS -g -O3"
|
||||||
|
EXTRA_CFLAGS="$EXTRA_CFLAGS -DSDL_VIDEO_STATIC_ANGLE"
|
||||||
|
EXTRA_LDFLAGS="-march=armv8-a -fPIE -L${DEVKITPRO}/libnx/lib -lEGL -lglapi -ldrm_nouveau -lnx"
|
||||||
CheckDeclarationAfterStatement
|
CheckDeclarationAfterStatement
|
||||||
|
|
||||||
# Set up files for the video library
|
# Set up files for the video library
|
||||||
if test x$enable_video = xyes; then
|
if test x$enable_video = xyes; then
|
||||||
AC_DEFINE(SDL_VIDEO_DRIVER_SWITCH, 1, [ ])
|
SOURCES="$SOURCES $srcdir/src/video/switch/*.c"
|
||||||
SOURCES="$SOURCES $srcdir/src/video/switch/*.c"
|
AC_DEFINE(SDL_VIDEO_DRIVER_SWITCH, 1, [ ])
|
||||||
SUMMARY_video="${SUMMARY_video} switch"
|
AC_DEFINE(SDL_VIDEO_OPENGL_EGL, 1, [ ])
|
||||||
have_video=yes
|
AC_DEFINE(SDL_VIDEO_OPENGL, 1, [ ])
|
||||||
|
AC_DEFINE(SDL_VIDEO_OPENGL_ES2, 1, [ ])
|
||||||
|
AC_DEFINE(SDL_VIDEO_RENDER_OGL_ES2, 1, [ ])
|
||||||
|
SUMMARY_video="${SUMMARY_video} switch_opengles2"
|
||||||
|
have_video=yes
|
||||||
fi
|
fi
|
||||||
# Set up files for the audio library
|
# Set up files for the audio library
|
||||||
if test x$enable_audio = xyes; then
|
if test x$enable_audio = xyes; then
|
||||||
|
|
|
@ -421,6 +421,7 @@ GLES2_CacheProgram(GLES2_RenderData *data, GLES2_ShaderCacheEntry *vertex,
|
||||||
GLES2_ShaderCacheEntry *shaderEntry;
|
GLES2_ShaderCacheEntry *shaderEntry;
|
||||||
GLint linkSuccessful;
|
GLint linkSuccessful;
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
/* Check if we've already cached this program */
|
/* Check if we've already cached this program */
|
||||||
entry = data->program_cache.head;
|
entry = data->program_cache.head;
|
||||||
while (entry) {
|
while (entry) {
|
||||||
|
|
|
@ -1477,7 +1477,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some platforms have OpenGL enabled by default */
|
/* Some platforms have OpenGL enabled by default */
|
||||||
#if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__ || __NACL__
|
#if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__ || __NACL__ || __SWITCH__
|
||||||
if (!_this->is_dummy && !(flags & SDL_WINDOW_VULKAN) && !(flags & SDL_WINDOW_METAL) && !SDL_IsVideoContextExternal()) {
|
if (!_this->is_dummy && !(flags & SDL_WINDOW_VULKAN) && !(flags & SDL_WINDOW_METAL) && !SDL_IsVideoContextExternal()) {
|
||||||
flags |= SDL_WINDOW_OPENGL;
|
flags |= SDL_WINDOW_OPENGL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
#include "SDL_log.h"
|
||||||
|
|
||||||
|
#if SDL_VIDEO_DRIVER_SWITCH
|
||||||
|
|
||||||
|
#include "SDL_video.h"
|
||||||
|
#include "SDL_switchopengles.h"
|
||||||
|
#include "SDL_switchvideo.h"
|
||||||
|
|
||||||
|
/* EGL implementation of SDL OpenGL support */
|
||||||
|
|
||||||
|
void
|
||||||
|
SWITCH_GLES_DefaultProfileConfig(_THIS, int *mask, int *major, int *minor)
|
||||||
|
{
|
||||||
|
*mask = SDL_GL_CONTEXT_PROFILE_ES;
|
||||||
|
*major = 2;
|
||||||
|
*minor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SWITCH_GLES_LoadLibrary(_THIS, const char *path)
|
||||||
|
{
|
||||||
|
return SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SWITCH_GLES_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
|
||||||
|
{
|
||||||
|
SDL_DisplayMode mode = {0, 0, 0, 0, 0};
|
||||||
|
SDL_GetCurrentDisplayMode(0, &mode);
|
||||||
|
*w = mode.w;
|
||||||
|
*h = mode.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_EGL_CreateContext_impl(SWITCH)
|
||||||
|
SDL_EGL_MakeCurrent_impl(SWITCH)
|
||||||
|
SDL_EGL_SwapWindow_impl(SWITCH)
|
||||||
|
|
||||||
|
// for SDL_egl.c compatibility
|
||||||
|
void *
|
||||||
|
SDL_LoadFunction(void *handle, const char *name)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SDL_UnloadObject(void *handle)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SDL_VIDEO_DRIVER_SWITCH */
|
||||||
|
|
||||||
|
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
|
||||||
|
#ifndef SDL_switchteopengles_h_
|
||||||
|
#define SDL_switchteopengles_h_
|
||||||
|
|
||||||
|
#if SDL_VIDEO_DRIVER_SWITCH
|
||||||
|
|
||||||
|
#include "../SDL_sysvideo.h"
|
||||||
|
#include "../SDL_egl_c.h"
|
||||||
|
|
||||||
|
/* OpenGLES functions */
|
||||||
|
#define SWITCH_GLES_GetAttribute SDL_EGL_GetAttribute
|
||||||
|
#define SWITCH_GLES_GetProcAddress SDL_EGL_GetProcAddress
|
||||||
|
#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);
|
||||||
|
|
||||||
|
#endif /* SDL_VIDEO_DRIVER_SWITCH */
|
||||||
|
#endif /* SDL_switchteopengles_h_ */
|
||||||
|
|
||||||
|
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -23,122 +23,319 @@
|
||||||
|
|
||||||
#if SDL_VIDEO_DRIVER_SWITCH
|
#if SDL_VIDEO_DRIVER_SWITCH
|
||||||
|
|
||||||
/* SDL internals */
|
|
||||||
#include "../SDL_sysvideo.h"
|
|
||||||
#include "../../events/SDL_keyboard_c.h"
|
|
||||||
#include "../../events/SDL_windowevents_c.h"
|
|
||||||
#include "SDL_switchtouch.h"
|
|
||||||
|
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
|
||||||
#define SWITCH_DATA "_SDL_SwitchData"
|
#include "../SDL_sysvideo.h"
|
||||||
#define SCREEN_WIDTH 1280
|
#include "../../render/SDL_sysrender.h"
|
||||||
#define SCREEN_HEIGHT 720
|
#include "../../events/SDL_keyboard_c.h"
|
||||||
|
#include "../../events/SDL_mouse_c.h"
|
||||||
|
#include "../../events/SDL_windowevents_c.h"
|
||||||
|
|
||||||
typedef struct
|
#include "SDL_switchvideo.h"
|
||||||
{
|
#include "SDL_switchopengles.h"
|
||||||
SDL_Surface *surface;
|
#include "SDL_switchtouch.h"
|
||||||
int x_offset;
|
|
||||||
int y_offset;
|
|
||||||
} SWITCH_WindowData;
|
|
||||||
|
|
||||||
static int SWITCH_VideoInit(_THIS);
|
static int
|
||||||
|
SWITCH_Available(void)
|
||||||
static int SWITCH_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
|
|
||||||
|
|
||||||
static void SWITCH_VideoQuit(_THIS);
|
|
||||||
|
|
||||||
static void SWITCH_PumpEvents(_THIS);
|
|
||||||
|
|
||||||
static int SWITCH_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void **pixels, int *pitch);
|
|
||||||
|
|
||||||
static int SWITCH_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects, int numrects);
|
|
||||||
|
|
||||||
static void SWITCH_DestroyWindowFramebuffer(_THIS, SDL_Window *window);
|
|
||||||
|
|
||||||
static int SWITCH_Available(void)
|
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SWITCH_DeleteDevice(SDL_VideoDevice *device)
|
static void
|
||||||
|
SWITCH_Destroy(SDL_VideoDevice *device)
|
||||||
{
|
{
|
||||||
SDL_free(device);
|
if (device) {
|
||||||
|
SDL_free(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDL_VideoDevice *SWITCH_CreateDevice(int devindex)
|
static SDL_VideoDevice *
|
||||||
|
SWITCH_CreateDevice(int devindex)
|
||||||
{
|
{
|
||||||
SDL_VideoDevice *device;
|
SDL_VideoDevice *device;
|
||||||
|
|
||||||
|
/* Initialize SDL_VideoDevice structure */
|
||||||
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
|
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
|
||||||
if (!device) {
|
if (device == NULL) {
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Setup amount of available displays */
|
||||||
|
device->num_displays = 0;
|
||||||
|
|
||||||
|
/* Set device free function */
|
||||||
|
device->free = SWITCH_Destroy;
|
||||||
|
|
||||||
|
/* Setup all functions which we can handle */
|
||||||
device->VideoInit = SWITCH_VideoInit;
|
device->VideoInit = SWITCH_VideoInit;
|
||||||
device->VideoQuit = SWITCH_VideoQuit;
|
device->VideoQuit = SWITCH_VideoQuit;
|
||||||
|
device->GetDisplayModes = SWITCH_GetDisplayModes;
|
||||||
device->SetDisplayMode = SWITCH_SetDisplayMode;
|
device->SetDisplayMode = SWITCH_SetDisplayMode;
|
||||||
device->PumpEvents = SWITCH_PumpEvents;
|
device->CreateSDLWindow = SWITCH_CreateWindow;
|
||||||
device->CreateWindowFramebuffer = SWITCH_CreateWindowFramebuffer;
|
device->CreateSDLWindowFrom = SWITCH_CreateWindowFrom;
|
||||||
device->UpdateWindowFramebuffer = SWITCH_UpdateWindowFramebuffer;
|
device->SetWindowTitle = SWITCH_SetWindowTitle;
|
||||||
device->DestroyWindowFramebuffer = SWITCH_DestroyWindowFramebuffer;
|
device->SetWindowIcon = SWITCH_SetWindowIcon;
|
||||||
|
device->SetWindowPosition = SWITCH_SetWindowPosition;
|
||||||
|
device->SetWindowSize = SWITCH_SetWindowSize;
|
||||||
|
device->ShowWindow = SWITCH_ShowWindow;
|
||||||
|
device->HideWindow = SWITCH_HideWindow;
|
||||||
|
device->RaiseWindow = SWITCH_RaiseWindow;
|
||||||
|
device->MaximizeWindow = SWITCH_MaximizeWindow;
|
||||||
|
device->MinimizeWindow = SWITCH_MinimizeWindow;
|
||||||
|
device->RestoreWindow = SWITCH_RestoreWindow;
|
||||||
|
device->SetWindowGrab = SWITCH_SetWindowGrab;
|
||||||
|
device->DestroyWindow = SWITCH_DestroyWindow;
|
||||||
|
|
||||||
device->free = SWITCH_DeleteDevice;
|
device->GL_LoadLibrary = SWITCH_GLES_LoadLibrary;
|
||||||
|
device->GL_GetProcAddress = SWITCH_GLES_GetProcAddress;
|
||||||
|
device->GL_UnloadLibrary = SWITCH_GLES_UnloadLibrary;
|
||||||
|
device->GL_CreateContext = SWITCH_GLES_CreateContext;
|
||||||
|
device->GL_MakeCurrent = SWITCH_GLES_MakeCurrent;
|
||||||
|
device->GL_SetSwapInterval = SWITCH_GLES_SetSwapInterval;
|
||||||
|
device->GL_GetSwapInterval = SWITCH_GLES_GetSwapInterval;
|
||||||
|
device->GL_SwapWindow = SWITCH_GLES_SwapWindow;
|
||||||
|
device->GL_DeleteContext = SWITCH_GLES_DeleteContext;
|
||||||
|
device->GL_DefaultProfileConfig = SWITCH_GLES_DefaultProfileConfig;
|
||||||
|
device->GL_GetDrawableSize = SWITCH_GLES_GetDrawableSize;
|
||||||
|
|
||||||
|
device->PumpEvents = SWITCH_PumpEvents;
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoBootStrap SWITCH_bootstrap = {
|
VideoBootStrap SWITCH_bootstrap = {
|
||||||
"Switch", "Video driver for Nintendo Switch (libnx)",
|
"Switch",
|
||||||
SWITCH_Available, SWITCH_CreateDevice
|
"OpenGL ES2 video driver for Nintendo Switch",
|
||||||
|
SWITCH_Available,
|
||||||
|
SWITCH_CreateDevice
|
||||||
};
|
};
|
||||||
|
|
||||||
static int SWITCH_VideoInit(_THIS)
|
/*****************************************************************************/
|
||||||
|
/* SDL Video and Display initialization/handling functions */
|
||||||
|
/*****************************************************************************/
|
||||||
|
int
|
||||||
|
SWITCH_VideoInit(_THIS)
|
||||||
{
|
{
|
||||||
SDL_DisplayMode mode;
|
SDL_VideoDisplay display;
|
||||||
|
SDL_DisplayMode current_mode;
|
||||||
|
SDL_DisplayData *data;
|
||||||
|
SDL_DisplayModeData *mdata;
|
||||||
|
|
||||||
gfxInitResolution(SCREEN_WIDTH, SCREEN_HEIGHT);
|
SDL_zero(current_mode);
|
||||||
gfxInitDefault();
|
current_mode.w = 1280;
|
||||||
gfxSetMode(GfxMode_TiledDouble);
|
current_mode.h = 720;
|
||||||
|
current_mode.refresh_rate = 60;
|
||||||
|
current_mode.format = SDL_PIXELFORMAT_RGBA8888;
|
||||||
|
mdata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||||
|
mdata->padding = 0;
|
||||||
|
current_mode.driverdata = mdata;
|
||||||
|
|
||||||
// add default mode (1280x720)
|
SDL_zero(display);
|
||||||
mode.format = SDL_PIXELFORMAT_ABGR8888;
|
display.desktop_mode = current_mode;
|
||||||
mode.w = SCREEN_WIDTH;
|
display.current_mode = current_mode;
|
||||||
mode.h = SCREEN_HEIGHT;
|
|
||||||
mode.refresh_rate = 60;
|
/* Allocate display internal data */
|
||||||
mode.driverdata = NULL;
|
data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData));
|
||||||
if (SDL_AddBasicVideoDisplay(&mode) < 0) {
|
if (data == NULL) {
|
||||||
return -1;
|
return SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
SDL_AddDisplayMode(&_this->displays[0], &mode);
|
data->egl_display = EGL_DEFAULT_DISPLAY;
|
||||||
|
display.driverdata = data;
|
||||||
|
|
||||||
// allow any resolution
|
SDL_AddVideoDisplay(&display);
|
||||||
mode.w = 0;
|
|
||||||
mode.h = 0;
|
|
||||||
SDL_AddDisplayMode(&_this->displays[0], &mode);
|
|
||||||
|
|
||||||
// init touch
|
// init touch
|
||||||
SWITCH_InitTouch();
|
SWITCH_InitTouch();
|
||||||
|
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SWITCH_VideoQuit(_THIS)
|
void
|
||||||
|
SWITCH_VideoQuit(_THIS)
|
||||||
{
|
{
|
||||||
|
// exit touch
|
||||||
SWITCH_QuitTouch();
|
SWITCH_QuitTouch();
|
||||||
gfxExit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SWITCH_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
|
void
|
||||||
|
SWITCH_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
|
||||||
{
|
{
|
||||||
SDL_SendWindowEvent(display->fullscreen_window,
|
SDL_DisplayMode mode;
|
||||||
SDL_WINDOWEVENT_RESIZED, mode->w, mode->h);
|
SDL_DisplayModeData *data;
|
||||||
|
|
||||||
|
// 1920x1080 (16/9) 16RGBA8888
|
||||||
|
if (appletGetOperationMode() == AppletOperationMode_Docked) {
|
||||||
|
SDL_zero(mode);
|
||||||
|
mode.w = 1920;
|
||||||
|
mode.h = 1080;
|
||||||
|
mode.refresh_rate = 60;
|
||||||
|
mode.format = SDL_PIXELFORMAT_RGBA8888;
|
||||||
|
data = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||||
|
data->padding = 0;
|
||||||
|
mode.driverdata = data;
|
||||||
|
SDL_AddDisplayMode(display, &mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1280x720 (16/9) RGBA8888
|
||||||
|
SDL_AddDisplayMode(display, &display->current_mode);
|
||||||
|
|
||||||
|
// 960x540 (16/9) RGBA8888
|
||||||
|
SDL_zero(mode);
|
||||||
|
mode.w = 960;
|
||||||
|
mode.h = 540;
|
||||||
|
mode.refresh_rate = 60;
|
||||||
|
mode.format = SDL_PIXELFORMAT_RGBA8888;
|
||||||
|
data = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||||
|
data->padding = 0;
|
||||||
|
mode.driverdata = data;
|
||||||
|
SDL_AddDisplayMode(display, &mode);
|
||||||
|
|
||||||
|
// 800x600 (4/3) RGBA8888
|
||||||
|
SDL_zero(mode);
|
||||||
|
mode.w = 800;
|
||||||
|
mode.h = 600;
|
||||||
|
mode.refresh_rate = 60;
|
||||||
|
mode.format = SDL_PIXELFORMAT_RGBA8888;
|
||||||
|
data = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||||
|
data->padding = (int) ((600.0f * 1.7774f) - 800.0f) / 2;
|
||||||
|
mode.driverdata = data;
|
||||||
|
SDL_AddDisplayMode(display, &mode);
|
||||||
|
|
||||||
|
// 640x480 (4/3) RGBA8888
|
||||||
|
SDL_zero(mode);
|
||||||
|
mode.w = 640;
|
||||||
|
mode.h = 480;
|
||||||
|
mode.refresh_rate = 60;
|
||||||
|
mode.format = SDL_PIXELFORMAT_RGBA8888;
|
||||||
|
data = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
|
||||||
|
data->padding = (int) ((480.0f * 1.7774f) - 640.0f) / 2;
|
||||||
|
mode.driverdata = data;
|
||||||
|
SDL_AddDisplayMode(display, &mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SWITCH_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
|
||||||
|
{
|
||||||
|
SDL_Renderer *renderer = SDL_GetRenderer(_this->windows);
|
||||||
|
SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfxConfigureResolution(mode->w + data->padding * 2, mode->h);
|
||||||
|
display->current_mode = *mode;
|
||||||
|
_this->windows->w = mode->w;
|
||||||
|
_this->windows->h = mode->h;
|
||||||
|
if (renderer) {
|
||||||
|
renderer->UpdateViewport(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SWITCH_PumpEvents(_THIS)
|
int
|
||||||
|
SWITCH_CreateWindow(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
SDL_WindowData *wdata;
|
||||||
|
//SDL_VideoDisplay *display;
|
||||||
|
|
||||||
|
/* Allocate window internal data */
|
||||||
|
wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
|
||||||
|
if (wdata == NULL) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
window->flags |= SDL_WINDOW_FULLSCREEN;
|
||||||
|
|
||||||
|
if (!_this->egl_data) {
|
||||||
|
return SDL_SetError("SWITCH_CreateWindow: EGL not initialized");
|
||||||
|
}
|
||||||
|
wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) &wdata->egl_surface);
|
||||||
|
|
||||||
|
if (wdata->egl_surface == EGL_NO_SURFACE) {
|
||||||
|
return SDL_SetError("Could not create GLES window surface");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup driver data for this window */
|
||||||
|
window->driverdata = wdata;
|
||||||
|
|
||||||
|
/* One window, it always has focus */
|
||||||
|
SDL_SetMouseFocus(window);
|
||||||
|
SDL_SetKeyboardFocus(window);
|
||||||
|
|
||||||
|
/* Window has been successfully created */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SWITCH_DestroyWindow(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
if (data->egl_surface != EGL_NO_SURFACE) {
|
||||||
|
SDL_EGL_DestroySurface(_this, data->egl_surface);
|
||||||
|
}
|
||||||
|
SDL_free(data);
|
||||||
|
window->driverdata = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SWITCH_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWITCH_SetWindowTitle(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWITCH_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWITCH_SetWindowPosition(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWITCH_SetWindowSize(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWITCH_ShowWindow(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWITCH_HideWindow(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWITCH_RaiseWindow(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWITCH_MaximizeWindow(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWITCH_MinimizeWindow(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWITCH_RestoreWindow(_THIS, SDL_Window *window)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void
|
||||||
|
SWITCH_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SWITCH_PumpEvents(_THIS)
|
||||||
{
|
{
|
||||||
if (!appletMainLoop()) {
|
if (!appletMainLoop()) {
|
||||||
SDL_Event ev;
|
SDL_Event ev;
|
||||||
|
@ -151,119 +348,4 @@ static void SWITCH_PumpEvents(_THIS)
|
||||||
SWITCH_PollTouch();
|
SWITCH_PollTouch();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SWITCH_SetResolution(u32 width, u32 height)
|
|
||||||
{
|
|
||||||
u32 x, y, w, h, i;
|
|
||||||
u32 *fb;
|
|
||||||
|
|
||||||
// clear framebuffers before switching res
|
|
||||||
for (i = 0; i < 2; i++) {
|
|
||||||
|
|
||||||
fb = (u32 *) gfxGetFramebuffer(&w, &h);
|
|
||||||
|
|
||||||
for (y = 0; y < h; y++) {
|
|
||||||
for (x = 0; x < w; x++) {
|
|
||||||
fb[gfxGetFramebufferDisplayOffset(x, y)] =
|
|
||||||
(u32) RGBA8_MAXALPHA(0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxFlushBuffers();
|
|
||||||
gfxSwapBuffers();
|
|
||||||
gfxWaitForVsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxConfigureResolution(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SWITCH_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void **pixels, int *pitch)
|
|
||||||
{
|
|
||||||
int bpp;
|
|
||||||
Uint32 r, g, b, a;
|
|
||||||
SDL_Surface *surface;
|
|
||||||
SWITCH_WindowData *data;
|
|
||||||
|
|
||||||
// create sdl surface framebuffer
|
|
||||||
SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ABGR8888, &bpp, &r, &g, &b, &a);
|
|
||||||
surface = SDL_CreateRGBSurface(0, window->w, window->h, bpp, r, g, b, a);
|
|
||||||
if (!surface) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// hold a pointer to our stuff
|
|
||||||
data = SDL_calloc(1, sizeof(SWITCH_WindowData));
|
|
||||||
data->surface = surface;
|
|
||||||
|
|
||||||
// use switch hardware scaling in fullscreen mode
|
|
||||||
if (window->flags & SDL_WINDOW_FULLSCREEN) {
|
|
||||||
float scaling = (float) window->h / (float) SCREEN_HEIGHT;
|
|
||||||
float w = SDL_min(SCREEN_WIDTH, SCREEN_WIDTH * scaling);
|
|
||||||
// calculate x offset, to respect aspect ratio
|
|
||||||
// round down to multiple of 4 for faster fb writes
|
|
||||||
data->x_offset = ((int) (w - window->w) / 2) & ~3;
|
|
||||||
data->y_offset = 0;
|
|
||||||
SWITCH_SetResolution((u32) w, (u32) window->h);
|
|
||||||
printf("gfxConfigureResolution: %i x %i (window: %i x %i, offset: %i x %i)\n",
|
|
||||||
(int) w, window->h, window->w, window->h, data->x_offset, data->y_offset);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data->x_offset = ((SCREEN_WIDTH - window->w) / 2) & ~3;
|
|
||||||
data->y_offset = (SCREEN_HEIGHT - window->h) / 2;
|
|
||||||
SWITCH_SetResolution(0, 0);
|
|
||||||
printf("gfxConfigureResolution: %i x %i (window: %i x %i, offset: %i x %i)\n",
|
|
||||||
1280, 720, window->w, window->h, data->x_offset, data->y_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
*format = SDL_PIXELFORMAT_ABGR8888;
|
|
||||||
*pixels = surface->pixels;
|
|
||||||
*pitch = surface->pitch;
|
|
||||||
|
|
||||||
SDL_SetWindowData(window, SWITCH_DATA, data);
|
|
||||||
|
|
||||||
// inform SDL we're ready to accept inputs
|
|
||||||
SDL_SetKeyboardFocus(window);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int SWITCH_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects, int numrects)
|
|
||||||
{
|
|
||||||
SWITCH_WindowData *data = (SWITCH_WindowData *) SDL_GetWindowData(window, SWITCH_DATA);
|
|
||||||
|
|
||||||
u32 fb_w, fb_h;
|
|
||||||
int x, y, w = window->w, h = window->h;
|
|
||||||
u32 *src = (u32 *) data->surface->pixels;
|
|
||||||
u32 *dst = (u32 *) gfxGetFramebuffer(&fb_w, &fb_h);
|
|
||||||
|
|
||||||
// prevent fb overflow in case of resolution change outside SDL
|
|
||||||
if (data->x_offset + w > fb_w) {
|
|
||||||
w = fb_w - data->x_offset;
|
|
||||||
}
|
|
||||||
if (data->y_offset + h > fb_h) {
|
|
||||||
h = fb_h - data->y_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (y = 0; y < h; y++) {
|
|
||||||
for (x = 0; x < w; x += 4) {
|
|
||||||
*((u128 *) &dst[gfxGetFramebufferDisplayOffset(
|
|
||||||
(u32) (x + data->x_offset), (u32) (y + data->y_offset))]) =
|
|
||||||
*((u128 *) &src[y * w + x]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxFlushBuffers();
|
|
||||||
gfxSwapBuffers();
|
|
||||||
// TODO: handle SDL_RENDERER_PRESENTVSYNC (SW_RenderDriver not accepting flags)
|
|
||||||
gfxWaitForVsync();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SWITCH_DestroyWindowFramebuffer(_THIS, SDL_Window *window)
|
|
||||||
{
|
|
||||||
SWITCH_WindowData *data = (SWITCH_WindowData *) SDL_GetWindowData(window, SWITCH_DATA);
|
|
||||||
SDL_FreeSurface(data->surface);
|
|
||||||
SDL_free(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* SDL_VIDEO_DRIVER_SWITCH */
|
#endif /* SDL_VIDEO_DRIVER_SWITCH */
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SDL_SWITCHVIDEO_H__
|
||||||
|
#define __SDL_SWITCHVIDEO_H__
|
||||||
|
|
||||||
|
#if SDL_VIDEO_DRIVER_SWITCH
|
||||||
|
|
||||||
|
#include "../../SDL_internal.h"
|
||||||
|
#include "../SDL_sysvideo.h"
|
||||||
|
|
||||||
|
#include "SDL_egl.h"
|
||||||
|
|
||||||
|
typedef struct SDL_DisplayData
|
||||||
|
{
|
||||||
|
EGLDisplay egl_display;
|
||||||
|
} SDL_DisplayData;
|
||||||
|
|
||||||
|
typedef struct SDL_DisplayModeData
|
||||||
|
{
|
||||||
|
int padding;
|
||||||
|
} SDL_DisplayModeData;
|
||||||
|
|
||||||
|
typedef struct SDL_WindowData
|
||||||
|
{
|
||||||
|
EGLSurface egl_surface;
|
||||||
|
} SDL_WindowData;
|
||||||
|
|
||||||
|
int SWITCH_VideoInit(_THIS);
|
||||||
|
void SWITCH_VideoQuit(_THIS);
|
||||||
|
void SWITCH_GetDisplayModes(_THIS, SDL_VideoDisplay *display);
|
||||||
|
int SWITCH_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
|
||||||
|
int SWITCH_CreateWindow(_THIS, SDL_Window *window);
|
||||||
|
int SWITCH_CreateWindowFrom(_THIS, SDL_Window *window, const void *data);
|
||||||
|
void SWITCH_SetWindowTitle(_THIS, SDL_Window *window);
|
||||||
|
void SWITCH_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon);
|
||||||
|
void SWITCH_SetWindowPosition(_THIS, SDL_Window *window);
|
||||||
|
void SWITCH_SetWindowSize(_THIS, SDL_Window *window);
|
||||||
|
void SWITCH_ShowWindow(_THIS, SDL_Window *window);
|
||||||
|
void SWITCH_HideWindow(_THIS, SDL_Window *window);
|
||||||
|
void SWITCH_RaiseWindow(_THIS, SDL_Window *window);
|
||||||
|
void SWITCH_MaximizeWindow(_THIS, SDL_Window *window);
|
||||||
|
void SWITCH_MinimizeWindow(_THIS, SDL_Window *window);
|
||||||
|
void SWITCH_RestoreWindow(_THIS, SDL_Window *window);
|
||||||
|
void SWITCH_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed);
|
||||||
|
void SWITCH_DestroyWindow(_THIS, SDL_Window *window);
|
||||||
|
void SWITCH_PumpEvents(_THIS);
|
||||||
|
|
||||||
|
#endif /* SDL_VIDEO_DRIVER_SWITCH */
|
||||||
|
#endif /* __SDL_SWITCHVIDEO_H__ */
|
||||||
|
|
||||||
|
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -14,52 +14,110 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include <video/SDL_sysvideo.h>
|
|
||||||
#include "SDL2/SDL.h"
|
#include "SDL2/SDL.h"
|
||||||
|
|
||||||
|
static SDL_DisplayMode modes[5];
|
||||||
|
|
||||||
|
static int mode_count = 0, current_mode = 0;
|
||||||
|
|
||||||
|
void print_info(SDL_Window *window, SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
int w, h;
|
||||||
|
SDL_DisplayMode mode;
|
||||||
|
|
||||||
|
SDL_GetWindowSize(window, &w, &h);
|
||||||
|
SDL_Log("window size: %i x %i\n", w, h);
|
||||||
|
SDL_GetRendererOutputSize(renderer, &w, &h);
|
||||||
|
SDL_Log("renderer size: %i x %i\n", w, h);
|
||||||
|
|
||||||
|
SDL_GetCurrentDisplayMode(0, &mode);
|
||||||
|
SDL_Log("display mode: %i x %i @ %i bpp (%s)",
|
||||||
|
mode.w, mode.h,
|
||||||
|
SDL_BITSPERPIXEL(mode.format),
|
||||||
|
SDL_GetPixelFormatName(mode.format));
|
||||||
|
}
|
||||||
|
|
||||||
|
void change_mode(SDL_Window *window)
|
||||||
|
{
|
||||||
|
current_mode++;
|
||||||
|
if (current_mode == mode_count) {
|
||||||
|
current_mode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetWindowDisplayMode(window, &modes[current_mode]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_rects(SDL_Renderer *renderer, int x, int y)
|
||||||
|
{
|
||||||
|
// R
|
||||||
|
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
|
||||||
|
SDL_Rect r = {x, y, 64, 64};
|
||||||
|
SDL_RenderFillRect(renderer, &r);
|
||||||
|
|
||||||
|
// G
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
|
||||||
|
SDL_Rect g = {x + 64, y, 64, 64};
|
||||||
|
SDL_RenderFillRect(renderer, &g);
|
||||||
|
|
||||||
|
// B
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
|
||||||
|
SDL_Rect b = {x + 128, y, 64, 64};
|
||||||
|
SDL_RenderFillRect(renderer, &b);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
SDL_Renderer *renderer;
|
SDL_Renderer *renderer;
|
||||||
int done = 0;
|
int done = 0, x = 0, w, h;
|
||||||
|
|
||||||
// redirect stdout to emulators
|
|
||||||
consoleDebugInit(debugDevice_SVC);
|
|
||||||
stdout = stderr;
|
|
||||||
|
|
||||||
// mandatory at least on switch, else gfx is not properly closed
|
// mandatory at least on switch, else gfx is not properly closed
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
|
||||||
printf("SDL_Init: %s\n", SDL_GetError());
|
SDL_Log("SDL_Init: %s\n", SDL_GetError());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a 800x600 window for demonstration.
|
// create a window (OpenGL always enabled)
|
||||||
// if SDL_WINDOW_FULLSCREEN flag is passed, it will be hardware scaled (stretched) to fit screen,
|
// available switch SDL2 video modes :
|
||||||
// will always be centered and aspect ratio maintained.
|
// 1920 x 1080 @ 32 bpp (SDL_PIXELFORMAT_RGBA8888) (docked only)
|
||||||
// maximum window dimension is currently limited to 1280x720
|
// 1280 x 720 @ 32 bpp (SDL_PIXELFORMAT_RGBA8888)
|
||||||
window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_FULLSCREEN);
|
// 960 x 540 @ 32 bpp (SDL_PIXELFORMAT_RGBA8888)
|
||||||
|
// 800 x 600 @ 32 bpp (SDL_PIXELFORMAT_RGBA8888)
|
||||||
|
// 640 x 480 @ 32 bpp (SDL_PIXELFORMAT_RGBA8888)
|
||||||
|
window = SDL_CreateWindow("sdl2_gles2", 0, 0, 640, 480, SDL_WINDOW_FULLSCREEN);
|
||||||
if (!window) {
|
if (!window) {
|
||||||
printf("SDL_CreateWindow: %s\n", SDL_GetError());
|
SDL_Log("SDL_CreateWindow: %s\n", SDL_GetError());
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch only support software renderer for now
|
// create a renderer (OpenGL ES2)
|
||||||
renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_SOFTWARE);
|
renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||||
if (!renderer) {
|
if (!renderer) {
|
||||||
printf("SDL_CreateRenderer: %s\n", SDL_GetError());
|
SDL_Log("SDL_CreateRenderer: %s\n", SDL_GetError());
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pint some info about display/window/renderer
|
||||||
|
print_info(window, renderer);
|
||||||
|
|
||||||
|
// list available display modes
|
||||||
|
mode_count = SDL_GetNumDisplayModes(0);
|
||||||
|
for (int i = 0; i < mode_count; i++) {
|
||||||
|
SDL_DisplayMode mode;
|
||||||
|
SDL_GetDisplayMode(0, i, &mode);
|
||||||
|
modes[i] = mode;
|
||||||
|
}
|
||||||
|
|
||||||
// open CONTROLLER_PLAYER_1 and CONTROLLER_PLAYER_2
|
// open CONTROLLER_PLAYER_1 and CONTROLLER_PLAYER_2
|
||||||
// when connected, both joycons are mapped to joystick #0,
|
// when railed, both joycons are mapped to joystick #0,
|
||||||
// else joycons are individually mapped to joystick #0, joystick #1, ...
|
// else joycons are individually mapped to joystick #0, joystick #1, ...
|
||||||
// https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L45
|
// https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L45
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
if (SDL_JoystickOpen(i) == NULL) {
|
if (SDL_JoystickOpen(i) == NULL) {
|
||||||
printf("SDL_JoystickOpen: %s\n", SDL_GetError());
|
SDL_Log("SDL_JoystickOpen: %s\n", SDL_GetError());
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -72,16 +130,21 @@ int main(int argc, char *argv[])
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
|
|
||||||
case SDL_JOYAXISMOTION:
|
case SDL_JOYAXISMOTION:
|
||||||
printf("Joystick %d axis %d value: %d\n",
|
SDL_Log("Joystick %d axis %d value: %d\n",
|
||||||
event.jaxis.which,
|
event.jaxis.which,
|
||||||
event.jaxis.axis, event.jaxis.value);
|
event.jaxis.axis, event.jaxis.value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_JOYBUTTONDOWN:
|
case SDL_JOYBUTTONDOWN:
|
||||||
printf("Joystick %d button %d down\n",
|
SDL_Log("Joystick %d button %d down\n",
|
||||||
event.jbutton.which, event.jbutton.button);
|
event.jbutton.which, event.jbutton.button);
|
||||||
|
// seek for joystick #0 down (A)
|
||||||
|
// https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L52
|
||||||
|
if (event.jbutton.which == 0 && event.jbutton.button == 0) {
|
||||||
|
change_mode(window);
|
||||||
|
print_info(window, renderer);
|
||||||
|
}
|
||||||
// seek for joystick #0 down (B)
|
// seek for joystick #0 down (B)
|
||||||
// https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L51
|
|
||||||
if (event.jbutton.which == 0 && event.jbutton.button == 1) {
|
if (event.jbutton.which == 0 && event.jbutton.button == 1) {
|
||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
|
@ -92,35 +155,68 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++) {
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
// Fill renderer bounds
|
||||||
SDL_RenderClear(renderer);
|
SDL_SetRenderDrawColor(renderer, 111, 111, 111, 255);
|
||||||
|
SDL_GetRendererOutputSize(renderer, &w, &h);
|
||||||
|
SDL_Rect f = {0, 0, w, h};
|
||||||
|
SDL_RenderFillRect(renderer, &f);
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
|
draw_rects(renderer, x, 0);
|
||||||
SDL_Rect bg = {0, 0, window->w, window->h};
|
draw_rects(renderer, x, h - 64);
|
||||||
SDL_RenderFillRect(renderer, &bg);
|
|
||||||
|
|
||||||
// R
|
|
||||||
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
|
|
||||||
SDL_Rect r = {0, 0, 64, 64};
|
|
||||||
SDL_RenderFillRect(renderer, &r);
|
|
||||||
|
|
||||||
// G
|
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
|
|
||||||
SDL_Rect g = {64, 0, 64, 64};
|
|
||||||
SDL_RenderFillRect(renderer, &g);
|
|
||||||
|
|
||||||
// B
|
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
|
|
||||||
SDL_Rect b = {128, 0, 64, 64};
|
|
||||||
SDL_RenderFillRect(renderer, &b);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
|
|
||||||
|
x++;
|
||||||
|
if (x > w - 192) {
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_DestroyRenderer(renderer);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// nxlink support
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static int s_nxlinkSock = -1;
|
||||||
|
|
||||||
|
static void initNxLink()
|
||||||
|
{
|
||||||
|
if (R_FAILED(socketInitializeDefault()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
s_nxlinkSock = nxlinkStdio();
|
||||||
|
if (s_nxlinkSock >= 0)
|
||||||
|
printf("printf output now goes to nxlink server\n");
|
||||||
|
else
|
||||||
|
socketExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deinitNxLink()
|
||||||
|
{
|
||||||
|
if (s_nxlinkSock >= 0) {
|
||||||
|
close(s_nxlinkSock);
|
||||||
|
socketExit();
|
||||||
|
s_nxlinkSock = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void userAppInit()
|
||||||
|
{
|
||||||
|
initNxLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
void userAppExit()
|
||||||
|
{
|
||||||
|
deinitNxLink();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue