diff options
Diffstat (limited to 'source/3rd-party/SDL2/src/video/raspberry')
8 files changed, 1171 insertions, 0 deletions
diff --git a/source/3rd-party/SDL2/src/video/raspberry/SDL_rpievents.c b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpievents.c new file mode 100644 index 0000000..4064355 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpievents.c @@ -0,0 +1,45 @@ +/* + 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" + +#if SDL_VIDEO_DRIVER_RPI + +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "../../events/SDL_keyboard_c.h" +#include "SDL_rpivideo.h" +#include "SDL_rpievents_c.h" + +#ifdef SDL_INPUT_LINUXEV +#include "../../core/linux/SDL_evdev.h" +#endif + +void RPI_PumpEvents(_THIS) +{ +#ifdef SDL_INPUT_LINUXEV + SDL_EVDEV_Poll(); +#endif + +} + +#endif /* SDL_VIDEO_DRIVER_RPI */ + diff --git a/source/3rd-party/SDL2/src/video/raspberry/SDL_rpievents_c.h b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpievents_c.h new file mode 100644 index 0000000..8b1737f --- /dev/null +++ b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpievents_c.h @@ -0,0 +1,31 @@ +/* + 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_rpievents_c_h_ +#define SDL_rpievents_c_h_ + +#include "SDL_rpivideo.h" + +void RPI_PumpEvents(_THIS); +void RPI_EventInit(_THIS); +void RPI_EventQuit(_THIS); + +#endif /* SDL_rpievents_c_h_ */ diff --git a/source/3rd-party/SDL2/src/video/raspberry/SDL_rpimouse.c b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpimouse.c new file mode 100644 index 0000000..4ea976b --- /dev/null +++ b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpimouse.c @@ -0,0 +1,386 @@ +/* + 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" + +#if SDL_VIDEO_DRIVER_RPI + +#include "SDL_assert.h" +#include "SDL_surface.h" +#include "SDL_hints.h" + +#include "SDL_rpivideo.h" +#include "SDL_rpimouse.h" + +#include "../SDL_sysvideo.h" +#include "../../events/SDL_mouse_c.h" +#include "../../events/default_cursor.h" + +/* Copied from vc_vchi_dispmanx.h which is bugged and tries to include a non existing file */ +/* Attributes changes flag mask */ +#define ELEMENT_CHANGE_LAYER (1<<0) +#define ELEMENT_CHANGE_OPACITY (1<<1) +#define ELEMENT_CHANGE_DEST_RECT (1<<2) +#define ELEMENT_CHANGE_SRC_RECT (1<<3) +#define ELEMENT_CHANGE_MASK_RESOURCE (1<<4) +#define ELEMENT_CHANGE_TRANSFORM (1<<5) +/* End copied from vc_vchi_dispmanx.h */ + +static SDL_Cursor *RPI_CreateDefaultCursor(void); +static SDL_Cursor *RPI_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y); +static int RPI_ShowCursor(SDL_Cursor * cursor); +static void RPI_MoveCursor(SDL_Cursor * cursor); +static void RPI_FreeCursor(SDL_Cursor * cursor); +static void RPI_WarpMouse(SDL_Window * window, int x, int y); +static int RPI_WarpMouseGlobal(int x, int y); + +static SDL_Cursor * +RPI_CreateDefaultCursor(void) +{ + return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY); +} + +/* Create a cursor from a surface */ +static SDL_Cursor * +RPI_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y) +{ + RPI_CursorData *curdata; + SDL_Cursor *cursor; + int ret; + VC_RECT_T dst_rect; + Uint32 dummy; + + SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888); + SDL_assert(surface->pitch == surface->w * 4); + + cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor)); + if (cursor == NULL) { + SDL_OutOfMemory(); + return NULL; + } + curdata = (RPI_CursorData *) SDL_calloc(1, sizeof(*curdata)); + if (curdata == NULL) { + SDL_OutOfMemory(); + SDL_free(cursor); + return NULL; + } + + curdata->hot_x = hot_x; + curdata->hot_y = hot_y; + curdata->w = surface->w; + curdata->h = surface->h; + + /* This usage is inspired by Wayland/Weston RPI code, how they figured this out is anyone's guess */ + curdata->resource = vc_dispmanx_resource_create(VC_IMAGE_ARGB8888, surface->w | (surface->pitch << 16), surface->h | (surface->h << 16), &dummy); + SDL_assert(curdata->resource); + vc_dispmanx_rect_set(&dst_rect, 0, 0, curdata->w, curdata->h); + /* A note from Weston: + * vc_dispmanx_resource_write_data() ignores ifmt, + * rect.x, rect.width, and uses stride only for computing + * the size of the transfer as rect.height * stride. + * Therefore we can only write rows starting at x=0. + */ + ret = vc_dispmanx_resource_write_data(curdata->resource, VC_IMAGE_ARGB8888, surface->pitch, surface->pixels, &dst_rect); + SDL_assert (ret == DISPMANX_SUCCESS); + + cursor->driverdata = curdata; + + return cursor; + +} + +/* Show the specified cursor, or hide if cursor is NULL */ +static int +RPI_ShowCursor(SDL_Cursor * cursor) +{ + int ret; + DISPMANX_UPDATE_HANDLE_T update; + RPI_CursorData *curdata; + VC_RECT_T src_rect, dst_rect; + SDL_Mouse *mouse; + SDL_VideoDisplay *display; + SDL_DisplayData *data; + VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FROM_SOURCE /* flags */ , 255 /*opacity 0->255*/, 0 /* mask */ }; + uint32_t layer = SDL_RPI_MOUSELAYER; + const char *env; + + mouse = SDL_GetMouse(); + if (mouse == NULL) { + return -1; + } + + if (cursor == NULL) { + /* FIXME: We hide the current mouse's cursor, what we actually need is *_HideCursor */ + + if (mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) { + curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata; + if (curdata->element > DISPMANX_NO_HANDLE) { + update = vc_dispmanx_update_start(10); + SDL_assert(update); + ret = vc_dispmanx_element_remove(update, curdata->element); + SDL_assert(ret == DISPMANX_SUCCESS); + ret = vc_dispmanx_update_submit_sync(update); + SDL_assert(ret == DISPMANX_SUCCESS); + curdata->element = DISPMANX_NO_HANDLE; + } + } + return 0; + } + + curdata = (RPI_CursorData *) cursor->driverdata; + if (curdata == NULL) { + return -1; + } + + if (mouse->focus == NULL) { + return -1; + } + + display = SDL_GetDisplayForWindow(mouse->focus); + if (display == NULL) { + return -1; + } + + data = (SDL_DisplayData*) display->driverdata; + if (data == NULL) { + return -1; + } + + if (curdata->element == DISPMANX_NO_HANDLE) { + vc_dispmanx_rect_set(&src_rect, 0, 0, curdata->w << 16, curdata->h << 16); + vc_dispmanx_rect_set(&dst_rect, mouse->x, mouse->y, curdata->w, curdata->h); + + update = vc_dispmanx_update_start(10); + SDL_assert(update); + + env = SDL_GetHint(SDL_HINT_RPI_VIDEO_LAYER); + if (env) { + layer = SDL_atoi(env) + 1; + } + + curdata->element = vc_dispmanx_element_add(update, + data->dispman_display, + layer, + &dst_rect, + curdata->resource, + &src_rect, + DISPMANX_PROTECTION_NONE, + &alpha, + DISPMANX_NO_HANDLE, // clamp + VC_IMAGE_ROT0); + SDL_assert(curdata->element > DISPMANX_NO_HANDLE); + ret = vc_dispmanx_update_submit_sync(update); + SDL_assert(ret == DISPMANX_SUCCESS); + } + + return 0; +} + +/* Free a window manager cursor */ +static void +RPI_FreeCursor(SDL_Cursor * cursor) +{ + int ret; + DISPMANX_UPDATE_HANDLE_T update; + RPI_CursorData *curdata; + + if (cursor != NULL) { + curdata = (RPI_CursorData *) cursor->driverdata; + + if (curdata != NULL) { + if (curdata->element != DISPMANX_NO_HANDLE) { + update = vc_dispmanx_update_start(10); + SDL_assert(update); + ret = vc_dispmanx_element_remove(update, curdata->element); + SDL_assert(ret == DISPMANX_SUCCESS); + ret = vc_dispmanx_update_submit_sync(update); + SDL_assert(ret == DISPMANX_SUCCESS); + } + + if (curdata->resource != DISPMANX_NO_HANDLE) { + ret = vc_dispmanx_resource_delete(curdata->resource); + SDL_assert(ret == DISPMANX_SUCCESS); + } + + SDL_free(cursor->driverdata); + } + SDL_free(cursor); + } +} + +/* Warp the mouse to (x,y) */ +static void +RPI_WarpMouse(SDL_Window * window, int x, int y) +{ + RPI_WarpMouseGlobal(x, y); +} + +/* Warp the mouse to (x,y) */ +static int +RPI_WarpMouseGlobal(int x, int y) +{ + RPI_CursorData *curdata; + DISPMANX_UPDATE_HANDLE_T update; + int ret; + VC_RECT_T dst_rect; + VC_RECT_T src_rect; + SDL_Mouse *mouse = SDL_GetMouse(); + + if (mouse == NULL || mouse->cur_cursor == NULL || mouse->cur_cursor->driverdata == NULL) { + return 0; + } + + /* Update internal mouse position. */ + SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y); + + curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata; + if (curdata->element == DISPMANX_NO_HANDLE) { + return 0; + } + + update = vc_dispmanx_update_start(10); + if (!update) { + return 0; + } + + src_rect.x = 0; + src_rect.y = 0; + src_rect.width = curdata->w << 16; + src_rect.height = curdata->h << 16; + dst_rect.x = x; + dst_rect.y = y; + dst_rect.width = curdata->w; + dst_rect.height = curdata->h; + + ret = vc_dispmanx_element_change_attributes( + update, + curdata->element, + 0, + 0, + 0, + &dst_rect, + &src_rect, + DISPMANX_NO_HANDLE, + DISPMANX_NO_ROTATE); + if (ret != DISPMANX_SUCCESS) { + return SDL_SetError("vc_dispmanx_element_change_attributes() failed"); + } + + /* Submit asynchronously, otherwise the peformance suffers a lot */ + ret = vc_dispmanx_update_submit(update, 0, NULL); + if (ret != DISPMANX_SUCCESS) { + return SDL_SetError("vc_dispmanx_update_submit() failed"); + } + return 0; +} + +/* Warp the mouse to (x,y) */ +static int +RPI_WarpMouseGlobalGraphicOnly(int x, int y) +{ + RPI_CursorData *curdata; + DISPMANX_UPDATE_HANDLE_T update; + int ret; + VC_RECT_T dst_rect; + VC_RECT_T src_rect; + SDL_Mouse *mouse = SDL_GetMouse(); + + if (mouse == NULL || mouse->cur_cursor == NULL || mouse->cur_cursor->driverdata == NULL) { + return 0; + } + + curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata; + if (curdata->element == DISPMANX_NO_HANDLE) { + return 0; + } + + update = vc_dispmanx_update_start(10); + if (!update) { + return 0; + } + + src_rect.x = 0; + src_rect.y = 0; + src_rect.width = curdata->w << 16; + src_rect.height = curdata->h << 16; + dst_rect.x = x; + dst_rect.y = y; + dst_rect.width = curdata->w; + dst_rect.height = curdata->h; + + ret = vc_dispmanx_element_change_attributes( + update, + curdata->element, + 0, + 0, + 0, + &dst_rect, + &src_rect, + DISPMANX_NO_HANDLE, + DISPMANX_NO_ROTATE); + if (ret != DISPMANX_SUCCESS) { + return SDL_SetError("vc_dispmanx_element_change_attributes() failed"); + } + + /* Submit asynchronously, otherwise the peformance suffers a lot */ + ret = vc_dispmanx_update_submit(update, 0, NULL); + if (ret != DISPMANX_SUCCESS) { + return SDL_SetError("vc_dispmanx_update_submit() failed"); + } + return 0; +} + +void +RPI_InitMouse(_THIS) +{ + /* FIXME: Using UDEV it should be possible to scan all mice + * but there's no point in doing so as there's no multimice support...yet! + */ + SDL_Mouse *mouse = SDL_GetMouse(); + + mouse->CreateCursor = RPI_CreateCursor; + mouse->ShowCursor = RPI_ShowCursor; + mouse->MoveCursor = RPI_MoveCursor; + mouse->FreeCursor = RPI_FreeCursor; + mouse->WarpMouse = RPI_WarpMouse; + mouse->WarpMouseGlobal = RPI_WarpMouseGlobal; + + SDL_SetDefaultCursor(RPI_CreateDefaultCursor()); +} + +void +RPI_QuitMouse(_THIS) +{ + +} + +/* This is called when a mouse motion event occurs */ +static void +RPI_MoveCursor(SDL_Cursor * cursor) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + /* We must NOT call SDL_SendMouseMotion() on the next call or we will enter recursivity, + * so we create a version of WarpMouseGlobal without it. */ + RPI_WarpMouseGlobalGraphicOnly(mouse->x, mouse->y); +} + +#endif /* SDL_VIDEO_DRIVER_RPI */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/raspberry/SDL_rpimouse.h b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpimouse.h new file mode 100644 index 0000000..919f811 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpimouse.h @@ -0,0 +1,43 @@ +/* + 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_RPI_mouse_h_ +#define SDL_RPI_mouse_h_ + +#include "../SDL_sysvideo.h" + +typedef struct _RPI_CursorData RPI_CursorData; +struct _RPI_CursorData +{ + DISPMANX_RESOURCE_HANDLE_T resource; + DISPMANX_ELEMENT_HANDLE_T element; + int hot_x, hot_y; + int w, h; +}; + +#define SDL_RPI_CURSORDATA(curs) RPI_CursorData *curdata = (RPI_CursorData *) ((curs) ? (curs)->driverdata : NULL) + +extern void RPI_InitMouse(_THIS); +extern void RPI_QuitMouse(_THIS); + +#endif /* SDL_RPI_mouse_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/raspberry/SDL_rpiopengles.c b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpiopengles.c new file mode 100644 index 0000000..b763007 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpiopengles.c @@ -0,0 +1,71 @@ +/* + 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_hints.h" +#include "SDL_log.h" + +#if SDL_VIDEO_DRIVER_RPI && SDL_VIDEO_OPENGL_EGL + +#include "SDL_rpivideo.h" +#include "SDL_rpiopengles.h" + +/* EGL implementation of SDL OpenGL support */ + +void +RPI_GLES_DefaultProfileConfig(_THIS, int *mask, int *major, int *minor) +{ + *mask = SDL_GL_CONTEXT_PROFILE_ES; + *major = 2; + *minor = 0; +} + +int +RPI_GLES_LoadLibrary(_THIS, const char *path) { + return SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY, 0); +} + +int +RPI_GLES_SwapWindow(_THIS, SDL_Window * window) { + SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata); + + if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed."); + return 0; + } + + /* Wait immediately for vsync (as if we only had two buffers), for low input-lag scenarios. + * Run your SDL2 program with "SDL_RPI_DOUBLE_BUFFER=1 <program_name>" to enable this. */ + if (wdata->double_buffer) { + SDL_LockMutex(wdata->vsync_cond_mutex); + SDL_CondWait(wdata->vsync_cond, wdata->vsync_cond_mutex); + SDL_UnlockMutex(wdata->vsync_cond_mutex); + } + + return 0; +} + +SDL_EGL_CreateContext_impl(RPI) +SDL_EGL_MakeCurrent_impl(RPI) + +#endif /* SDL_VIDEO_DRIVER_RPI && SDL_VIDEO_OPENGL_EGL */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/source/3rd-party/SDL2/src/video/raspberry/SDL_rpiopengles.h b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpiopengles.h new file mode 100644 index 0000000..9724a5f --- /dev/null +++ b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpiopengles.h @@ -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_rpiopengles_h_ +#define SDL_rpiopengles_h_ + +#if SDL_VIDEO_DRIVER_RPI && SDL_VIDEO_OPENGL_EGL + +#include "../SDL_sysvideo.h" +#include "../SDL_egl_c.h" + +/* OpenGLES functions */ +#define RPI_GLES_GetAttribute SDL_EGL_GetAttribute +#define RPI_GLES_GetProcAddress SDL_EGL_GetProcAddress +#define RPI_GLES_UnloadLibrary SDL_EGL_UnloadLibrary +#define RPI_GLES_SetSwapInterval SDL_EGL_SetSwapInterval +#define RPI_GLES_GetSwapInterval SDL_EGL_GetSwapInterval +#define RPI_GLES_DeleteContext SDL_EGL_DeleteContext + +extern int RPI_GLES_LoadLibrary(_THIS, const char *path); +extern SDL_GLContext RPI_GLES_CreateContext(_THIS, SDL_Window * window); +extern int RPI_GLES_SwapWindow(_THIS, SDL_Window * window); +extern int RPI_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); +extern void RPI_GLES_DefaultProfileConfig(_THIS, int *mask, int *major, int *minor); + +#endif /* SDL_VIDEO_DRIVER_RPI && SDL_VIDEO_OPENGL_EGL */ + +#endif /* SDL_rpiopengles_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/raspberry/SDL_rpivideo.c b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpivideo.c new file mode 100644 index 0000000..c4f4a60 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpivideo.c @@ -0,0 +1,442 @@ +/* + 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" + +#if SDL_VIDEO_DRIVER_RPI + +/* References + * http://elinux.org/RPi_VideoCore_APIs + * https://github.com/raspberrypi/firmware/blob/master/opt/vc/src/hello_pi/hello_triangle/triangle.c + * http://cgit.freedesktop.org/wayland/weston/tree/src/rpi-renderer.c + * http://cgit.freedesktop.org/wayland/weston/tree/src/compositor-rpi.c + */ + +/* SDL internals */ +#include "../SDL_sysvideo.h" +#include "SDL_version.h" +#include "SDL_syswm.h" +#include "SDL_loadso.h" +#include "SDL_events.h" +#include "../../events/SDL_mouse_c.h" +#include "../../events/SDL_keyboard_c.h" +#include "SDL_hints.h" + +#ifdef SDL_INPUT_LINUXEV +#include "../../core/linux/SDL_evdev.h" +#endif + +/* RPI declarations */ +#include "SDL_rpivideo.h" +#include "SDL_rpievents_c.h" +#include "SDL_rpiopengles.h" +#include "SDL_rpimouse.h" + +static int +RPI_Available(void) +{ + return 1; +} + +static void +RPI_Destroy(SDL_VideoDevice * device) +{ + SDL_free(device->driverdata); + SDL_free(device); +} + +static int +RPI_GetRefreshRate() +{ + TV_DISPLAY_STATE_T tvstate; + if (vc_tv_get_display_state( &tvstate ) == 0) { + //The width/height parameters are in the same position in the union + //for HDMI and SDTV + HDMI_PROPERTY_PARAM_T property; + property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE; + vc_tv_hdmi_get_property(&property); + return property.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC ? + tvstate.display.hdmi.frame_rate * (1000.0f/1001.0f) : + tvstate.display.hdmi.frame_rate; + } + return 60; /* Failed to get display state, default to 60 */ +} + +static SDL_VideoDevice * +RPI_Create() +{ + SDL_VideoDevice *device; + SDL_VideoData *phdata; + + /* Initialize SDL_VideoDevice structure */ + device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); + if (device == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + /* Initialize internal data */ + phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData)); + if (phdata == NULL) { + SDL_OutOfMemory(); + SDL_free(device); + return NULL; + } + + device->driverdata = phdata; + + /* Setup amount of available displays */ + device->num_displays = 0; + + /* Set device free function */ + device->free = RPI_Destroy; + + /* Setup all functions which we can handle */ + device->VideoInit = RPI_VideoInit; + device->VideoQuit = RPI_VideoQuit; + device->GetDisplayModes = RPI_GetDisplayModes; + device->SetDisplayMode = RPI_SetDisplayMode; + device->CreateSDLWindow = RPI_CreateWindow; + device->CreateSDLWindowFrom = RPI_CreateWindowFrom; + device->SetWindowTitle = RPI_SetWindowTitle; + device->SetWindowIcon = RPI_SetWindowIcon; + device->SetWindowPosition = RPI_SetWindowPosition; + device->SetWindowSize = RPI_SetWindowSize; + device->ShowWindow = RPI_ShowWindow; + device->HideWindow = RPI_HideWindow; + device->RaiseWindow = RPI_RaiseWindow; + device->MaximizeWindow = RPI_MaximizeWindow; + device->MinimizeWindow = RPI_MinimizeWindow; + device->RestoreWindow = RPI_RestoreWindow; + device->SetWindowGrab = RPI_SetWindowGrab; + device->DestroyWindow = RPI_DestroyWindow; +#if 0 + device->GetWindowWMInfo = RPI_GetWindowWMInfo; +#endif + device->GL_LoadLibrary = RPI_GLES_LoadLibrary; + device->GL_GetProcAddress = RPI_GLES_GetProcAddress; + device->GL_UnloadLibrary = RPI_GLES_UnloadLibrary; + device->GL_CreateContext = RPI_GLES_CreateContext; + device->GL_MakeCurrent = RPI_GLES_MakeCurrent; + device->GL_SetSwapInterval = RPI_GLES_SetSwapInterval; + device->GL_GetSwapInterval = RPI_GLES_GetSwapInterval; + device->GL_SwapWindow = RPI_GLES_SwapWindow; + device->GL_DeleteContext = RPI_GLES_DeleteContext; + device->GL_DefaultProfileConfig = RPI_GLES_DefaultProfileConfig; + + device->PumpEvents = RPI_PumpEvents; + + return device; +} + +VideoBootStrap RPI_bootstrap = { + "RPI", + "RPI Video Driver", + RPI_Available, + RPI_Create +}; + +/*****************************************************************************/ +/* SDL Video and Display initialization/handling functions */ +/*****************************************************************************/ +int +RPI_VideoInit(_THIS) +{ + SDL_VideoDisplay display; + SDL_DisplayMode current_mode; + SDL_DisplayData *data; + uint32_t w,h; + + /* Initialize BCM Host */ + bcm_host_init(); + + SDL_zero(current_mode); + + if (graphics_get_display_size( 0, &w, &h) < 0) { + return -1; + } + + current_mode.w = w; + current_mode.h = h; + current_mode.refresh_rate = RPI_GetRefreshRate(); + /* 32 bpp for default */ + current_mode.format = SDL_PIXELFORMAT_ABGR8888; + + current_mode.driverdata = NULL; + + SDL_zero(display); + display.desktop_mode = current_mode; + display.current_mode = current_mode; + + /* Allocate display internal data */ + data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData)); + if (data == NULL) { + return SDL_OutOfMemory(); + } + + data->dispman_display = vc_dispmanx_display_open( 0 /* LCD */); + + display.driverdata = data; + + SDL_AddVideoDisplay(&display); + +#ifdef SDL_INPUT_LINUXEV + if (SDL_EVDEV_Init() < 0) { + return -1; + } +#endif + + RPI_InitMouse(_this); + + return 1; +} + +void +RPI_VideoQuit(_THIS) +{ +#ifdef SDL_INPUT_LINUXEV + SDL_EVDEV_Quit(); +#endif +} + +void +RPI_GetDisplayModes(_THIS, SDL_VideoDisplay * display) +{ + /* Only one display mode available, the current one */ + SDL_AddDisplayMode(display, &display->current_mode); +} + +int +RPI_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) +{ + return 0; +} + +static void +RPI_vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *data) +{ + SDL_WindowData *wdata = ((SDL_WindowData *) data); + + SDL_LockMutex(wdata->vsync_cond_mutex); + SDL_CondSignal(wdata->vsync_cond); + SDL_UnlockMutex(wdata->vsync_cond_mutex); +} + +int +RPI_CreateWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *wdata; + SDL_VideoDisplay *display; + SDL_DisplayData *displaydata; + VC_RECT_T dst_rect; + VC_RECT_T src_rect; + VC_DISPMANX_ALPHA_T dispman_alpha; + DISPMANX_UPDATE_HANDLE_T dispman_update; + uint32_t layer = SDL_RPI_VIDEOLAYER; + const char *env; + + /* Disable alpha, otherwise the app looks composed with whatever dispman is showing (X11, console,etc) */ + dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; + dispman_alpha.opacity = 0xFF; + dispman_alpha.mask = 0; + + /* Allocate window internal data */ + wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData)); + if (wdata == NULL) { + return SDL_OutOfMemory(); + } + display = SDL_GetDisplayForWindow(window); + displaydata = (SDL_DisplayData *) display->driverdata; + + /* Windows have one size for now */ + window->w = display->desktop_mode.w; + window->h = display->desktop_mode.h; + + /* OpenGL ES is the law here, buddy */ + window->flags |= SDL_WINDOW_OPENGL; + + /* Create a dispman element and associate a window to it */ + dst_rect.x = 0; + dst_rect.y = 0; + dst_rect.width = window->w; + dst_rect.height = window->h; + + src_rect.x = 0; + src_rect.y = 0; + src_rect.width = window->w << 16; + src_rect.height = window->h << 16; + + env = SDL_GetHint(SDL_HINT_RPI_VIDEO_LAYER); + if (env) { + layer = SDL_atoi(env); + } + + dispman_update = vc_dispmanx_update_start( 0 ); + wdata->dispman_window.element = vc_dispmanx_element_add (dispman_update, + displaydata->dispman_display, + layer /* layer */, + &dst_rect, + 0 /*src*/, + &src_rect, + DISPMANX_PROTECTION_NONE, + &dispman_alpha /*alpha*/, + 0 /*clamp*/, + 0 /*transform*/); + wdata->dispman_window.width = window->w; + wdata->dispman_window.height = window->h; + vc_dispmanx_update_submit_sync(dispman_update); + + if (!_this->egl_data) { + if (SDL_GL_LoadLibrary(NULL) < 0) { + return -1; + } + } + wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) &wdata->dispman_window); + + if (wdata->egl_surface == EGL_NO_SURFACE) { + return SDL_SetError("Could not create GLES window surface"); + } + + /* Start generating vsync callbacks if necesary */ + wdata->double_buffer = SDL_FALSE; + if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) { + wdata->vsync_cond = SDL_CreateCond(); + wdata->vsync_cond_mutex = SDL_CreateMutex(); + wdata->double_buffer = SDL_TRUE; + vc_dispmanx_vsync_callback(displaydata->dispman_display, RPI_vsync_callback, (void*)wdata); + } + + /* 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 +RPI_DestroyWindow(_THIS, SDL_Window * window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); + SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata; + + if(data) { + if (data->double_buffer) { + /* Wait for vsync, and then stop vsync callbacks and destroy related stuff, if needed */ + SDL_LockMutex(data->vsync_cond_mutex); + SDL_CondWait(data->vsync_cond, data->vsync_cond_mutex); + SDL_UnlockMutex(data->vsync_cond_mutex); + + vc_dispmanx_vsync_callback(displaydata->dispman_display, NULL, NULL); + + SDL_DestroyCond(data->vsync_cond); + SDL_DestroyMutex(data->vsync_cond_mutex); + } + +#if SDL_VIDEO_OPENGL_EGL + if (data->egl_surface != EGL_NO_SURFACE) { + SDL_EGL_DestroySurface(_this, data->egl_surface); + } +#endif + SDL_free(data); + window->driverdata = NULL; + } +} + +int +RPI_CreateWindowFrom(_THIS, SDL_Window * window, const void *data) +{ + return -1; +} + +void +RPI_SetWindowTitle(_THIS, SDL_Window * window) +{ +} +void +RPI_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon) +{ +} +void +RPI_SetWindowPosition(_THIS, SDL_Window * window) +{ +} +void +RPI_SetWindowSize(_THIS, SDL_Window * window) +{ +} +void +RPI_ShowWindow(_THIS, SDL_Window * window) +{ +} +void +RPI_HideWindow(_THIS, SDL_Window * window) +{ +} +void +RPI_RaiseWindow(_THIS, SDL_Window * window) +{ +} +void +RPI_MaximizeWindow(_THIS, SDL_Window * window) +{ +} +void +RPI_MinimizeWindow(_THIS, SDL_Window * window) +{ +} +void +RPI_RestoreWindow(_THIS, SDL_Window * window) +{ +} +void +RPI_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed) +{ + +} + +/*****************************************************************************/ +/* SDL Window Manager function */ +/*****************************************************************************/ +#if 0 +SDL_bool +RPI_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info) +{ + if (info->version.major <= SDL_MAJOR_VERSION) { + return SDL_TRUE; + } else { + SDL_SetError("application not compiled with SDL %d.%d", + SDL_MAJOR_VERSION, SDL_MINOR_VERSION); + return SDL_FALSE; + } + + /* Failed to get window manager information */ + return SDL_FALSE; +} +#endif + +#endif /* SDL_VIDEO_DRIVER_RPI */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/source/3rd-party/SDL2/src/video/raspberry/SDL_rpivideo.h b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpivideo.h new file mode 100644 index 0000000..b2eb670 --- /dev/null +++ b/source/3rd-party/SDL2/src/video/raspberry/SDL_rpivideo.h @@ -0,0 +1,104 @@ +/* + 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_RPIVIDEO_H__ +#define __SDL_RPIVIDEO_H__ + +#include "../../SDL_internal.h" +#include "../SDL_sysvideo.h" + +#include <bcm_host.h> +#include "GLES/gl.h" +#include "EGL/egl.h" +#include "EGL/eglext.h" + +typedef struct SDL_VideoData +{ + uint32_t egl_refcount; /* OpenGL ES reference count */ +} SDL_VideoData; + + +typedef struct SDL_DisplayData +{ + DISPMANX_DISPLAY_HANDLE_T dispman_display; +} SDL_DisplayData; + + +typedef struct SDL_WindowData +{ + EGL_DISPMANX_WINDOW_T dispman_window; +#if SDL_VIDEO_OPENGL_EGL + EGLSurface egl_surface; +#endif + + /* Vsync callback cond and mutex */ + SDL_cond *vsync_cond; + SDL_mutex *vsync_cond_mutex; + SDL_bool double_buffer; + +} SDL_WindowData; + +#define SDL_RPI_VIDEOLAYER 10000 /* High enough so to occlude everything */ +#define SDL_RPI_MOUSELAYER SDL_RPI_VIDEOLAYER + 1 + + +/****************************************************************************/ +/* SDL_VideoDevice functions declaration */ +/****************************************************************************/ + +/* Display and window functions */ +int RPI_VideoInit(_THIS); +void RPI_VideoQuit(_THIS); +void RPI_GetDisplayModes(_THIS, SDL_VideoDisplay * display); +int RPI_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); +int RPI_CreateWindow(_THIS, SDL_Window * window); +int RPI_CreateWindowFrom(_THIS, SDL_Window * window, const void *data); +void RPI_SetWindowTitle(_THIS, SDL_Window * window); +void RPI_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon); +void RPI_SetWindowPosition(_THIS, SDL_Window * window); +void RPI_SetWindowSize(_THIS, SDL_Window * window); +void RPI_ShowWindow(_THIS, SDL_Window * window); +void RPI_HideWindow(_THIS, SDL_Window * window); +void RPI_RaiseWindow(_THIS, SDL_Window * window); +void RPI_MaximizeWindow(_THIS, SDL_Window * window); +void RPI_MinimizeWindow(_THIS, SDL_Window * window); +void RPI_RestoreWindow(_THIS, SDL_Window * window); +void RPI_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed); +void RPI_DestroyWindow(_THIS, SDL_Window * window); + +/* Window manager function */ +SDL_bool RPI_GetWindowWMInfo(_THIS, SDL_Window * window, + struct SDL_SysWMinfo *info); + +/* OpenGL/OpenGL ES functions */ +int RPI_GLES_LoadLibrary(_THIS, const char *path); +void *RPI_GLES_GetProcAddress(_THIS, const char *proc); +void RPI_GLES_UnloadLibrary(_THIS); +SDL_GLContext RPI_GLES_CreateContext(_THIS, SDL_Window * window); +int RPI_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context); +int RPI_GLES_SetSwapInterval(_THIS, int interval); +int RPI_GLES_GetSwapInterval(_THIS); +int RPI_GLES_SwapWindow(_THIS, SDL_Window * window); +void RPI_GLES_DeleteContext(_THIS, SDL_GLContext context); + +#endif /* __SDL_RPIVIDEO_H__ */ + +/* vi: set ts=4 sw=4 expandtab: */ |