AMIGA-Magazin · Ausgabe 5/99 · Grundlagen: Grafikkarten-Hardware (Folge 3)

Aktuelles Heft 5/99

Gute Karten in der Hinterhand

Vor allem durch die zahlreichen Programme aus dem Public-Domain-Bereich werden die Fähigkeiten der Grafikkarten erst so richtig ausgenutzt. Sind auch Sie ein Programmierer und wollen Ihr Programm grafikkartenfähig machen? Dann finden Sie in diesem Teil die entsprechenden Informationen.

von Michael Christoph

Hinweise zum Öffnen von Bibliotheken
cybergraphics.library V40.x (bei V2)
[kein define bei CyberGfx, "cybergraphics/cybergraphics.h"]
cybergraphics.library V41.3 (bei V3)
[kein define bei CyberGfx, "cybergraphics/cybergraphics.h"]
cybergraphics.library V42.0 (bei V4)
[define CYBERGFXNAME in "cybergraphx/cybergraphics.h"]
Picasso96API.library V2.270 (V1.42)
[define P96NAME in "libraries/Picasso96.h"]
Während CyberGraphX bereits eine sehr ausgereifte Intuition-Emulation bereitstellt, die alle wichtigen Funktionen der intuition- und graphics.library patcht, sind dennoch nur maximal 256 Farben möglich. Das liegt vor allem am Interface der Orginal-Funktionen, die durchgän-gig Farbregister (0 bis maximal 255) statt RGB-Farbwerte benutzen. Aus die- sem Grund muß jede Applikation, die mehr als 256 Farben darstellen will, direkt auf die Funktionen der cybergraphics- bzw.Picasso96API.library zurückgreifen.

Dieser Kursteil soll Ihnen eine Übersicht der Möglichkeiten bieten und aufzeigen, welche Teile anzupassen sind.

Da die Dokumentationen zu Picasso96 noch sehr »löchrig« sind, werden Sie hier hauptsächlich den Umgang mit dem verbreiteten CyberGraphX-System finden. Beginnen wir mit einem theoretischen Überblick der notwendigen Änderungen bzw. Anforderungen. Alle wichtigen Grafik-Funktionen werden automatisch von CyberGraphX und Picasso96 gepatcht, so daß hier erst einmal keine Änderungen notwendig sind.

/* Beispiel für CyberGraphX */
struct Library *CyberGfxBase;

if((CyberGfxBase=OpenLibrary("cybergraphics.library",41)))
{ /*
   * CyberGraphX-Funktionen können benutzt werden
   */
   CloseLibrary(CyberGfxBase);
}
else
   printf("ERROR: can`t open cybergraphics.library V41.\n");
/* Beispiel für Piccasso96 */

struct Library *P96Base;

if((P96Base=OpenLibrary("Picasso96API.library",2)))
{
  /*
   * Picasso96-Funktionen können benutzt werden
   */
  CloseLibrary(P96Base);
}
else
  printf("ERROR: can`t open Picasso96API.library V2.\n");
Listing 1: So öffnen Sie Libraries für Grafikkarten
Das Programm sollte einen Screenmode-Requester bieten, um komfortabel die Auflösung und Farbtiefe für den Arbeitsbildschirm bestimmen zu können. In diesem Zusammenhang sollte auch die Auswahl eines Zeichensatzes möglich sein. Bei hohen Auflösungen der Grafikkarte sollte auch ein größerer (meist proportionaler) Font zum Einsatz kommen, damit der Nutzer die Bildschirmtexte ohne Lupe lesen kann. Hieraus ergibt sich, daß das Programm also auch den Font anpassen muß. Beispiel: Gadgets sollten so programmiert sein, daß Texte nicht »überstehen«. MUI bietet hier sicher eine einfache Möglichkeit, um beide Anforderungen ohne viel Programmieraufwand abdecken zu können. Aber auch das Programm »GadToolsBox«, mit dem Programmoberflächen entworfen werden können, bietet eine teilweise automatische Fontsensivität an. Mit diesen Anforderungen ist Ihr Programm bereits uneingeschränkt grafikkartentauglich. Sollen nun mehr als 256 Farben zum Einsatz kommen, müssen Sie die Grafikausgabe und evtl. die Grafik-Bearbeitungsfunktionen anpassen. Wollen Sie nicht nur eine Farbtiefe unterstützen, kann die mehrfache Ausführung der Routinen notwendig sein. Dann kann je nach aktueller Farbtiefe die entsprechende Routine aufgerufen werden.

* Planar oder Chunky?

