Graphics modes
Graphics modes are the common denominator for most Allegro programs. While it
is possible to write platform specific programs using Allegro which don't set
a graphic mode through the routines provided in this chapter, these are not
very common.
The first thing to note is that due to the wide range of supported platforms,
a graphic mode is the only way to safely communicate with the user. When
Allegro was a DOS only library (versions 3.x and previous), it was frequent
for programmers to use functions from the C standard library to communicate
with the user, like calling printf() before setting a graphic mode or maybe
scanf() to read the user's input. However, what would happen for such a game
running under Windows where there is no default console output or it may be
hidden from the user? Even if the game compiled successfully, it would be
unplayable, especially if there was vital information for the user in those
text only messages.
Allegro provides the allegro_message() function to deal with this problem,
but this is not a very user friendly method of communicating with the user
and its main purpose is displaying small error like messages when no graphic
mode is available. Therefore, the first thing your Allegro program should do
is set a graphic mode, and from there on, use Allegro's text output routines
to display messages to the user, just like `allegro/examples/exhello.c' does.
Setting a graphic mode involves deciding how to allocate the memory of the
video card for your program. On some platforms this means creating a virtual
screen bigger than the physical resolution to do hardware scrolling or page
flipping. Virtual screens can cause a lot of confusion, but they are really
quite simple. Warning: patronising explanation coming up, so you may wish to
skip the rest of this paragraph. Think of video memory as a rectangular piece
of paper which is being viewed through a small hole (your monitor) in a bit of
cardboard. Since the paper is bigger than the hole you can only see part of it
at any one time, but by sliding the cardboard around you can alter which
portion of the image is visible. You could just leave the hole in one position
and ignore the parts of video memory that aren't visible, but you can get all
sorts of useful effects by sliding the screen window around, or by drawing
images in a hidden part of video memory and then flipping across to display
them.
For example, you could select a 640x480 mode in which the monitor acts as a
window onto a 1024x1024 virtual screen, and then move the visible screen
around in this larger area (hardware scrolling). Initially, with the visible
screen positioned at the top left corner of video memory, this setup would
look like:
(0,0)------------(640,0)----(1024,0)
| | |
| visible screen | |
| | |
(0,480)----------(640,480) |
| |
| the rest of video memory |
| |
(0,1024)--------------------(1024,1024)
With a virtual screen bigger than the visible screen you can perform smooth
CPU inexpensive scrolling: you draw your graphics once, and then only tell
the video card to show a different portion of the screen. However, virtual
screens are not supported on all platforms, and on some they might be
emulated through software, losing any performance. On top of that, many video
cards only allow horizontal scrolling in steps of 32 bytes. This is not a
problem if your game runs in 24 or 32 bit, but it tends to mean jerky
scrolling for other color depths.
The other reason you could use virtual screens for is page flipping. This
means showing one portion of the virtual screen while your program draws to
the hidden one. When you finish, you show the part you have been drawing to
and repeat the process with the area now hidden. The result is a perfectly
smooth screen update without flickering or other graphical artifacts.
Scrolling manually to one part of the video memory is one non portable way to
accomplish this. The portable way is to use functions like
create_system_bitmap(), create_video_bitmap(), show_video_bitmap(), etc. These
functions divide the memory of the video card in areas and switch between
them, a feature supported on all platforms and video cards (given that they
have enough memory for the screen resolutions you asked for).
The last thing you need to know about setting a graphic mode are drivers.
Each platform has a number of graphic drivers wich support a different range
of hardware or behave in different ways. To avoid cluttering your own code
with #ifdefs and dealing with drivers added after you release your program,
Allegro provides several so called magic drivers. These magic drivers don't
really exists, they wrap around a specific kind of functionality.
The magic drivers you can use are:
-
GFX_AUTODETECT:
Allegro will try to set the specified resolution with the current color
depth in fullscreen mode. Failing that, it will try to repeat the same
operation in windowed mode. If the call to set_gfx_mode() succeeds, you
are guaranteed to have set the specified resolution in the current color
depth, but you don't know if the program is running fullscreen or
windowed.
-
GFX_AUTODETECT_FULLSCREEN:
Allegro will try to set the specified resolution with the current color
depth in fullscreen mode. If that is not possible, set_gfx_mode() will
fail.
-
GFX_AUTODETECT_WINDOWED:
Allegro will try to set the specified resolution with the current color
depth in a windowed mode. If that is not possible, set_gfx_mode() will
fail. When it comes to windowed modes, the `specified resolution' actually
means the graphic area your program can draw on, without including window
decorations (if any). Note that in windowed modes running with a color
depth other than the desktop may result in non optimal performance due to
internal color conversions in the graphic driver. Use
desktop_color_depth() to your advantage in these situations.
-
GFX_SAFE:
Using this driver Allegro guarantees that a graphic mode will always be
set correctly. It will try to select the resolution that you request, and
if that fails, it will fall back upon whatever mode is known to be
reliable on the current platform (this is 320x200 VGA mode under DOS, a
640x480 resolution under Windows, the actual framebuffer's resolution
under Linux if it's supported, etc). If it absolutely cannot set any
graphics mode at all, it will return negative as usual, meaning that
there's no possible video output on the machine, and that you should abort
your program immediately, possibly after notifying this to the user with
allegro_message.
This fake driver is useful for situations where you just want to get into
some kind of workable display mode, and can't be bothered with trying
multiple different resolutions and doing all the error checking yourself.
Note however, that after a successful call to set_gfx_mode with this
driver, you cannot make any assumptions about the width, height or color
depth of the screen: your code will have to deal with this little detail.
-
GFX_TEXT:
Closes any previously opened graphics mode, making you unable to use the
global variable `screen', and in those environments that have text modes,
sets one previously used or the closest match to that (usually 80x25).
With this driver the size parameters of set_gfx_mode don't mean anything,
so you can leave them all to zero or any other number you prefer.