4.3 KiB
| title | author | date | isbn | publisher | category | chapter | pages |
|---|---|---|---|---|---|---|---|
| Michael Abrash's Graphics Programming Black Book, Special Edition | Michael Abrash | 1997-07-01 | 1576101746 | The Coriolis Group | Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development | 35 | 670-671 |
The result of all this is simply a single pixel drawn in the color set
up in EVGALine. EVGADot may seem excessively complex for a
function that does nothing more that draw one pixel, but programming the
VGA isn't trivial (as we've seen in the early chapters of this part).
Besides, while the explanation of EVGADot is lengthy, the code
itself is only five lines long.
Line drawing would be somewhat faster if the code of EVGADot were
made an inline part of Octant0 and Octant1, thereby saving the
overhead of preparing parameters and calling the function. Feel free to
do this if you wish; I maintained EVGADot as a separate function for
clarity and for ease of inserting a pixel-drawing function for a
different graphics adapter, should that be desired. If you do install a
pixel-drawing function for a different adapter, or a fundamentally
different mode such as a 256-color SuperVGA mode, remember to remove the
hardware-dependent outportb lines in EVGALine itself.
Comments on the C Implementation
EVGALine does no error checking whatsoever. My assumption in writing
EVGALine was that it would be ultimately used as the lowest-level
primitive of a graphics software package, with operations such as error
checking and clipping performed at a higher level. Similarly,
EVGALine is tied to the VGA's screen coordinate system of (0,0) to
(639,199) (in mode 0EH), (0,0) to (639,349) (in modes 0FH and 10H), or
(0,0) to (639,479) (in mode 12H), with the upper left corner considered
to be (0,0). Again, transformation from any coordinate system to the
coordinate system used by EVGALine can be performed at a higher
level. EVGALine is specifically designed to do one thing: draw lines
into the display memory of the VGA. Additional functionality can be
supplied by the code that calls EVGALine.
The version of EVGALine shown in Listing 35.1 is reasonably fast,
but it is not as fast as it might be. Inclusion of EVGADot directly
into Octant0 and Octant1, and, indeed, inclusion of Octant0
and Octant1 directly into EVGALine would speed execution by
saving the overhead of calling and parameter passing. Handpicked
register variables might speed performance as well, as would the use of
word OUTs rather than byte OUTs. A more significant performance
increase would come from eliminating separate calculation of the address
and mask for each pixel. Since the location of each pixel relative to
the previous pixel is known, the address and mask could simply be
adjusted from one pixel to the next, rather than recalculated from
scratch.
These enhancements are not incorporated into the code in Listing 35.1 for a couple of reasons. One reason is that it's important that the workings of the algorithm be clearly visible in the code, for learning purposes. Once the implementation is understood, rewriting it for improved performance would certainly be a worthwhile exercise. Another reason is that when flat-out speed is needed, assembly language is the best way to go. Why produce hard-to-understand C code to boost speed a bit when assembly-language code can perform the same task at two or more times the speed?
Given which, a high-speed assembly language version of EVGALine
would seem to be a logical next step.
Bresenham's Algorithm in Assembly
Listing 35.3 is a high-performance implementation of Bresenham's
algorithm, written entirely in assembly language. The code is callable
from C just as is Listing 35.1, with the same name, EVGALine, and
with the same parameters. Either of the two can be linked to any program
that calls EVGALine, since they appear to be identical to the
calling program. The only difference between the two versions is that
the sample program in Listing 35.2 runs over three times as fast on a
486 with an ISA-bus VGA when calling the assembly-language version of
EVGALine as when calling the C version, and the difference would be
considerably greater yet on a local bus, or with the use of write mode
3. Link each version with Listing 35.2 and compare performance—the
difference is startling.