Bevor wir loslegen, wollen wir uns kurz den verschiedenen Farbmodellen bzw. Bitmap-Modi widmen: Planar und Chunky. Bei den Amiga-Bitmaps kommen je nach Farbtiefe eine bis acht Bitplanes zum Einsatz. Der Farbwert für einen Pixel wird indirekt durch das verwendete Farbregister festgelegt, welches in der Bitmap eingetragen ist. Wird der Farbwert in einem der Farbregister verändert, werden dadurch automatisch alle anderen Pixel auf dem Bildschirm angepaßt, die ebenfalls dieses Farbregister verwenden. Anders verhält es sich bei den Grafikkartenauflösungen ­ diese arbeiten mit dem Chunky-Format. Dabei erfolgt der Bildaufbau in quasi einer Bitmap, wobei jeweils ein Byte (acht aufeinanderfolgende Bits) das Farbregister festlegen. Vom Speicherverbrauch her besteht kein Unterschied, allerdings ist der Zugriff einfacher. Den Inhalt eines Registers kann man direkt als Bytewert auslesen und muß ihn nicht anhand acht einzelner Bits aus den Bitplanes zusammensetzen. Dadurch erhöht sich automatisch die Verarbeitungsgeschwindigkeit.

Bei den höheren Farbtiefen, mit mehr acht Planes, existieren keine Farbregister mehr. Bei einem 16-Bit-Bild würden 65536 Farbregister benötigt, die je vier Byte belegen. Das ergibt eine 256 KByte große Farbtabelle. Hierbei werden die Farbwerte direkt für jeden Pixel definiert. Damit besteht keine Möglichkeit mehr, alle gleichfarbigen Pixel auf dem Bildschirm auf einmal zu ändern. Wird diese Funktion benötigt, muß eine entsprechende Routine alle Pixel des Bildes durchlaufen und dabei jeweils bei Bedarf den neuen Farbwert eintragen. 24-Bit-Modi arbeiten nach einem ähnlichen Schema. Hierbei werden die Bilddaten aber wieder byteweise abgelegt. Dabei kommen drei Planes zum Einsatz: eine für den Rot-, eine für den Grün- und eine für den Blauanteil der Farbe. Es stehen 256 Farbabstufungen (entspricht acht Bit) je Grundfarbe zur Verfügung, die zusammen 24 Bit ergeben und ein Farbspektrum von 16.8 Millionen Farbwerten ermöglichen.

Beachten Sie: Oft sind die Daten für Rot und Blau vertauscht ­ die Plane-Daten liegen also in der Reihenfolge Blau/Grün/Rot vor. Es stehen aber meist auch hier Formate zur Verfügung, die die Bilddaten in einem Stück verwalten und jeweils für ein ULONG pro Bildpunkt verantwortlich ist. Je nach Formataufbau werden meist die obersten acht Bit für den Alpha-Kanal verwendet, der aber selten benutzt bzw. beachtet wird. Beide Grafikkartensysteme bieten eine Menge an unterschiedlicher Bitmap-Formaten und Farbtiefen an. Es empfiehlt sich auf alle Fälle die jeweilige Einleitung der Autodocs bzw. die Include-Files zu lesen.

Mode-ID ermitteln
Die meisten der folgenden Funktion werden normalerweise von der CyberGraphX- und Picasso96-Software gepatcht, so daß auch bei Aufruf der »neutralen« Amiga-Funktionen die jeweils korrekten Werte zurückgeliefert werden. Umgekehrt dürfen aber nur die CyberGraphX-Mode-IDs bzw. Bitmaps an die CyberGraphX-Funktionen übergeben werden. Das gilt ebenso für Picasso96! Beginnen wir mit der graphics.library:
ULONG modeid = BestModeID( Tag tag1, ... );
mögliche Tags sind:
BIDTAG_Depth (UBYTE)gewünschte Farbtiefe (1-8, 15, 16 oder 24)
BIDTAG_DesiredWidth (UWORD)gewünschte Bildschirmbreite in Pixel
BIDTAG_DesiredHeight (UWORD)gewünschte Bildschirmhöhe in Pixel
BIDTAG_MonitorID (ULONG)es kann eine Monitor-Kennung angegeben werden, wenn nur bestimmte Monitortypen unterstützt werden sollen. Beispielsweise PAL_MONITOR_ID (definiert in graphics/modeid.h), wenn nur PAL-Modi zum Zuge kommen sollen.
Bei CyberGraphX sieht das so aus:
ULONG modeid = BestCModeIDTags( Tag tag1, ... );
CYBRBIDTG_Depth (ULONG)gewünschte Farbtiefe (8, 15, 16 oder 24)
CYBRBIDTG_NominalWidth (UWORD)gewünschte Bildschirmbreite in Pixel
CYBRBIDTG_NominalHeight (UWORD)gewünschte Bildschirmhöhe in Pixel
und bei Picasso96:
ULONG modeid = p96BestModeIDTags( Tag tag1, ...);
P96BIDTAG_Depthgewünschte Farbtiefe (8, 15, 16 oder 24)
P96BIDTAG_NominalWidthgewünschte Bildschirmbreite in Pixel
P96BIDTAG_NominalHeightgewünschte Bildschirmhöhe in Pixel
Zusätzlich sind im Zusammenhang mit der PicassoIV-Grafikkarte auch die folgenen Tags von Interesse:
P96BIDTAG_VideoCompatibleTRUE, wenn der Bildschirm über Pablo darstellbar (Videokompatibel) sein muß
P96BIDTAG_PabloIVCompatibleTRUE, wenn der Bildschirm über die PabloIV darstellbar sein muß
P96BIDTAG_PalomaIVCompatibleTRUE, wenn die Eingabedaten der PalomaIV dargestellt werden sollen
Im Normalfall wird der ermittelte Bildschirmmodus zurückgeliefert. Konnte kein passender Modus ermittelt werden, wird INVALID_ID zurückgeliefert. Will Ihr Programm komfortabel sein, sollte sich ein Screenmode-Requester öffnen, um dem Benutzer die Auswahl des Bildschirmmoduses zu ermöglichen.

