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_Depth | gewünschte Farbtiefe (8, 15, 16 oder 24) |
P96BIDTAG_NominalWidth | gewünschte Bildschirmbreite in Pixel |
P96BIDTAG_NominalHeight | gewünschte Bildschirmhöhe in Pixel |
Zusätzlich sind im Zusammenhang mit der
PicassoIV-Grafikkarte auch die folgenen Tags von
Interesse:
|
P96BIDTAG_VideoCompatible | TRUE, wenn der Bildschirm über Pablo darstellbar
(Videokompatibel) sein muß
|
P96BIDTAG_PabloIVCompatible | TRUE, wenn der Bildschirm über die PabloIV darstellbar sein
muß |
P96BIDTAG_PalomaIVCompatible | TRUE, 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_ISCYBERGFX | Feststellung, ob die Bitmap eine CyberGraphX-Bitmap ist |
CYBRMATTR_WIDTH | liefert die Breite der Bitmap in Pixel |
CYBRMATTR_HEIGHT | liefert die Höhe der Bitmap in Pixel |
CYBRMATTR_DEPTH | liefert die Bits je Pixel |
CYBRMATTR_BPPIX | liefert die Bytes je Pixel |
| |
Picasso96 |
ULONG result = p96GetBitMapAttr( struct BitMap *bitmap, ULONG attribut ); |
Mögliche Attributte sind hierbei: |
P96BMA_ISP96 | um festzustellen, ob die Bitmap eine Picasso96-Bitmap ist |
P96BMA_WIDTH | liefert die Breite der Bitmap in Pixel |
P96BMA_HEIGHT | liefert die Höhe der Bitmap in Pixel |
P96BMA_DEPTH | liefert die Bits je Pixel |
P96BMA_BYTESPERPIXEL | liefert die Bytes je Pixel |
P96BMA_RGBFORMAT | liefert direkt das Bitmap-Format zurück (RGBFB_xxx) |
| |
graphics.library |
ULONG result = GetBitMapAttr( struct BitMap *bitmap, ULONG attribute ); |
BMA_WIDTH | liefert die Breite der Bitmap in Pixel |
BMA_HEIGHT | liefert die Höhe der Bitmap in Pixel |
BMA_DEPTH | liefert die Bits je Pixel |
BMA_FLAGS | hier 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
© 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.