In meinem letzten Artikel ging es um die
3Dfx-Karte und welche Performance-Gewinne sie bringt
bei Verwendung der Programmbibliothek Mesa. Ich habe dort kurz über die Vor- und
Nachteile der Kombination von Mesa und 3Dfx
geschrieben. Diesmal will ich etwas detaillierter
über diese Nachteile berichten und Tips zu ihrer
Umgehung geben
Miguels Artikel
erklärt, wie man mit Hilfe der GLUT-Library in
Teilfenster des Hauptwindows zeichnen kann. Für
jedes Subwindow wird ein neuer, vom Hauptfenster
separater Kontext erzeugt. Leider unterstützt der
Mesa-3Dfx-Treiber nur einen aktuellen Kontext. Will
man mit einer 3Dfx Teilfenster benutzen, stellt man
fest, daß sie nicht innerhalb des Hauptfensters
erzeugt werden, sondern dieses verdecken. Das führt
zu einem schnellen Blinken, wenn Haupt- und
Teilfenster abwechselnd gezeichnet werden. Klar, daß
dieser Effekt nicht erwünscht ist. Wer Teilfenster
benutzen will, muß auf den Artikel von Miguel
warten, in dem er erklären will, wie man sie durch
Manipulation des Matrix-Stacks einsetzen kann.
Ich möchte hier jetzt gerne zeigen, wie man den
Fokus behalten kann, wenn man mit der 3Dfx
Fullscreen zeichnet. In diesem Fall wird der
3Dfx-Framebuffer anstelle der 2D-Grafikkarte
benutzt. Dadurch wird ein Fenster für das Programm
auf dem 2D-Desktop erzeugt, die gesamte Grafik aber
Fullscreen von der 3Dfx erstellt. Bei einem System mit einem
Bildschirm übernimmt die 3Dfx diesen, so daß man das
Fenster auf dem 2D-Desktop nicht sehen kann. Ist ein
zweiter Monitor angeschlossen, zeigt einer das
Fullscreen-Bild der 3Dfx und der andere den
2D-Desktop mit dem Programm-Fenster.
Wenn nur ein Monitor angeschlossen ist, gibt es
häufig Schwierigkeiten den Fokus auf dem 2D-Desktop zu
behalten, weil dieser ja unsichtbar ist. Verliert das
Programm auf diesem Desktop den Fokus, kann es keine
Eingaben mehr verarbeiten. Dann kann es natürlich auch
nicht feststellen, wenn der Anwender die "Ende"-Taste
drückt, und er kann andererseits nicht den Menüeintrag
anklicken -- denn das Programmfenster ist unsichtbar.
In dieser Situation ist es also nicht möglich, das
Programm zu beenden.
Ein bißchen Trickserei mit glutFullScreen() und
glViewport() hilft aus diesem Dilemma.
glutFullScreen() vergrößert das Programmfenster so,
daß es den ganzen 2D-Desktop einnimmt. Ruft man
glutFullScreen() nach dem Erzeugen eines Fensters
auf, kann die Maus es nicht mehr verlassen, denn es
ist ja genauso groß wie der Desktop. So kann das
Fenster den Fokus nicht mehr verlieren.
Die Funktion glViewport() legt den Viewport des
Programms fest, in dem die
ganze Grafik erscheint. Normalerweise ruft man
glViewport() während einer Resize-Operation auf, um
den Viewport an die neuen Fensterabmessungen
anzupassen. Hier sollte man glViewport() mit den
Größen aufrufen, mit denen man die 3Dfx betreibt:
bei 640x480 also glViewport(0,0,640,480) und bei
800x600 entsprechend glViewport(0,0,800,600).
Dadurch benutzt das Programm nur diesen Teil des
Fensters, das eigentlich den ganzen Bildschirm
einnimmt.
Eine für die 3Dfx modifizierte Version von
Miguels schattiertem Dreieck liegt hier: (../../common/March1998/example3.c, ../../common/March1998/Makefile). Ich habe einfach die
Teilfenster weggelassen, glutFullscreen() an der
richtigen Stelle eingetragen (nach dem Erzeugen der
Fenster) und glViewport() im Reshape-Callback so
geändert, daß der Viewport den 640x480 Pixeln meiner
3Dfx-Karte entspricht. Läßt man das Programm ohne
die 3D-Karte laufen läßt (also MESA_GLX_FX nicht
gesetzt ist), kann man sehen, daß das
Programm-Fenster den ganzen Bildschirm einnimmt, zum
Zeichnen aber nur eine 640x480 Pixel große Fläche
benutzt wird. Läuft das Programm mit der 3Dfx,
zeichnet es auf den ganzen Bildschirm.
Außerdem fällt auf, daß das Programm ohne 3Dfx
sehr langsam ist. Das liegt daran, daß das ganze
Fenster neu gezeichnet werden muß anstelle des
kleineren Viewports. Dadurch gibt es
Performance-Einbußen beim Zeichen in den 2D-Desktop.
Es ist also sinnvoll, in Applikationen die An-
oder Abwesenheit der 3Dfx durch Prüfen von
MESA_GLX_FX festzustellen. Dann kann man entweder
die Kombination glutFullScreen()/glViewport()
benutzen, wenn die Karte vorhanden ist, oder eben
darauf verzichten.
|