Der DirectDraw - Transparenzmechanismus
Wurden Höhe und Breite des Fensters ermittelt, geht es an die eigentliche Erzeugung des Puffer-Surfaces.
Weil diesmal nicht die Größe eines Bildes die Größe des Surfaces bestimmt, müssen Höhe und Breite in den
Elementen lHeight und lWidth des Surface-Descriptors, also der DDSURFACEDESC-Struktur,
hinterlegt werden. Damit die Methode CreateSurface diese Werte auch berücksichtigt, müssen außerdem
die Flags DDSD_HEIGHT und DDSD_WIDTH angegeben werden:
backBufferDesc.lFlags = _
DDSD_CAPS Or DDSD_HEIGHT Or _
DDSD_WIDTH
backBufferDesc.lWidth = _
rClient.Right
backBufferDesc.lHeight = _
rClient.Bottom
backBufferDesc.ddsCaps.lCaps _
= DDSCAPS_OFFSCREENPLAIN _
Set backBufferSurface = _
dd.CreateSurface(backBufferDesc)
Den für das Backbuffer-Surface benötigten Speicherplatz bezieht DirectDraw standardmäßig aus dem
Videospeicher der Grafikkarte. Das garantiert höchste Performance, denn das Kopieren von Speicherbereichen
innerhalb der
Grafikkarte ist deutlich schneller als das Kopieren eines Surfaces aus dem Hauptspeicher in den
Grafikspeicher. Dennoch trifft man in verschiedenen Beispielprogrammen oft auf das Capability-Flag DDSCAPS_SYSTEMMOEMORY.
Es bewirkt, dass der Speicher eines Surfaces aus dem Hauptspeicher des Rechners bezogen wird. Allerdings wird der Programmablauf
dadurch merklich verzögert, weshalb ein Verzicht auf dieses Flag angebracht ist. Beim Zeichnen in das Puffer-Surface gelten prinzipiell
dieselben Beschränkungen wie beim Primary-Surface: Objekte, die in das Surface hineinkopiert werden sollen, müssen vollständig in das
Zielsurface hineinpassen. Ist das nicht der Fall, wird die Blt-Operation abgebrochen. Hier hilft nur ein Clipper, der bei
Blt-Operationen am Rand des Surfaces die nicht benötigten Bereiche abschneidet:
Dim r(1) As Rect
r(0) = rClient
Set Clipper = dd. _
CreateClipper(0)
Clipper.SetClipList 1, r
doubleBufferSurface. _
SetClipper Clipper
Anders als für das Primary-Surface, dessen Clipper-Objekt über das Fensterhandle des Ausgabefensters initialisiert wird,
muss das Clipper-Objekt für das Puffer-Surface durch Angabe eines RECT-Arrays initialisiert werden. Jedes der in einem
Array zusammengefassten Rectangles gibt einen beschreibbaren Bereich des Puffer-Surfaces an. Im allgemeinen genügt jedoch ein
einziges Rechteck, das in der linken, oberen Ecke (0,0) des Surfaces beginnt und sich über die gesamte Höhe und Breite des Surfaces
erstreckt. Dieses Rechteck wird in ein ein-elementiges RECT-Array übertragen, das anschließend via SetClipList zur
Initialisierung des Clipper-Objektes übergeben wird. In Aktion können Sie dieses Feature im Programm auf der
Heft-CD \Quellen\DirectX\DirectX4 sehen.
Game-Loop
Selbst wenn man die Ausgabe eines neuen Bildes an ein Timer-Control koppelt, erreicht man niemals eine Bildwiederholrate
von mehr als 50 Bildern pro Sekunde bzw. 50 Hz. Das liegt daran, dass das Timer-Control eine zeitliche Auflösung von nur
einer 50stel Sekunde besitzt. Um höhere Bildraten jenseits der 50 Hz zu erreichen, müssen daher eigene Mechanismen
implementiert werden, die eine möglichst hohe Performance garantieren. Hier nutzt man die sogenannte Idle-Time einer
Anwendung. Das ist die Zeit, die ein Programm damit verbringt, nutzlos auf die nächste eingehende Nachricht zu warten.
Durch Ausnutzung der Idle-Time, in der keine Tastatur-, Maus-, Fenster- oder sonstige Nachrichten zur Bearbeitung anstehen,
kann man das letzte Quentchen Speed aus einer DirectDraw-Anwendung herausholen. Was in C/C++-Programmen aus dem Hinzufügen einer
weiteren Codezeile besteht, ist unter Visual Basic allerdings deutlich komplizierter. Denn die Bearbeitung der eingehenden
Nachrichten erfolgt vollautomatisch, so dass ein Programm zunächst gar keine Möglichkeit besitzt, zu ermitteln, ob eine Nachricht
zur Bearbeitung ansteht oder nicht. Doch mit ein paar API-Tricks lässt sich Abhilfe schaffen.
Und so geht es: Man erweitert das Programm einfach durch ein Modul, in dem ein Sub Main den Einstiegspunkt
der Anwendung bildet. Innerhalb dieser Methode bildet man die sogenannte Message-Pump nach. Das ist jener Teil eines
jeden Programms, der für die Auswertung der Nachrichten einer Anwendung zuständig ist und der in einem Visual-Basic-Programm
üblicherweise vor den Augen des geplagten Entwicklers verborgen ist.
|