fb_sdl: update to use sdl2

Following the official migration guide of SDL [1], the
fb_sdl framebuffer driver was update from SDL1 to SDL2.

The sdl2 port in world/src/lib/sdl2 is used.

Since SDL1 is in maintenance mode [2], support for other
display servers than X11 will never be implemented. In
particular, support for Wayland is missing from SDL1.

Fortunately, a port of sdl2 is maintained in genode-world.

As SDL2 is actively developed, it will provide support for
modern hardware architectures, and has mature support for
Wayland [3].

[1]: https://wiki.libsdl.org/SDL2/MigrationGuide
[2]: https://wiki.debian.org/Wayland#SDL1_.28unsupported.29
[3]: https://wiki.debian.org/Wayland#SDL2_.28supported_since_2.0.2.2B-.29

Issue #4993
This commit is contained in:
Robin Eklind 2023-09-07 18:18:02 +02:00 committed by Christian Helmuth
parent 5abd2dddb8
commit 9799adda79
3 changed files with 77 additions and 44 deletions

View File

@ -114,12 +114,12 @@ static inline Input::Keycode convert_keycode(int sdl_keycode)
case SDLK_F15: return KEY_F15; case SDLK_F15: return KEY_F15;
/* special keys */ /* special keys */
case SDLK_PRINT: return KEY_PRINT; case SDLK_PRINTSCREEN: return KEY_PRINT;
case SDLK_SCROLLOCK: return KEY_SCROLLLOCK; case SDLK_SCROLLLOCK: return KEY_SCROLLLOCK;
case SDLK_MENU: return KEY_MENU; case SDLK_MENU: return KEY_MENU;
/* key state modifier keys */ /* key state modifier keys */
case SDLK_NUMLOCK: return KEY_NUMLOCK; case SDLK_NUMLOCKCLEAR: return KEY_NUMLOCK;
case SDLK_CAPSLOCK: return KEY_CAPSLOCK; case SDLK_CAPSLOCK: return KEY_CAPSLOCK;
case SDLK_RSHIFT: return KEY_RIGHTSHIFT; case SDLK_RSHIFT: return KEY_RIGHTSHIFT;
case SDLK_LSHIFT: return KEY_LEFTSHIFT; case SDLK_LSHIFT: return KEY_LEFTSHIFT;
@ -127,8 +127,8 @@ static inline Input::Keycode convert_keycode(int sdl_keycode)
case SDLK_LCTRL: return KEY_LEFTCTRL; case SDLK_LCTRL: return KEY_LEFTCTRL;
case SDLK_RALT: return KEY_RIGHTALT; case SDLK_RALT: return KEY_RIGHTALT;
case SDLK_LALT: return KEY_LEFTALT; case SDLK_LALT: return KEY_LEFTALT;
case SDLK_RMETA: return KEY_RIGHTMETA; case SDLK_RGUI: return KEY_RIGHTMETA;
case SDLK_LMETA: return KEY_LEFTMETA; case SDLK_LGUI: return KEY_LEFTMETA;
default: return KEY_UNKNOWN; default: return KEY_UNKNOWN;
} }

View File

