[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Lost] [PATCH] [1/5] + cdi: Interface fuer Grafiktreiber
Am Dienstag, 14. Oktober 2008 16:00:45 schrieb Mathias Gottschlag:
> 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;
> +};
Es gibt eigentlich keine richtige Stelle dafür, ich mache den Kommentar
einfach mal hier: Steckt irgendeine tiefere Logik dahinter, was ihr typedeft
und was nicht?
> +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;
Was ist denn ein Bildschirm und wann ist er aktiv? Ich dachte jetzt erst an
das physische Stück Hardware, aber das kann ja kaum gemeint sein. Ich kriege
da zumindest die Bedeutung "aktiv" nicht unter. Andererseits würde der
momentane Modus genau dazu passen.
=> Erläuternder Kommentar dringend notwendig
> + // 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);
Was bedeutet leeren? Komplett schwarz machen?
> +
> + /**
> + * 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); + /**
Wäre für color nicht ein uint32_t eher, was ihr wollt?
> + * 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) +{
Entweder cdi_(video_)?upload_bitmap oder static, falls das geht.
> + // 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) +{
Kommentar? do_buffer ist jetzt wirklich nicht selbsterklärend...
> + // 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;
> + }
Dieses Konstrukt sieht nicht besonders schön aus, finde ich... Wie wäre es mit
einem Array mit VIDEO_CMD_* als Index und der Länge als Wert, und nach der
Längenprüfung dann ein switch? Gewinnt dann immer noch keinen
Schönheitspreis, aber wäre vielleicht mal ein erster Schritt.
> + }
> +
> + 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;
Fehlt da nicht wenigstens ein TODO?
> +}
> +
> +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
Sind ja noch ein ganzer Haufen TODOs drin. Willst du das trotzdem schonmal
einchecken? Außerdem entspricht es unserem Codestil nur teilweise. Die
Punkte, die mir in dieser Hinsicht am meisten aufgefallen sind:
- Pointer: Es heißt int* foo, nicht int *foo
- ifs: Nie einzeilig, immer Klammern
- Pointer: NULL statt 0
Die Logik habe ich jetzt nicht besonders genau angeschaut, sondern erstmal nur
das Interface usw. Aber ich gehe davon aus, daß du den Code schonmal getestet
hast, insofern wird die Umsetzung nicht total kaputt sein.
Kevin