Porting Guide for Sample VEX Server
Scott Hennes & Todd Brunhoff
Tektronix, Inc.
April 20, 1990

The sample server manages a) one video input: a Parallax ???, b) one video
output: a Tektronix Option 9 board, and c) one video device: a
Pioneer LD-V6000A LaserDisc player.

The server code is structured into these directories:
    extensions/vex/server/dix: device independent code
    extensions/vex/server/include: server header files
    extensions/vex/server/ddx/plx: Parallax Video input code
    extensions/vex/server/ddx/devices: Pioneer LaserDisc code
    extensions/vex/server/ddx/tekdvi: Tektronix Option 9 Video out code
Additionally, the server uses header files in extensions/vex/include.
(Note that ddx/tekdvi is not distributed, but if you see references
to it anywhere, you'll know what it means).

To port the sample server to a new set of video devices, you must write
routines ddxVexInit() and ddxVexReset(), which are essentially the vex
equivalents of InitOutput() and the ddxCloseScreen() functions.  The
intent is that ddxVexInit() discovers all of the video inputs, outputs
and devices.  In ddxVexInit, you must initialize function pointers for
the routines in the VideoScreenRec for each screen.  You must also
initialize function pointers for the routines in the DeviceElement
structure for each Video device.  These routines are described later.

You must define 'VIDEOX' at compile time to enable the VEX extension.
This define is also used by some of the Imakefiles to change what
software to expect; e.g. extensions/Imakefile.  The extension must be
initialized in server/ddx/mi/miinitext.c by calling
VexExtensionInit().  The patches on this distribution add this
initialization.

The ChangeConnectivity and ChangeOwnership requests are decoded by
the extension dix layer, but no action is taken.  Connectivity events
implemented, but no code exists to generate them.

1. ddx Initialization routines.

1a Routines which are directly called from dix at initialization:

/*
 * Perform ddx initialization for VEX.  If the screen has video hardware,
 * allocate a VideoScreenRec structure and initialize all the elements.
 * (ddx allocates and frees all space attached to VideoScreenRec
 * structures).  If the screen does not have video hardware, set
 * *pVideoScreenRecs to NULL.
 *
 * Return FALSE if allocation failure, else TRUE.
 *
 * Warning!! This interface may change!
 */
Bool
ddxVexInit(pScreen, pVideoScreenRecs)
    ScreenPtr pScreen;                  /* Screen to be initialized */
    VideoScreenRec **pVideoScreenRecs;  /* Video data for the screen */
Sample routine is in extensions/vex/server/ddx/plx/plxinit.c.

/*
 * ddx should free whatever it attached to the VideoScreenRec for
 * this screen, and also do whatever else it needs to for server
 * reset.  This routine will be called by dix for each screen.
 */
void
ddxVexReset(pVideoScreenRec)
    ScreenPtr pScreen;                  /* Screen to be reset */
    VideoScreenRec **pVideoScreenRec;   /* Video data for the screen */
Sample routine is in extensions/vex/server/ddx/plx/plxinit.c.

1b. Routines for function vectors in VideoScreenRec structure:

/*
 * This routine allows ddx to update the screen's DeviceInfo before
 * QueryVideo generates its reply for the client.
 *
 * Return FALSE if allocation failure, else TRUE.
 */
static Bool
xxxQueryVideo(pScreen, pdeviceInfo)
    ScreenPtr pScreen;
    DeviceInfo *pdeviceInfo;
The sample server does not take any action in this routine.

/*
 * ddx opportunity to delete anything it hung onto a DeviceInfo passed to
 * xxxQueryVideo from dix during a QueryVideo.
 */
static void
xxxFreeDeviceInfo()

Not used in the sample server at this time.

/*
 * This routine is undefined at this time
 */
static void
xxxChangeConnectivity()

Not used in the sample server at this time.

/*
 * This routine take the (digested) arguments from a RenderVideo
 * request and attempts to produce a video picture in the specified
 * drawable.  If the hardware cannot do precisely what the request
 * asks for, then it should do something close, and generate a
 * VideoViolation event with state=Subset.  If it cannot do the
 * request at all, then the state=Fail.  The reason for failure
 * may be that the client is too stupid to do the right thing,
 * or that it is occluded by a window and cannot produce a clipped
 * picture.
 *
 * If the routine detects some request error not discernable by
 * dix, it should return False, else True.
 *
 * If the opaque member is set in the RENDERMODEL, then the server
 * should do its best to remember which pixels are video and which
 * are graphic.  Specifically, within the server, video pixels get
 * copied to a pixmap, and then back to a window, they should be
 * displayed as video pixels.
 */
Bool
xxxRenderVideo(vp, render)
    VideoScreenPtr vp;
    VideoActionPtr render;
Sample routine is in extensions/vex/server/ddx/plx/plxrender.c.

/*
 * This routine take the (digested) arguments from a CaptureGraphics
 * request and attempts to capture the graphics in the specified
 * drawable and produce some video signal as output.  If the hardware
 * cannot do precisely what the request asks for, then it should do
 * something close, and generate a VideoViolation event with
 * state=Subset.  If it cannot do the request at all, then the
 * state=Fail.  The reason for failure may be that the client picked
 * an "unaligned" source rectangle, or that the source region includes
 * bits from two framebuffers and cannot be captured.
 *
 * If the routine detects some request error not discernable by
 * dix, it should return False, else True.
 */
Bool
dviCaptureGraphics(vp, capture)
    VideoScreenPtr vp;          /* Screen to capture */
    VideoActionPtr capture;     /* Capture parameters */
Sample routine is not provided (but will be soon)

/*
 * This routine should implement the protocol semantics for StopVideo.
 * Namely, if the drawable is of a core visual type, then leave the
 * last frame in the drawable.  If the visual class is VideoGray or
 * VideoColor, the result is undefined, but either the picture ought
 * to stay on the screen or it should be completely removed and an
 * area filled with a solid color take its place.  The former is preferred.
 */
void
xxxStopVideo(vp, pDrawable, action)
    VideoScreenPtr      vp;
    DrawablePtr pDrawable;
    int action;                 /* Render/Capture bits */
Sample routine is in extensions/vex/server/ddx/plx/plxvideo.c.

/*
 * This routine do any preparation necessary for a ddx CopyWindow.
 * For example, the video digitization process may need to be shut down
 * for some child window.
 */
Bool
xxxPreCopyWindow(pWindow, lastposition, pRegionSrc)
    WindowPtr pWindow;
    DDXPointRec lastposition;
    RegionPtr pRegionSrc;
Sample routine is in extensions/vex/server/ddx/plx/plxrender.c.

/*
 * This is the followup to xxxPreCopyWindow(): if it had shut down
 * the video digitization, this routine should start it up again.
 */
void
xxxPostCopyWindow(pWindow, lastposition, pRegionSrc)
    WindowPtr pWindow;
    DDXPointRec lastposition;
    RegionPtr pRegionSrc;
Sample routine is in extensions/vex/server/ddx/plx/plxrender.c.



1c. Routines for function vectors in DeviceElement structure.

/*
 * Change control settings on a device.  For the sake of VideoControl
 * events, when a setting is made, this routine should either:
 *  - return immediately and arrange to asynchronously decide
 *    when the setting was done.
 *  - block, waiting for the setting to be set.
 *
 *  Returns FALSE if BadValue error.  TRUE otherwise.
 */
Bool
xxxChangeVideoControls(pDeviceElement, index, pvalue, valueReturn)
    DeviceElement *pDeviceElement;
    int index;                          /* index of ControlElement */
    char *pvalue;                       /* Setting data */
    int *valueReturn;                   /* Failing value for dix */
Sample is in extensions/vex/server/ddx/devices/pioneerini.c under
the name ChangeLDV6000Ctrls().

/*
 * Fill in the value for this control.
 * The caller has allocated the proper space which "value" points
 * to and will free it when it is no longer needed
 *
 * Returns FALSE if BadAlloc, TRUE otherwise.
 */
Bool
xxxQueryVideoControls(pDeviceElement, index, value)
    DeviceElement *pDeviceElement;
    int index;                          /* index of ControlElement */
    char *value;                        /* Value to return to dix */
Sample is in extensions/vex/server/ddx/devices/pioneerini.c under
the name QueryLDV6000Ctrls().



2. dix Routines


/*
 * Create a list of unique VEX depths/visuals.  Take a list of
 * depths/visuals that the video hardware supports and make a list of
 * those which are NOT part of the core list for this screen.
 * Fill in numVisuals, visuals, pDepths, and nDepths fields of pVideoScreenRec.
 *
 * Return FALSE if allocation fails, TRUE otherwise.
 */
Bool
CreateVideoDepths(pScreen, pVideoScreenRec, nvideoDepths, videoDepths)
    ScreenPtr pScreen;                  /* Screen for video data */
    VideoScreenPtr pVideoScreenRec;     /* video data */
    int nvideoDepths;                   /* number of video depths */
    VideoVisual *videoDepths;           /* list of video depths */
Routine is in extensions/vex/server/dix/vexutils.c

/*
 * Free a list of depth structures created by CreateVideoDepths.
 */
void
FreeDepths(nDepths, pDepths)
    int nDepths;                /* number of depth structures */
    DepthPtr pDepths;           /* list of depth structures */
Routine is in extensions/vex/server/dix/vexutils.c

/*
 * Get a VideoDrawRec structure for a given drawable.  Create
 * one if one does not already exist.
 *
 * Returns NULL if alloc error, else returns a VideoDrawPtr.
 */
VideoDrawPtr GetVideoDrawable(vp, pDraw)
    VideoScreenPtr vp;          /* Video screen */
    DrawablePtr pDraw;          /* Drawable */
Routine is in extensions/vex/server/dix/vexutils.c

void
SendVideoControlEvent(vid, name, state)
    VideoID     vid;    /* ID of device which owns control */
    Atom        name;   /* Name of control */
    int         state;  /* VEXControlSuccess, VEXControlFail,
                         * or VEXControlDenied */
Routine is in extensions/vex/server/dix/vexevents.c.

void
SendVideoViolationEvent(pDraw, vid, action, state)
    DrawablePtr pDraw;          /* Drawable on which to report the event */
    VideoIO     vid;            /* VideoIO whose constraints were violated */
    unsigned long actionMask;   /* VEXScale|VEXPlacement|VEXClip|VEXOverlap */
    int         state;          /* VEXViolationSuccess, VEXViolationFail,
				 * or VEXViolationSubset */
Routine is in extensions/vex/server/dix/vexevents.c.

/*
 * This routine should be called by ddx when a device's status
 * changes.
 *
 * Set a device's status on or offline.  If the requested status
 * does not differ from the current state, or if "vid" is not a
 * valid Device VideoId for the given screen, this routine has
 * no effect.
 * If "generateEvent" is TRUE, this routine will send a VideoChange
 * event to all appropriate clients.
 */
void
SetDeviceStatus(vid, onLine, generateEvent)
    VideoID vid;                /* Set status of this video device */
    Bool onLine;                /* TRUE or FALSE */
    Bool generateEvent;         /* TRUE if this routine should generate a
Routine is in extensions/vex/server/dix/query.c

/*
 * Stop a video action (Render and/or Capture) on a drawable.
 * This routine calls the dix routine (*vp->StopVideo).
 * Generates Override event(s) on the drawable.
 */
StopVideo(vp, vDraw, pDraw, action)
    VideoScreenPtr      vp;	/* Video screen of drawable */
    VideoDrawPtr        vDraw;	/* Drawable whose video is to be stopped */
    DrawablePtr         pDraw;	/* Drawable whose video is to be stopped */
    int                 action;	/* (VEXStopRenderVideo | VEXStopCaptureVideo) */
Routine is in extensions/vex/server/dix/render.c

