[comp.sys.ibm.pc] Screen-writing speed & snow elimination

dmt@mtunb.ATT.COM (Dave Tutelman) (03/13/89)

In the past couple of months, there have been a number of notes
(and responses) on the subjects of:
   -	Snow on the screen, and code to eliminate it.
   -	Why the BIOS is so slow.
   -	Fast routines to write to the screen.

I've recently had the occasion to check the performance of various
screen-writing routines (including the BIOS).  The attached paper
is (1) a tutorial on snow elimination techniques, and (2) the results
of my performance measurements.

Enjoy!

+---------------------------------------------------------------+
|    Dave Tutelman						|
|    Physical - AT&T Bell Labs  -  Lincroft, NJ			|
|    Logical -  ...att!mtunb!dmt				|
|    Audible -  (201) 576 2442					|
+---------------------------------------------------------------+






                    _S_N_O_W-_F_R_E_E _S_C_R_E_E_N _W_R_I_T_I_N_G _v_s. _V_I_D_E_O _B_I_O_S:
                         _T_U_T_O_R_I_A_L _A_N_D _P_E_R_F_O_R_M_A_N_C_E _T_E_S_T_S

                                 Dave Tutelman
                                16 Tilton Drive
                               Wayside, NJ 07712

                                (201) 922 - 9576










                      1. Principles of Snow Elimination
                        1.1. Theory
                        1.2. Practice


                      2. Performance
                        2.1. Test Measurements
                          2.1.1. Basic Measurements
                          2.1.2. Effect of Snow Elimination
                          2.1.3. Effect of String Writes
                          2.1.4. Effect of Pointer Computation
                        2.2. Why is BIOS so Slow?



























       Screen Writing                                           2-13-89





                                     - 2 -


       _1. _P_r_i_n_c_i_p_l_e_s _o_f _S_n_o_w _E_l_i_m_i_n_a_t_i_o_n

       If you write programs for MSDOS PCs, you face an interesting
       dilemma: how to write to the screen.
         - If you use the BIOS, you will take a performance hit; it's
           _s_l_o_w.
         - If you write directly to video RAM to speed it up, you have
           to write different code for each kind of video display. And
           some displays have an added difficulty, "snow", which is
           notoriously hard to eliminate.

       Snow is the visual noise that appears on the screen of certain
       displays when a program reads or writes to the video RAM. The CGA
       (IBM Color Graphics Adapter) is particularly snowy, but is hardly
       the only offender.

       This note discusses where snow comes from, and how to eliminate
       it by writing to video RAM during retrace. It also gives some
       detailed performance measurements that show how much speed can be
       gained by avoiding the BIOS calls; improvements of a factor of
       ten are common, and the gain can be as high as a factor of
       seventy.

       _1._1. _T_h_e_o_r_y

       When IBM introduced the Color Graphics display adapter (CGA),
       they made an unfortunate design decision. A display adapter needs
       to read from its memory "as needed" by the raster sweep, and
       write to its memory "as needed" by the CPU. To save money on the
       board, they didn't do this with a true dual-port memory; instead,
       they allowed the CPU to take precedence over the raster when they
       access the video RAM on the same memory cycle. During such
       cycles, the video generator can't read from memory, and doesn't
       know what video signal to put out. So it guesses, and usually
       wrong (hey, what's the chance of getting eight bits all right).
       Wrong guesses look like snow on the screen.

       IBM overcame this hardware deficiency in software. They wrote
       their video driver in the BIOS so that it writes to memory only
       when the video beam is turned off; At the end of each horizontal
       line on the screen, the adapter turns off the beam and allows it
       to _r_e_t_r_a_c_e back to the left edge of the screen to begin the next
       horizontal line. It is possible to do a "snowless" write to video
       memory if you do it only during the retrace. You can also use the
       vertical retrace (which is of much longer duration), while the
       beam is returned from the bottom of the screen to the top.

       The BIOS writes to the screen only during horizontal or vertical
       retrace, and so can your program. It is possible to tell when the
       display is retracing, because a bit in the display adapter's
       status register is 1 during horizontal retrace, and another bit
       is 1 during vertical retrace.

       Let's show some actual code to do such a write. Our first example
       will be simple (really naive); in other words, it looks good but
       doesn't work. We will evolve our code until we have a working

       Screen Writing                                           2-13-89





                                     - 3 -


       snowless write.

       Suppose we want to write a word _v_i_d_w_o_r_d to video RAM. We've saved
       the offset in video RAM in the variable _v_i_d_o_f_f_s_e_t. (We'll use
       conventions of the "C" language, and Turbo C where we can't say
       things "portably".) We know that:
         - The segment part of the base address of the CGA is 0xB800.
         - The CGA'a status register is at input port 0x3DA.
         - The horizontal sweep bit is bit 0; the vertical sweep bit is
           bit 1. Thus the combined sweep mask on the status byte is
           0x09.
       Thus the C code to do a snow-free write might be:

               /* Just spin until a retrace bit turns on. */
               while (( inportb (0x3DA) & 0x09 ) == 0 )   { };


               /* We're in retrace; write it. */
               poke ( 0xB800, vidword, vidoffset );

       Might be, but isn't. Unfortunately, probability says you'll
       encounter a horizontal retrace much more often than a vertical
       retrace, and the horizontal one lasts a very short time. The code
       above looks tight, but it's not nearly tight enough; by the time
       it actually writes to video RAM, the retrace will be over. If you
       ever encounter a program where the "snow" is in a vertical band a
       fixed distance from the left edge of the screen, you'll be
       observing a failed attempt at snow elimination. Instead of
       removing the snow, it just _s_y_n_c_h_r_o_n_i_z_e_s it to the horizontal
       sweep.

       The table below shows the sweep characteristics of a CGA display.
       Other displays have similar characteristics, varying from the CGA
       by a factor of less than two.

                                    Horizontal        Vertical
                                    -----------     -------------
            Sweeps per second         15,750             60
            Duration of retrace     10 microsec     2158 microsec

       Thus the horizontal retrace is a more attractive target (we can
       write to the screen more frequently), but a much harder one to
       hit than the vertical retrace. The next section shows the
       programming techniques to catch the retrace as frequently as
       possible, in order to maximize our throughput to the screen.

       Before proceeding, however, it's worth mentioning another
       technique for snow elimination: turning off the video altogether
       for a short burst of screen writes. The video can be disabled by
       simply turning off a bit in the mode register of the display
       adapter. It can stay off for the time required to write about 250
       characters (three lines on the screen) according to Brad Davidson
       (Usenet message number 1884@druxq.UUCP, August 6, 1985). However,
       it's not clear how often you can do this before the flicker
       becomes annoying. Since you have to wait for vertical retrace to
       start, you couldn't possibly do this more than 30 times a second

       Screen Writing                                           2-13-89





                                     - 4 -


       (assuming you could get away with turning off the display every
       other frame); that's a maximum rate of 7500 characters per
       second. The use of retrace gives about the same rate, but without
       the program complexity of having to buffer three lines and send a
       burst to the screen. For this reason, I won't discuss it any
       further here.

       _1._2. _P_r_a_c_t_i_c_e

       I'll start off assuming that you want your code to run across a
       variety of DOS machines, including 4.77 MHz PCs and clones. If
       you're going to try for the horizontal retrace, you have to
       detect it and use it in under 10 microseconds (less than 50
       machine cycles on a "slow" PC or XT).

       You will need to program it in assembler. Pascal or C won't give
       you the speed to catch the horizontal retrace. The reason is that
       you must point a register pair (say, ES:DI, so we can use a
       "string-move" instruction) at the target area in video RAM _b_e_f_o_r_e
       you start to look for H-retrace; if you find retrace and _t_h_e_n
       load the pointer into the register pair, you'll be late in
       writing. It's impossible to express this constraint in Pascal or
       C; you have to code it yourself in assembler.

       Once again, we want to write _v_i_d_w_o_r_d to location _v_i_d_o_f_f_s_e_t.
       Suppose we've also stored the video seqment in _v_i_d_s_e_g_m_e_n_t and the
       port address in _v_i_d_p_o_r_t. We've even been clever enough to put
       vidoffset and vidsegment in adjacent words, so we can load them
       into registers with a single instruction. The code we have so far
       is:

               mov  dx,vidport              ;Address of control register
               mov  cx,vidword              ;Data to be written
               les  di,dword ptr [vidoffset]  ;Load pointer into ES:DI
               mov  ah,9                    ;2-bit mask for V+H retrace


            wait_retrace:
               in   al,dx                   ;Get the status register to AL
               test al,ah                   ;V+H retrace mask
               jz   wait_retrace            ;loop till either bit turns on


               mov  ax,cx                   ;put the data in the accumulator
               stosw                        ;do the screen write

       This is a lot better than our last try. We have much less
       "synchronized snow" than we had before, but it's not all gone.
       What's wrong?

       Well, the code to detect horizontal retrace and use it is now
       shorter than the retrace itself, so we're doing some snow
       reduction. However, there's a strong possibility that we'll start
       to search for H-retrace while we're already in it, and even late
       in it. If we start our loop late in the H-retrace, we'll be out
       of it before we do the write, hence the remaining snow at the

       Screen Writing                                           2-13-89





                                     - 5 -


       left edge of the screen. To eliminate all the snow, we must first
       make sure we're _o_u_t _o_f _t_h_e _r_e_t_r_a_c_e before we start to look for
       it. That way we'll be sure to find it early in the retrace. The
       code below does that.


               mov  dx,vidport              ;Address of control register
               mov  cx,vidword              ;Data to be written
               les  di,dword ptr [vidoffset]  ;Load pointer into ES:DI
               mov  ah,9                    ;2-bit mask for V+H retrace


            wait_sweep:
               in   al,dx                   ;Get the status register to AL
               test al,1                    ;H-retrace?
               jnz  wait_sweep              ;... Yes. Wait till it turns off


            wait_retrace:
               in   al,dx                   ;Get the status register to AL
               test al,ah                   ;V+H retrace mask
               jz   wait_retrace            ;loop till either bit turns on


            do_it:
               mov  ax,cx                   ;put the data in the accumulator
               stosw                        ;do the screen write

       This is almost the code that I use in my routines. However, to
       enhance performance, I add a couple of checks:
         - I keep a static variable called _s_n_o_w_o_k, which I set to 1 for
           display adapters that don't put snow on the screen. If this
           variable is set, I bypass the snow suppression code.
         - Before I check for the horizontal sweep, I look to see if
           we're in vertical retrace. The V-retrace is thousands of
           microseconds, and the retrace bit turns off long before the
           beam turns back on, so we can be write to video RAM any time
           we see it.
         - I change a <TEST,JNZ> pair of instructions to <RCR,JC>, which
           saves a couple of machine cycles.
       The resulting code is:
















       Screen Writing                                           2-13-89





                                     - 6 -


               mov  dx,vidport              ;Address of control register
               mov  cx,vidword              ;Data to be written
               les  di,dword ptr [vidoffset]  ;Load pointer into ES:DI
               mov  ah,9                    ;2-bit mask for V+H retrace
               test snowok,1                ;Do we need to do snow suppression?
               jz   do_it                   ;... No.
               in   al,dx                   ;Read the status register
               test al,8                    ;Vertical retrace in progress?
               jnz  do_it                   ;... Yes. Don't need to wait


            wait_sweep:
               in   al,dx                   ;Get the status register to AL
               rcr  al,1                    ;Faster than  TEST AL,1
               jc   wait_sweep              ;Still in H-retrace. Wait


            wait_retrace:
               in   al,dx                   ;Get the status register to AL
               test al,ah                   ;V+H retrace mask
               jz   wait_retrace            ;loop till either bit turns on


            do_it:
               mov  ax,cx                   ;put the data in the accumulator
               stosw                        ;do the screen write

       Before we move on to performance measurements, however, I'd like
       to comment on a few differences between this and a code fragment
       recently posted by Ward Christensen (Usenet message
       5082@phoenix.Princeton.EDU, January 2, 1989). Ward attributes the
       code to "FASTWRITE", by an author whose name he's forgotten.

         - Ward recommends bypassing the snow elimination code if the
           board is a monochrome board instead of a CGA; he claims that
           the sweep bit doesn't toggle with a mono board, and the
           program will hang. In my experience, bypassing snow removal
           for a mono board is a good idea, but _n_o_t because it hangs the
           program; it doesn't. However, the mono board doesn't have
           inherent snow; the video memory is better designed. Without
           the retrace checks, the program will run a lot faster.

           As Ward points out, the best way to decide what to do is to
           look at the video mode variable in the BIOS. If the mode is
           7, it's a mono board. If the mode is 0 to 6, it's a CGA (or
           another display in CGA-compatible mode).

         - FASTWRITE recommends turning off interrupts while looking for
           retrace and writing to the screen. It (and other snow removal
           programs I've seen) accomplish this by surrounding the snow
           removal code with a CLI-STI instruction pair.

           I oppose this in principle, and find it unnecessary in
           practice. I believe that turning off interrupts should only
           be done if the system or application will be corrupted by the
           occurrence of an interrupt (e.g.- while switching stacks, or

       Screen Writing                                           2-13-89





                                     - 7 -


           unloading the received byte from a UART before the next byte
           overwrites it). But what is the consequence of being
           interrupted in our routine? Either a spot of snow on the
           screen or a delay in the output of a character. Either is
           invisible if interrupts are infrequent events; neither
           threatens the integrity of any other operation of the
           computer.

         - FASTWRITE doesn't treat vertical retrace as a special case.
           This slows the "screen throughput" by 5%-10%, as measured by
           the techniques in the next section.

       _2. _P_e_r_f_o_r_m_a_n_c_e

       _2._1. _T_e_s_t _M_e_a_s_u_r_e_m_e_n_t_s

       _2._1._1. _B_a_s_i_c _M_e_a_s_u_r_e_m_e_n_t_s

       I made a series of measurements of "screen throughput" in
       characters per second, on several MSDOS Personal Computers.
       Throughput was measured by sending 20,000 to 100,000 characters
       to the screen, and timing the duration with a stopwatch. The
       calling program was written in C, and made repeated calls to a
       function _d_p_u_t_c (_y, _x, _c_h_a_r_a_c_t_e_r, _c_o_l_o_r), which was itself coded
       in assembler. The calling program was, roughly speaking:

                 for (n=0; n<N; n++)
                     for (i=0; i<25; i++)
                         for (j=0; j<80; j++)
                             dputc (i, j, n+' ', 0x07);

       where N was chosen to give a reasonable time to measure with a
       stopwatch.

       Table 1 shows the results, for three different versions of the
       _d_p_u_t_c () function.
         - The first version simply invokes the appropriate BIOS
           functions to move the cursor and write the character. This
           establishes a _b_a_s_e_l_i_n_e _t_h_r_o_u_g_h_p_u_t for each computer.
         - The second version is coded in assembler, using the snow
           elimination code discussed earlier in these notes.
         - The third version establishes a maximum throughput for the
           computer, by writing directly to video RAM without worrying
           about snow. The CGA and the AT&T 400-line displays showed
           plenty of snow with this version.
       The numbers in the table show the baseline throughput, and the
       improvement factor over the baseline for each of the faster
       versions. For instance, the AT&T PC 6300 PLUS can write to the
       screen using the BIOS at 1000 characters per second.  If it spews
       characters at the screen raw (without snow elimination), it can
       go at 15 times that speed, or 15,000 characters per second.






       Screen Writing                                           2-13-89





                                     - 8 -


                                    TABLE 1
                     CHARACTER WRITING SPEED USING dputc()


         Computer        IBM     Clone   AT&T    IBM     AT&T    AT&T
                          XT      XT     6300    AT      6300+   6386
                         -----   -----   -----   -----   -----   -----
         CPU Chip        8088    8088    8086    286     286     386
                         -----   -----   -----   -----   -----   -----
         Display Board   CGA     Herc    AT&T    CGA     AT&T    EGA
                                 Mono    400-ln          400-ln
                         -----   -----   -----   -----   -----   -----
         Characters      360     380     770     830     1000    2800
            per second
            using BIOS
         Improvement
            factor
            over BIOS:
          -Snow            8      11      11       8      12       8
            eliminated
          -Just write     14      12      14      16      15      13
            to video

       The results are pretty consistent.  Calling a snow-free
       assembly-coded function improves throughput by a factor of ten
       over the BIOS, for a wide range of processors and displays. The
       maximum obtainable improvement (forgetting the snow elimination
       altogether and just writing blindly to the video RAM) gives an
       improvement factor of 14 over the BIOS.

       _2._1._2. _E_f_f_e_c_t _o_f _S_n_o_w _E_l_i_m_i_n_a_t_i_o_n

       Looking at the table, we see that we can pick up most of the
       improvement even if we wait for retrace to eliminate snow. The
       speed with snow eliminated is between 50% and 92% of the maximum
       raw speed possible.

       I ran some measurements on the relative contributions of the
       vertical and horizontal retrace to the speed of the snow-free
       functions.

         - The functions using only horizontal retrace were about 20%
           slower than the functions using both vertical and horizontal
           retrace.

         - The functions using only vertical retrace were _v_e_r_y _s_l_o_w.
           They were within a factor of two of the baseline BIOS
           results, and slower than the BIOS in some cases.

       _2._1._3. _E_f_f_e_c_t _o_f _S_t_r_i_n_g _W_r_i_t_e_s

       There is a way to gain a major improvement even over these
       results. Remember that we're writing from a C program that loops
       and calls _d_p_u_t_c() for each character.  But most programs do the
       vast majority of their screen output as _c_h_a_r_a_c_t_e_r _s_t_r_i_n_g_s, not
       isolated characters. This suggests an opportunity to code an

       Screen Writing                                           2-13-89





                                     - 9 -


       assembler routine _d_p_u_t_s() that writes a snow-free string when
       called. Such a function would be faster by saving:
         - The less-efficient C code for the inner loop of the program.
         - The overhead of a function call for the vast majority of
           screen writes.
         - The need to compute the offset in video RAM for each
           character; the pointer just needs to be stepped.

       I have coded the _d_p_u_t_s() function, and measured it with a program
       that's output-equivalent to the previous test program:

                 line [80] = '\0';
                 for (n=0; n<N; n++) {
                     for (j=0; j<80; j++)
                         line [j] = n+' ';
                     for (i=0; i<25; i++)
                         dputs (i, 0, line, 0x07);
                 }

       The results, shown in Table 2, are in the form of improvement
       factors over the corresponding row of the character-at-a-time
       tests.

                                    TABLE 2
                       STRING WRITING SPEED USING dputs()


         Computer        IBM     Clone   AT&T    IBM     AT&T    AT&T
                         XT       XT     6300    AT      6300+   6386
                         -----   -----   -----   -----   -----   -----
         CPU Chip        8088    8088    8086    286     286     386
                         -----   -----   -----   -----   -----   -----
         Display Board   CGA     Herc    AT&T    CGA     AT&T    EGA
                                 Mono    400-ln          400-ln
                         -----   -----   -----   -----   -----   -----
         Improvement
            factor over
            dputc() tests
          -BIOS            1.5     1.5     1.5     1.4     1.5     1.5
            calls
          -Snow            4       4       3       2.3     2       1.3
            eliminated
          -Just write      5.5     6       5       4       4.5     4
            to video

       We can see that, except for the 386 box, the total improvement
       over the baseline BIOS data ranges between factors of 20 and 44.
       For instance, the improvement for the XT clone is the previous
       improvement factor (11), times the improvement due to writing
       strings (4), or 44. Where snow elimination isn't a problem, the
       improvement factor can be even higher. For instance, the Hercules
       monochrome board, with no snow problem, can have its screen
       written by a factor of 72 (12 times 6) faster than the BIOS.




       Screen Writing                                           2-13-89





                                    - 10 -


       _2._1._4. _E_f_f_e_c_t _o_f _P_o_i_n_t_e_r _C_o_m_p_u_t_a_t_i_o_n

       To my surprise, one thing for which I've occasionally criticized
       the BIOS design was _n_o_t much of a speed factor.  The BIOS
       recalculates the video RAM address offset each time it is called.
       Since the 8088 is horribly slow at multiplying, it would seem
       smart to remember the last location written and the offset
       associated with it. If the new location is close (say, in the
       same row), simply adjust the old offset by addition rather than
       computing a new one from scratch by multiplication.

       To test this assertion, I measured throughput using both methods,
       for a few of the test machines; the results are shown in Table 3.

                                    TABLE 3
                   IMPROVEMENT DUE TO INCREMENTAL COMPUTATION


                   CPU Chip        8088    8086    286
                                   ----    ----    ----
                   Snow            1.00    1.00    1.00
                      eliminated
                   Just write      2.22    1.03    0.95
                      to video

       The "adjustment" method showed a difference only in the "raw
       write" case. Where we took the trouble to eliminate snow, the
       time spent waiting for retrace completely masked any improvement
       in the offset computation.

       Even in the case of raw writes, the results were hardly decisive.
       The slowest of the machines (using a 4.77 MHz 8088 CPU) saw a
       significant improvement. The improvement in the case of the 8 MHz
       8086 chip was barely measurable. With the 286 chip (where the
       multiply instruction is much faster), computing from scratch was
       actually faster than adjusting the old offset.


       _2._2. _W_h_y _i_s _B_I_O_S _s_o _S_l_o_w?

       Unfortunately, most of the problem is in the fundamental design
       of the BIOS, not the implementation. It is impossible to make any
       major improvements by cleverly implementing the functions as
       defined. Here are the major contributing factors:

         - The use of the software interrupt as the function interface
           carries more overhead than a function call, but not all that
           much. However, grouping functions together on an interrupt
           (and selecting which function by switching on the value of
           AH) requires every function call to be handled by a
           "dispatcher" that burns a nontrivial number of machine
           cycles.

         - The selection of function calls is itself a botch. In the
           first place, there is no string write call, and we have seen
           how big a difference it can make. (String write has recently

       Screen Writing                                           2-13-89





                                    - 11 -


           been added to the BIOS, but portable programs obviously won't
           use that call since it won't be in most BIOSes in the field.)

         - An additional problem with the function set is that the
           screen write functions only write where the cursor is, and
           they don't move the cursor automatically. One reason that the
           BIOS is so slow is that, when a program writes a string, it
           has to make _t_w_o BIOS calls for each character: one to write
           the character and the other to advance the cursor. My dputc()
           and dputs() functions write to an arbitrary place on the
           screen, independent of where the visible cursor is blinking.














































       Screen Writing                                           2-13-89

flong@sdsu.UUCP (Fred J. E. Long) (03/13/89)

Please correct me if I am wrong, but can't you do this for fast writes:

1) Write the characters to page 2
2) Switch to page 2 for viewing
3) Write the characters to page 1
4) Go back to page 1 for viewing

