diff --git a/include/SDL2/SDL_config.h b/include/SDL2/SDL_config.h new file mode 100644 index 0000000..9ac7118 --- /dev/null +++ b/include/SDL2/SDL_config.h @@ -0,0 +1,20 @@ +/* + * \brief SDL config header + * \author Josef Soentgen + * \date 2016-01-05 + */ + +/* + * Copyright (C) 2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _SDL_config_h +#define _SDL_config_h + +#include +#include + +#endif /* _SDL_config_h */ diff --git a/include/SDL2/SDL_config_genode.h b/include/SDL2/SDL_config_genode.h new file mode 100644 index 0000000..9548953 --- /dev/null +++ b/include/SDL2/SDL_config_genode.h @@ -0,0 +1,139 @@ +/* + * \brief SDL config Genode header + * \author Josef Soentgen + * \date 2016-01-05 + */ + +/* + * Copyright (C) 2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _SDL_config_genode_h +#define _SDL_config_genode_h + +#ifdef __LP64__ +#define SIZEOF_VOIDP 8 +#else +#define SIZEOF_VOIDP 4 +#endif +#define HAVE_GCC_ATOMICS 1 + +#define HAVE_SYS_TYPES_H 1 +#define HAVE_STDIO_H 1 +#define STDC_HEADERS 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STDARG_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_CTYPE_H 1 +#define HAVE_MATH_H 1 +// #define HAVE_ICONV_H 1 +// #define HAVE_SIGNAL_H 1 + +#define HAVE_MALLOC 1 +#define HAVE_CALLOC 1 +#define HAVE_REALLOC 1 +#define HAVE_FREE 1 +#define HAVE_ALLOCA 1 +// #define HAVE_GETENV 1 +// #define HAVE_SETENV 1 +// #define HAVE_PUTENV 1 +// #define HAVE_UNSETENV 1 +// #define HAVE_QSORT 1 +#define HAVE_ABS 1 +#define HAVE_BCOPY 1 +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCMP 1 +#define HAVE_STRLEN 1 +#define HAVE_STRLCPY 1 +#define HAVE_STRLCAT 1 +#define HAVE_STRDUP 1 +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRTOULL 1 +#define HAVE_STRTOD 1 +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +#define HAVE_STRCASECMP 1 +#define HAVE_STRNCASECMP 1 +#define HAVE_VSSCANF 1 +#define HAVE_VSNPRINTF 1 +#define HAVE_M_PI /**/ +#define HAVE_ATAN 1 +#define HAVE_ATAN2 1 +#define HAVE_ACOS 1 +#define HAVE_ASIN 1 +#define HAVE_CEIL 1 +#define HAVE_COPYSIGN 1 +#define HAVE_COS 1 +#define HAVE_COSF 1 +#define HAVE_FABS 1 +#define HAVE_FLOOR 1 +#define HAVE_LOG 1 +#define HAVE_POW 1 +#define HAVE_SCALBN 1 +#define HAVE_SIN 1 +#define HAVE_SINF 1 +#define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#define HAVE_FSEEKO 1 +// #define HAVE_FSEEKO64 1 +// #define HAVE_SIGACTION 1 +// #define HAVE_SA_SIGACTION 1 +// #define HAVE_SETJMP 1 +#define HAVE_NANOSLEEP 1 +#define HAVE_SYSCONF 1 +#define HAVE_CLOCK_GETTIME 1 +#define HAVE_MPROTECT 1 +#define HAVE_ICONV 1 +/* #undef HAVE_PTHREAD_SET_NAME_NP */ +#define HAVE_SEM_TIMEDWAIT 1 + +/* #undef SDL_ATOMIC_DISABLED */ +/* #undef SDL_AUDIO_DISABLED */ +/* #undef SDL_CPUINFO_DISABLED */ +/* #undef SDL_EVENTS_DISABLED */ +/* #undef SDL_FILE_DISABLED */ +#define SDL_JOYSTICK_DISABLED 1 +/* #undef SDL_HAPTIC_DISABLED */ +/* #undef SDL_LOADSO_DISABLED */ +/* #undef SDL_RENDER_DISABLED */ +/* #undef SDL_THREADS_DISABLED */ +/* #undef SDL_TIMERS_DISABLED */ +/* #undef SDL_VIDEO_DISABLED */ +#define SDL_POWER_DISABLED 1 +/* #undef SDL_FILESYSTEM_DISABLED */ + +#define SDL_AUDIO_DRIVER_GENODE 1 + +#define SDL_INPUT_GENODE 1 + +#define SDL_LOADSO_DLOPEN 1 + +#define SDL_THREAD_PTHREAD 1 + +#define SDL_TIMER_UNIX 1 + +#define SDL_VIDEO_DRIVER_GENODE 1 + +#define SDL_FILESYSTEM_UNIX 1 + +// #define SDL_ASSEMBLY_ROUTINES 1 + +#endif /* _SDL_config_genode_h */ diff --git a/lib/import/import-sdl2.mk b/lib/import/import-sdl2.mk new file mode 100644 index 0000000..46db469 --- /dev/null +++ b/lib/import/import-sdl2.mk @@ -0,0 +1,4 @@ +SDL2_PORT_DIR := $(call select_from_ports,sdl2) + +INC_DIR += $(SDL2_PORT_DIR)/include $(SDL2_PORT_DIR)/include/SDL2 +REP_INC_DIR += include/SDL2 diff --git a/lib/mk/sdl2.mk b/lib/mk/sdl2.mk new file mode 100644 index 0000000..634882b --- /dev/null +++ b/lib/mk/sdl2.mk @@ -0,0 +1,114 @@ +SDL2_PORT_DIR := $(call select_from_ports,sdl2) +SDL2_DIR := $(SDL2_PORT_DIR)/src/lib/sdl2 + +# build shared object +SHARED_LIB = yes + +CC_OPT += -DGENODE + +CC_WARN += -Wno-unused-variable + +# because of AARCH_64 : /gcc/aarch64-none-elf/8.3.0/include/arm_neon.h: narrowing conversion +CC_WARN += -Wno-narrowing + +INC_DIR += $(SDL2_PORT_DIR)/include +INC_DIR += $(SDL2_PORT_DIR)/include/SDL2 + +# +# In case we use the depot add the location +# to the global include path. +# +ifeq ($(CONTRIB),) +REP_INC_DIR += include/SDL2 +endif + +# backends +SRC_CC = audio/SDL_genodeaudio.cc \ + video/SDL_genode_fb_video.cc \ + video/SDL_genode_fb_events.cc \ + loadso/SDL_loadso.cc + +INC_DIR += $(REP_DIR)/include/SDL2 \ + $(REP_DIR)/src/lib/sdl2 \ + $(REP_DIR)/src/lib/sdl2/thread \ + $(REP_DIR)/src/lib/sdl2/video + +# main files +SRC_C = SDL.c \ + SDL_assert.c \ + SDL_error.c \ + SDL_hints.c \ + SDL_log.c +INC_DIR += $(SDL2_DIR)/src + +# atomic subsystem +SRC_C += $(addprefix atomic/,$(notdir $(wildcard $(SDL2_DIR)/src/atomic/*.c))) + +# audio subsystem +SRC_C += $(addprefix audio/,$(notdir $(wildcard $(SDL2_DIR)/src/audio/*.c))) +INC_DIR += $(SDL2_DIR)/src/audio + +# sensor subsystem +SRC_C += $(addprefix sensor/,$(notdir $(wildcard $(SDL2_DIR)/src/sensor/*.c))) + +# cpuinfo subsystem +SRC_C += cpuinfo/SDL_cpuinfo.c + +# event subsystem +SRC_C += $(addprefix events/,$(notdir $(wildcard $(SDL2_DIR)/src/events/*.c))) +INC_DIR += $(SDL2_DIR)/src/events + +# file I/O subsystem +SRC_C += file/SDL_rwops.c + +# filesystem subsystem +SRC_C += filesystem/unix/SDL_sysfilesystem.c + +# haptic subsystem +SRC_C += haptic/SDL_haptic.c \ + haptic/dummy/SDL_syshaptic.c +INC_DIR += $(SDL2_DIR)/src/haptic + +# joystick subsystem +SRC_C += joystick/SDL_joystick.c \ + joystick/SDL_gamecontroller.c \ + joystick/dummy/SDL_sysjoystick.c +INC_DIR += $(SDL2_DIR)/src/joystick + +# render subsystem +SRC_C += $(addprefix render/,$(notdir $(wildcard $(SDL2_DIR)/src/render/*.c))) +SRC_C += $(addprefix render/software/,$(notdir $(wildcard $(SDL2_DIR)/src/render/software/*.c))) +INC_DIR += $(SDL2_DIR)/src/render $(SDL2_DIR)/src/render/software + +# stdlib files +SRC_C += stdlib/SDL_getenv.c \ + stdlib/SDL_malloc.c \ + stdlib/SDL_qsort.c \ + stdlib/SDL_stdlib.c \ + stdlib/SDL_string.c + +# thread subsystem +SRC_C += thread/SDL_thread.c \ + thread/generic/SDL_syscond.c \ + thread/generic/SDL_sysmutex.c \ + thread/generic/SDL_systls.c \ + thread/pthread/SDL_syssem.c \ + thread/pthread/SDL_systhread.c + +# timer subsystem +SRC_C += timer/unix/SDL_systimer.c + +# video subsystem +SRC_C += $(addprefix video/,$(notdir $(wildcard $(SDL2_DIR)/src/video/*.c))) +INC_DIR += $(SDL2_DIR)/src/video +SRC_C += $(addprefix video/yuv2rgb/,$(notdir $(wildcard $(SDL2_DIR)/src/video/yuv2rgb/*.c))) + +SRC_CC += sdl_main.cc + +# we need libc +LIBS = libc + +# backend path +vpath % $(REP_DIR)/src/lib/sdl2 + +vpath % $(SDL2_DIR)/src diff --git a/lib/symbols/sdl2 b/lib/symbols/sdl2 new file mode 100644 index 0000000..1aa8224 --- /dev/null +++ b/lib/symbols/sdl2 @@ -0,0 +1,86 @@ +SDL_AssertionsQuit T +SDL_CondSignal T +SDL_CondWait T +SDL_CondWaitTimeout T +SDL_CreateCond T +SDL_CreateMutex T +SDL_CreateRGBSurfaceFrom T +SDL_CreateRenderer T +SDL_CreateTexture T +SDL_CreateThread T +SDL_CreateWindow T +SDL_Delay T +SDL_DestroyCond T +SDL_DestroyMutex T +SDL_DestroyRenderer T +SDL_DestroyTexture T +SDL_DestroyWindow T +SDL_EnableScreenSaver T +SDL_FillRect T +SDL_FreeSurface T +SDL_GL_BindTexture T +SDL_GL_GetProcAddress T +SDL_GL_UnbindTexture T +SDL_GetClipboardText T +SDL_GetDisplayUsableBounds T +SDL_GetErrBuf T +SDL_GetError T +SDL_GetKeyName T +SDL_GetMouseState T +SDL_GetRendererInfo T +SDL_GetTicks T +SDL_GetWindowSize T +SDL_GetWindowSurface T +SDL_Init T +SDL_LockMutex T +SDL_LogCritical T +SDL_LogDebug T +SDL_LogError T +SDL_LogInfo T +SDL_LogMessageV T +SDL_LogWarn T +SDL_MapRGB T +SDL_PollEvent T +SDL_PushEvent T +SDL_Quit T +SDL_RenderClear T +SDL_RenderCopy T +SDL_RenderCopyEx T +SDL_RenderGetScale T +SDL_RenderGetViewport T +SDL_RenderPresent T +SDL_RenderSetLogicalSize T +SDL_RestoreWindow T +SDL_SetClipboardText T +SDL_SetHint T +SDL_SetWindowFullscreen T +SDL_SetWindowIcon T +SDL_SetWindowSize T +SDL_ShowWindow T +SDL_UnlockMutex T +SDL_UpdateWindowSurface T +SDL_UpdateYUVTexture T +SDL_WaitEvent T +SDL_WaitThread T +SDL_free T +SDL_malloc T +SDL_strdup T +_ZN4Libc9Component9constructERNS_3EnvE T +SDL_HasNEON T +SDL_Has3DNow T +SDL_SIMDGetAlignment T +SDL_GetSystemRAM T +SDL_HasARMSIMD T +SDL_HasRDTSC T +SDL_HasAltiVec T +SDL_GetCPUCacheLineSize T +SDL_GetCPUCount T +SDL_HasMMX T +SDL_HasSSE T +SDL_HasSSE2 T +SDL_HasSSE3 T +SDL_HasSSE41 T +SDL_HasSSE42 T +SDL_HasAVX T +SDL_HasAVX2 T +SDL_HasAVX512F T diff --git a/ports/sdl2.hash b/ports/sdl2.hash new file mode 100644 index 0000000..433ad4f --- /dev/null +++ b/ports/sdl2.hash @@ -0,0 +1 @@ +7a460a4a9dc514c19cfe330420f7b3ca674ce554 diff --git a/ports/sdl2.port b/ports/sdl2.port new file mode 100644 index 0000000..4f85625 --- /dev/null +++ b/ports/sdl2.port @@ -0,0 +1,20 @@ +LICENSE := zlib +VERSION := 2.0.12 +DOWNLOADS := sdl2.archive + +URL(sdl2) := http://www.libsdl.org/release/SDL2-$(VERSION).tar.gz +SHA(sdl2) := 349268f695c02efbc9b9148a70b85e58cefbbf704abd3e91be654db7f1e2c863 +SIG(sdl2) := ${URL(sdl2)}.sig +KEY(sdl2) := 1528635D8053A57F77D1E08630A59377A7763BE6 +DIR(sdl2) := src/lib/sdl2 + +PATCHES := src/lib/sdl2/backends.patch +PATCH_OPT := -p1 -d src/lib/sdl2 + +# wipe original 'SDL_config.h' file because it conflicts with our version +_dirs: remove_default_config +remove_default_config: $(DOWNLOADS) + $(VERBOSE)rm src/lib/sdl2/include/SDL_config*.h + +DIRS := include/SDL2 +DIR_CONTENT(include/SDL2) := src/lib/sdl2/include/*.h diff --git a/run/sdl2.run b/run/sdl2.run new file mode 100644 index 0000000..8ead339 --- /dev/null +++ b/run/sdl2.run @@ -0,0 +1,17 @@ +set build_components { test/sdl2 } + +set app_config { + + + + + + + } + +set boot_modules { + test-sdl2 + libc.lib.so vfs.lib.so sdl2.lib.so +} + +source ${genode_dir}/repos/world/run/nitpicker_app.inc diff --git a/src/lib/sdl2/SDL_genode_internal.h b/src/lib/sdl2/SDL_genode_internal.h new file mode 100644 index 0000000..bec66bb --- /dev/null +++ b/src/lib/sdl2/SDL_genode_internal.h @@ -0,0 +1,24 @@ +/* + * \brief Genode-specific data structures + * \author Josef Soentgen + * \date 2017-11-21 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SDL_GENODE_INTERNAL_H_ +#define _SDL_GENODE_INTERNAL_H_ + +struct Video +{ + bool resize_pending; + int width; + int height; +}; + +#endif /* _SDL_GENODE_INTERNAL_H_ */ diff --git a/src/lib/sdl2/audio/SDL_genodeaudio.cc b/src/lib/sdl2/audio/SDL_genodeaudio.cc new file mode 100644 index 0000000..edb5d9f --- /dev/null +++ b/src/lib/sdl2/audio/SDL_genodeaudio.cc @@ -0,0 +1,32 @@ +/* + * \brief Genode-specific audio backend + * \author Alexander Boettcher + * \date 2020-05-20 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +extern "C" { + +#include "SDL_internal.h" +#include "SDL_audio.h" +#include "SDL_audio_c.h" +#include "SDL_audiodev_c.h" + +static int GenodeAudio_Init(SDL_AudioDriverImpl *) +{ + printf("Audio not supported\n"); + return 0; +} + +AudioBootStrap GenodeAudio_bootstrap = { + "genode", "Genode audio driver", GenodeAudio_Init, 0 +}; + +} /* extern "C" */ + diff --git a/src/lib/sdl2/backends.patch b/src/lib/sdl2/backends.patch new file mode 100644 index 0000000..ef7875e --- /dev/null +++ b/src/lib/sdl2/backends.patch @@ -0,0 +1,68 @@ +--- a/src/audio/SDL_sysaudio.h ++++ b/src/audio/SDL_sysaudio.h +@@ -207,6 +207,7 @@ + extern AudioBootStrap ANDROIDAUDIO_bootstrap; + extern AudioBootStrap PSPAUDIO_bootstrap; + extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap; ++extern AudioBootStrap GenodeAudio_bootstrap; + + #endif /* SDL_sysaudio_h_ */ + +--- a/src/audio/SDL_audio.c ++++ b/src/audio/SDL_audio.c +@@ -143,6 +144,9 @@ static const AudioBootStrap *const bootstrap[] = { + #if SDL_AUDIO_DRIVER_EMSCRIPTEN + &EmscriptenAudio_bootstrap, + #endif ++#if SDL_AUDIO_DRIVER_GENODE ++ &GenodeAudio_bootstrap, ++#endif + NULL + }; + +--- a/src/video/SDL_sysvideo.h ++++ b/src/video/SDL_sysvideo.h +@@ -430,6 +430,7 @@ + extern VideoBootStrap Emscripten_bootstrap; + extern VideoBootStrap QNX_bootstrap; + extern VideoBootStrap OFFSCREEN_bootstrap; ++extern VideoBootStrap GenodeVideo_bootstrap; + + extern SDL_VideoDevice *SDL_GetVideoDevice(void); + extern int SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode); +--- a/src/video/SDL_video.c ++++ b/src/video/SDL_video.c +@@ -108,6 +108,9 @@ static VideoBootStrap *bootstrap[] = { + #if SDL_VIDEO_DRIVER_DUMMY + &DUMMY_bootstrap, + #endif ++#if SDL_VIDEO_DRIVER_GENODE ++ &GenodeVideo_bootstrap, ++#endif + NULL + }; + +--- a/src/dynapi/SDL_dynapi.h ++++ b/src/dynapi/SDL_dynapi.h +@@ -49,6 +49,8 @@ + #define SDL_DYNAMIC_API 0 + #elif defined(__clang_analyzer__) + #define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */ ++#elif defined(GENODE) ++#define SDL_DYNAMIC_API 0 + #endif + + /* everyone else. This is where we turn on the API if nothing forced it off. */ +--- a/src/audio/SDL_wave.c ++++ b/src/audio/SDL_wave.c +@@ -23,8 +23,10 @@ + #ifdef HAVE_LIMITS_H + #include + #else ++#ifndef SDL_VIDEO_DRIVER_GENODE + #ifndef SIZE_MAX + #define SIZE_MAX ((size_t)-1) ++#endif /* SDL_VIDEO_DRIVER_GENODE */ + #endif + #ifndef INT_MAX + /* Make a lucky guess. */ diff --git a/src/lib/sdl2/loadso/SDL_loadso.cc b/src/lib/sdl2/loadso/SDL_loadso.cc new file mode 100644 index 0000000..78371da --- /dev/null +++ b/src/lib/sdl2/loadso/SDL_loadso.cc @@ -0,0 +1,38 @@ +/* + * \brief Genode-specific shared-object backend + * \author Norman Feske + * \date 2013-03-29 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +extern "C" { + +#include + +#include "SDL_config.h" +#include "SDL_loadso.h" + +void *SDL_LoadObject(const char *sofile) +{ + return dlopen(sofile, 0); +} + + +void *SDL_LoadFunction(void *handle, const char *name) +{ + return dlsym(handle, name); +} + + +void SDL_UnloadObject(void* handle) +{ + dlclose(handle); +} + +} diff --git a/src/lib/sdl2/sdl_main.cc b/src/lib/sdl2/sdl_main.cc new file mode 100644 index 0000000..24e1e6f --- /dev/null +++ b/src/lib/sdl2/sdl_main.cc @@ -0,0 +1,137 @@ +/* + * \brief Entry point for SDL applications with a main() function + * \author Josef Soentgen + * \date 2017-11-21 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include +#include + +/* libc includes */ +#include /* 'malloc' and 'exit' */ +#include + +extern char **genode_argv; +extern int genode_argc; +extern char **genode_envp; + +/* initial environment for the FreeBSD libc implementation */ +extern char **environ; + +/* provided by the application */ +extern "C" int main(int argc, char *argv[], char *envp[]); + + +/* provided by our SDL backend */ +extern void sdl_init_genode(Genode::Env &env); + + + +static void* sdl_main(void *) +{ + exit(main(genode_argc, genode_argv, genode_envp)); + return nullptr; +} + + +void Libc::Component::construct(Libc::Env &env) +{ + using Genode::Xml_node; + using Genode::Xml_attribute; + + env.config([&] (Xml_node const &node) { + int argc = 0; + int envc = 0; + char **argv; + char **envp; + + /* count the number of arguments and environment variables */ + node.for_each_sub_node([&] (Xml_node const &node) { + /* check if the 'value' attribute exists */ + if (node.has_type("arg") && node.has_attribute("value")) + ++argc; + else + if (node.has_type("env") && node.has_attribute("key") && node.has_attribute("value")) + ++envc; + }); + + if (argc == 0 && envc == 0) + return; /* from lambda */ + + /* arguments and environment are a contiguous array (but don't count on it) */ + argv = (char**)malloc((argc + envc + 1) * sizeof(char*)); + envp = &argv[argc]; + + /* read the arguments */ + int arg_i = 0; + int env_i = 0; + node.for_each_sub_node([&] (Xml_node const &node) { + /* insert an argument */ + if (node.has_type("arg")) try { + Xml_attribute attr = node.attribute("value"); + + Genode::size_t const arg_len = attr.value_size()+1; + char *arg = argv[arg_i] = (char*)malloc(arg_len); + + attr.with_raw_value([&] (char const *start, size_t length) { + Genode::copy_cstring(arg, start, Genode::min(arg_len, length + 1)); }); + + ++arg_i; + + } catch (Xml_node::Nonexistent_sub_node) { } + + else + + /* insert an environment variable */ + if (node.has_type("env")) try { + Xml_attribute key_attr = node.attribute("key"); + Xml_attribute val_attr = node.attribute("value"); + + Genode::size_t const pair_len = + key_attr.value_size() + + val_attr.value_size() + 1; + char *env = envp[env_i] = (char*)malloc(pair_len); + + Genode::size_t off = 0; + key_attr.with_raw_value([&] (char const *start, size_t length) { + Genode::copy_cstring(&env[off], start, Genode::min(key_attr.value_size()+1, length + 1)); }); + + off = key_attr.value_size(); + env[off++] = '='; + val_attr.with_raw_value([&] (char const *start, size_t length) { + Genode::copy_cstring(&env[off], start, Genode::min(val_attr.value_size()+1, length + 1)); }); + ++env_i; + + } catch (Xml_node::Nonexistent_sub_node) { } + }); + + envp[env_i] = NULL; + + /* register command-line arguments at Genode's startup code */ + genode_argc = argc; + genode_argv = argv; + genode_envp = environ = envp; + }); + + /* pass env to SDL backend */ + sdl_init_genode(env); + + pthread_attr_t attr; + pthread_t main_thread; + + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 768 * 1024); + + if (pthread_create(&main_thread, &attr, sdl_main, nullptr)) { + Genode::error("failed to create SDL main thread"); + exit(1); + } +} diff --git a/src/lib/sdl2/video/SDL_genode_fb_events.cc b/src/lib/sdl2/video/SDL_genode_fb_events.cc new file mode 100644 index 0000000..83ef774 --- /dev/null +++ b/src/lib/sdl2/video/SDL_genode_fb_events.cc @@ -0,0 +1,376 @@ +/* + * \brief Genode-specific event backend + * \author Stefan Kalkowski + * \date 2008-12-12 + */ + +/* + * Copyright (c) <2008> Stefan Kalkowski + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include + +/* local includes */ +#include + + +Genode::Lock event_lock; +Video video_events; + + +static Genode::Env *_global_env = nullptr; + +static Genode::Constructible _global_nitpicker { }; + + +Genode::Env &global_env() +{ + if (!_global_env) { + Genode::error("sdl_init_genode() not called, aborting"); + throw Genode::Exception(); + } + + return *_global_env; +} + + +Nitpicker::Connection &global_nitpicker() +{ + if (!_global_nitpicker.constructed()) + _global_nitpicker.construct(global_env()); + + return *_global_nitpicker; +} + + +void sdl_init_genode(Genode::Env &env) +{ + _global_env = &env; +} + + +extern "C" { + +#include +#include "SDL_events_c.h" +#include "SDL_sysevents.h" +#include "SDL_genode_fb_events.h" + + + static Genode::Constructible input; + static SDL_Scancode scancodes[SDL_NUM_SCANCODES]; +// static SDL_Keycode keymap[SDL_NUM_SCANCODES]; + static int buttonmap[SDL_NUM_SCANCODES]; + + static SDL_Scancode getscancode(Input::Keycode const keycode) + { + if (keycode < 0 || keycode > sizeof(scancodes) / sizeof(scancodes[0])) + return SDL_SCANCODE_UNKNOWN; + return scancodes[keycode]; + } + + void Genode_Fb_PumpEvents(SDL_VideoDevice * const device) + { + SDL_Window * const window = SDL_GetMouseFocus(); + if (!window) + return; + + if (!input.constructed()) /* XXX */ { + Genode_Fb_InitOSKeymap(device); + /* there is a default map using the scancode array */ +// SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES); + } + + Genode::Lock_guard guard(event_lock); + + if (video_events.resize_pending) { + video_events.resize_pending = false; + + int const width = video_events.width; + int const height = video_events.height; + +#if 0 + bool const quit = width == 0 && height == 0; + + if (!quit) + SDL_PrivateResize(width, height); + else { + /* at least try to quit w/o other event handling */ + if (SDL_PrivateQuit()) + return; + else + Genode::warning("could not deliver requested SDL_QUIT event"); + } +#else + printf("XXX resize pending XXX\n"); +#endif + } + + if (!input->pending()) + return; + + SDL_MouseID const mouse_id = 0; + + input->for_each_event([&] (Input::Event const &curr) { + + curr.handle_absolute_motion([&] (int x, int y) { + SDL_SendMouseMotion(window, mouse_id, 0 /* !relative */, x, y); + }); + + curr.handle_relative_motion([&] (int x, int y) { + SDL_SendMouseMotion(window, mouse_id, 1 /* relative */, x, y); + }); + + /* return true if keycode refers to a button */ + auto const mouse_button = [] (Input::Keycode key) { + return key >= Input::BTN_MISC && key <= Input::BTN_GEAR_UP; }; + + curr.handle_press([&] (Input::Keycode key, Genode::Codepoint codepoint) { + if (mouse_button(key)) + SDL_SendMouseButton(window, mouse_id, SDL_PRESSED, buttonmap[key]); + else + SDL_SendKeyboardKey(SDL_PRESSED, getscancode(key)); + }); + + curr.handle_release([&] (Input::Keycode key) { + if (mouse_button(key)) + SDL_SendMouseButton(window, mouse_id, SDL_RELEASED, buttonmap[key]); + else + SDL_SendKeyboardKey(SDL_RELEASED, getscancode(key)); + }); + }); + } + + + void Genode_Fb_InitOSKeymap(SDL_VideoDevice *t) + { + try { + input.construct(_global_env->rm(), + _global_nitpicker->input_session()); + } catch (...) { + Genode::error("no input driver available!"); + return; + } + + using namespace Input; + + /* Prepare button mappings */ + for (int i=0; i Stefan Kalkowski + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef _SDL_genode_fb_events_h +#define _SDL_genode_fb_events_h + +extern void Genode_Fb_InitOSKeymap(SDL_VideoDevice *t); +extern void Genode_Fb_PumpEvents(SDL_VideoDevice *t); + +#endif // _SDL_genode_fb_events_h diff --git a/src/lib/sdl2/video/SDL_genode_fb_video.cc b/src/lib/sdl2/video/SDL_genode_fb_video.cc new file mode 100644 index 0000000..a72412c --- /dev/null +++ b/src/lib/sdl2/video/SDL_genode_fb_video.cc @@ -0,0 +1,380 @@ +/* + * \brief Genode-specific video backend + * \author Stefan Kalkowski + * \date 2008-12-12 + */ + +/* + * Copyright (c) <2008> Stefan Kalkowski + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* Genode includes */ +#include +#include +#include +#include + +/* local includes */ +#include + + +extern Genode::Env &global_env(); +extern Nitpicker::Connection &global_nitpicker(); + +extern Genode::Lock event_lock; +extern Video video_events; + + +extern "C" { + +#include "../../SDL_internal.h" + +#include + +#include +#include +#include +#include +#include "SDL_sysvideo.h" +#include "SDL_pixels_c.h" +#include "SDL_events_c.h" +#include "SDL_genode_fb_events.h" + + struct Sdl_framebuffer + { + Genode::Env &_env; + Nitpicker::Connection &_nitpicker; + Nitpicker::Session::View_handle _view { + _nitpicker.create_view() }; + + void _handle_mode_change() + { + Genode::Lock_guard guard(event_lock); + + Framebuffer::Mode mode = _nitpicker.mode(); + + video_events.resize_pending = true; + video_events.width = mode.width(); + video_events.height = mode.height(); + } + + Genode::Signal_handler _mode_handler { + _env.ep(), *this, &Sdl_framebuffer::_handle_mode_change }; + + Sdl_framebuffer(Genode::Env &env, Nitpicker::Connection &nitpicker) + : + _env(env), _nitpicker(nitpicker) + { + _nitpicker.mode_sigh(_mode_handler); + + using namespace Nitpicker; + _nitpicker.enqueue(_view, Session::View_handle()); + _nitpicker.execute(); + } + + ~Sdl_framebuffer() + { + /* clean up and reduce noise about invalid signals */ + _nitpicker.mode_sigh(Genode::Signal_context_capability()); + dataspace(0, 0); + _nitpicker.destroy_view(_view); + } + + /************************************ + ** Framebuffer::Session Interface ** + ************************************/ + + Genode::Dataspace_capability dataspace(int width, int height) + { + _nitpicker.buffer( + ::Framebuffer::Mode(width, height, Framebuffer::Mode::RGB565), + false); + + ::Framebuffer::Mode mode = _nitpicker.framebuffer()->mode(); + + using namespace Nitpicker; + Area area( + Genode::min(mode.width(), width), + Genode::min(mode.height(), height)); + + typedef Nitpicker::Session::Command Command; + _nitpicker.enqueue( + _view, Rect(Point(0, 0), area)); + _nitpicker.execute(); + + return _nitpicker.framebuffer()->dataspace(); + } + + Framebuffer::Mode mode() const { + return _nitpicker.mode(); } + + void refresh(int x, int y, int w, int h) { + _nitpicker.framebuffer()->refresh(x, y, w, h); } + + void title(char const *string) + { + _nitpicker.enqueue(_view, string); + _nitpicker.execute(); + } + }; + + static char const * const surface_name = "genode_surface"; + + struct Genode_Driverdata + { + Genode::Constructible framebuffer; + Genode::Constructible fb_mem; + Genode::Constructible fb_double; + Framebuffer::Mode scr_mode; + }; + + /**************************************** + * Genode_Fb driver bootstrap functions * + ****************************************/ + + static int GenodeVideo_Available(void) + { + return 1; + } + + + static void GenodeVideo_DeleteDevice(SDL_VideoDevice * const device) + { + if (!device || !device->driverdata) + return; + + Genode_Driverdata &drv = *(Genode_Driverdata *)device->driverdata; + + if (drv.framebuffer.constructed()) + drv.framebuffer.destruct(); + } + + static int Genode_Fb_CreateWindowFramebuffer(SDL_VideoDevice * const device, + SDL_Window * const window, + Uint32 * format, + void ** pixels, + int *pitch) + { + if (!device || !window || !format || !pixels || !pitch || !device->driverdata) + return SDL_SetError("invalid pointer"); + + Genode_Driverdata &drv = *(Genode_Driverdata *)device->driverdata; + + Uint32 const surface_format = SDL_PIXELFORMAT_RGB565; + + /* Free the old surface */ + SDL_Surface *surface = (SDL_Surface *)SDL_GetWindowData(window, + surface_name); + if (surface) { + SDL_SetWindowData(window, surface_name, NULL); + SDL_FreeSurface(surface); + surface = NULL; + } + + /* get 16bit RGB mask values */ + int bpp; + Uint32 r_mask, g_mask, b_mask, a_mask; + if (!SDL_PixelFormatEnumToMasks(surface_format, &bpp, &r_mask, &g_mask, + &b_mask, &a_mask)) + return SDL_SetError("pixel format setting failed"); + + /* get dimensions */ + int w, h; + SDL_GetWindowSize(window, &w, &h); + + /* allocate and attach memory for framebuffer */ + if (drv.fb_mem.constructed()) + drv.fb_mem.destruct(); + + drv.fb_mem.construct(global_env().rm(), + drv.framebuffer->dataspace(w, h)); + + bool use_double = true; + if (use_double) + drv.fb_double.construct(global_env().ram(), + global_env().rm(), + w * h * bpp / 8); + + void * const fb_mem = drv.fb_double.constructed() + ? drv.fb_double->local_addr() + : drv.fb_mem->local_addr(); + + surface = SDL_CreateRGBSurfaceFrom(fb_mem, w, h, bpp, + w * bpp / 8 /* pitch */, + r_mask, g_mask, b_mask, a_mask); + if (!surface) + return SDL_SetError("setting surface failed"); + + /* set name and user data */ + SDL_SetWindowData(window, surface_name, surface); + + *format = surface_format; + *pixels = surface->pixels; + *pitch = surface->pitch; + + /* set focus to window */ + SDL_SetMouseFocus(window); + + return 0; + } + + static int Genode_Fb_UpdateWindowFramebuffer(SDL_VideoDevice * const device, + SDL_Window * const window, + SDL_Rect const * const rects, + int const num_rects) + { + if (!device || !device->driverdata) + return SDL_SetError("invalid pointer");; + + Genode_Driverdata &drv = *(Genode_Driverdata *)device->driverdata; + + SDL_Surface *surface = (SDL_Surface *) SDL_GetWindowData(window, + surface_name); + if (!surface) + return SDL_SetError("Could not get surface for window"); + + for(int i = 0; i < num_rects; i++) { + + if (drv.fb_double.constructed()) { + memcpy(drv.fb_mem->local_addr(), + drv.fb_double->local_addr(), + drv.fb_double->size()); + } + + drv.framebuffer->refresh(rects[i].x, rects[i].y, + rects[i].w, rects[i].h); + } + + return 0; + } + + static void Genode_Fb_DestroyWindowFramebuffer(SDL_VideoDevice * const, + SDL_Window * const window) + { + SDL_Surface *surface = (SDL_Surface *)SDL_SetWindowData(window, + surface_name, + NULL); + if (surface) + SDL_FreeSurface(surface); + } + + static void GenodeVideo_Quit(SDL_VideoDevice * const) + { + /* revert device->displays structures ? */ + } + + static int GenodeVideo_Init(SDL_VideoDevice * const device) + { + if (!device || !device->driverdata) + return SDL_SetError("invalid pointer");; + + Genode_Driverdata &drv = *(Genode_Driverdata *)device->driverdata; + + if (!drv.framebuffer.constructed()) { + Genode::error("framebuffer not initialized"); + return -1; + } + + /* Get the framebuffer size and mode infos */ + drv.scr_mode = drv.framebuffer->mode(); + + /* set mode specific values */ + switch(drv.scr_mode.format()) { + case Framebuffer::Mode::RGB565: + { + Genode::log("We use pixelformat rgb565."); + + device->displays = (SDL_VideoDisplay *)(SDL_calloc(1, sizeof(*device->displays))); + if (!device->displays) + return SDL_SetError("Memory allocation failed"); + + SDL_DisplayMode mode { + .format = SDL_PIXELFORMAT_RGB565, + .w = drv.scr_mode.width(), + .h = drv.scr_mode.height(), + .refresh_rate = 0, + .driverdata = nullptr + }; + + SDL_VideoDisplay &display = device->displays[0]; + if (!SDL_AddDisplayMode(&display, &mode)) + return SDL_SetError("Setting display mode failed"); + + display.current_mode = mode; + device->num_displays = 1; + + break; + } + default: + SDL_SetError("Couldn't get console mode info"); + GenodeVideo_Quit(device); + return -1; + } + + return 0; + } + + static SDL_VideoDevice *GenodeVideo_CreateDevice(int const devindex) + { + SDL_VideoDevice *device; + Genode_Driverdata *data; + + device = (SDL_VideoDevice*) SDL_calloc(1, sizeof(SDL_VideoDevice)); + if (!device) { + SDL_OutOfMemory(); + return nullptr; + } + + data = (Genode_Driverdata*) SDL_calloc(1, sizeof(Genode_Driverdata)); + if (!data) { + SDL_free(device); + SDL_OutOfMemory(); + return nullptr; + } + + data->framebuffer.construct(global_env(), global_nitpicker()); + + device->driverdata = data; + + /* video */ + device->VideoInit = GenodeVideo_Init; + device->VideoQuit = GenodeVideo_Quit; + device->free = GenodeVideo_DeleteDevice; + + /* framebuffer */ + device->CreateWindowFramebuffer = Genode_Fb_CreateWindowFramebuffer; + device->UpdateWindowFramebuffer = Genode_Fb_UpdateWindowFramebuffer; + device->DestroyWindowFramebuffer = Genode_Fb_DestroyWindowFramebuffer; + + device->PumpEvents = Genode_Fb_PumpEvents; + + return device; + } + + VideoBootStrap GenodeVideo_bootstrap = { + "Genode_Fb", "SDL Genode Framebuffer video driver", + GenodeVideo_Available, GenodeVideo_CreateDevice + }; + +} //extern "C" diff --git a/src/test/sdl2/main.cc b/src/test/sdl2/main.cc new file mode 100644 index 0000000..0810d62 --- /dev/null +++ b/src/test/sdl2/main.cc @@ -0,0 +1,229 @@ +/* + * \brief Simple SDL test program + * \author Stefan Kalkowski + * \date 2008-12-12 + */ + +/* + * Copyright (c) <2008> Stefan Kalkowski + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/* SDL includes */ +#include + +/* Genode includes */ +#include +#include + +static void draw(SDL_Surface * const screen, int w, int h, int v) +{ + if (screen == nullptr) { return; } + + /* paint something into pixel buffer */ + short* const pixels = (short*) screen->pixels; + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + pixels[i*w+j] = ((i+v)/32)*32*64 + ((j+v)/32)*32 + (i*j+v)/1024; + } + } +} + +static SDL_Window *create_window(int w, int h) +{ + SDL_Window *window = SDL_CreateWindow("sdl2 test window", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + w, h, + SDL_WINDOW_FULLSCREEN); + if (window == nullptr) { + printf("Error: could not create window: %s\n", SDL_GetError()); + } + + return window; +} + +#if 0 +static SDL_Surface *resize_screen(SDL_Surface * const screen, int w, int h) +{ + if (screen == nullptr) { return nullptr; } + + int oldw = screen->w; + int oldh = screen->h; + + SDL_Surface *nscreen = set_video_mode(w, h); + if (nscreen == nullptr) { + printf("Error: could not resize %dx%d -> %dx%d: %s\n", + oldw, oldh, w, h, SDL_GetError()); + return nullptr; + } + + return nscreen; +} +#endif + +static void dump_supported_features() +{ + int const cpu_count = SDL_GetCPUCount(); + int const cache_l1 = SDL_GetCPUCacheLineSize(); + + SDL_bool const has_rdtsc = SDL_HasRDTSC(); + SDL_bool const has_altivec = SDL_HasAltiVec(); + SDL_bool const has_mmx = SDL_HasMMX(); + SDL_bool const has_3dnow = SDL_Has3DNow(); + SDL_bool const has_sse = SDL_HasSSE(); + SDL_bool const has_sse2 = SDL_HasSSE2(); + SDL_bool const has_sse3 = SDL_HasSSE3(); + SDL_bool const has_sse41 = SDL_HasSSE41(); + SDL_bool const has_sse42 = SDL_HasSSE42(); + SDL_bool const has_avx = SDL_HasAVX(); + SDL_bool const has_avx2 = SDL_HasAVX2(); + SDL_bool const has_avx512f = SDL_HasAVX512F(); + SDL_bool const has_armsimd = SDL_HasARMSIMD(); + SDL_bool const has_armneon = SDL_HasNEON(); + int const system_ram = SDL_GetSystemRAM(); + size_t simd_alignment = SDL_SIMDGetAlignment(); + + Genode::log("CPU count : " , cpu_count, + ", L1 cache line size: ", cache_l1); + Genode::log("System ram: ", system_ram, + ", SIMD alignment: ", simd_alignment); + Genode::log("Features:", has_rdtsc ? " rdtsc" : "", + has_altivec ? " altivec" : "", + has_mmx ? " mmx" : "", + has_3dnow ? " 3dnow" : "", + has_sse ? " sse" : "", + has_sse2 ? " sse2" : "", + has_sse3 ? " sse3" : "", + has_sse41 ? " sse41" : "", + has_sse42 ? " sse42" : "", + has_avx ? " avx" : "", + has_avx2 ? " avx2" : "", + has_avx512f ? " avx512f" : "", + has_armsimd ? " ARM SIMD" : "", + has_armneon ? " ARM NEON" : ""); +} + + +extern "C" void wait_for_continue(); + + +int main(int, char*[] ) +{ +// wait_for_continue(); + + if (SDL_Init(SDL_INIT_VIDEO) == -1) { + printf("%u SDL error: %s\n", __LINE__, SDL_GetError()); + return 1; + } + + dump_supported_features(); + + SDL_Window * const window = create_window(0, 0); + if (!window) { + printf("%u SDL error: %s\n", __LINE__, SDL_GetError()); + return 1; + } + + SDL_Surface *surface = SDL_GetWindowSurface(window); + if (!surface) { + printf("%u SDL error: %s\n", __LINE__, SDL_GetError()); + return 1; + } + + /* test renderer setup */ + SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, + SDL_RENDERER_SOFTWARE); +// SDL_RENDERER_ACCELERATED); + if (!renderer) { + printf("%u SDL error: %s\n", __LINE__, SDL_GetError()); + return 1; + } + + SDL_RendererInfo renderer_info; + if (SDL_GetRendererInfo(renderer, &renderer_info)) { + printf("%u SDL error: %s\n", __LINE__, SDL_GetError()); + return 1; + } + + printf("renderer: %s\n", renderer_info.name); + + int content_width = 640; + int content_height = 480; + if (SDL_RenderSetLogicalSize(renderer, content_width, content_height)) { + printf("%u SDL error: %s\n", __LINE__, SDL_GetError()); + return 1; + } + + /* test some primitives */ + if (SDL_FillRect(surface, NULL, + SDL_MapRGB( surface->format, 0xFF, 0xFF, 0xFF ))) { + printf("%u SDL error: %s\n", __LINE__, SDL_GetError()); + return 1; + } + + if (SDL_UpdateWindowSurface(window)) { + printf("%u SDL error: %s\n", __LINE__, SDL_GetError()); + return 1; + } + + SDL_Delay(1000); + + unsigned loop_cnt = 0; + + bool done = false; + while (!done) { + loop_cnt ++; + + draw(surface, surface->w, surface->h, loop_cnt*10); + SDL_Delay(50); + + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_KEYDOWN: + printf("%s\n", SDL_GetKeyName(event.key.keysym.sym)); + done = true; + break; +/* + case SDL_VIDEORESIZE: + screen = resize_screen(screen, event.resize.w, event.resize.h); + if (screen == nullptr) { done = true; } + + break; +*/ + } + } + + //Update the surface + if (SDL_UpdateWindowSurface(window)) { + printf("%u SDL error: %s\n", __LINE__, SDL_GetError()); + return 1; + } + } + + SDL_DestroyWindow(window); + SDL_Quit(); + + return 0; +} diff --git a/src/test/sdl2/target.mk b/src/test/sdl2/target.mk new file mode 100644 index 0000000..912af1c --- /dev/null +++ b/src/test/sdl2/target.mk @@ -0,0 +1,3 @@ +TARGET = test-sdl2 +LIBS = libc sdl2 +SRC_CC = main.cc