* Start und Bibliotheken nutzen

Attribute auslesen
ULONG result = GetCyberIDAttr(ULONG modeid, ULONG attribut);
CYBRIDATTR_WIDTH
liefert die tatsächliche Breite des Bildschirms in Pixel
CYBRIDATTR_HEIGHT
liefert die tatsächliche Höhe
CYBRIDATTR_DEPTH
liefert die maximale Farbtiefe

Piccaso 96:
ULONG result = p96GetModeIDAttr(ULONG modeid,ULONG attribut);
P96IDA_WIDTH
liefert die tatsächliche Breite des Bildschirms in Pixel
P96IDA_HEIGHT
liefert die tatsächliche Höhe des Bildschirms in Pixel
P96IDA_DEPTH
liefert die maximale Farbtiefe
Bevor die Funktionen aus den Grafikkarten-Libraries benutzt werden können, muß wie üblich die entsprechene Library geöffnet werden. Ein Beispiel dazu finden Sie in Listing 1.

Beachten Sie bitte die unterschiedlichen Include-Pfade von CyberGraphics (bis V3) und CyberGraphX (ab V4)! Das Picasso-Include wird im libraries-Verzeichnis abgelegt. Für die Prototypen muß clib/cybergraphics_protos.h bzw. clib/picasso96_ protos.h includiert werden.
Sie können Ihr Programm natürlich für beide Systeme auslegen, wobei dadurch allerdings ein erhöhter Entwicklungs- und Wartungsaufwand notwendig ist. Vorteilhaft ist vor allem die Entwicklung von CyberGraphX-kompatibler Software, da dieses System zur Zeit am meisten verbreitet ist. Darüber hinaus kann man auch unter installierter Picasso96-Umgebung auf die cybergraphics.library zurückgreifen, da diese vom Picasso96-System emuliert wird (Version 41.4 von CyberGraphX). Die Entwicklung von »nur Picasso96-Software« ist zur Zeit nur dann sinnvoll, wenn die zusätzlichen Möglichkeiten der PicassoIV-Grafikkarte benötigt werden. Momentan existieren allerdings keine Dokumentationen, wie die PabloIV/PalomaIV/Concertio-Erweiterungen der PicassoIV-Karte anzusprechen sind!


struct DimensionInfo dinfo;
if(GetDisplayInfoData(NULL,(UBYTE*)&dinfo,
      sizeof(dinfo),DTAG_DIMS,modeid))
{
  printf("Width: %ld  Height: %ld  Colordepth: %ld\n",
        dinfo.Nominal.MaxX-dinfo.Nominal.MinX+1,
        dinfo.Nominal.MaxY-dinfo.Nominal.MinY+1,
        dinfo.MaxDepth );
}
Listing 2: Sicherheitshalber die Amiga-Funktion
GetDisplayInfoData() verwenden
Während in den Beschreibungen zu CyberGraphX und Picasso96 jeweils das Entfernen aller »andersartiger« Grafikkartensoftware gefordert wird, kann ich jedoch bestätigen, daß zumindest die beiden Systeme gleichzeitig installiert sein können und auch abwechselnd benutzbar sind! Hinzu kommt noch, daß ich auch zwei Grafikkarten gleichzeitig eingebaut habe (»CyberVision 64« und »PicassoIV«). Den Monitorausgang der PicassoIV habe ich dabei mit dem Eingang der CyberVision 64 verbunden und dort auch den Monitor angeschlossen.


Grafiksysteme: Der schematische Vergleich zwischen Planar- und Chunky-Mode
Die Ausgaben beider Grafikkarten und das ausgegebene Amiga-Signal gibt ein Monitor ohne Umstecken aus. Allerdings stimmt auch, daß nicht beide Grafikkartensysteme gleichzeitig benutzt werden können, was jedoch theoretisch möglich wäre! So entscheide ich während des Bootens, ob die CyberVision 64-Karte mit CyberGraphX oder die PicassoIV-Karte mit Picasso96 zum Einsatz kommen soll. Genauere Infos hierzu finden Sie auf meiner Homepage unter

