]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools, ui: Add support for SDL framebuffer output target
authorPekka Enberg <penberg@kernel.org>
Fri, 3 Jun 2011 15:28:24 +0000 (18:28 +0300)
committerPekka Enberg <penberg@kernel.org>
Fri, 3 Jun 2011 17:59:04 +0000 (20:59 +0300)
This patch adds support for SDL based framebuffer. Use the '--sdl' command line
option to enable the feature.

Acked-by: Ingo Molnar <mingo@elte.hu>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: John Floren <john@jfloren.net>
Cc: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/Makefile
tools/kvm/config/feature-tests.mak
tools/kvm/include/kvm/sdl.h [new file with mode: 0644]
tools/kvm/kvm-run.c
tools/kvm/ui/sdl.c [new file with mode: 0644]

index 17c795be3ff1288cdcdee5a5f1e59c0849771403..55949aa487f4f884612411f97aef281d79a77bb5 100644 (file)
@@ -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.
index 0801b54d09acf7b3ea11e841aed183b83cdd3644..bfd10ca652ab44ca710dd955dcda709e9ff08115 100644 (file)
@@ -136,3 +136,13 @@ int main(void)
        return 0;
 }
 endef
+
+define SOURCE_SDL
+#include <SDL/SDL.h>
+
+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 (file)
index 0000000..a5aa411
--- /dev/null
@@ -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 */
index e6e180b8070a3eb9697c4d6bc2da57b0eaafd01c..8398287b624aba0b3961e123be0ac60eaa74a4a4 100644 (file)
@@ -32,6 +32,7 @@
 #include <kvm/ioeventfd.h>
 #include <kvm/i8042.h>
 #include <kvm/vnc.h>
+#include <kvm/sdl.h>
 #include <kvm/framebuffer.h>
 
 /* 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 (file)
index 0000000..bc69ed9
--- /dev/null
@@ -0,0 +1,76 @@
+#include "kvm/sdl.h"
+
+#include "kvm/framebuffer.h"
+#include "kvm/util.h"
+
+#include <SDL/SDL.h>
+#include <pthread.h>
+
+#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);
+}