Can you do this, or am I thinking of Apple ]['s ?

-- 
Fred J. E. Long	
San Diego State University, San Diego, California  92093
ARPA: flong%midgard@ucscc.ucsc.edu	
UUCP: ...!ucsd!sdsu!flong

jc58+@andrew.cmu.edu (Johnny J. Chin) (03/14/89)

Yes, you may write to page 2 and flip back and forth BUT ....
it will still cause snow.

And what's worse ... you can't do that with a standard monochrome card.

I've tried it and writing to any of the pages still makes the CGA snow.
And on the monochrome, writing to pages other then page 0 causes unpredictable
results.
      __________                                ___
     /          \                          /   /    /_/ / /\/
    _/  /   /   /                       __/.  /__  / / / / /
   /     /     /
  /           / 4730 Centre Ave. #412   ARPAnet: Johnny.J.Chin@andrew.cmu.edu
 /  -------  /  Pittsburgh, PA  15213   BITnet:  jc58@andrew
 \__________/   (412) 268-8936          UUCP: ...!harvard!andrew.cmu.edu!jc58
 Computer Dr.

Disclaimer:   The views expressed herein are STRICTLY my own, and not CMU's.

spolsky-joel@CS.YALE.EDU (Joel Spolsky) (03/14/89)

In article <3562@sdsu.UUCP> flong@sdsu.UCSD.EDU (Fred J. E. Long) writes:
| 
| Please correct me if I am wrong, but can't you do this for fast writes:
| 
| 1) Write the characters to page 2
| 2) Switch to page 2 for viewing
| 3) Write the characters to page 1
| 4) Go back to page 1 for viewing