http://www.meicky-soft.de/gfxcards/gfxcards.html

Wollen Sie für beide Systeme Software entwickeln, ist die gleichzeitige Installation beider Systeme zu empfehlen. Eine Alternative besteht nur darin, eine eigene Partition für jedes Grafikkartensystem zu verwenden und per Boot-Manager zu entscheiden, welches benutzt werden soll.

Minimal kann man aber die cybergraphics.library V41 voraussetzen, was der Paketversion 3 entspricht. Diese Version läßt sich bei Bedarf kostenlos aus dem Internet laden. Anders verhält es sich mit der Version 4 (Library-Version 42.x). Diese Version wird kommerziell von Ossowskis Schatztruhe vertrieben, wobei es auch günstige Up-date-Preise für registrierte »Aufsteiger« gibt. Lediglich wenn Ihr Programm auf Funktionen zurückgreift, die in V41 fehlerhaft sind, sollte eine V42-Library vom Programm verlangt werden.

Beim Picasso-System kann der Programmierer die aktuelle Version verlangen (z.Z. V2), da diese kostenlos im Internet verfügbar ist.

* Den Bildschirmmodus ermitteln

Bitmap-Formate erkennen
  
CyberGraphX
ULONG result = GetCyberMapAttr( struct BitMap *bitmap, ULONG attribut );
Mögliche Attributte sind hierbei:
CYBRMATTR_ISCYBERGFXFeststellung, ob die Bitmap eine CyberGraphX-Bitmap ist
CYBRMATTR_WIDTHliefert die Breite der Bitmap in Pixel
CYBRMATTR_HEIGHTliefert die Höhe der Bitmap in Pixel
CYBRMATTR_DEPTHliefert die Bits je Pixel
CYBRMATTR_BPPIXliefert die Bytes je Pixel
  
Picasso96
ULONG result = p96GetBitMapAttr( struct BitMap *bitmap, ULONG attribut );
Mögliche Attributte sind hierbei:
P96BMA_ISP96um festzustellen, ob die Bitmap eine Picasso96-Bitmap ist
P96BMA_WIDTHliefert die Breite der Bitmap in Pixel
P96BMA_HEIGHTliefert die Höhe der Bitmap in Pixel
P96BMA_DEPTHliefert die Bits je Pixel
P96BMA_BYTESPERPIXELliefert die Bytes je Pixel
P96BMA_RGBFORMATliefert direkt das Bitmap-Format zurück (RGBFB_xxx)
  
graphics.library
ULONG result = GetBitMapAttr( struct BitMap *bitmap, ULONG attribute );
BMA_WIDTHliefert die Breite der Bitmap in Pixel
BMA_HEIGHTliefert die Höhe der Bitmap in Pixel
BMA_DEPTHliefert die Bits je Pixel
BMA_FLAGShier ist BMF_STANDARD interessant um festzustellen, ob die Bitmap im Speicher ist
Fast immer wird es notwendig sein, die Mode-ID für den Grafikkarten-Bildschirm dynamisch zu ermitteln. Vor allem bei Picasso96 ist dieser Weg notwendig, da hier die Mode-IDs auf jedem Rechner unterschiedlich ausfallen können. CyberGraphX stellt immer die selben Mode-IDs zur Verfügung, die allerdings von der eingebauten Grafikkarte abhängen können. Daher sollten Sie auf keinen Fall eine feste ModeID in das Programm codieren!

Es besteht zwar die Möglichkeit, die Mode-ID per Shellargument bzw. Tooltype zu übergeben, vorteilhafter ist jedoch die automatische Ermittlung. Zusätzlich sollte wahlweise ein Screenmode-Requester zur komfortablen Auswahl angeboten werden. Wie das einfach zu bewerkstelligen ist, finden Sie im Kasten »Mode-ID ermitteln« und in den Beispielsourcen.

* Screenmode-Daten bestimmen

Die ermittelte ModeID kann allerdings in Breite und Höhe von der gewünschten Anforderung abweichen! Zusätzlich zu beachten: Bei Verwendung von BestModeID() der graphics.library, kann diese Funktion auch eine PAL- (bzw. andere Amiga) Auflösung zurückliefern, wenn die Auflösung oder Farbtiefe dies erlauben! Wollen Sie »unbedingt« eine Grafikkartenauflösung, sollten Sie auf die Funktion BestCModeIDTags() der cybergraphics.library zurückgreifen. Dabei kann es jedoch passieren, daß INVALID_ID zurückgeliefert wird, wenn keine passende Auflösung existiert. Es wird keinesfalls eine passende Amiga-Auflösung zurückgegeben! Sollen Attribute zu einem Bildschirmmodus ermittelt werden (z.B. in welcher Breite oder Höhe ein entsprechender Bildschirm zu öffnen ist), so stehen die Funktionen aus Kasten »Attribute auslesen« hierfür bereit.

