SDL 2.0 has been released more than 7 years ago and should be available
everywhere. Replace barebox's SDL 1.2 with SDL 2.0 instead:

 - better maintained

 - At least on Debian, you can't install x86_64 and i386 libsdl-dev at
   the same time, which makes a quick use of CONFIG_SANDBOX_LINUX_I386
   harder as the user needs to reinstall libraries. With SDL 2.0, it
   works

 - SDL 2.0 has easier audio API, which will be used in a later commit

 - Wayland support for sandbox video driver

Port to SDL 2.0 and as we touch everything anyway, rename the
sdl_ functions to start with sdl_video_ to differentiate from upcoming
sdl_sound_.

Signed-off-by: Ahmad Fatoum <[email protected]>
---
 arch/sandbox/Kconfig                          |   3 +
 arch/sandbox/Makefile                         |   6 +-
 .../sandbox/mach-sandbox/include/mach/linux.h |  17 +-
 arch/sandbox/os/Makefile                      |   4 +-
 arch/sandbox/os/sdl.c                         | 146 ++++++++++--------
 drivers/video/Kconfig                         |   1 +
 drivers/video/sdl.c                           |  37 +++--
 7 files changed, 120 insertions(+), 94 deletions(-)

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index d9fc0c947b02..deff7f56a025 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -43,3 +43,6 @@ config 64BIT
 
 config SANDBOX_LINUX_I386
        bool "32-bit x86 barebox" if CC_HAS_LINUX_I386_SUPPORT
+
+config SDL
+       bool
diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile
index 17f9a298d773..ea594944e4eb 100644
--- a/arch/sandbox/Makefile
+++ b/arch/sandbox/Makefile
@@ -37,8 +37,8 @@ archprepare: maketools
 
 PHONY += maketools
 
-ifeq ($(CONFIG_DRIVER_VIDEO_SDL),y)
-SDL_LIBS := $(shell pkg-config sdl --libs)
+ifeq ($(CONFIG_SDL),y)
+SDL_LIBS := $(shell pkg-config sdl2 --libs)
 endif
 
 ifeq ($(CONFIG_GPIO_LIBFTDI1),y)
@@ -64,7 +64,7 @@ endif
 BAREBOX_LDFLAGS += \
        -Wl,-T,$(BAREBOX_LDS) \
        -Wl,--whole-archive $(BAREBOX_OBJS) -Wl,--no-whole-archive \
-       -lrt -lpthread $(SDL_LIBS) $(FTDI1_LIBS) \
+       -lrt $(SDL_LIBS) $(FTDI1_LIBS) \
        $(SANITIZER_LIBS)
 
 cmd_barebox__ = $(CC) -o $@ $(BAREBOX_LDFLAGS)
diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h 
b/arch/sandbox/mach-sandbox/include/mach/linux.h
index b26bfc24a291..c636a9af9cd2 100644
--- a/arch/sandbox/mach-sandbox/include/mach/linux.h
+++ b/arch/sandbox/mach-sandbox/include/mach/linux.h
@@ -38,13 +38,16 @@ struct linux_console_data {
 
 extern int sdl_xres;
 extern int sdl_yres;
-void sdl_close(void);
-int sdl_open(int xres, int yres, int bpp, void* buf);
-void sdl_stop_timer(void);
-void sdl_start_timer(void);
-void sdl_get_bitfield_rgba(struct fb_bitfield *r, struct fb_bitfield *g,
-                           struct fb_bitfield *b, struct fb_bitfield *a);
-void sdl_setpixel(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
+struct sdl_fb_info {
+       void *screen_base;
+       int xres;
+       int yres;
+       int bpp;
+       int rmask, gmask, bmask, amask;
+};
+int sdl_video_open(const struct sdl_fb_info *);
+void sdl_video_pause(void);
+void sdl_video_close(void);
 
 struct ft2232_bitbang;
 struct ft2232_bitbang *barebox_libftdi1_open(int vendor_id, int device_id,
diff --git a/arch/sandbox/os/Makefile b/arch/sandbox/os/Makefile
index 15d688bfdd1b..575b1a213050 100644
--- a/arch/sandbox/os/Makefile
+++ b/arch/sandbox/os/Makefile
@@ -17,8 +17,8 @@ endif
 obj-y = common.o tap.o
 obj-$(CONFIG_MALLOC_LIBC) += libc_malloc.o
 
-CFLAGS_sdl.o = $(shell pkg-config sdl --cflags)
-obj-$(CONFIG_DRIVER_VIDEO_SDL) += sdl.o
+CFLAGS_sdl.o = $(shell pkg-config sdl2 --cflags)
+obj-$(CONFIG_SDL) += sdl.o
 
 CFLAGS_ftdi.o = $(shell pkg-config libftdi1 --cflags)
 obj-$(CONFIG_GPIO_LIBFTDI1) += ftdi.o
diff --git a/arch/sandbox/os/sdl.c b/arch/sandbox/os/sdl.c
index 9a35279eb79e..623e24cf0b26 100644
--- a/arch/sandbox/os/sdl.c
+++ b/arch/sandbox/os/sdl.c
@@ -1,103 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <[email protected]>
- *
- * GPL v2
+ * Copyright (c) 2021 Ahmad Fatoum
  */
 
 #include <stdio.h>
+#include <stdbool.h>
 #include <SDL.h>
-#include <time.h>
-#include <signal.h>
 #include <mach/linux.h>
-#include <unistd.h>
-#include <pthread.h>
 
-struct fb_bitfield {
-       uint32_t offset;                        /* beginning of bitfield        
*/
-       uint32_t length;                        /* length of bitfield           
*/
-       uint32_t msb_right;                     /* != 0 : Most significant bit 
is */
-                                       /* right */
-};
+static void sdl_perror(const char *what)
+{
+       printf("SDL: Could not %s: %s.\n", what, SDL_GetError());
+}
 
-static SDL_Surface *real_screen;
-static void *buffer = NULL;
-pthread_t th;
+static struct sdl_fb_info info;
+static SDL_atomic_t shutdown;
+SDL_Window *window;
 
-static void sdl_copy_buffer(SDL_Surface *screen)
+static int scanout(void *ptr)
 {
-       if (SDL_MUSTLOCK(screen)) {
-               if (SDL_LockSurface(screen) < 0)
-                       return;
+       SDL_Renderer *renderer;
+       SDL_Surface *surface;
+       SDL_Texture *texture;
+       void *buf = info.screen_base;
+       int ret = -1;
+
+       renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+       if (!renderer) {
+               sdl_perror("create renderer");
+               return -1;
        }
 
-       memcpy(screen->pixels, buffer, screen->pitch * screen->h);
+       surface = SDL_CreateRGBSurface(0, info.xres, info.yres, info.bpp,
+                                      info.rmask, info.gmask, info.bmask, 
info.amask);
+       if (!surface) {
+               sdl_perror("create surface");
+               goto destroy_renderer;
+       }
 
-       if(SDL_MUSTLOCK(screen))
-               SDL_UnlockSurface(screen);
-}
+       texture = SDL_CreateTextureFromSurface(renderer, surface);
+       if (!texture) {
+               sdl_perror("create texture");
+               goto free_surface;
+       }
 
-static void *threadStart(void *ptr)
-{
-       while (1) {
-               usleep(1000 * 100);
+       while (!SDL_AtomicGet(&shutdown)) {
+               SDL_Delay(100);
 
-               sdl_copy_buffer(real_screen);
-               SDL_Flip(real_screen);
+               SDL_UpdateTexture(texture, NULL, buf, surface->pitch);
+               SDL_RenderClear(renderer);
+               SDL_RenderCopy(renderer, texture, NULL, NULL);
+               SDL_RenderPresent(renderer);
        }
 
-       return 0;
-}
+       ret = 0;
 
-void sdl_start_timer(void)
-{
-       pthread_attr_t attr;
-       pthread_attr_init(&attr);
-       pthread_create(&th, &attr, threadStart, NULL);
-}
+       SDL_DestroyTexture(texture);
+free_surface:
+       SDL_FreeSurface(surface);
+destroy_renderer:
+       SDL_DestroyRenderer(renderer);
 
-void sdl_stop_timer(void)
-{
-       pthread_cancel(th);
+       return ret;
 }
 
-void sdl_get_bitfield_rgba(struct fb_bitfield *r, struct fb_bitfield *g,
-                           struct fb_bitfield *b, struct fb_bitfield *a)
+static SDL_Thread *thread;
+
+void sdl_video_close(void)
 {
-       SDL_Surface *screen = real_screen;
-
-       r->length = 8 - screen->format->Rloss;
-       r->offset = screen->format->Rshift;
-       g->length = 8 - screen->format->Gloss;
-       g->offset = screen->format->Gshift;
-       b->length = 8 - screen->format->Bloss;
-       b->offset = screen->format->Bshift;
-       a->length = 8 - screen->format->Aloss;
-       a->offset = screen->format->Ashift;
+       SDL_AtomicSet(&shutdown, true); /* implies full memory barrier */
+       SDL_WaitThread(thread, NULL);
+       SDL_AtomicSet(&shutdown, false);
+       SDL_DestroyWindow(window);
+       SDL_QuitSubSystem(SDL_INIT_VIDEO);
 }
 
-int sdl_open(int xres, int yres, int bpp, void* buf)
+int sdl_video_open(const struct sdl_fb_info *_info)
 {
-       int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
+       info = *_info;
 
-       if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
-               printf("Could not initialize SDL: %s.\n", SDL_GetError());
+       if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
+               sdl_perror("initialize SDL Video");
                return -1;
        }
 
-       real_screen = SDL_SetVideoMode(xres, yres, bpp, flags);
-       if (!real_screen) {
-               sdl_close();
-               fprintf(stderr, "Couldn't create renderer: %s\n", 
SDL_GetError());
-               return -1;
+       window = SDL_CreateWindow("barebox", SDL_WINDOWPOS_CENTERED, 
SDL_WINDOWPOS_CENTERED,
+                                 info.xres, info.yres, 0);
+       if (!window) {
+               sdl_perror("create window");
+               goto quit_subsystem;
        }
 
-       buffer = buf;
+       /* All scanout needs to happen in the same thread, because not all
+        * graphic backends are thread-safe. The window is created in the main
+        * thread though to work around libEGL crashing with 
SDL_VIDEODRIVER=wayland
+        */
+
+       thread = SDL_CreateThread(scanout, "video-scanout", NULL);
+       if (!thread) {
+               sdl_perror("start scanout thread");
+               goto destroy_window;
+       }
 
        return 0;
-}
 
-void sdl_close(void)
-{
-       sdl_stop_timer();
-       SDL_Quit();
+destroy_window:
+       SDL_DestroyWindow(window);
+quit_subsystem:
+       SDL_QuitSubSystem(SDL_INIT_VIDEO);
+
+       return -1;
 }
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 9ec6ea4248c1..b6d468c63c03 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -82,6 +82,7 @@ endif
 config DRIVER_VIDEO_SDL
        bool "SDL framebuffer driver"
        depends on SANDBOX
+       select SDL
 
 config DRIVER_VIDEO_PXA
        bool "PXA27x framebuffer driver"
diff --git a/drivers/video/sdl.c b/drivers/video/sdl.c
index 9811b2cf128e..e9debc51b1e9 100644
--- a/drivers/video/sdl.c
+++ b/drivers/video/sdl.c
@@ -13,23 +13,25 @@
 #include <errno.h>
 #include <gui/graphic_utils.h>
 
+#define to_mask(color) GENMASK(color.length - 1, color.offset)
+
 static void sdlfb_enable(struct fb_info *info)
 {
-       int ret;
-
-       ret = sdl_open(info->xres, info->yres, info->bits_per_pixel,
-                    info->screen_base);
-       if (ret)
-               return;
-       sdl_get_bitfield_rgba(&info->red, &info->green, &info->blue, 
&info->transp);
-
-       sdl_start_timer();
+       struct sdl_fb_info sdl_info = {
+               .screen_base = info->screen_base,
+               .xres = info->xres, .yres = info->yres, .bpp = 
info->bits_per_pixel,
+               .rmask = to_mask(info->red),
+               .gmask = to_mask(info->green),
+               .bmask = to_mask(info->blue),
+               .amask = to_mask(info->transp),
+       };
+
+       sdl_video_open(&sdl_info);
 }
 
 static void sdlfb_disable(struct fb_info *info)
 {
-       sdl_stop_timer();
-       sdl_close();
+       sdl_video_close();
 }
 
 static struct fb_ops sdlfb_ops = {
@@ -48,10 +50,19 @@ static int sdlfb_probe(struct device_d *dev)
        fb = xzalloc(sizeof(*fb));
        fb->modes.modes = fb->mode = dev->platform_data;
        fb->modes.num_modes = 1;
-       fb->bits_per_pixel = 4 << 3;
        fb->xres = fb->mode->xres;
        fb->yres = fb->mode->yres;
 
+       fb->bits_per_pixel = 32;
+       fb->transp.length = 8;
+       fb->red.length = 8;
+       fb->green.length = 8;
+       fb->blue.length = 8;
+       fb->transp.offset = 24;
+       fb->red.offset = 16;
+       fb->green.offset = 8;
+       fb->blue.offset = 0;
+
        fb->priv = fb;
        fb->fbops = &sdlfb_ops;
 
@@ -68,7 +79,6 @@ static int sdlfb_probe(struct device_d *dev)
 
        kfree(fb->screen_base);
        kfree(fb);
-       sdl_close();
        return ret;
 }
 
@@ -78,7 +88,6 @@ static void sdlfb_remove(struct device_d *dev)
 
        kfree(fb->screen_base);
        kfree(fb);
-       sdl_close();
 }
 
 static struct driver_d sdlfb_driver = {
-- 
2.30.0


_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to