The IBM MDA (monochrome display adapter) only has one page. So, unless
you want to write two sets of i/o routines, no, you can't.

+----------------+----------------------------------------------------------+
|  Joel Spolsky  | bitnet: spolsky@yalecs.bitnet     uucp: ...!yale!spolsky |
|                | internet: spolsky@cs.yale.edu     voicenet: 203-436-1483 |
+----------------+----------------------------------------------------------+
                                                      #include <disclaimer.h>

dmt@mtunb.ATT.COM (Dave Tutelman) (03/15/89)

>In article <3562@sdsu.UUCP> flong@sdsu.UCSD.EDU (Fred J. E. Long) writes:
>| Please correct me if I am wrong, but can't you do this for fast writes:
>| 
>| 1) Write the characters to page 2
>| 2) Switch to page 2 for viewing
>| 3) Write the characters to page 1
>| 4) Go back to page 1 for viewing

In article <53527@yale-celray.yale.UUCP> spolsky-joel@CS.YALE.EDU (Joel Spolsky) responds:
>The IBM MDA (monochrome display adapter) only has one page. So, unless
>you want to write two sets of i/o routines, no, you can't.

Actually, the MDA doesn't have a snow problem at all, so you don't need to
go to this trouble.  Fortunate indeed, because Joel is right that it
has only one page (though the Hercules monochrome has several).  Joel
is also right that you'll need multiple routines: one with the page
switching and one without.