Zurückgeliefert wird der ermittelte Wert entsprechend dem attribut-Tag. Bei ungültigen Tags wird -1 zurückgegeben. Die Funktionen dürfen nur bei den jeweils eigenen Mode-IDs verwendet werden. Wie sich die Moduszugehörigkeit prüfen läßt, erfahren Sie im Abschnitt »Grafikkartenmodus«.

Achtung: Die Funktion GetCyberIDAttr() liefert sowohl bei Benutzung unter CyberGraphX, als auch bei der Picasso96-Emulation für alle drei Tags den Wert -1 zurück! Die Picasso-Funktion hingegen liefert die erwarteten Werte. Zur Sicherheit sollte daher die Amiga-Funktion GetDisplayInfoData() zum Einsatz kommen (s. Listing 2).

* Der Grafikkartenmodus

Soll im Programm festgestellt werden, ob es sich beim gewählten/übergebenen Bildschirmmodus um einen CyberGraphX-, einen Picasso96- oder einen Amiga-Bildschirm handelt, nutzen Sie die folgenden Funktionen:

CyberGraphX:

BOOL res = IsCyberModeID ( ULONG modeid );

Picasso96:

ULONG res = p96GetMode IDAttr( ULONG modeid, ULONG attribut );

wobei als attribut P96IDA_ISP96 übergeben werden muß.

Zeichenfunktionen von CyberGraphX
ULONG ReadRGBPixel(struct RastPort *rp, UWORD x, UWORD y);

Liefert den Farbwert des Pixels an der Position x/y im Format AARRGGBB mit jeweils 8 Bit Breite. Bei Farbtiefen kleiner/gleich 8 Bit sollte die graphics.library-Funktion ReadPixel() Verwendung finden. Sie liefert allerdings das Farbregister, mit dem der Pixel ausgegeben wird.

ULONG WriteRGBPixel(struct RastPort *rp, UWORD x, UWORD y, ULONG argb);

Zeichnet einen Pixel mit dem Farbwert argb (jeweils als 8 Bit AARRGGBB-Wert definiert) an der Position x,y in den RastPort.

LONG ReadPixelArray(APTR dstrect, UWORD dstx, UWORD dsty, UWORD dstmode, struct RastPort *rp, UWORD srcx, UWORD srcy, UWORD sizex, UWORD sizey, UBYTE dstformat);
LONG WritePixelArray(APTR srcrect, UWORD srcx, UWORD srcy, UWORD srcmode, struct RastPort *rp, UWORD dstx, UWORD dsty, UWORD sizex, UWORD sizey, UBYTE srcformat);

Mit diesen beiden Funktionen können mehrere Pixel gleichzeitig gelesen oder geschrieben werden.

LONG ScalePixelArray(APTR srcrect, UWORD srcw, UWORD srch, UWORD srcmode, struct RastPort *rp, UWORD dstx, UWORD dsty, UWORD dsth, UWBYTE srcformat);

Mit dieser Funktion läßt sich ein rechteckiger Bereich (Definition mit srcrect/srcw/srch/srcmode/srcformat) beliebig verkleinert/vergrößert auf den Bereich dstx/dsty/dsth ausgeben.

LONG MovePixelArray(UWORD srcx, UWORD srcy, struct RastPort *rp, UWORD dstx, UWORD dsty, UWORD sizex, UWORD sizey);

Alle Pixel des Rechtecks in der Größe sizex mal sizey werden von srcx/srcy nach dstx/dsty verschoben

LONG FillPixelArray(struct RastPort *rp, UWORD dstx, UWORD dsty, UWORD sizex, UWORD sizey, ULONG argb);

Füllt den rechteckigen Bereich von dstx/dsty in der Größe sizex/sizey mit dem Farbwert argb. Der Farbwert ist als AARRGGBB mit jeweils 8 Bit zu definieren.

LONG InvertPixelArray(struct RastPort *rp, UWORD dstx, UWORD dsty, UWORD sizex, UWORD sizey);

Invertiert alle Pixel von dstx/dsty in der Größe von sizex/sizey. Damit lassen sich beispielsweise Bereiche hervorheben oder Objekte als »aktiv kennzeichnen. Wenn Sie direkt auf die Bitmap zugreifen, um Veränderungen vorzunehmen, muß solange der Zugriff anderer Tasks per LockBitMapTags() unterbunden werden. Ansonsten kann es sehr schnell zu Falschdarstellungen kommen, wenn beispielsweise CyberGraphX den Inhalt am Monitor ausgibt, aber die Bitmap-Daten erst zur Hälfte neu gefüllt wurden. Nur wenn die Funktion einen Wert größer als Null zurückliefert, konnte die Bitmap gesperrt werden und ein Zugriff ist erlaubt. Mit UnLockBitMap() ist diese Sperre wieder aufzuheben. Die Sperrung sollte so kurz wie möglich ausfallen (maximal ein Frame) und während dieser Zeit sind keine anderen Library-Aufrufe möglich!

