Port of SDL 2.0.14

Fixes #210
This commit is contained in:
Josef Söntgen
2016-01-05 23:59:52 +01:00
committed by Norman Feske
parent 9903036142
commit 72cdf74805
18 changed files with 1725 additions and 0 deletions

20
include/SDL2/SDL_config.h Normal file
View File

@@ -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 <SDL_platform.h>
#include <SDL_config_genode.h>
#endif /* _SDL_config_h */

View File

@@ -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 */

View File

@@ -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

114
lib/mk/sdl2.mk Normal file
View File

@@ -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

86
lib/symbols/sdl2 Normal file
View File

@@ -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

1
ports/sdl2.hash Normal file
View File

@@ -0,0 +1 @@
7a460a4a9dc514c19cfe330420f7b3ca674ce554

20
ports/sdl2.port Normal file
View File

@@ -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

17
run/sdl2.run Normal file
View File

@@ -0,0 +1,17 @@
set build_components { test/sdl2 }
set app_config {
<start name="test-sdl2">
<resource name="RAM" quantum="32M"/>
<config ld_verbose="yes">
<vfs> <dir name="dev"> <log/> </dir> </vfs>
<libc stdout="/dev/log"/>
</config>
</start>}
set boot_modules {
test-sdl2
libc.lib.so vfs.lib.so sdl2.lib.so
}
source ${genode_dir}/repos/world/run/nitpicker_app.inc

View File

@@ -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_ */

View File

@@ -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" */

View File

@@ -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 <limits.h>
#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. */

View File

@@ -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 <dlfcn.h>
#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);
}
}

137
src/lib/sdl2/sdl_main.cc Normal file
View File

@@ -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 <base/sleep.h>
#include <libc/component.h>
/* libc includes */
#include <stdlib.h> /* 'malloc' and 'exit' */
#include <pthread.h>
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);
}
}

View File

