[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Lost] [PATCH] [1/5] + cdi: Interface fuer Grafiktreiber



Ein Interface für Grafiktreiber von mir und Janosch.

Mathias
From e03c440f1e7e240e9cd9917c44b5b01c30c7c640 Mon Sep 17 00:00:00 2001
From: Mathias Gottschlag <mathias-go@xxxxxx>
Date: Tue, 14 Oct 2008 15:49:15 +0200
Subject: [PATCH] + cdi: Interface fuer Grafiktreiber

---
 src/modules/cdi/include/cdi.h        |    3 +-
 src/modules/cdi/include/cdi/video.h  |  270 ++++++++++++++++++++++++++++++++++
 src/modules/cdi/lib/video/draw.c     |  204 +++++++++++++++++++++++++
 src/modules/cdi/lib/video/draw.h     |   23 +++
 src/modules/cdi/lib/video/video.c    |  195 ++++++++++++++++++++++++
 src/modules/cdi/lib/video/video.h    |   26 ++++
 src/modules/cdi/lib/video/vscreens.c |  250 +++++++++++++++++++++++++++++++
 src/modules/cdi/lib/video/vscreens.h |   47 ++++++
 8 files changed, 1017 insertions(+), 1 deletions(-)
 create mode 100644 src/modules/cdi/include/cdi/video.h
 create mode 100644 src/modules/cdi/lib/video/draw.c
 create mode 100644 src/modules/cdi/lib/video/draw.h
 create mode 100644 src/modules/cdi/lib/video/video.c
 create mode 100644 src/modules/cdi/lib/video/video.h
 create mode 100644 src/modules/cdi/lib/video/vscreens.c
 create mode 100644 src/modules/cdi/lib/video/vscreens.h

diff --git a/src/modules/cdi/include/cdi.h b/src/modules/cdi/include/cdi.h
index cc3c7b9..689b550 100644
--- a/src/modules/cdi/include/cdi.h
+++ b/src/modules/cdi/include/cdi.h
@@ -20,7 +20,8 @@
 typedef enum {
     CDI_UNKNOWN         = 0,
     CDI_NETWORK         = 1,
-    CDI_STORAGE         = 2
+    CDI_STORAGE         = 2,
+    CDI_VIDEO           = 3
 } cdi_device_type_t;
 
 struct cdi_driver;