Beide Funktionen liefern TRUE, wenn es sich um den jeweils »eigenen« Screenmode handelt. Trifft keine der beiden Abfragen zu, so handelt es sich (höchstwahrscheinlich) um eine Amiga-Auflösung. Das muß allerdings nicht der Fall sein. Wird die Mode-ID z.B. vom Benutzer per Zahlenwert dem Programm mitgeteilt, besteht die Möglichkeit einer Falscheingabe.

Wie kann jedoch ermittelt werden, ob die Mode-ID gültig ist? Am einfachsten könnte ein Bildschirm mit der angegebenen Mode-ID (Tag SA_DisplayID) geöffnet werden. Schlägt dies fehl, ist die Mode-ID wahrscheinlich ungültig, wobei allerdings auch andere Fehlerquellen existieren (z.B. Speichermangel). Aber auch die graphics.library bietet hierfür eine passende Funktion an:

ULONG res = ModeNotAvailable( ULONG modeid );

Liefert die Funktion 0 zurück, so handelt es sich um einen gültigen Modus, der auf dem aktuellen Rechner dargestellt werden kann. Vor allen bei der Darstellung von Bilddateien, kann es oftmals vorkommen, daß der Modus, der beim Erstellen verwendet wurde, nicht beim Betrachter verfügbar ist. In diesem Fall sollte man zur Lösung aus Listing 3 greifen, um automatisch den passenden Modus zu verwenden.

Anhand der oben gezeigten Funktion GetDisplayInfoData(...,DTAG_DIMS,modeid) kann auf die tatsächliche Größe des Bildschirmmoduses geschlossen werden. Diese Werte werden zum Öffnen des Screens benötigt.

Um von der ModeID auf den zugehörigen Namen zu kommen, läßt sich ebenfalls die Funktion GetDisplayInfoData() der graphics.library nutzen (s. Listing 4). Die genaue Nutzung läßt sich kann im Beispielprogramm GfxSystem.c (Funktion GetDisplayIDName()) nachvollziehen.

* Bitmap-Daten ermitteln

Mit einer gültigen Mode-ID können Sie nun den Bildschirm wie gewohnt mit OpenScreenTags() öffnen. Dabei wird automatisch Speicher für die Bitmaps reserviert, um die Ausgabedaten aufzunehmen. Bevor nun direkt in eine Bitmap geschrieben wird, muß unbedingt festgestellt werden, um welches Format es sich handelt. Auch hierfür stehen wieder zwei ähnliche Funktionen zur Verfügung (s. Kasten »Bitmap-Formate erkennen«)

Vor allem die Breite des Bildschirms kann sich von der Breite der Bitmap unterscheiden, da letztere normalerweise auf ein Vielfaches aufgerundet wird (bei den Amiga-AGA-Bitmaps z.B. auf ein 64faches). Nur wenn man mit Hilfe der graphics.library die Werte ermittelt, kann man über die Blitterfunktionen auf die Bitmap (mit Ausnahmen) zugreifen!

Arbeitet Ihr Programm nur mit maximal 256 Farben, können Sie auf die Formatermittlung verzichten und wie bisher mit den normalen Amiga-Graphics-Funktionen in die Bitmaps bzw. RastPort zeichnen. Wollen Sie hingegen mehr Farben verwenden, so sollten Sie bereits beim Öffnen des Bildschirms das gewünschte Bitmap-RGB-Format übergeben. Ansonsten müssen Sie für jedes, von CyberGraphX unterstütztes Format, eine eigene Bearbeitungsfunktion erstellen. Durch das vorgegebene Format können Sie einfach »von Hand« die Bitmaps bearbeiten, was aber nur im »geschützten« Zustand erfolgen darf. Mehr dazu lesen in einem folgenden Abschnitt.

* Weitere Funktionen

CyberGraphX stellt aber auch Funktionen bereit, um die Bitmaps zu bearbeiten. Hier eine kurze Aufzählung (ohne Gewähr auf Vollständigkeit). Zuerst ist sicherzustellen, daß es sich bei den jeweiligen Bitmaps auch tatsächlich um eine CyberGraphX-Bitmap handelt (prüfbar per GetCyberMapAttr(bitmap,CYBRMATTR_ISCYBERGFX)).

