Re: Swap Ready on the Onyx

New Message Reply Date view Thread view Subject view Author view

Allan Schaffer (aschaffe)
Wed, 26 Apr 1995 22:34:51 -0700


On Apr 27, 11:26am, Simon Bennett wrote:
> Thanx... but I still can't seem to get this to work.... Is there
> anything else I have to do? Does genlock have to be running?

Yes -- there are 3 general steps to take when synchronizing
swapbuffers on multiple pipes:

  - the wiring of the genlock and swap ready signals
  - genlocking the pipes,
  - and the use of mswapbuffers.

I have a (long) cookbook-style document describing swapready, written
by one of the RealityEngine engineers. It's a bit dated now -- the
example program could use updating, as do a few things that the text
says to never do. For example, the part about never changing the
cursor may have been specific to releases prior to 5.3.

It should serve as an excellent reference. I'll append below.

> BTW - where is the GANGDRAW flag to mswapbuffers() documented? It's not
> in the mswapbuffers manpage.

I've discovered that GANGDRAW is the new word for DUALDRAW. Both
DUALDRAW and GANGDRAW are #define'd to be 0x200 in gl/gl.h right
now.

Allan
-----------------------

        GangDraw (also called Swap Ready) operation
        ===========================================

GangDraw is a mechanism that permits multiple graphics pipelines to
swap at precisely the same time. This is particularly useful in
simulators, where multiple screens (e.g. a front and two side views)
must be synchronized to all update simultaneously.

GangDraw is NOT designed as a general-purpose synchronization
mechanism. It is targeted exclusively for the simulator market; as
such, it has several restrictions and limitations. Within these
limits, it works well; but it is easy to violate these limits, and
the result is usually a crashed or hung graphics pipeline.

Overview
--------

To set up a system for GangDraw operation, you must follow these steps:

        1) Ensure that all hardware is correct;
        2) Ensure that all system software is correct;
        3) Cable the system correctly;
        4) Genlock the pipes together;
        5) Run a test program to verify the setup;
        6) Modify your software;
        7) Pay attention to the GangDraw restrictions.

1) Hardware Prerequisites
-------------------------

You MUST have up-to-date hardware, or GangDraw mode will not work.

        DG2 (the display board of the RealityEngine): the small eight-pin
                PAL with part number 1045 must be at revision 5 or later.
                Part 1045-005 with checksum 167C is good; 1045-004 30AC is
                bad. A test program is provided below that will help in
                determining if the DG2 is out of date.

        EF# (the plate with the video output connectors): early versions
                of the output panel were missing a resistor, and had no
                output on the SYNC BNC connector. This means you cannot
                use this pipe as a sync source for genlock.

2) Software Prerequisites
-------------------------

You MUST be running Irix 5.2 or later. All GangDraw support is built
in to the graphics code; there is no special subsystem to load.

3) System Cabling
-----------------

First, the pipelines must be genlocked together. This involves
selecting a sync source, and distributing it to all graphics pipes.
You can either use one graphics pipeline as the sync source, or use
an external sync source; this depends on your overall system
configuration. Most installations use one pipe as the sync master;
and they usually select pipe 0 as the master. (It doesn't matter
which pipe is the master; but selecting pipe 0 makes it easier to
remember).

Then, you connect all of the `Swap Ready' BNC connectors together.
You may use BNC `T' connectors if necessary. DO NOT use a terminator
on this line! Below are sample cable configurations (please excuse
the ASCII graphics):