diff --git a/src/modules/cdi/include/cdi/video.h b/src/modules/cdi/include/cdi/video.h
new file mode 100644
index 0000000..2191240
--- /dev/null
+++ b/src/modules/cdi/include/cdi/video.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2007 Mathias Gottschlag, Janosch Graef
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it 
+ * and/or modify it under the terms of the Do What The Fuck You Want 
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+#ifndef _CDI_VIDEO_H_
+#define _CDI_VIDEO_H_
+
+#include "cdi.h"
+#include "cdi/lists.h"
+
+typedef struct {
+  unsigned int width;
+  unsigned int height;
+  unsigned int depth;
+  enum {
+    CDI_VIDEO_TEXT,
+    CDI_VIDEO_GRAPHIC
+  } type;
+} cdi_video_mode_t;
+
+typedef enum {
+  CDI_VIDEO_PRIO_HIGH,
+  CDI_VIDEO_PRIO_NORMAL,
+  CDI_VIDEO_PRIO_LOW,
+} cdi_video_usage_hint_t;
+
+typedef enum {
+  CDI_VIDEO_FMT_MONO_1,
+  CDI_VIDEO_FMT_MONO_8,
+  CDI_VIDEO_FMT_R8G8B8_24,
+  CDI_VIDEO_FMT_B8G8R8_24,
+  CDI_VIDEO_FMT_R8G8B8_32,
+  CDI_VIDEO_FMT_B8G8R8_32,
+  CDI_VIDEO_FMT_R5G6B5_16,
+  CDI_VIDEO_FMT_B5G6R5_16,
+  CDI_VIDEO_FMT_R5G5B5_16,
+  CDI_VIDEO_FMT_B5G5R5_16,
+  CDI_VIDEO_FMT_GREY_8,
+} cdi_video_bitmap_format_t;
+
+struct cdi_video_bitmap {
+  int width;
+  int height;
+  cdi_video_bitmap_format_t format;
+  char *pixeldata;
+};
+
+typedef enum {
+  CDI_VIDEO_ROP_COPY,
+  CDI_VIDEO_ROP_OR,
+  CDI_VIDEO_ROP_AND,
+  CDI_VIDEO_ROP_XOR,
+} cdi_video_raster_op_t;
+
+struct cdi_video_device {
+  /// CDI-Geraet
+  struct cdi_device dev;
+
+  /// Liste der Bildschirme
+  cdi_list_t displays;
+};
+
+struct cdi_video_display {
+  /// Videogeraet, dem dieser Bildschirm angehoert
+  struct cdi_video_device *device;
+
+  /// Ob Bildschirm aktiviert ist
+  int activated;
+
+  // Derzeitiger ROP
+  cdi_video_raster_op_t raster_op;
+
+  /// Momentaner Modus
+  cdi_video_mode_t *mode;
+};
+
+struct cdi_video_driver {
+  /// CDI-Treiber
+  struct cdi_driver drv;
+
+  // Basis-Funktionen
+  /**
+   * Aktiviert einen Bildschirm
+   *  @param display Bildschirm
+   *  @return 0 = Erfolg; -1 = Fehlschlag
+   *  @note Kann nur angewendet werden wenn der Bildschirm _nicht_ aktiviert ist
+   */
+  int (*display_enable)(struct cdi_video_display *display);
+
+  /**
+   * Deaktiviert einen Bildschirm
+   *  @param display Bildschirm
+   *  @return 0 = Erfolg; -1 = Fehlschlag
+   *  @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  int (*display_disable)(struct cdi_video_display *display);
+
+  /**
+   * Leert einen Bildschirm
+   *  @param display Bildschirm
+   *  @return 0 = Erfolg; -1 = Fehlschlag
+   *  @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  int (*display_clear)(struct cdi_video_display *display);
+
+  /**
+   * Setzt die Aufloesung eines Bildschirms
+   *  @param display Bildschirm
+   *  @param mode Modus
+   *  @return 0 = Erfolg; -1 = Fehlschlag
+   */
+  int (*display_set_mode)(struct cdi_video_display *display,cdi_video_mode_t *mode);
+
+  /**
+   * Gibt eine Liste aller Modi zurueck
+   *  @param display Bildschirm
+   *  @return Liste aller moeglichen Modi
+   */
+  cdi_list_t (*display_get_mode_list)(struct cdi_video_display *display);
+
+  // Bitmap-Funktionen
+
+  /**
+   * Erstellt ein Bitmap
+   * @param device Videogeraet
+   * @param width Breite des Bitmaps
+   * @param height Hoehe des Bitmaps
+   * @param format Format der Pixeldaten
+   * @param data Pixel, oder 0, wenn das Bitmap vom Treiber beschrieben wird
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  struct cdi_video_bitmap *(*bitmap_create)(struct cdi_video_device *device, unsigned int width, unsigned int height, cdi_video_bitmap_format_t format, void *data);
+
+  /**
+   * Loescht ein Bitmap
+   * @param device Videogeraet
+   * @param bitmap Zu loeschendes Bitmap
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  void (*bitmap_destroy)(struct cdi_video_device *device, struct cdi_video_bitmap *bitmap);
+
+ /**
+   * Setzt den Gebrauchsmodus eines Bitmaps (bestimmt zB, ob ein Bitmap gecacht wird)
+   * @param device Videogeraet
+   * @param bitmap Betroffenes Bitmap
+   * @param hint Hinweis auf die Priorität des Bitmaps
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  void (*bitmap_set_usage_hint)(struct cdi_video_device *device, struct cdi_video_bitmap *bitmap, cdi_video_usage_hint_t hint);
+
+  // Zeichen-Funktionen
+
+  /**
+   * Setzt den Raster-Op für die folgenden Zeichenfunktionen.
+   * Der Raster-Op bestimmt, auf welche Art Grafik gezeichnet wird.
+   * @param display Display, auf das gezeichnet wird
+   * @param rop Raster-Op
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  void (*set_raster_op)(struct cdi_video_display *display, cdi_video_raster_op_t rop);
+
+  /**
+   * Setzt das Ziel für alle Zeichenfunktionen. Kann entweder ein Bitmap oder der Bildschirm sein.
+   * @param display Betroffenes Display
+   * @param bitmap Zielbitmap fuer alle Zeichenfunktionen. Wenn 0, dann wird auf den Bildschirm gerendert.
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  void (*set_target)(struct cdi_video_display *display, struct cdi_video_bitmap *bitmap);
+
+  /**
+   * Zeichnet eine Linie
+   * @param display Display, auf das gezeichnet wird
+   * @param x1 X-Koordinate des Anfangs
+   * @param y1 Y-Koordinate des Anfangs
+   * @param x1 X-Koordinate des Endpunktes
+   * @param y1 Y-Koordinate des Endpunktes
+   * @param color Farbe der Linie
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  void (*draw_line)(struct cdi_video_display *display, unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, int color);
+  /**
+   * Zeichnet ein Rechteck
+   * @param display Display, auf das gezeichnet wird
+   * @param x X-Koordinate
+   * @param y Y-Koordinate
+   * @param width Breite
+   * @param height Hoehe
+   * @param color Farbe des Rechtecks
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  void (*draw_rectangle)(struct cdi_video_display *display, unsigned int x, unsigned int y, unsigned int width, unsigned int height, int color);
+  /**
+   * Zeichnet eine Ellipse
+   * @param display Display, auf das gezeichnet wird
+   * @param x X-Koordinate
+   * @param y Y-Koordinate
+   * @param width Breite
+   * @param height Hoehe
+   * @param color Farbe der Ellipse
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  void (*draw_ellipse)(struct cdi_video_display *display, unsigned int x, unsigned int y, unsigned int width, unsigned int height, int color);
+
+  /**
+   * Kopiert einen Bereich des Bildschirminhalts
+   * @param display Display, auf das gezeichnet wird
+   * @param x X-Koordinate (Ziel)
+   * @param y Y-Koordinate (Ziel)
+   * @param srcx X-Koordinate (Quelle)
+   * @param srcy Y-Koordinate (Quelle)
+   * @param width Breite
+   * @param height Hoehe
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  void (*copy_screen)(struct cdi_video_display *display, unsigned int x, unsigned int y, unsigned int srcx, unsigned int srcy, unsigned int width, unsigned int height);
+
+  /**
+   * Zeichnet ein Bitmap
+   * @param display Display, auf das gezeichnet wird
+   * @param bitmap Zu zeichnendes Bitmap
+   * @param x X-Koordinate
+   * @param y Y-Koordinate
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  void (*draw_bitmap)(struct cdi_video_display *display, struct cdi_video_bitmap *bitmap, unsigned int x, unsigned int y);
+
+  /**
+   * Zeichnet ein Bitmap
+   * @param display Display, auf das gezeichnet wird
+   * @param bitmap Zu zeichnendes Bitmap
+   * @param x X-Koordinate (Ziel)
+   * @param y Y-Koordinate (Ziel)
+   * @param srcx X-Koordinate (Quelle)
+   * @param srcy Y-Koordinate (Quelle)
+   * @param width Breite
+   * @param height Hoehe
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+  void (*draw_bitmap_part)(struct cdi_video_display *display, struct cdi_video_bitmap *bitmap, unsigned int x, unsigned int y, unsigned int srcx, unsigned int srcy, unsigned int width, unsigned int height);
+
+  /**
+   * Zeichnet einen Punkt
+   *  @param display Display, auf dem gezeichnet wird
+   * @param x X-Koordinate (Ziel)
+   * @param y Y-Koordinate (Ziel)
+   * @note Kann nur angewendet werden wenn der Bildschirm aktiviert ist
+   */
+   void (*draw_dot)(struct cdi_video_display *display, unsigned int x, unsigned int y, int color);
+};
+
+/**
+ * Initialisiert die Datenstrukturen fuer einen Grafikkartentreiber
+ */
+void cdi_video_driver_init(struct cdi_video_driver* driver);
+/**
+ * Deinitialisiert die Datenstrukturen fuer einen Grafikkartentreiber
+ */
+void cdi_video_driver_destroy(struct cdi_video_driver* driver);
+/**
+ * Registiert einen Grafikkartentreiber
+ */
+void cdi_video_driver_register(struct cdi_video_driver* driver);
+
+#endif
diff --git a/src/modules/cdi/lib/video/draw.c b/src/modules/cdi/lib/video/draw.c
new file mode 100644
index 0000000..56c230f
--- /dev/null
+++ b/src/modules/cdi/lib/video/draw.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2008 Mathias Gottschlag
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it 
+ * and/or modify it under the terms of the Do What The Fuck You Want 
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+#include "draw.h"
+#include "vscreens.h"
+#include "video.h"
+#include <video/commands.h>
+#include <video/drawing.h>
+#include <cdi/video.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int upload_bitmap(int card, int index, int pid, int width, int height, int format, int datalength, void *data)
+{
+    // Treiberfunktion aufrufen
+    struct vscreen *vscreen = get_vscreen(card, index);
+    if (!vscreen) return 0;
+    if (vscreen->owner != pid) return 0;
+    struct cdi_video_bitmap *bitmap = videocards[card].driver->bitmap_create(videocards[card].card, width, height, format, data);
+    if (!bitmap) return 0;
+    
+    // Bitmap an Liste anhaengen
+    int id = ++vscreen->maxbitmapid;
+    struct vscreen_bitmap *vsbitmap = malloc(sizeof(struct vscreen_bitmap));
+    vsbitmap->bitmap = bitmap;
+    vsbitmap->id = id;
+    vscreen->bitmaps = cdi_list_push(vscreen->bitmaps, vsbitmap);
+    return id;
+}
+int destroy_bitmap(int card, int index, int pid, int bitmap)
+{
+    struct vscreen *vscreen = get_vscreen(card, index);
+    if (!vscreen) return 0;
+    if (vscreen->owner != pid) return 0;
+    // Aus Liste heraussuchen und loeschen
+    struct vscreen_bitmap *vsbitmap = 0;
+    int i;
+    for (i = 0; i < cdi_list_size(vscreen->bitmaps); i++) {
+        struct vscreen_bitmap *tmp = cdi_list_get(vscreen->bitmaps, i);
+        if (tmp->id == bitmap) {
+            vsbitmap = tmp;
+            cdi_list_remove(vscreen->bitmaps, i);
+            break;
+        }
+    }
+    if (!vsbitmap) return 0;
+    
+    // Treiberfunktion aufrufen
+    videocards[card].driver->bitmap_destroy(videocards[card].card, vsbitmap->bitmap);
+    free(vsbitmap);
+    return 1;
+}
+int destroy_all_bitmaps(int card, int index, int pid)
+{
+    struct vscreen *vscreen = get_vscreen(card, index);
+    if (!vscreen) return 0;
+    if (vscreen->owner != pid) return 0;
+    // Alle Bitmaps aus der Liste loeschen
+    struct vscreen_bitmap *vsbitmap;
+    while ((vsbitmap = cdi_list_pop(vscreen->bitmaps)) != 0) {
+        videocards[card].driver->bitmap_destroy(videocards[card].card, vsbitmap->bitmap);
+        free(vsbitmap);
+    }
+    return 1;
+}
+struct cdi_video_bitmap *get_bitmap(int card, int index, int id)
+{
+    struct vscreen *vscreen = get_vscreen(card, index);
+    if (!vscreen) return 0;
+    int i;
+    for (i = 0; i < cdi_list_size(vscreen->bitmaps); i++) {
+        struct vscreen_bitmap *vsbitmap = cdi_list_get(vscreen->bitmaps, i);
+        if (vsbitmap->id == id) return vsbitmap->bitmap;
+    }
+    return 0;
+}
+
+int video_do_buffer(int card, int index, int screen, int pid, unsigned int length)
+{
+    // Screen/Bildschirm heraussuchen
+    if (index != videocards[card].activevscreen) return 0;
+    struct vscreen *vscreen = get_vscreen(card, index);
+    if (!vscreen) return 0;
+    if (vscreen->owner != pid) return 0;
+    struct cdi_video_display *display = cdi_list_get(videocards[card].card->displays, screen);
+    if (!display) return 0;
+    
+    // Buffer
+    if (!vscreen->cmdbufferid) {
+        return 0;
+    }
+    if (!length) return 1;
+    if (length > 64 * 1024) length = 64 * 1024;
+    
+    char *buffer = vscreen->cmdbuffer;
+    
+    // Buffer parsen
+    while (length > 0) {
+        if ((length >= 2) && (buffer[0] == VIDEO_CMD_SET_ROP)) {
+            cdi_video_raster_op_t rop = CDI_VIDEO_ROP_COPY;
+            if (buffer[1] == ROP_AND) {
+                rop = CDI_VIDEO_ROP_AND;
+            } else if (buffer[1] == ROP_OR) {
+                rop = CDI_VIDEO_ROP_OR;
+            } else if (buffer[1] == ROP_XOR) {
+                rop = CDI_VIDEO_ROP_XOR;
+            }
+            videocards[card].driver->set_raster_op(display, rop);
+            buffer += 2;
+            length -= 2;
+        } else if ((length >= 12) && (buffer[0] == VIDEO_CMD_DRAW_RECT)) {
+            unsigned int color = *((unsigned int*)(buffer + 1)) & 0xFFFFFF;
+            unsigned short x = *((unsigned short*)(buffer + 4));
+            unsigned short y = *((unsigned short*)(buffer + 6));
+            unsigned short width = *((unsigned short*)(buffer + 8));
+            unsigned short height = *((unsigned short*)(buffer + 10));
+            videocards[card].driver->draw_rectangle(display, x, y, width, height, color);
+            buffer += 12;
+            length -= 12;
+        } else if ((length >= 12) && (buffer[0] == VIDEO_CMD_DRAW_ELLIPSE)) {
+            unsigned int color = *((unsigned int*)(buffer + 1)) & 0xFFFFFF;
+            unsigned short x = *((unsigned short*)(buffer + 4));
+            unsigned short y = *((unsigned short*)(buffer + 6));
+            unsigned short width = *((unsigned short*)(buffer + 8));
+            unsigned short height = *((unsigned short*)(buffer + 10));
+            videocards[card].driver->draw_ellipse(display, x, y, width, height, color);
+            buffer += 12;
+            length -= 12;
+        } else if ((length >= 12) && (buffer[0] == VIDEO_CMD_DRAW_LINE)) {
+            unsigned int color = *((unsigned int*)(buffer + 1)) & 0xFFFFFF;
+            unsigned short x1 = *((unsigned short*)(buffer + 4));
+            unsigned short y1 = *((unsigned short*)(buffer + 6));
+            unsigned short x2 = *((unsigned short*)(buffer + 8));
+            unsigned short y2 = *((unsigned short*)(buffer + 10));
+            videocards[card].driver->draw_line(display, x1, y1, x2, y2, color);
+            buffer += 12;
+            length -= 12;
+        } else if ((length >= 8) && (buffer[0] == VIDEO_CMD_DRAW_DOT)) {
+            unsigned int color = *((unsigned int*)(buffer + 1)) & 0xFFFFFF;
+            unsigned short x = *((unsigned short*)(buffer + 4));
+            unsigned short y = *((unsigned short*)(buffer + 6));
+            videocards[card].driver->draw_dot(display, x, y, color);
+            buffer += 8;
+            length -= 8;
+        } else if ((length >= 9) && (buffer[0] == VIDEO_CMD_DRAW_BITMAP)) {
+            unsigned int bitmapid = *((unsigned int*)(buffer + 1));
+            unsigned short x = *((unsigned short*)(buffer + 5));
+            unsigned short y = *((unsigned short*)(buffer + 7));
+            // Bitmap heraussuchen
+            struct cdi_video_bitmap *bitmap = get_bitmap(card, index, bitmapid);
+            // Zeichnen
+            if (bitmap) {
+                videocards[card].driver->draw_bitmap(display, bitmap, x, y);
+            } else {
+                printf("[ cdi/video ] Bitmap nicht gefunden!\n");
+            }
+            buffer += 9;
+            length -= 9;
+        } else if ((length >= 17) && (buffer[0] == VIDEO_CMD_DRAW_BITMAP_PART)) {
+            unsigned int bitmapid = *((unsigned int*)(buffer + 1));
+            unsigned short x = *((unsigned short*)(buffer + 5));
+            unsigned short y = *((unsigned short*)(buffer + 7));
+            unsigned short srcx = *((unsigned short*)(buffer + 9));
+            unsigned short srcy = *((unsigned short*)(buffer + 11));
+            unsigned short width = *((unsigned short*)(buffer + 13));
+            unsigned short height = *((unsigned short*)(buffer + 15));
+            // Bitmap heraussuchen
+            struct cdi_video_bitmap *bitmap = get_bitmap(card, index, bitmapid);
+            // Zeichnen
+            if (bitmap) {
+                videocards[card].driver->draw_bitmap_part(display, bitmap, x, y, srcx, srcy, width, height);
+            } else {
+                printf("[ cdi/video ] Bitmap nicht gefunden!\n");
+            }
+            buffer += 17;
+            length -= 17;
+        } else if ((length >= 13) && (buffer[0] == VIDEO_CMD_COPY_SCREEN)) {
+            unsigned short x = *((unsigned short*)(buffer + 1));
+            unsigned short y = *((unsigned short*)(buffer + 3));
+            unsigned short srcx = *((unsigned short*)(buffer + 5));
+            unsigned short srcy = *((unsigned short*)(buffer + 7));
+            unsigned short width = *((unsigned short*)(buffer + 9));
+            unsigned short height = *((unsigned short*)(buffer + 11));
+            // Zeichnen
+            videocards[card].driver->copy_screen(display, x, y, srcx, srcy, width, height);
+            buffer += 13;
+            length -= 13;
+        } else {
+            // TODO
+            break;
+        }
+    }
+
+    return 1;
+}
+
+
diff --git a/src/modules/cdi/lib/video/draw.h b/src/modules/cdi/lib/video/draw.h
new file mode 100644
index 0000000..7186064
--- /dev/null
+++ b/src/modules/cdi/lib/video/draw.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2008 Mathias Gottschlag
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it 
+ * and/or modify it under the terms of the Do What The Fuck You Want 
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+#ifndef _DRAW_H_
+#define _DRAW_H_
+
+#include <cdi/video.h>
+
+int upload_bitmap(int card, int index, int pid, int width, int height, int format, int datalength, void *data);
+int destroy_bitmap(int card, int index, int pid, int bitmap);
+int destroy_all_bitmaps(int card, int index, int pid);
+struct cdi_video_bitmap *get_bitmap(int card, int index, int id);
+
+int video_do_buffer(int card, int index, int screen, int pid, unsigned int length);
+
+#endif
diff --git a/src/modules/cdi/lib/video/video.c b/src/modules/cdi/lib/video/video.c
new file mode 100644
index 0000000..b781bb0
--- /dev/null
+++ b/src/modules/cdi/lib/video/video.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2008 Mathias Gottschlag
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it 
+ * and/or modify it under the terms of the Do What The Fuck You Want 
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <lostio.h>
+#include <video/commands.h>
+#include <rpc.h>
+#include <syscall.h>
+
+#include "video.h"
+#include "vscreens.h"
+#include "draw.h"
+
+int videocard_count = 0;
+struct cdi_video_driver* videodriver = 0;
+
+//Interface über RPC
+void rpc_video_interface(pid_t pid,
+                          dword correlation_id,
+                          size_t data_size,
+                          void* data);
+
+/**
+ * Initialisiert die Datenstrukturen fuer einen Grafikkartentreiber
+ */
+void cdi_video_driver_init(struct cdi_video_driver* driver)
+{
+    cdi_driver_init((struct cdi_driver*) driver);
+    
+    register_message_handler("VIDEODRV", rpc_video_interface);
+}
+
+/**
+ * Deinitialisiert die Datenstrukturen fuer einen Grafikkartentreiber
+ */
+void cdi_video_driver_destroy(struct cdi_video_driver* driver)
+{
+    cdi_driver_destroy((struct cdi_driver*) driver);
+}
+
+/**
+ * Registiert einen Grafikkartentreiber
+ */
+void cdi_video_driver_register(struct cdi_video_driver* driver)
+{
+    videodriver = driver;
+    cdi_driver_register((struct cdi_driver*) driver);
+
+    int i;
+    for (i = 0; i < cdi_list_size(driver->drv.devices); i++) {
+        videocards[i].card = cdi_list_get(driver->drv.devices, i);
+        videocards[i].activevscreen = -1;
+        videocards[i].vscreens = cdi_list_create();
+        videocards[i].driver = driver;
+        videocard_count++;
+    }
+}
+
+void rpc_video_interface(pid_t pid,
+                          dword correlation_id,
+                          size_t data_size,
+                          void* data)
+{
+    int result = 1;
+    // Befehlsinformation auslesen
+    dword *command = data;
+    if (data_size < sizeof(int) * 2) {
+        rpc_send_dword_response(pid, correlation_id, 0);
+        return;
+    }
+    
+    dword device_number = command[0];
+    // Anzahl der Devices zurueckgeben
+    if (device_number == 0xFFFFFFFF) {
+        rpc_send_dword_response(pid, correlation_id, videocard_count);
+        return;
+    }
+    // Kaputte Geraetenummer
+    if (device_number >= videocard_count) {
+        rpc_send_dword_response(pid, correlation_id, 0);
+        return;
+    }
+    // Befehl ausführen
+    switch (command[1]) {
+        case VIDEO_ADD_VSCREEN:
+            if (data_size < sizeof(int) * 4) {
+                result = 0;
+            } else {
+                result = vscreen_add(device_number, command[2], command[3]);
+            }
+            break;
+        case VIDEO_REMOVE_VSCREEN:
+            if (data_size < sizeof(int) * 3) {
+                result = 0;
+            } else {
+                vscreen_remove(device_number, command[2]);
+            }
+            break;
+        case VIDEO_SET_ACTIVE_VSCREEN:
+            if (data_size < sizeof(int) * 3) {
+                result = 0;
+            } else {
+                vscreen_set_active(device_number, command[2]);
+            }
+            break;
+        case VIDEO_GET_ACTIVE_VSCREEN:
+            result = vscreen_get_active(device_number);
+            break;
+
+        case VIDEO_SET_RESOLUTION:
+            if (data_size < sizeof(int) * 8) {
+                result = 0;
+            } else {
+                int index = command[2];
+                int screen = command[3];
+                int width = command[4];
+                int height = command[5];
+                int depth = command[6];
+                int text = command[7];
+                result = vscreen_set_resolution(device_number, index, screen, pid,
+                    width, height, depth, text);
+            }
+            break;
+        case VIDEO_GET_RESOLUTION:
+            break;
+        case VIDEO_GET_RESOLUTION_LIST:
+            break;
+        case VIDEO_UPLOAD_BITMAP:
+            if (data_size < sizeof(int) * 7) {
+                result = 0;
+            } else {
+                int index = command[2];
+                int width = command[3];
+                int height = command[4];
+                int format = command[5];
+                int length = command[6];
+                if ((length != 0) && (data_size < sizeof(int) * 7 + length)) {
+                    result = 0;
+                } else {
+                    void *data = 0;
+                    if (length) data = &command[7];
+                    result = upload_bitmap(device_number, index, pid, width, height, format, length, data);
+                }
+            }
+            break;
+        case VIDEO_DESTROY_BITMAP:
+            if (data_size < sizeof(int) * 4) {
+                result = 0;
+            } else {
+                int index = command[2];
+                int bitmap = command[3];
+                result = destroy_bitmap(device_number, index, pid, bitmap);
+            }
+            break;
+            break;
+        case VIDEO_DESTROY_ALL_BITMAPS:
+            if (data_size < sizeof(int) * 3) {
+                result = 0;
+            } else {
+                int index = command[2];
+                result = destroy_all_bitmaps(device_number, index, pid);
+            }
+            break;
+        case VIDEO_COMMAND_STREAM:
+           if (data_size < sizeof(int) * 5) {
+                result = 0;
+            } else {
+                int index = command[2];
+                int screen = command[3];
+                int length = command[4];
+                result = video_do_buffer(device_number, index, screen, pid, length);
+            }
+            break;
+        case VIDEO_GET_COMMAND_BUFFER:
+            if (data_size < sizeof(int) * 2) {
+                result = 0;
+            } else {
+                result = vscreen_get_command_buffer(device_number, command[2], pid);
+            }
+            break;
+    }
+    
+    rpc_send_dword_response(pid, correlation_id, result);
+}
+
diff --git a/src/modules/cdi/lib/video/video.h b/src/modules/cdi/lib/video/video.h
new file mode 100644
index 0000000..cebde01
--- /dev/null
+++ b/src/modules/cdi/lib/video/video.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2008 Mathias Gottschlag
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it 
+ * and/or modify it under the terms of the Do What The Fuck You Want 
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+#ifndef VIDEO_H
+#define VIDEO_H
+
+#include "vscreens.h"
+
+extern int videocard_count;
+struct {
+    struct cdi_video_device* card;
+    int activevscreen;
+    cdi_list_t vscreens;
+    struct cdi_video_driver* driver;
+} videocards[10];
+// FIXME: Dynamische Anzahl
+
+#endif
+
diff --git a/src/modules/cdi/lib/video/vscreens.c b/src/modules/cdi/lib/video/vscreens.c
new file mode 100644
index 0000000..b338cce
--- /dev/null
+++ b/src/modules/cdi/lib/video/vscreens.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2008 Mathias Gottschlag
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it 
+ * and/or modify it under the terms of the Do What The Fuck You Want 
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+#include "vscreens.h"
+#include "video.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <video/commands.h>
+#include <rpc.h>
+#include <syscall.h>
+#include "cdi/bios.h"
+
+struct vscreen *get_vscreen(int card, int index)
+{
+    int i;
+    for (i = 0; i < cdi_list_size(videocards[card].vscreens); i++) {
+        struct vscreen *screen = cdi_list_get(videocards[card].vscreens, i);
+        if (screen->index == index) {
+            return screen;
+        }
+    }
+    return 0;
+}
+
+int vscreen_add(int card, int index, int pid)
+{
+    struct vscreen *screen = get_vscreen(card, index);
+    if (!screen) {
+        screen = malloc(sizeof(struct vscreen));
+        screen->screencount = 0;
+        screen->mode = 0;
+        screen->owner = pid;
+        screen->index = index;
+        screen->cmdbufferid = 0;
+        screen->cmdbuffer = 0;
+        screen->maxbitmapid = 0;
+        screen->bitmaps = cdi_list_create();
+        videocards[card].vscreens = cdi_list_push(videocards[card].vscreens, screen);
+        printf("Neuer vscreen(%d), PID = %d.\n", index, pid);
+        if (videocards[card].activevscreen == -1) vscreen_set_active(card, index);
+        return 1;
+    } else {
+        return 0;
+    }
+}
+void vscreen_remove(int card, int index)
+{
+    int i;
+    struct vscreen *screen;
+    for (i = 0; i < cdi_list_size(videocards[card].vscreens); i++) {
+        screen = cdi_list_get(videocards[card].vscreens, i);
+        if (screen->index == index) {
+            if (videocards[card].activevscreen == index) vscreen_set_active(card, 0);
+            // TODO: Daten loeschen (Bitmaps)
+            
+            // Vscreen entfernen
+            if (screen->mode) free(screen->mode);
+            close_shared_memory(screen->cmdbufferid);
+            videocards[card].vscreens = cdi_list_remove(videocards[card].vscreens, i);
+            free(screen);
+            return;
+        }
+    }
+}
+void vscreen_set_active(int card, int index)
+{
+    // Virtuelle Screens raussuchen
+    struct vscreen *oldvscreen = get_vscreen(card, videocards[card].activevscreen);
+    struct vscreen *newvscreen = get_vscreen(card, index);
+    if (newvscreen == oldvscreen) return;
+    
+    if (oldvscreen && oldvscreen->owner) {
+        // Benutzer des Screens mitteilen, dass er ab jetzt ungültig ist
+        int command[1];
+        command[0] = VIDEO_CLIENT_DEACTIVATE;
+        rpc_get_dword(oldvscreen->owner,
+                      "VIDEOLIB",
+                      sizeof(int),
+                      (char*)command);
+    }
+    
+    // Bildschirmauflösungen ändern / Bildschirme (de)aktivieren
+    if (newvscreen && oldvscreen) {
+        printf("Wechsle Aufloesung.\n");
+        int mindisplays = oldvscreen->screencount;
+        if (newvscreen->screencount < mindisplays) mindisplays = newvscreen->screencount;
+        
+        int i;
+        for (i = 0; i < mindisplays; i++) {
+            struct cdi_video_display *display = cdi_list_get(videocards[card].card->displays, i);
+            if (!display) {
+                break;
+            }
+            if (oldvscreen->mode[i] && newvscreen->mode[i]) {
+                videocards[card].driver->display_set_mode(display, newvscreen->mode[i]);
+            } else if (oldvscreen->mode[i]) {
+                videocards[card].driver->display_disable(display);
+            } else if (newvscreen->mode[i]) {
+                videocards[card].driver->display_set_mode(display, newvscreen->mode[i]);
+                videocards[card].driver->display_enable(display);
+            }
+        }
+        if (newvscreen->screencount > oldvscreen->screencount) {
+            for (i = mindisplays; i < newvscreen->screencount; i++) {
+                struct cdi_video_display *display = cdi_list_get(videocards[card].card->displays, i);
+                if (!display) {
+                    break;
+                }
+                if (newvscreen->mode[i]) {
+                    videocards[card].driver->display_set_mode(display, newvscreen->mode[i]);
+                    videocards[card].driver->display_enable(display);
+                }
+            }
+        } else {
+            for (i = mindisplays; i < oldvscreen->screencount; i++) {
+                struct cdi_video_display *display = cdi_list_get(videocards[card].card->displays, i);
+                if (!display) {
+                    break;
+                }
+                if (oldvscreen->mode[i]) {
+                    videocards[card].driver->display_disable(display);
+                }
+            }
+        }
+    } else if (newvscreen) {
+        int i;
+        for (i = 0; i < newvscreen->screencount; i++) {
+            struct cdi_video_display *display = cdi_list_get(videocards[card].card->displays, i);
+            if (!display) {
+                break;
+            }
+            if (newvscreen->mode[i]) {
+                videocards[card].driver->display_set_mode(display, newvscreen->mode[i]);
+                videocards[card].driver->display_enable(display);
+            }
+        }
+    } else if (oldvscreen) {
+        int i;
+        for (i = 0; i < oldvscreen->screencount; i++) {
+            struct cdi_video_display *display = cdi_list_get(videocards[card].card->displays, i);
+            if (!display) {
+                break;
+            }
+            if (oldvscreen->mode[i]) {
+                videocards[card].driver->display_disable(display);
+            }
+        }
+    }
+    videocards[card].activevscreen = index;
+    
+    if (newvscreen && newvscreen->owner) {
+        // Benutzer des Screens mitteilen, dass er ab jetzt gültig ist
+        int command[1];
+        command[0] = VIDEO_CLIENT_ACTIVATE;
+        rpc_get_dword(newvscreen->owner,
+                      "VIDEOLIB",
+                      sizeof(int),
+                      (char*)command);
+    }
+}
+int vscreen_get_active(int card)
+{
+    return videocards[card].activevscreen;
+}
+
+int vscreen_set_resolution(int card, int index, int screen, int pid, int width, int height, int bpp, int text)
+{
+    printf("Setze Aufloesung (%d).\n", index);
+    // Screen/Bildschirm heraussuchen
+    struct vscreen *vscreen = get_vscreen(card, index);
+    if (!vscreen) return 0;
+    if (vscreen->owner != pid) return 0;
+    struct cdi_video_display *display = cdi_list_get(videocards[card].card->displays, screen);
+    if (!display) return 0;
+    
+    // Platz schaffen fuer Modus
+    if (vscreen->screencount <= screen) {
+        vscreen->mode = realloc(vscreen->mode, (screen + 1) * sizeof(void*));
+        memset(vscreen->mode + vscreen->screencount, 0x00, (screen + 1 - vscreen->screencount) * sizeof(void*));
+        vscreen->screencount = screen + 1;
+    }
+    
+    // Liste mit Modi laden und Modus heraussuchen
+    cdi_video_mode_t *newmode = 0;
+    cdi_list_t modes = videocards[card].driver->display_get_mode_list(display);
+    int i;
+    for (i = 0; i < cdi_list_size(modes); i++) {
+        cdi_video_mode_t *mode = cdi_list_get(modes, i);
+        if ((mode->width == width) && (mode->height == height) && (mode->depth == bpp) && (mode->type == 1 - text))
+        {
+            newmode = mode;
+            break;
+        }
+    }
+    
+    if (!newmode) {
+        // Bestmoeglichen Modus waehlen
+        // TODO
+    }
+    
+    if (!newmode) {
+        printf("Kein Modus gefunden.\n");
+        return 0;
+    }
+    
+    cdi_video_mode_t *oldmode = vscreen->mode[screen];
+    vscreen->mode[screen] = newmode;
+    
+    if (videocards[card].activevscreen == index) {
+        // Bildschirmaufloesung setzen
+        videocards[card].driver->display_set_mode(display, newmode);
+        if (!oldmode) {
+            videocards[card].driver->display_enable(display);
+        }
+    }
+    
+    return 1;
+}
+cdi_video_mode_t *vscreen_get_resolution(int card, int index, int screen)
+{
+    return 0;
+}
+
+dword vscreen_get_command_buffer(int card, int index, int pid)
+{
+    // Screen/Bildschirm heraussuchen
+    struct vscreen *vscreen = get_vscreen(card, index);
+    if (!vscreen) return 0;
+    if (vscreen->owner != pid) return 0;
+    
+    // Schon erstellt?
+    if (vscreen->cmdbufferid) {
+        return vscreen->cmdbufferid;
+    }
+    
+    // Neuen Buffer erstellen
+    // FIXME: Ne feste Groesse ist dumm.
+    vscreen->cmdbufferid = create_shared_memory(64 * 1024);
+    vscreen->cmdbuffer = open_shared_memory(vscreen->cmdbufferid);
+    return vscreen->cmdbufferid;
+}
+
diff --git a/src/modules/cdi/lib/video/vscreens.h b/src/modules/cdi/lib/video/vscreens.h
new file mode 100644
index 0000000..1a807b1
--- /dev/null
+++ b/src/modules/cdi/lib/video/vscreens.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2008 Mathias Gottschlag
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it 
+ * and/or modify it under the terms of the Do What The Fuck You Want 
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+#ifndef VSCREENS_H
+#define VSCREENS_H
+
+#include <types.h>
+
+#include "cdi/video.h"
+
+struct vscreen_bitmap {
+    int id;
+    struct cdi_video_bitmap *bitmap;
+};
+
+struct vscreen {
+    int screencount;
+    cdi_video_mode_t **mode;
+    pid_t owner;
+    int index;
+    dword cmdbufferid;
+    char *cmdbuffer;
+    int maxbitmapid;
+    cdi_list_t bitmaps;
+};
+
+struct vscreen *get_vscreen(int card, int index);
+
+int vscreen_add(int card, int index, int pid);
+void vscreen_remove(int card, int index);
+void vscreen_set_active(int card, int index);
+int vscreen_get_active(int card);
+
+int vscreen_set_resolution(int card, int index, int screen, int pid, int width, int height, int bpp, int text);
+cdi_video_mode_t *vscreen_get_resolution(int card, int index, int screen);
+
+dword vscreen_get_command_buffer(int card, int index, int pid);
+
+#endif
+
-- 
1.5.4.3