Außerdem sollten die Funktionen nur bei Bitmaps mit mehr als 8 Bit Tiefe zum Einsatz kommen. Dieser Wert läßt sich mit GetCyberMapAttr(bitmap,CYBRMATTR_DEPTH) feststellen. Bei acht oder weniger Bitmaps, finden die Funktionen der graphics.library Verwendung. Viele Funktionen sind erst ab cybergraphics.library V41 verfügbar (Paket V3). Daher sollte die entsprechende Library bereits beim Programmstart angefordert werden. Die Funktionsliste finden Sie in »Zeichenfunktionen von CyberGraphX«. Zur genauen Funktionsweise bzw. Parametererklärung lesen Sie unbedingt in den Autodocs zu CyberGraphX nach.

Die meist gleichnamigen Funktionen der Picasso96 API.library haben ein »p96« dem Funktionsnamen vorausgestellt:

p96LockBitMap() /
p96UnlockBitMap(), p96ReadPixel() /
p96WritePixel(), p96ReadPixelArray() /
p96WritePixelArray(), p96RectFill(),
p96ReadTrueColorData() /
p96WriteTrueColorData()

Während CyberGraphX viele der Amiga-Funktionen patcht, verlangt das Picasso96-System teilweise den Aufruf der eigenen Funktionen. Hier eine kurze Gegenüberstellung: Bitmaps dürfen Sie auf keinen Fall von Hand erzeugen, auch wenn sie nur für interne Berechnungen/Rendering benutzt werden. AmigaOS bietet seit der Version 3 die beiden Funktion AllocBitmap() bzw. FreeBitmap() hierfür an. Bei Picasso96 hingegen müssen die bei-den Funktionen p96AllocBitMap() und p96FreeBitMap() zum Einsatz kommen.

Etwas unverständlich sind die beiden Funktionen p96OpenScreenTags() und p96CloseScreen() - sie sind zum Öffnen und Schließen von Bildschirmen. Während zwar weitere Picasso96-eigene Tags zur Verfügung gestellt werden, sind auch statt der normalen SA-Tags eigene Definitionen vorhanden. Daß es besser geht, zeigt CyberGraphX. Hier werden alle Daten transparent im normalen OpenScreenTags()-Aufruf verarbeitet.

ULONG modeid; struct BitMapHeader bmhd;
/* Bilddaten einlesen in bmhd und die ModeID
   aus dem Chunk CAMG ermitteln */
if(ModeNotAvailable(modeid) != 0)
  modeid=BestModeID(BIDTAG_DesiredWidth,
         bmhd.bmh_Width, BIDTAG_DesiredHeight,
         bmhd.bmh_Height, BIDTAG_Depth,
         bmhd.bmh_Depth, TAG_DONE);
Listing 3: Fehler mit einer Abfrage vermeiden
Als Besonderheit ermöglicht das Picasso96-System die Darstellung der vom Paloma-Modul eingelesenen Videodaten in einem Fen-ster. Außer den dafür notwendigen Funktionen p96PIP_OpenTagList() und p96PIP_Close(), sind leider keine weiteren Informationen in den Autodocs enthalten. Deshalb ist noch kein sinnvoller Einsatz dieser Features möglich.

Für Picasso96-Entwickler, die Grafiken über das Pablo-Modul auf Video ausgeben möchten, ist noch interessant, daß auch hier eine transparente Farbe möglich ist, die dann das eingespielte Paloma-Signal anzeigt. Bei Amiga-Grafiken ersetzt das Genlock das Farbregister 0 durch das zugespielte Videosignal. Picasso96 hingegen verwendet das Farbregister 255 als transparent! Das heißt in der Praxis: Nachbearbeitung vorhandener Grafiken oder eine interne Routine kümmert sich um das Ummappen von Farbregister 0 auf 255. Zu diesem Thema werden Sie leider ebenfalls keine Informationen in den Picasso96-Autodocs finden.

* Die Beispiel-Programme

Viele der angesprochenen Funktionen finden Sie in den beiden Beispielprogrammen GfxSystem.c und GfxWindow.c. Das erste Programm liegt als reine Shell-Version vor. Es zeigt, wie automatisch ein passender Bildschirmmodus ermittelt wird, entsprechend vorgegebener Werte für Breite, Höhe und Farbtiefe (WIDTH, HEIGHT, DEPTH). Sie finden auch eine Universalroutine, um von der Mode-ID auf den Namen zu kommen. Auch die Gültigkeitsprüfung der Mode-ID wird gezeigt. Die Mode-ID läßt sich dabei direkt übergeben (MODEID), wobei auch die hexadezimale Angabe möglich ist (z.B. MODEID=0x21004). Je nach übergebenem Parameter wird außerdem ein Screenmode-Requester zur Auswahl geöffnet (MODEREQ) oder die komplette Liste der verfügbaren Modi ausgegeben (MODELIST).

Das zweite Programm, GfxWindow.c, ist ein vollständiges Anwendungsprogramm. Bei der Definition eines beliebigen Bildschirms hilft ein Screenmode-Requester, den das Programm bereitstellt. Den zu verwendenden Zeichensatz kann man auch einstellen. Per File-Requester wird eine Grafik-Datei gewählt, die dann auf dem Bildschirm (in einem »unsichtbaren« Fenster) angezeigt wird.