Two pipes, pipe 0 serving as master:

                Pipe 0 Pipe 1
                Master Slave

    swap rdy o)-------------------(o

    sync out o)-------- o
                            \
    sync in o ----------(o

    sync loop o x
                                        ^= 75 ohm terminator

Three pipes, pipe 0 serving as master:

                Pipe 0 Pipe 1 Pipe 2
                Master Slave Slave

    swap rdy o)-------------------(o)-------------------(o

    sync out o)-------- o o
                            \
    sync in o ----------(o ----------(o
                                                  /
    sync loop o o)-------- x
                                                              ^= 75 ohm

Two pipes, external sync source:

                Pipe 0 Pipe 1
                Slave Slave

    swap rdy o)-------------------(o

    sync out o o

    sync in -----(o ----------(o
                            /
    sync loop o)-------- x
                                        ^= 75 ohm terminator

Three pipes, external sync source:

                Pipe 0 Pipe 1 Pipe 2
                Slave Slave Slave

    swap rdy o)-------------------(o)-------------------(o

    sync out o o o

    sync in -----(o ----------(o ----------(o
                            / /
    sync loop o)-------- o)-------- x
                                                              ^= 75 ohm

4) Genlock all pipes together
-----------------------------

You must select a common VOF for all pipes. You cannot run in
genlocked mode with different VOFs running. If you are using an
external sync source, then that source must exactly match the timing
of your selected VOF.

For the examples below, we will use the normal hires VOF,
1280x1024_60.

On the `master' pipe, select the format normally. For example:

        setenv DISPLAY :0
        /usr/gfx/setmon -x 1280x1024_60

On all `slave' pipes, select the format, and specify external genlock
with the -g flag. For example:

        setenv DISPLAY :1
        /usr/gfx/setmon -g -x 1280x1024_60
        setenv DISPLAY :2
        /usr/gfx/setmon -g -x 1280x1024_60

Then restart graphics with the new VOFs:

        /usr/gfx/stopgfx; /usr/gfx/startgfx &

(If you are familiar with the use of setmon, you may also do the
above interactively with the -n flag if you wish; however, restarting
the graphics is recommended, as this resets all of the GangDraw state
variables).

Unfortunately, there is no good way to verify that all pipes are
actually genlocked together without a dual-trace oscilliscope.

5) Testing the setup
--------------------

The first thing to do is to verify normal system operation. All
normal (i.e. non-GangDraw) programs should run normally. Verify this
first. If normal programs hang, or if the graphics pipe crashes, the
system is cabled incorrectly.

If the system runs normally, then enter and compile the sample
program at the end of this document. (You should compile it on your
own system, and not use a pre-compiled binary, so that you know that
you have the correct libraries installed).

One very important note: NEVER kill this program with a `kill -9' or
similar statement. The proper way to exit the program is by hitting
the escape key (with the cursor in it's window, of course!). If you
exit it by sending it a kill signal, it may leave internal variables
in a strange state, and any future tests run on the system will be
invalid. If you accidentally kill the program in this way, restart
the graphics (by /usr/gfx/stopgfx; /usr/gfx/startgfx &) to reset the
system to a known working state.

Now, run the program with no argument on pipe 0. It should put up a
300 x 300 black rectangle with a zero in the corner. The colour of
the rectangle will slowly change, as the number in the corner
increments. The rate of change (assuming a lightly loaded system)
should be smooth; over time the program will very gradually slow
down, but the program should never visibly stop.

If the program stops, disconnect the swap ready cable (see step 4)
from this pipe. If the program continues, there is something wrong
with the cabling; the line is terminated in some manner. If the
program stops with no cables connected, then the DG2 is out of date.
The most likely cause is an out-of date PAL #1045; check this for the
correct revision. (An out-of-date PAL will cause the test program to
stop at certain specific numbers, but not others).

Once the program has run smoothly for 10 seconds or so, exit it via
the ESC key, and try it on the other pipeline(s), one at a time.

If the program runs smoothly on each pipeline individually, then you
are ready for a final test. Run the program with a small argument
(e.g. gangdraw 10) on one pipeline. It should run smoothly, and
quickly. Now, run the program with a large argument (e.g. gangdraw
500) on another pipeline (NOT on the same pipeline!). That program
should run smoothly, but slowly; and the original program should slow
down to the same speed as the second one. If the first program does
not slow down, check that the swap ready cables are attached.

If the programs run fine individually, but the pipes hang when you
try to run them together, then the pipes are not genlocked together.
In fact, 99.9% of the time GangDraw isn't working, it's because of
genlock problems.

6) Software Modifications
-------------------------

To modify an existing program to use the GangDraw mechanism is quite
easy. You change existing calls to swapbuffers() or mswapbuffers() to
include the GANGDRAW parameter.

First, change all instances of

        swapbuffers();

to

        mswapbuffers(NORMALDRAW);

which are exactly equivilent statements. Next, whenever you want to
have a synchronized swap (i.e. all pipes swap simultaneously), add
the GANGDRAW parameter to the mswapbuffers call; e.g. change

        mswapbuffers(NORMALDRAW);

to

        mswapbuffers(NORMALDRAW | GANGDRAW);

You should read the restrictions below before modifying a program.
Also, you must take care to undo the GangDraw mechanism before
exiting the program; this can be done by simply calling
mswapbuffers(NORMALDRAW), i.e. without the GANGDRAW parameter, which
turns GangDraw off. See the sample code below (gangdraw.c).

7) GangDraw Restrictions
------------------------

First, you may run one, and ONLY one, GangDraw program per pipeline.
This mechanism serves only to synchronize pipelines to each other; it
cannot be used to synchronize two programs running on the same pipe.

You must also exit the program cleanly; the only way that the GL
knows that you are exiting your GangDraw application is if you call
mswapbuffers without the GANGDRAW argument. Otherwise, the pipeline
will hold on to the Swap Ready output line, which will prevent a
GangDraw program from running on any other pipeline.

Another major restriction is that you MUST not change the shape of
the cursor while running a GangDraw program. Changing the cursor
shape can cause a fatal pipe crash. Note that this implies that a
GangDraw program is a full-screen application only, since 4Dwm
changes the shape of the cursor as you cross a window border. (Note
that it is the act of loading a cursor that causes the crash, and not
the actual change in shape; so even reloading the exact same glyph as
is currently active will cause this crash).

If you must run with multiple windows active, you should disable
visible cursors completely within the window manager to avoid this
problem.

One minor restriction is that you must swap at least once every
second or so. If you stop swapping for longer than a second, the
graphics pipeline will time out (there is a watchdog that checks for
at least some activity every so often). In practice, most simulations
should update themselves at least this often.

It is also worth mentioning that, when a pipe is being delayed, ALL
graphics activity on that pipe is halted, even activity in other,
unrelated windows. In practice, since this is designed for
full-screen windows only, this should not be a problem.

/*
 * gangdraw.c
 *
 * A test program for the GangDraw feature on RealityEngine.
 * Also serves as sample code.
 *
 * compile with: cc -o gangdraw gangdraw.c -lgl
 */

#include <stdio.h>
#include <gl.h>
#include <get.h>
#include <device.h>

int
main(int argc, char **argv)
{
    int clear_count = 1;
    long vidreg, color = 0;
    int n, i;
    char ntimes[20];
    long queued;
    short dummy;

    if (argc > 1)
        clear_count = atoi(argv[1]);

    foreground();
    prefposition(200, 599, 500, 899);
    winopen(argv[0]);
    doublebuffer();
    RGBmode();
    gconfig();

    qdevice(ESCKEY);

    for (n = 0; ; n++) {
        while (qtest()) {
            queued = qread(&dummy);
            if (queued == ESCKEY) {
                mswapbuffers(NORMALDRAW);
                gexit();
            }
        }
        cpack(color++);
        for (i = 0; i < clear_count; i++)
            clear();
        cmov2i(8, 8);
        cpack(0x00ffffff);
        sprintf(ntimes, "%8d", n);
        charstr(ntimes);
        if (n < 1)
            mswapbuffers(NORMALDRAW);
        else
            mswapbuffers(GANGDRAW|NORMALDRAW);
    }
}

-- 
Allan Schaffer                                              aschaffe++at++sgi.com
Silicon Graphics                   http://reality.sgi.com/employees/aschaffe

New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:51:26 PDT

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.