However, let's see if there is something to be gained from page-switching.
The most speed you can hope to gain is the difference between raw screen writes
and those protected by waiting for retrace.  The price of this is the
need to keep two copies of the screen up-to-date.  (I assume you want
to make incremental updates to an existing screen, not just repaint
the whole screen each time you change it.  That means that the "off-screen"
page must be kept identical to the "on-screen" one.)

Thus, to make the two-page technique pay off, you've got to be able to do
raw screen writes at least twice as fast as the retrace-protected
writes, because you've got to do twice as many of them.
My measurements show precious few cases where the raw writes were
more than twice as fast as the retrace-protected writes.  In the majority
of machines (especially the slower ones, where algorithm performance 
buys the most), the speed gain is less than x1.5.  In those cases,
keeping two pages is a net loss.

So here are the places where keeping two screens might be worthwhile:

   -	The cases where the speedup is worth it.  From my data, that
	includes cases like a PC6300 PLUS (286 box) or a PC6386
	(386 box) with a display that NEEDS snow removal.

   -	Painting a brand new screen for the first time.  Some programs
	have places where the entire screen context changes.  Page
	switching is a way of making that happen insantly and
	snow-free.

   -	Those programs where there is "dead time" after a screen
	write, that can be used for updating the off-screen page.
	Many places in interactive programs have this characteristic.
	However, it's got to be more than one or two characters to
	pay off; even the BIOS has no apparent performance problem
	where you write less than a line.

   -	Those programs where the APPEARANCE of speed is more important
	than real speed.  With page switching, the update is done
	invisibly and then "snaps" to the screen; you don't watch
	the screen being painted.  (I've always found this sort
	of operation more annoying than watching the screen go; if
	it were actually slower, it'd be intolerable.  However, no
	accounting for taste  :-)