struct NameInfo ninfo;
if(GetDisplayInfoData(NULL,(UBYTE*)&ninfo,
   sizeof(ninfo),DTAG_NAME,id))
   /* Ok, der Name steht in "ninfo.name" */
else
   /* ModeID ungültig oder kein Text zu
      diesem Modus verfügbar */
Listing 4: Über die Mode-ID den richtigen Namen finden.
Hierzu kommen die Funktionen der datatypes.library zum Einsatz, um beliebige Bildformate einfach verarbeiten zu können. Wie bereits im zweiten Kursteil angesprochen, sollte unbedingt der neue picture.datatype V43 im System existieren. Damit ist sicher, daß auch Grafiken mit mehr als 256 Farben in ihrer vollen Farbpracht auf den Bildschirm kommen (entsprechende Farbtiefe vorausgesetzt). Über »Laden mit Anpassung« wird die Mode-ID direkt aus der Grafik ausgelesen und ein entsprechender Bildschirm bereitgestellt. Bei übergroßen Grafiken läßt sich der Sichtbereich über die Cursor-Tasten bestimmen. Sollte der gewählte Screenmode nicht vom Monitor darstellbar sein ­ ein Druck auf die Escape-Taste bzw. ein CTRL-C-Signal in der Shell beenden das Programm. Das Programm aktiviert automatisch die Farbpalette des geladenen Bildes.

Bei ungünstiger Farbgebung setzt die Space-Taste die ersten vier Farbregister auf (meine) Default-Werte zurück. Dadurch werden die Bildschirmelemente und Menüs wieder wählbar.

Der eingestellte Screenmode und Font läßt sich speichern, wodurch die Abfrage beim Programmstart entfällt. Die mitgegebenen Shell-Argumente werden aber trotzdem noch beachtet, wodurch einfach abweichende Screenmode-Parameter übergeben werden können.

Der Sourcecode sollte ausreichend dokumentiert sein und weist bei gegebenem Anlaß auf die Besonderheiten der einzelnen Routinen oder Funktionen hin. Die Aufgaben wurden in einzelne Routinen zerlegt, welche hierdurch auch in den eigenen Programmen zum Einsatz kommen können.

Kursübersicht
Folge 1
Grafikkarten-Hardware, Vorteile, Einbau,Einstellungen und Treiber
Folge 2
Grafikkarten-Software, Zubehör-Programme und Tools zur Nutzung von Grafikkarten
Folge 3
Grafikkarten-Programmierung, Planar-Chunky-Bitmaps, Farbtabellen, wichtige Funktionen der cybergraphics- und Picasso96API.library
Das Programm verwendet (je nach Vorhandensein) automatisch die Funktionen der cybergraphics- bzw. Picasso96API.library. Auch ohne einer der Libraries läuft das Programm und benutzt dann einfach die Funktionen der graphics.library. Das in ANSI-C geschriebene Programm läßt sich mit jedem beliebigen C-Compiler übersetzen. Spezielle Anforderungen (oder SAS-spezifische Tags) kommen nicht zum Einsatz. Die Aufrufe für die gängigsten Compiler stehen im Dateikopf. Beachten Sie, daß die Developer-Archive vom CyberGraphXund Picasso96-System installiert sein müssen, damit die Programme übersetzbar sind. MaxonC- bzw. StormC-Benutzer müssen außerdem noch zusätzlichen Dateien installieren (finden Sie im Beispiel-Archive auf der Magazin-Homepage). Das ist notwendig, da zum einen ein anderes »pragma amicall«-Format zum Einsatz kommt und zum anderen für die Tags-Funktionen entsprechende Stub-Routinen bereitgestellt werden müssen. Damit ist auch dieser dritte und gleichzeitig letzte Teil über die Grafikkarten abgeschlossen. Ich hoffe, Ihnen den Umgang und die Funktionsweise von Grafikkarten verständlich gemacht zu haben. Die Programmierer unter Ihnen sollten jetzt auch über das notwendige Wissen verfügen, um eigene Programme anpassen zu können.

Für Fragen stehe ich gerne zur Verfügung ­ am einfachsten per E-Mail:

Michael Christoph.

Die Beispielprogramme und Compilerarchive können direkt von der Homepage des Programmierers geladen werden:

http://www.meicky-soft.de/gfxcards/amgfxkurs.html
lb


 Hauptseite © 1999 All Rights Reserved. Alle Rechte vorbehalten Franzis' Verlag GmbH
Veröffentlichung und Vervielfältigung nur mit schriftlicher Genehmigung des Verlags

Kommentare, Fragen, Korrekturen und Kritik bitte an Webmaster AMIGA schicken.
Zuletzt aktualisiert am 04. Mai 1999, Michael Christoph.