84 lines
4.6 KiB
Markdown
84 lines
4.6 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[Previous](35-05.html) [Table of Contents](index.html) [Next](35-07.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
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 {#Heading10}
|
||
|
||
**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 **OUT**s rather than byte **OUT**s. 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 {#Heading11}
|
||
|
||
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.
|
||
|
||
------------------------ --------------------------------- --------------------
|
||
[Previous](35-05.html) [Table of Contents](index.html) [Next](35-07.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
* * * * *
|
||
|
||
Graphics Programming Black Book © 2001 Michael Abrash
|