In summary, good idea Fred, and it works.  But its advantages are
limited to special cases.  If I wanted to write ONE way of doing
it for all my console programs, I'd use retrace-protection.

+---------------------------------------------------------------+
|    Dave Tutelman						|
|    Physical - AT&T Bell Labs  -  Lincroft, NJ			|
|    Logical -  ...att!mtunb!dmt				|
|    Audible -  (201) 576 2442					|
+---------------------------------------------------------------+

brad@looking.UUCP (Brad Templeton) (03/16/89)

It is possible to write a complete 80 by 25 page full of information on
a slow 4.7 mhz PC to a snowy colour card in 1/15 second by waiting for
retrace, and thus getting no snow.

I wrote a curses library package ages ago that's used in some of my
software packages that does just this.  1/15th of a second is just
barely noticeable.  You can't notice anything on a machine faster than a
PC.

No fancy bank switch schemes are needed, just good retrace waiting code.
-- 
Brad Templeton, Looking Glass Software Ltd.  --  Waterloo, Ontario 519/884-7473

shurr@cbnews.ATT.COM (Larry A. Shurr) (03/18/89)

In article <53527@yale-celray.yale.UUCP> spolsky-joel@CS.YALE.EDU (Joel Spolsky) writes:
}In article <3562@sdsu.UUCP> flong@sdsu.UCSD.EDU (Fred J. E. Long) writes:

}| Please correct me if I am wrong, but can't you do this for fast writes:

}| 1) Write the characters to page 2
}| 2) Switch to page 2 for viewing
}| 3) Write the characters to page 1
}| 4) Go back to page 1 for viewing

}The IBM MDA (monochrome display adapter) only has one page. So, unless
}you want to write two sets of i/o routines, no, you can't.

True and it also doesn't eliminate the need for snow removal if your
CGA requires snow removal to begin with, so it doesn't eliminate that
overhead.

regards, Larry
-- 
Signed: Larry A. Shurr (att!cbnews!cbema!las or osu-cis!apr!las)
Clever signature, Wonderful wit, Outdo the others, Be a big hit! - Burma Shave
(With apologies to the real thing.  The above represents my views only.)