original in en Phil Ross
In my last article I wrote about the 3Dfx and how well it did at providing Mesa hardware acceleration capabilities. I touched upon the advantages and disadvantages of using Mesa+3Dfx, and this time I would like to go into detail about some of these disadvantages and how a developer can get around them.
To begin with, Miguel's informative article explains how to use the GLUT library to render into subwindows within the main window. When you use subwindows, a new context is created separately from the context of the main window. Unfortunately, the 3Dfx driver for Mesa only supports one context at the moment. If you try to use subwindows on the 3Dfx you will see that instead of rendering the subwindow into the main window, the subwindow is rendered over top of the main window. This produces a quick flashing effect as the main window and subwindow are alternately rendered very fast. This is obviously not the effect we want from subwindows so you will have to wait for Miguel's future explanation of how to get around using subwindows by manipulating matrix stacks.
Second, I would like to show how one can overcome the problem with keeping the mouse focus when using fullscreen rendering with the 3Dfx. When using fullscreen rendering with the 3Dfx, the rendering is done to the 3Dfx's framebuffer instead of your 2D video adapter's framebuffer. The result is that a window is created for the program on your 2D desktop, but all of the rendering for the program is done fullscreen to the 3Dfx. On a single headed system, the 3Dfx takes over the monitor and you will not be able to see the window on the 2D desktop, but on a dual headed system, one monitor will show your 2D desktop and the window created for the program, and on the other monitor you will see fullscreen rendering of the program.
On single headed systems it can often be tricky to have the program's window keep the window focus on the 2D desktop because you wont be able to see the window. If the program's window on the 2D desktop loses focus, it will be unable to accept input. If the program cant accept input to detect when the user presses a designated exit key, and the user can't see the 2D desktop to be able to locate the exit button on the window and close the program, the user might not be able to shutdown the program!
A trick you can use to work around this is to use the glutFullScreen() and glViewport() functions. The glutFullScreen() function resizes the program's window to the dimensions of the 2D desktop so that the window becomes fullscreen on the 2D desktop. What you can do is call glutFullScreen() after creating a window to make the window fullscreen on the 2D desktop. When the window is fullscreen, there is not way for the mouse to leave the window, so the window can not lose focus.
The glViewport() function tells the program how big the viewport will be for the program. When you specify a viewport, all of the rendering is done into that viewport. For the 3Dfx, where you would normally call glViewport() in a reshape callback function to set the viewport to the new dimensions of the window, make a call to glViewport() with the dimensions of the resolution of the 3Dfx. If you were running the 3Dfx at 640x480 you would call glViewport(0,0,640,480) and if you were running at 800x600 you would call glViewport(0,0,800,600). This will make the program render to the viewport dimensions that you specified as the resolution of your 3Dfx card even though the window is fullscreen.
I've included a version of Miguel's smooth-shaded triangle modified to work on the 3Dfx (example3.c, Makefile). I simply excluded the subwindows, added glutFullscreen() in the proper place (after window creation), and changed glViewport() in the reshape callback function to force the viewport to 640x480 (the resolution of my 3Dfx carx). You will notice if you run without the 3D (by not setting MESA_GLX_FX environment variable) the program's window will open to the full dimensions of your desktop, but rendering is only done to a 640x480 area within that window. If you run the program with the 3Dfx, you will see the rendering is done to the full size of the 3dfx and the program will now lose focus.
Something else to note, when you run the program without the 3Dfx, the program may run really slow due to the fact that the full window is being updated instead of just the viewport. This is quite a performance hit when rendering to your 2D desktop but it's fine for fullscreen 3Dfx. For this reason, you may want to write your programs to detect whether or not the 3Dfx is being used (by detecting and reading the MESA_GLX_FX environment variable) and either using glutFullScreen() force glViewport() trick if the 3Dfx detected or not use the trick if the 3Dfx is not detected.