@@ -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 <nitpicker_session/connection.h>
#include <base/log.h>
#include <input_session/connection.h>
#include <input/event.h>
#include <input/keycodes.h>
/* local includes */
#include <SDL_genode_internal.h>
Genode::Lock event_lock;
Video video_events;
static Genode::Env *_global_env = nullptr;
static Genode::Constructible<Nitpicker::Connection> _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 <SDL2/SDL.h>
#include "SDL_events_c.h"
#include "SDL_sysevents.h"
#include "SDL_genode_fb_events.h"
static Genode::Constructible<Input::Session_client> 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<Genode::Lock> 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<SDL_NUM_SCANCODES; i++)
{
switch(i)
{
case BTN_LEFT: buttonmap[i]=SDL_BUTTON_LEFT; break;
case BTN_RIGHT: buttonmap[i]=SDL_BUTTON_RIGHT; break;
case BTN_MIDDLE: buttonmap[i]=SDL_BUTTON_MIDDLE; break;
case BTN_0:
case BTN_1:
case BTN_2:
case BTN_3:
case BTN_4:
case BTN_5:
case BTN_6:
case BTN_7:
case BTN_8:
case BTN_9:
case BTN_SIDE:
case BTN_EXTRA:
case BTN_FORWARD:
case BTN_BACK:
case BTN_TASK:
case BTN_TRIGGER:
case BTN_THUMB:
case BTN_THUMB2:
case BTN_TOP:
case BTN_TOP2:
case BTN_PINKIE:
case BTN_BASE:
case BTN_BASE2:
case BTN_BASE3:
case BTN_BASE4:
case BTN_BASE5:
case BTN_BASE6:
case BTN_DEAD:
case BTN_A:
case BTN_B:
case BTN_C:
case BTN_X:
case BTN_Y:
case BTN_Z:
case BTN_TL:
case BTN_TR:
case BTN_TL2:
case BTN_TR2:
case BTN_SELECT:
case BTN_START:
case BTN_MODE:
case BTN_THUMBL:
case BTN_THUMBR:
case BTN_TOOL_PEN:
case BTN_TOOL_RUBBER:
case BTN_TOOL_BRUSH:
case BTN_TOOL_PENCIL:
case BTN_TOOL_AIRBRUSH:
case BTN_TOOL_FINGER:
case BTN_TOOL_MOUSE:
case BTN_TOOL_LENS:
case BTN_TOUCH:
case BTN_STYLUS:
case BTN_STYLUS2:
case BTN_TOOL_DOUBLETAP:
case BTN_TOOL_TRIPLETAP:
case BTN_GEAR_DOWN:
case BTN_GEAR_UP:
default: buttonmap[i]=0;
}
}
/* Prepare key mappings */
for(int i = 0; i < SDL_NUM_SCANCODES; i++)
{
/* Genode to SDL scancode mappings */
switch (i)
{
case KEY_RESERVED: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_ESC: scancodes[i]=SDL_SCANCODE_ESCAPE; break;
case KEY_1: scancodes[i]=SDL_SCANCODE_1; break;
case KEY_2: scancodes[i]=SDL_SCANCODE_2; break;
case KEY_3: scancodes[i]=SDL_SCANCODE_3; break;
case KEY_4: scancodes[i]=SDL_SCANCODE_4; break;
case KEY_5: scancodes[i]=SDL_SCANCODE_5; break;
case KEY_6: scancodes[i]=SDL_SCANCODE_6; break;
case KEY_7: scancodes[i]=SDL_SCANCODE_7; break;
case KEY_8: scancodes[i]=SDL_SCANCODE_8; break;
case KEY_9: scancodes[i]=SDL_SCANCODE_9; break;
case KEY_0: scancodes[i]=SDL_SCANCODE_0; break;
case KEY_MINUS: scancodes[i]=SDL_SCANCODE_MINUS; break;
case KEY_EQUAL: scancodes[i]=SDL_SCANCODE_EQUALS; break;
case KEY_BACKSPACE: scancodes[i]=SDL_SCANCODE_BACKSPACE; break;
case KEY_TAB: scancodes[i]=SDL_SCANCODE_TAB; break;
case KEY_Q: scancodes[i]=SDL_SCANCODE_Q; break;
case KEY_W: scancodes[i]=SDL_SCANCODE_W; break;
case KEY_E: scancodes[i]=SDL_SCANCODE_E; break;
case KEY_R: scancodes[i]=SDL_SCANCODE_R; break;
case KEY_T: scancodes[i]=SDL_SCANCODE_T; break;
case KEY_Y: scancodes[i]=SDL_SCANCODE_Y; break;
case KEY_U: scancodes[i]=SDL_SCANCODE_U; break;
case KEY_I: scancodes[i]=SDL_SCANCODE_I; break;
case KEY_O: scancodes[i]=SDL_SCANCODE_O; break;
case KEY_P: scancodes[i]=SDL_SCANCODE_P; break;
case KEY_LEFTBRACE: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_RIGHTBRACE: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_ENTER: scancodes[i]=SDL_SCANCODE_RETURN; break;
case KEY_LEFTCTRL: scancodes[i]=SDL_SCANCODE_LCTRL; break;
case KEY_A: scancodes[i]=SDL_SCANCODE_A; break;
case KEY_S: scancodes[i]=SDL_SCANCODE_S; break;
case KEY_D: scancodes[i]=SDL_SCANCODE_D; break;
case KEY_F: scancodes[i]=SDL_SCANCODE_F; break;
case KEY_G: scancodes[i]=SDL_SCANCODE_G; break;
case KEY_H: scancodes[i]=SDL_SCANCODE_H; break;
case KEY_J: scancodes[i]=SDL_SCANCODE_J; break;
case KEY_K: scancodes[i]=SDL_SCANCODE_K; break;
case KEY_L: scancodes[i]=SDL_SCANCODE_L; break;
case KEY_SEMICOLON: scancodes[i]=SDL_SCANCODE_SEMICOLON; break;
case KEY_APOSTROPHE: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_GRAVE: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_LEFTSHIFT: scancodes[i]=SDL_SCANCODE_LSHIFT; break;
case KEY_BACKSLASH: scancodes[i]=SDL_SCANCODE_BACKSLASH; break;
case KEY_Z: scancodes[i]=SDL_SCANCODE_Z; break;
case KEY_X: scancodes[i]=SDL_SCANCODE_X; break;
case KEY_C: scancodes[i]=SDL_SCANCODE_C; break;
case KEY_V: scancodes[i]=SDL_SCANCODE_V; break;
case KEY_B: scancodes[i]=SDL_SCANCODE_B; break;
case KEY_N: scancodes[i]=SDL_SCANCODE_N; break;
case KEY_M: scancodes[i]=SDL_SCANCODE_M; break;
case KEY_COMMA: scancodes[i]=SDL_SCANCODE_COMMA; break;
case KEY_DOT: scancodes[i]=SDL_SCANCODE_PERIOD; break;
case KEY_SLASH: scancodes[i]=SDL_SCANCODE_SLASH; break;
case KEY_RIGHTSHIFT: scancodes[i]=SDL_SCANCODE_RSHIFT; break;
case KEY_LEFTALT: scancodes[i]=SDL_SCANCODE_LALT; break;
case KEY_SPACE: scancodes[i]=SDL_SCANCODE_SPACE; break;
case KEY_CAPSLOCK: scancodes[i]=SDL_SCANCODE_CAPSLOCK; break;
case KEY_F1: scancodes[i]=SDL_SCANCODE_F1; break;
case KEY_F2: scancodes[i]=SDL_SCANCODE_F2; break;
case KEY_F3: scancodes[i]=SDL_SCANCODE_F3; break;
case KEY_F4: scancodes[i]=SDL_SCANCODE_F4; break;
case KEY_F5: scancodes[i]=SDL_SCANCODE_F5; break;
case KEY_F6: scancodes[i]=SDL_SCANCODE_F6; break;
case KEY_F7: scancodes[i]=SDL_SCANCODE_F7; break;
case KEY_F8: scancodes[i]=SDL_SCANCODE_F8; break;
case KEY_F9: scancodes[i]=SDL_SCANCODE_F9; break;
case KEY_F10: scancodes[i]=SDL_SCANCODE_F10; break;
case KEY_NUMLOCK: scancodes[i]=SDL_SCANCODE_NUMLOCKCLEAR; break;
case KEY_SCROLLLOCK: scancodes[i]=SDL_SCANCODE_SCROLLLOCK; break;
case KEY_KP7: scancodes[i]=SDL_SCANCODE_KP_7; break;
case KEY_KP8: scancodes[i]=SDL_SCANCODE_KP_8; break;
case KEY_KP9: scancodes[i]=SDL_SCANCODE_KP_9; break;
case KEY_KPMINUS: scancodes[i]=SDL_SCANCODE_KP_MINUS; break;
case KEY_KP4: scancodes[i]=SDL_SCANCODE_KP_4; break;
case KEY_KP5: scancodes[i]=SDL_SCANCODE_KP_5; break;
case KEY_KP6: scancodes[i]=SDL_SCANCODE_KP_6; break;
case KEY_KPPLUS: scancodes[i]=SDL_SCANCODE_KP_PLUS; break;
case KEY_KP1: scancodes[i]=SDL_SCANCODE_KP_1; break;
case KEY_KP2: scancodes[i]=SDL_SCANCODE_KP_2; break;
case KEY_KP3: scancodes[i]=SDL_SCANCODE_KP_3; break;
case KEY_KP0: scancodes[i]=SDL_SCANCODE_KP_0; break;
case KEY_KPDOT: scancodes[i]=SDL_SCANCODE_KP_PERIOD; break;
case KEY_ZENKAKUHANKAKU: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_102ND: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_F11: scancodes[i]=SDL_SCANCODE_F11; break;
case KEY_F12: scancodes[i]=SDL_SCANCODE_F12; break;
case KEY_RO: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_KATAKANA: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_HIRAGANA: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_HENKAN: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_KATAKANAHIRAGANA: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_MUHENKAN: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_KPJPCOMMA: scancodes[i]=SDL_SCANCODE_UNKNOWN; break;
case KEY_KPENTER: scancodes[i]=SDL_SCANCODE_KP_ENTER; break;
case KEY_RIGHTCTRL: scancodes[i]=SDL_SCANCODE_RCTRL; break;
case KEY_KPSLASH: scancodes[i]=SDL_SCANCODE_KP_DIVIDE; break;
case KEY_SYSRQ: scancodes[i]=SDL_SCANCODE_SYSREQ; break;
case KEY_RIGHTALT: scancodes[i]=SDL_SCANCODE_RALT; break;
case KEY_LINEFEED: scancodes[i]=SDL_SCANCODE_RETURN; break;
case KEY_HOME: scancodes[i]=SDL_SCANCODE_HOME; break;
case KEY_UP: scancodes[i]=SDL_SCANCODE_UP; break;
case KEY_PAGEUP: scancodes[i]=SDL_SCANCODE_PAGEUP; break;
case KEY_LEFT: scancodes[i]=SDL_SCANCODE_LEFT; break;
case KEY_RIGHT: scancodes[i]=SDL_SCANCODE_RIGHT; break;
case KEY_END: scancodes[i]=SDL_SCANCODE_END; break;
case KEY_DOWN: scancodes[i]=SDL_SCANCODE_DOWN; break;
case KEY_PAGEDOWN: scancodes[i]=SDL_SCANCODE_PAGEDOWN; break;
case KEY_INSERT: scancodes[i]=SDL_SCANCODE_INSERT; break;
case KEY_DELETE: scancodes[i]=SDL_SCANCODE_DELETE; break;
case KEY_POWER: scancodes[i]=SDL_SCANCODE_POWER; break;
case KEY_KPEQUAL: scancodes[i]=SDL_SCANCODE_KP_EQUALS; break;
default: scancodes[i] = SDL_SCANCODE_UNKNOWN; break;
}
}
}
} /* exern "C" */

