summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmad Fatoum <ahmad@a3f.at>2021-01-31 21:18:40 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2021-02-08 10:57:05 +0100
commit12ad41f91f1824eb141e368294d97860644ab777 (patch)
tree032da73369f4cf1e2a4614c87b358a87fa64659b
parentf38f34a2f41e5981f2995231d94688d31104befc (diff)
downloadbarebox-12ad41f91f1824eb141e368294d97860644ab777.tar.gz
barebox-12ad41f91f1824eb141e368294d97860644ab777.tar.xz
sandbox: migrate to SDL 2.0
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 <ahmad@a3f.at> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--arch/sandbox/Kconfig3
-rw-r--r--arch/sandbox/Makefile6
-rw-r--r--arch/sandbox/mach-sandbox/include/mach/linux.h17
-rw-r--r--arch/sandbox/os/Makefile4
-rw-r--r--arch/sandbox/os/sdl.c146
-rw-r--r--drivers/video/Kconfig1
-rw-r--r--drivers/video/sdl.c37
7 files changed, 120 insertions, 94 deletions
diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 5d1702480f..1a4e3bacf6 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -44,3 +44,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 17f9a298d7..ea594944e4 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 b26bfc24a2..c636a9af9c 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 15d688bfdd..575b1a2130 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 9a35279eb7..623e24cf0b 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 <plagnioj@jcrosoft.com>
- *
- * 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 9ec6ea4248..b6d468c63c 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 9811b2cf12..e9debc51b1 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 = {