@ -22,7 +22,8 @@
/* Linux includes */ /* Linux includes */
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wconversion"
#include <SDL/SDL.h> #pragma GCC diagnostic ignored "-Wtype-limits"
#include <SDL2/SDL.h>
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
/* local includes */ /* local includes */
@ -37,7 +38,10 @@ namespace Fb_sdl {
/* fatal exceptions */ /* fatal exceptions */
struct Sdl_init_failed : Genode::Exception { }; struct Sdl_init_failed : Genode::Exception { };
struct Sdl_videodriver_not_supported : Genode::Exception { }; struct Sdl_videodriver_not_supported : Genode::Exception { };
struct Sdl_setvideomode_failed : Genode::Exception { }; struct Sdl_createwindow_failed : Genode::Exception { };
struct Sdl_createrenderer_failed : Genode::Exception { };
struct Sdl_creatergbsurface_failed : Genode::Exception { };
struct Sdl_createtexture_failed : Genode::Exception { };
struct Fb_sdl::Main struct Fb_sdl::Main
@ -65,17 +69,6 @@ struct Fb_sdl::Main
throw Sdl_init_failed(); throw Sdl_init_failed();
} }
/*
* We're testing only X11.
*/
char driver[16] = { 0 };
SDL_VideoDriverName(driver, sizeof(driver));
if (::strcmp(driver, "x11") != 0) {
error("fb_sdl works on X11 only. "
"Your SDL backend is ", Genode::Cstring(driver), ".");
throw Sdl_videodriver_not_supported();
}
SDL_ShowCursor(0); SDL_ShowCursor(0);
} }
@ -85,25 +78,62 @@ struct Fb_sdl::Main
{ {
Area const size; Area const size;
SDL_Renderer &_sdl_renderer = _init_sdl_renderer();
SDL_Surface &_sdl_surface = _init_sdl_surface(); SDL_Surface &_sdl_surface = _init_sdl_surface();
SDL_Texture &_sdl_texture = _init_sdl_texture();
SDL_Renderer &_init_sdl_renderer()
{
unsigned const window_flags = 0;
SDL_Window *window_ptr = SDL_CreateWindow("fb_sdl", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, size.w(), size.h(), window_flags);
if (!window_ptr) {
error("SDL_CreateWindow failed (", Genode::Cstring(SDL_GetError()), ")");
throw Sdl_createwindow_failed();
}
SDL_SetWindowResizable(window_ptr, SDL_TRUE);
int const index = -1;
unsigned const renderer_flags = SDL_RENDERER_SOFTWARE;
SDL_Renderer *renderer_ptr = SDL_CreateRenderer(window_ptr, index, renderer_flags);
if (!renderer_ptr) {
error("SDL_CreateRenderer failed (", Genode::Cstring(SDL_GetError()), ")");
throw Sdl_createrenderer_failed();
}
return *renderer_ptr;
}
SDL_Surface &_init_sdl_surface() SDL_Surface &_init_sdl_surface()
{ {
unsigned const bpp = 32; unsigned const flags = 0;
unsigned const flags = SDL_SWSURFACE | SDL_RESIZABLE; unsigned const bpp = 32;
unsigned const red_mask = 0x00FF0000;
SDL_Surface *surface_ptr = nullptr; unsigned const green_mask = 0x0000FF00;
unsigned const blue_mask = 0x000000FF;
if (SDL_VideoModeOK(size.w(), size.h(), bpp, flags)) unsigned const alpha_mask = 0xFF000000;
surface_ptr = SDL_SetVideoMode(size.w(), size.h(), bpp, flags);
SDL_Surface *surface_ptr = SDL_CreateRGBSurface(flags, size.w(), size.h(), bpp, red_mask, green_mask, blue_mask, alpha_mask);
if (!surface_ptr) { if (!surface_ptr) {
error("SDL_SetVideoMode failed (", Genode::Cstring(SDL_GetError()), ")"); error("SDL_CreateRGBSurface failed (", Genode::Cstring(SDL_GetError()), ")");
throw Sdl_setvideomode_failed(); throw Sdl_creatergbsurface_failed();
} }
return *surface_ptr; return *surface_ptr;
} }
SDL_Texture &_init_sdl_texture()
{
SDL_Texture *texture_ptr = SDL_CreateTexture(&_sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, size.w(), size.h());
if (!texture_ptr) {
error("SDL_CreateTexture failed (", Genode::Cstring(SDL_GetError()), ")");
throw Sdl_createtexture_failed();
}
return *texture_ptr;
}
Sdl_screen(Area size) : size(size) { } Sdl_screen(Area size) : size(size) { }
template <typename FN> template <typename FN>
@ -113,9 +143,12 @@ struct Fb_sdl::Main
fn(surface); fn(surface);
} }
void flush(Capture::Rect rect) void flush()
{ {
SDL_UpdateRect(&_sdl_surface, rect.x1(), rect.y1(), rect.w(), rect.h()); SDL_UpdateTexture(&_sdl_texture, nullptr, _sdl_surface.pixels, _sdl_surface.pitch);
SDL_RenderClear(&_sdl_renderer);
SDL_RenderCopy(&_sdl_renderer, &_sdl_texture, nullptr, nullptr);
SDL_RenderPresent(&_sdl_renderer);
} }
}; };
@ -151,8 +184,7 @@ struct Fb_sdl::Main
}); });
/* flush pixels in SDL window */ /* flush pixels in SDL window */
affected.for_each_rect([&] (Capture::Rect const rect) { _sdl_screen->flush();
_sdl_screen->flush(rect); });
} }
void _handle_timer() void _handle_timer()
@ -185,14 +217,16 @@ void Fb_sdl::Main::_handle_sdl_event(Event_batch &batch, SDL_Event const &event)
{ {
using namespace Input; using namespace Input;
if (event.type == SDL_VIDEORESIZE) { if (event.type == SDL_WINDOWEVENT_RESIZED) {
if (event.resize.w < 0 || event.resize.h < 0) { int w = event.window.data1;
int h = event.window.data2;
if (w < 0 || h < 0) {
warning("attempt to resize to negative size"); warning("attempt to resize to negative size");
return; return;
} }
_resize(Area((unsigned)event.resize.w, (unsigned)event.resize.h)); _resize(Area((unsigned)w, (unsigned)h));
return; return;
} }
@ -234,10 +268,6 @@ void Fb_sdl::Main::_handle_sdl_event(Event_batch &batch, SDL_Event const &event)
case SDL_KEYUP: case SDL_KEYUP:
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_WHEELUP
|| event.button.button == SDL_BUTTON_WHEELDOWN)
/* ignore */
return;
batch.submit(Release{keycode}); batch.submit(Release{keycode});
return; return;
@ -245,12 +275,15 @@ void Fb_sdl::Main::_handle_sdl_event(Event_batch &batch, SDL_Event const &event)
case SDL_KEYDOWN: case SDL_KEYDOWN:
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
if (event.button.button == SDL_BUTTON_WHEELUP) batch.submit(Press{keycode});
return;
case SDL_MOUSEWHEEL:
if (event.wheel.y > 0)
batch.submit(Wheel{0, 1}); batch.submit(Wheel{0, 1});
else if (event.button.button == SDL_BUTTON_WHEELDOWN) else if (event.wheel.y < 0)
batch.submit(Wheel{0, -1}); batch.submit(Wheel{0, -1});
else
batch.submit(Press{keycode});
return; return;
default: default:

View File

@ -2,5 +2,5 @@ TARGET = fb_sdl
LIBS = lx_hybrid blit LIBS = lx_hybrid blit
REQUIRES = linux REQUIRES = linux
SRC_CC = main.cc SRC_CC = main.cc
LX_LIBS = sdl LX_LIBS = sdl2
INC_DIR += $(PRG_DIR) INC_DIR += $(PRG_DIR) /usr/include/SDL2