From: Pekka Enberg Date: Fri, 3 Jun 2011 15:28:24 +0000 (+0300) Subject: kvm tools, ui: Add support for SDL framebuffer output target X-Git-Tag: next-20110824~3^2~226 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=2ed18aa259bd61f99e021fd349e25f16b2fcd8b7;p=karo-tx-linux.git kvm tools, ui: Add support for SDL framebuffer output target This patch adds support for SDL based framebuffer. Use the '--sdl' command line option to enable the feature. Acked-by: Ingo Molnar Cc: Cyrill Gorcunov Cc: John Floren Cc: Sasha Levin Signed-off-by: Pekka Enberg --- diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index 17c795be3ff1..55949aa487f4 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -71,6 +71,14 @@ ifeq ($(has_vncserver),y) LIBS += -lvncserver endif +FLAGS_SDL=$(CFLAGS) -lSDL +has_SDL := $(call try-cc,$(SOURCE_SDL),$(FLAGS_SDL)) +ifeq ($(has_SDL),y) + OBJS += ui/sdl.o + CFLAGS += -DCONFIG_HAS_SDL + LIBS += -lSDL +endif + DEPS := $(patsubst %.o,%.d,$(OBJS)) # Exclude BIOS object files from header dependencies. diff --git a/tools/kvm/config/feature-tests.mak b/tools/kvm/config/feature-tests.mak index 0801b54d09ac..bfd10ca652ab 100644 --- a/tools/kvm/config/feature-tests.mak +++ b/tools/kvm/config/feature-tests.mak @@ -136,3 +136,13 @@ int main(void) return 0; } endef + +define SOURCE_SDL +#include + +int main(void) +{ + SDL_Init(SDL_INIT_VIDEO); + return 0; +} +endef diff --git a/tools/kvm/include/kvm/sdl.h b/tools/kvm/include/kvm/sdl.h new file mode 100644 index 000000000000..a5aa411a2c58 --- /dev/null +++ b/tools/kvm/include/kvm/sdl.h @@ -0,0 +1,17 @@ +#ifndef KVM__SDL_H +#define KVM__SDL_H + +#include "kvm/util.h" + +struct framebuffer; + +#ifdef CONFIG_HAS_SDL +void sdl__init(struct framebuffer *fb); +#else +static inline void sdl__init(struct framebuffer *fb) +{ + die("SDL support not compiled in. (install the SDL-dev[el] package)"); +} +#endif + +#endif /* KVM__SDL_H */ diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c index e6e180b8070a..8398287b624a 100644 --- a/tools/kvm/kvm-run.c +++ b/tools/kvm/kvm-run.c @@ -32,6 +32,7 @@ #include #include #include +#include #include /* header files for gitish interface */ @@ -72,6 +73,7 @@ static const char *virtio_9p_dir; static bool single_step; static bool readonly_image[MAX_DISK_IMAGES]; static bool vnc; +static bool sdl; extern bool ioport_debug; extern int active_console; @@ -117,6 +119,7 @@ static const struct option options[] = { OPT_STRING('\0', "virtio-9p", &virtio_9p_dir, "root dir", "Enable 9p over virtio"), OPT_BOOLEAN('\0', "vnc", &vnc, "Enable VNC framebuffer"), + OPT_BOOLEAN('\0', "sdl", &sdl, "Enable SDL framebuffer"), OPT_GROUP("Kernel options:"), OPT_STRING('k', "kernel", &kernel_filename, "kernel", @@ -538,7 +541,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix) memset(real_cmdline, 0, sizeof(real_cmdline)); strcpy(real_cmdline, "notsc noapic noacpi pci=conf1"); - if (vnc) { + if (vnc || sdl) { strcat(real_cmdline, " video=vesafb console=tty0"); vidmode = 0x312; } else { @@ -630,13 +633,19 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix) kvm__init_ram(kvm); + if (vnc || sdl) + fb = vesa__init(kvm); + if (vnc) { kbd__init(kvm); - fb = vesa__init(kvm); + if (fb) + vnc__init(fb); } - if (fb) - vnc__init(fb); + if (sdl) { + if (fb) + sdl__init(fb); + } fb__start(); diff --git a/tools/kvm/ui/sdl.c b/tools/kvm/ui/sdl.c new file mode 100644 index 000000000000..bc69ed95b0b7 --- /dev/null +++ b/tools/kvm/ui/sdl.c @@ -0,0 +1,76 @@ +#include "kvm/sdl.h" + +#include "kvm/framebuffer.h" +#include "kvm/util.h" + +#include +#include + +#define FRAME_RATE 25 + +static void sdl__write(struct framebuffer *fb, u64 addr, u8 *data, u32 len) +{ + memcpy(&fb->mem[addr - fb->mem_addr], data, len); +} + +static void *sdl__thread(void *p) +{ + Uint32 rmask, gmask, bmask, amask; + struct framebuffer *fb = p; + SDL_Surface *guest_screen; + SDL_Surface *screen; + SDL_Event ev; + Uint32 flags; + + if (SDL_Init(SDL_INIT_VIDEO) != 0) + die("Unable to initialize SDL"); + + rmask = 0x000000ff; + gmask = 0x0000ff00; + bmask = 0x00ff0000; + amask = 0x00000000; + + guest_screen = SDL_CreateRGBSurfaceFrom(fb->mem, fb->width, fb->height, fb->depth, fb->width * fb->depth / 8, rmask, gmask, bmask, amask); + if (!guest_screen) + die("Unable to create SDL RBG surface"); + + flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL; + + screen = SDL_SetVideoMode(fb->width, fb->height, fb->depth, flags); + if (!screen) + die("Unable to set SDL video mode"); + + for (;;) { + SDL_BlitSurface(guest_screen, NULL, screen, NULL); + SDL_UpdateRect(screen, 0, 0, 0, 0); + while (SDL_PollEvent(&ev)) { + switch (ev.type) { + case SDL_QUIT: + goto exit; + } + } + SDL_Delay(1000 / FRAME_RATE); + } +exit: + return NULL; +} + +static int sdl__start(struct framebuffer *fb) +{ + pthread_t thread; + + if (pthread_create(&thread, NULL, sdl__thread, fb) != 0) + return -1; + + return 0; +} + +static struct fb_target_operations sdl_ops = { + .start = sdl__start, + .write = sdl__write, +}; + +void sdl__init(struct framebuffer *fb) +{ + fb__attach(fb, &sdl_ops); +}