View File

@@ -0,0 +1,37 @@
/*
* \brief Genode-specific event backend header
* \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.
*/
#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

View File

@@ -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 <base/attached_ram_dataspace.h>
#include <base/env.h>
#include <base/log.h>
#include <nitpicker_session/connection.h>
/* local includes */
#include <SDL_genode_internal.h>
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 <dlfcn.h>
#include <SDL.h>
#include <SDL_video.h>
#include <SDL_mouse.h>
#include <SDL_mouse_c.h>
#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<Genode::Lock> 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<Sdl_framebuffer> _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<Session::Command::To_front>(_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<Command::Geometry>(
_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<Nitpicker::Session::Command::Title>(_view, string);
_nitpicker.execute();
}
};
static char const * const surface_name = "genode_surface";
struct Genode_Driverdata
{
Genode::Constructible<Sdl_framebuffer> framebuffer;
Genode::Constructible<Genode::Attached_dataspace> fb_mem;
Genode::Constructible<Genode::Attached_ram_dataspace> 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<void>()
: drv.fb_mem->local_addr<void>();
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<void>(),
drv.fb_double->local_addr<void>(),
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"

229
src/test/sdl2/main.cc Normal file
View File

@@ -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 <SDL2/SDL.h>
/* Genode includes */
#include <base/env.h>
#include <timer_session/connection.h>
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;
}

3
src/test/sdl2/target.mk Normal file
View File

@@ -0,0 +1,3 @@
TARGET = test-sdl2
LIBS = libc sdl2
SRC_CC = main.cc