Re: DIVO video texturing

New Message Reply Date view Thread view Subject view Author view

Angus Dorbie (dorbie++at++sgi.com)
Tue, 31 Aug 1999 17:46:33 -0700


Here is the improved divo texturing example code.

Cheers,Angus.

/*
/* This code works for CCIR601 525 using DIVO on ONYX2.
/* It has been modified from movietex.c to work and is
/* probably better for other platforms also but this has
/* not been confirmed so both examples exist here.
/* movietex.c almost certainly has some problems.
/* do a diff to see the differences if you are interested
/* in using video texture on other systems. Remember there's
/* an O2 specific example in this directory also.
 */

#ifndef IRISGL /* this program is OpenGL-only! */

#include <stdlib.h>
#include <getopt.h> /* for cmdline handler */
#include <X11/keysym.h>
#include <vl/vl.h>
#include <getopt.h> /* for cmdline handler */
#include <Performer/pf.h>
#include <Performer/pfutil.h>
#include <Performer/pfdu.h>

/*
 * file: videotex.c
 * ----------------
 *
 * demonstrates use of video input for textures across SGI product line
 *
 * cmdline controls
 * -m procsplit : multiprocess mode
 * -v : use fake video loop from memory - not real video input
 *
 * Run-time controls:
 * ESC-key: exits
 * g/s-keys: stats profile
 * SPACE : toggle spinning of video cube
 */

#define NUMANIMFRAMES 7
unsigned int animation[];
#define TEXW 8
#define TEXH 8

/* Performer config vars */
static int ProcSplit = PFMP_DEFAULT;
static int Video = 1;
static char ProgName[PF_MAXSTRING];

static pfMatrix texture_matrix = {
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
};

/*
** As usual, anything that the cull or draw processes need to access must be
** placed in shared memory. I put these things in shared memory just in
** case an application might have a use for them there.
*/
typedef struct {
    /* video scene stuff */
    pfTexture *vtex;
    pfGeoState *gstate;
     
    /* video stuff */
    int tvxsize, tvysize; /* size of texture */
    int vXSize, vYSize; /* video frame size */
    int fXSize, fYSize; /* memory field size */
    int F1_is_first; /* Which field is first (i.e., spacially higher) */
    int packing;
    VLServer svr;
    VLPath path;
    VLNode src, drn;
    GLXVideoSourceSGIX glxvidsrc;
     
    /* video config controls */
    int interlace;
    int vldmedia; /* use old style VL (RE and OCTANE) */
    int divo;
    int octane;
     
    /* program controls */
    pfPipeWindow *pw;
    pfWSConnection dsp;
    int spin;
    int stats;
    int XInputInited;
    int exitFlag;

} shareData;
shareData *Shared;

static void OpenPipeWin(pfPipeWindow *pw);
static pfGeoSet *cube( void );
static void InitXInput(pfWSConnection dsp);
static void GetXInput(Display *dsp);

/******************************************************************************
 * VL Variables and Routines
 ******************************************************************************
 */

int capType = VL_CAPTURE_NONINTERLEAVED;

/* VL Draw Process Variables */
#ifndef IRIX6_2
DMbufferpool pool = 0; /* needed for cleanup */
#endif

void
UpdateTiming(void)
{
    VLControlValue timing, dominance;

    if (vlGetControl(Shared->svr, Shared->path, Shared->src, VL_TIMING, &timing) <0) {
        vlPerror("VlGetControl of timing");
        exit(EXIT_FAILURE);
    }
    /*
     * in 525 ("NTSC"), the odd field is drawn first (higher spacially).
     * in 625 ("PAL"), the even field is drawn first
     */
    Shared->F1_is_first = ( (timing.intVal == VL_TIMING_625_SQ_PIX) ||
                  (timing.intVal == VL_TIMING_625_CCIR601) );

    if (Shared->divo)
    {
#ifndef IRIX6_2
        if (vlGetControl(Shared->svr, Shared->path, Shared->src,
                                    VL_FIELD_DOMINANCE, &dominance) <0)
        {
            vlPerror("VlGetControl of dominance");
            exit(EXIT_FAILURE);
        }
        Shared->F1_is_first ^= (dominance.intVal == VL_F2_IS_DOMINANT);
#endif
    }
}

static void
InitializeVL(void)
{
#ifndef IRIX6_2
    DMparams* plist;
#endif
    VLControlValue size;
    VLDevList devlist;
    VLTransferDescriptor xferDesc;
    VLControlValue val;
    VLDev deviceId;
    int devicenum = -1;
    int mask;
    int frameSize;

     
     
    /* open connection to VL server */
    if (!(Shared->svr = vlOpenVideo(""))) {
        printf("couldn't open connection to VL server\n");
        exit(EXIT_FAILURE);
    }

    /* Get the list of devices that the daemon supports */
    if (vlGetDeviceList(Shared->svr, &devlist) < 0) {
        fprintf(stderr, "%s: getting device list: %s\n",
                ProgName, vlStrError(vlErrno));
        exit(1);
    }

    /* Set up a source node from video */
    Shared->src = vlGetNode(Shared->svr, VL_SRC, VL_VIDEO, VL_ANY);

    /* Set up a drain node in memory */
    if (Shared->vldmedia)
        Shared->drn = vlGetNode(Shared->svr, VL_DRN, VL_MEM, VL_ANY);
    else
        Shared->drn = vlGetNode(Shared->svr, VL_DRN, VL_TEXTURE, VL_ANY);

    /*
     * If the user didn't specify a device create a path using the first
     * device that will support it
     */
    if (devicenum == -1) {
        if ((Shared->path = vlCreatePath(Shared->svr, VL_ANY, Shared->src, Shared->drn)) < 0) {
            vlPerror(ProgName);
            exit(1);
        }
        /* Get the device number and name */
        devicenum = vlGetDevice(Shared->svr, Shared->path);
    }
    else
    {
        /* Create a path using the user specified device */
        deviceId = devlist.devices[devicenum].dev;
        if ((Shared->path = vlCreatePath(Shared->svr, deviceId, Shared->src, Shared->drn)) < 0)
            {
                vlPerror(ProgName);
                exit(1);
            }
    }

    /* Set up the hardware for and define the usage of the path */
    if (vlSetupPaths(Shared->svr, (VLPathList)&Shared->path, 1, VL_SHARE, VL_SHARE) < 0) {
        vlPerror(ProgName);
        exit(1);
    }

    if (Shared->vldmedia)
    {
        /*
         * Specify what path-related events we want to receive.
         * In this example we want transfer complete and transfer failed
         * events only.
         */
        mask= VLStreamStartedMask | VLTransferCompleteMask | VLTransferFailedMask
| VLStreamStoppedMask | VLSequenceLostMask;
        vlSelectEvents(Shared->svr, Shared->path, mask);
    }

    /* VL Congif vars and defaults */
    if (Shared->vldmedia)
    {
#ifndef IRIX6_2
        if (Shared->divo)
            Shared->packing = VL_PACKING_4444_8; /* DIVO only */
        else
            Shared->packing = VL_PACKING_ABGR_8; /* O2 */
#endif
    }
    else
        Shared->packing = VL_PACKING_RGB_8;

    val.intVal = Shared->packing;
    if (vlSetControl(Shared->svr, Shared->path, Shared->drn, VL_PACKING, &val) < 0) {
        vlPerror("vlSetControl(VL_PACKING)");
        pfNotify(PFNFY_NOTICE, PFNFY_PRINT, "PACKING: %d", Shared->packing);
        exit(1);
    }

    if (Shared->divo)
    {
#ifndef IRIX6_2
        int cspace = VL_COLORSPACE_RGB;
        val.intVal = cspace;
        if (vlSetControl(Shared->svr, Shared->path, Shared->drn, VL_COLORSPACE, &val) < 0) {
            vlPerror("vlSetControl(VL_COLORSPACE_RGB)");
            exit(1);
        }
#endif
    }

    /*
     * we want individual fields, so we can demonstrate manual interleaving
     */
    val.intVal = capType;
    if (vlSetControl(Shared->svr, Shared->path, Shared->drn, VL_CAP_TYPE, &val) < 0) {
        vlPerror("vlSetControl(VL_CAP_TYPE)");
        exit(1);
    }
     
    /* get input mem frame size */
    vlGetControl(Shared->svr, Shared->path, Shared->src, VL_SIZE, &size);\
    Shared->fXSize = size.xyVal.x;
    Shared->fYSize = size.xyVal.y;
    fprintf(stderr,"frame: xsize is %d, ysize is %d\n",size.xyVal.x, size.xyVal.y);
    /* get video field size for texture which is based on field size */
    vlGetControl(Shared->svr, Shared->path, Shared->drn, VL_SIZE, &size);
    fprintf(stderr,"field: xsize is %d, ysize is %d\n",size.xyVal.x, size.xyVal.y);
    Shared->vXSize = size.xyVal.x;
    Shared->vYSize = size.xyVal.y;

    frameSize = vlGetTransferSize(Shared->svr, Shared->path); /**/
#ifndef IRIX6_2
    if (dmParamsCreate(&plist)) {
        printf("dmParamsCreate failed!\n");
        exit(1);
    }
#endif

    if (Shared->vldmedia) /* O2 and ONYX2 */
    {
#ifndef IRIX6_2
        {
            int videoBufCt;
            dmBufferSetPoolDefaults(plist, 4, frameSize, DM_FALSE, DM_FALSE);
            dmParamsSetInt(plist, DM_BUFFER_COUNT, 0);
            vlDMGetParams(Shared->svr, Shared->path, Shared->drn, plist);
            videoBufCt = dmParamsGetInt(plist, DM_BUFFER_COUNT);
            dmParamsSetInt(plist, DM_BUFFER_COUNT, videoBufCt + 1);
            if (dmBufferCreatePool(plist, &pool) != DM_SUCCESS)
            {
                printf("dmBufferCreatePool failed %s\n", dmGetError(0, 0));
            }
            dmParamsDestroy(plist);
        }
     
        if (!pool) {
            vlPerror(ProgName);
            exit(1);
        }
     
        /* Associate the pool with the path */
        if (vlDMPoolRegister(Shared->svr, Shared->path, Shared->drn, pool))
        {
            vlPerror(ProgName);
            dmBufferDestroyPool(pool);
            exit(1);
        }
#endif
    }
    UpdateTiming();

    /* On Octane and Sirius, use GLXVideoSource to get video data */
    if (!Shared->vldmedia) {
      Shared->dsp = pfGetCurWSConnection();
      Shared->glxvidsrc =
        glXCreateGLXVideoSourceSGIX(Shared->dsp, DefaultScreen(Shared->dsp),
                                    Shared->svr,Shared->path,
                                    VL_TEXTURE,Shared->drn);
    }

    if (Shared->divo)
    {
        xferDesc.mode = VL_TRANSFER_MODE_CONTINUOUS;
        xferDesc.count = 0;
        xferDesc.delay = 0;
        xferDesc.trigger = VLTriggerImmediate;
     
        /* Do not need gl cxt or win for this. */
        vlBeginTransfer(Shared->svr, Shared->path, 1, &xferDesc);
    }
    else
        vlBeginTransfer(Shared->svr, Shared->path, 0, NULL );
}

void
cleanup(void)
{
    vlEndTransfer(Shared->svr, Shared->path);
#ifndef IRIX6_2
    if (pool)
    {
        vlDMPoolDeregister(Shared->svr, Shared->path, Shared->drn, pool);
        dmBufferDestroyPool(pool);
    }
#endif
    vlDestroyPath(Shared->svr, Shared->path);
    vlCloseVideo(Shared->svr);
    exit(EXIT_SUCCESS);
}

void
ProcessVideoEvents(void)
{
    VLEvent ev;

    if (vlCheckEvent(Shared->svr,
VLSequenceLostMask|VLStreamPreemptedMask|VLTransferCompleteMask|VLTransferFailedMask |
                        VLStreamStartedMask | VLStreamStoppedMask,
                     &ev) == -1) {
        return;
    }
    switch(ev.reason) {
      case VLSequenceLost:
        pfNotify(PFNFY_INFO,PFNFY_PRINT,"VLSequenceLost....\n");
        break;
      case VLTransferComplete:
        pfNotify(PFNFY_DEBUG,PFNFY_PRINT,"VLTransferComplete....\n");
        break;
      case VLTransferFailed:
        pfNotify(PFNFY_NOTICE,PFNFY_PRINT,"VLTransfer FAILED ....\n");
        break;
      case VLStreamPreempted:
        cleanup();
        exit(EXIT_SUCCESS);
        /*NOTREACHED*/
      default:
        break;
    }
}

/******************************************************************************
 * Performer Structural Routines
 ******************************************************************************
 */

static void
ConfigDraw( int pipe, uint stage )
{
    /* Ininialize VL in draw stage config function */
    if (Video)
        InitializeVL();
     
}

static void
InitVideoTexture(void)
{
    int texFormat;
    unsigned int *img=NULL;
     
    Shared->tvxsize = TEXW;
    Shared->tvysize = TEXH;
     
    if (!Shared->vtex)
    {
        pfNotify(PFNFY_NOTICE,PFNFY_PRINT,"Video Texture not initialized!!!!");
        return;
    }
     
    {
        float vheight = Shared->vYSize * 2.0f; /* XXX assume draw config is done */
        float s_scale, t_scale;

        /* Establish offsets that will align right side of the video texture on
         * a 32 texel boundary. This is a requirement of Impact graphics.
         */
        int fieldWidth = Shared->vXSize;
        int xOffset = ((fieldWidth + 0x001f) & ~0x001f) - fieldWidth;

        /* well zero sounds just fine to me,
         * besides the above tends to produce an offset of 16
         * and the texture coordinates and matrix don't even
         * know about this shift so it can't work
         */
        xOffset = 0;
         
        pfTexLoadOrigin(Shared->vtex, PFTEX_ORIGIN_DEST, xOffset, 0);
        pfNotify(PFNFY_NOTICE, PFNFY_PRINT, "Tex Load x offset: %d", xOffset);

        /* compute texture size - must be power of 2 in each dimension */
        Shared->tvxsize = 1;
        Shared->tvysize = 1;
        while (Shared->tvxsize < Shared->vXSize) Shared->tvxsize <<= 1;
         while (Shared->tvysize < vheight) Shared->tvysize <<= 1;
        s_scale = (float)Shared->vXSize / (float)Shared->tvxsize;
        t_scale = vheight / (float)Shared->tvysize;

        texture_matrix[0][0] = s_scale;
        texture_matrix[1][1] = -t_scale;
        texture_matrix[3][1] = t_scale;
    }

    if (Video) {
    /* configure the pfTexture for video */
    pfTexImage(Shared->vtex, img, 4, Shared->tvxsize, Shared->tvysize, 0);
    pfTexLoadSize(Shared->vtex, Shared->vXSize, Shared->vYSize);
    /* these modes are important */
    pfTexFilter(Shared->vtex, PFTEX_MINFILTER, PFTEX_LINEAR);
    pfTexFilter(Shared->vtex, PFTEX_MAGFILTER, PFTEX_LINEAR);
    pfTexFormat(Shared->vtex, PFTEX_SUBLOAD_FORMAT, PF_ON);
    pfTexFormat(Shared->vtex, PFTEX_INTERNAL_FORMAT, GL_RGBA8_EXT);
     
    /* Texture external format should match the VL packing format */
    switch(Shared->packing)
    {
#ifndef IRIX6_2
        case VL_PACKING_X4444_5551:
            texFormat = PFTEX_UNSIGNED_SHORT_5_5_5_1;
            break;
        case VL_PACKING_444_332:
            texFormat = PFTEX_UNSIGNED_BYTE_3_3_2;
            break;
        case VL_PACKING_4444_8:
#endif
        case VL_PACKING_ABGR_8:
        default:
            texFormat = PFTEX_PACK_8;
    }
    pfTexFilter(Shared->vtex, PFTEX_EXTERNAL_FORMAT, texFormat);
    
    pfTexLoadMode(Shared->vtex, PFTEX_LOAD_BASE, PFTEX_BASE_AUTO_SUBLOAD);

    pfTexLoadMode(Shared->vtex, PFTEX_LOAD_SOURCE, PFTEX_SOURCE_VIDEO);
       

    if (Shared->vldmedia)
      {
        /* these settings come from InitializeVL called in the draw process */
        pfTexLoadVal(Shared->vtex, PFTEX_LOAD_VIDEO_VLSERVER, (void*)Shared->svr);
        pfTexLoadVal(Shared->vtex, PFTEX_LOAD_VIDEO_VLPATH, (void*)Shared->path);
        pfTexLoadVal(Shared->vtex, PFTEX_LOAD_VIDEO_VLDRAIN, (void*)Shared->drn);
      }
     
    if (Shared->interlace)
      {
        pfTexLoadMode(Shared->vtex, PFTEX_LOAD_VIDEO_INTERLACED,
                      (Shared->F1_is_first ? PFTEX_VIDEO_INTERLACED_ODD : PFTEX_VIDEO_INTERLACED_EVEN));
      }
    }
}
  
static void
OpenPipeWin(pfPipeWindow *pw)
{
    /* a pfState is created for the pfPipeWindow upon open */
    pfOpenPWin(pw);
     
    /* set the per-draw process video params on the pfTexture */
      InitVideoTexture();

}

/*
** This program doesn't need to have a draw callback, but I put one in just
** in case DIVO apps need to do something here (such as initiate the video
** load or do some sort of synchronization).
*/
static void
drawfunc(pfChannel *chan, void *data)
{
    pfClearChan(chan);

    if (Video) {
      if (!Shared->vldmedia) {
        glXMakeCurrentReadSGI(Shared->dsp,pfGetPWinCurWSDrawable(Shared->pw),
                              Shared->glxvidsrc,
                              pfGetPWinGLCxt(Shared->pw));
      }
    }

    pfDraw();
    if (Shared->stats)
        pfDrawChanStats(chan);
     
    /* XXXX Yuck - we'd like this to be in the application process!
     * Also, putting it here means it can hold off swapbuffers
     * so we will need to had a post-swap-func callback to Performer
     */
    if (Video)
        ProcessVideoEvents();

   {
   int err;
   if ((err = glGetError()) != GL_NO_ERROR)
        pfNotify(PFNFY_NOTICE,PFNFY_USAGE,"OpenGL Error 0x%x - %s",err, gluErrorString(err));
   }
}

static int
docmdline(int argc, char *argv[])
{
    int opt;

    strcpy(ProgName, argv[0]);
     
    /* process command-line arguments */
    while ((opt = getopt(argc, argv, "m:p:sv?")) != -1)
    {
        switch (opt)
        {
        case 's':
            Shared->spin ^= 1;
            break;
        case 'm':
        case 'p':
            ProcSplit = atoi(optarg);
            break;
        case 'v':
            Video ^= 1;
        }
    }
    return optind;
}

int
main (int argc, char *argv[])
{
    float t = 0;
    pfScene *scene;
    pfGroup *root;
    pfPipe *p;
    pfChannel *chan;
    pfSphere bsphere;
    pfGeode *geode;
    pfTexture *vtex;
    pfGeoState *gstate;
    pfGeoSet *gset;
    pfCoord view;
    void *arena;
    int arg;
    unsigned int *img=NULL;
    int queryvals[2];
static int querytoks[] = {PFQFTR_VLDMEDIA, PFQFTR_INTERLACE, 0};

    pfInit();
    arena = pfGetSharedArena();
    Shared = pfCalloc(1, sizeof(shareData), arena);
    Shared->stats = 1;
     
    /* query machine dependent parameters */
    {
        pfMQueryFeature(querytoks, queryvals);
        Shared->vldmedia = (queryvals[0] != 0);
        Shared->interlace = 1;
        /* check for DIVO vs Sirius */
        Shared->divo = ((strncasecmp(pfGetMachString(), "IRL", 3)== 0) ||
                        (strncasecmp(pfGetMachString(), "IRE",3)== 0));
        /* another check for Octane because the video is flipped vertically */
        if (!Shared->divo)
        {
            Shared->octane = (strncasecmp(pfGetMachString(), "MGRAS", 5)== 0);
        }
        if (!Shared->divo)
            Shared->interlace = 0;
        pfNotify(PFNFY_NOTICE, PFNFY_PRINT, "Config %s: vl=%d divo=%d octane=%d",
            pfGetMachString(), Shared->vldmedia, Shared->divo, Shared->octane);
    }
     
    arg = docmdline(argc, argv);
     
    pfMultiprocess(ProcSplit);
    pfConfig();

    /* Shared->put these in shared memory so draw process can access them */

    /* set up scene graph */
    geode = pfNewGeode();
    gset = cube();
    pfAddGSet(geode, gset);
    root = pfNewGroup();
    pfAddChild(root, geode);
    scene = pfNewScene();
    pfAddChild(scene, root);
    pfAddChild(scene, pfNewLSource());

    /* make video texture */
    Shared->vtex = vtex = pfNewTex(arena);

    /* make a window */
    p = pfGetPipe(0);
    pfStageConfigFunc(0, PFPROC_DRAW, ConfigDraw);
     
    Shared->pw = pfNewPWin(p);
    pfPWinType(Shared->pw, PFPWIN_TYPE_X);
    pfPWinName(Shared->pw, "videotex");
    pfPWinOriginSize(Shared->pw, 0, 0, 720, 486);
    pfPWinConfigFunc(Shared->pw, OpenPipeWin);

    /* OpenWindow and Init Draw */
    pfConfigStage(0, PFPROC_DRAW);
    pfConfigPWin(Shared->pw);
    pfFrame();
     
    /* make a channel */
    chan = pfNewChan(p);
    pfChanScene(chan, scene);
    pfChanFOV(chan, 45, 45);
    pfChanTravFunc(chan, PFTRAV_DRAW, drawfunc); /* per-frame draw func */

    /* determine extent of scene's geometry */
    pfGetNodeBSphere (root, &bsphere);
    pfChanNearFar(chan, 0.5f, 10.0f * bsphere.radius);

    pfTexRepeat(vtex, PFTEX_WRAP_S, PFTEX_CLAMP);
    pfTexRepeat(vtex, PFTEX_WRAP_T, PFTEX_CLAMP);
     
    /* make a geostate */
    gstate = pfNewGState (arena);
    pfGSetGState(gset, gstate);
    pfGStateMode(gstate, PFSTATE_ENTEXTURE, 1);
    pfGStateAttr(gstate, PFSTATE_TEXTURE, vtex);
    pfGStateMode(gstate, PFSTATE_ENTEXMAT, 1);
    pfGStateMode(gstate, PFSTATE_CULLFACE, PFCF_BACK);
    pfGStateAttr(gstate, PFSTATE_TEXMAT, texture_matrix);

    if (!Video) {
        img = (unsigned int *) pfCalloc(Shared->tvxsize * Shared->tvysize * sizeof(int), 1, NULL);
    }

    pfFrame();

    while (!Shared->exitFlag)
    {
        static int i=0;
        float s, c;
        unsigned int *pb;
         
        /* set view position for next frame */
        if (Shared->spin)
        {
        t = pfGetTime();
        /* Compute new view position for next frame. */
        pfSinCos(45.0f*t, &s, &c);
        pfSetVec3(view.hpr, 45.0f*t, -20.0f, 0);
        pfSetVec3(view.xyz, 3.0f * bsphere.radius * s,
                -3.0f * bsphere.radius *c,
                 1.1f * bsphere.radius);
        }
        else
        {
            pfSetVec3(view.hpr, 0.0f, 0.0f, 0);
            /* assumes 2x2x2 cube centered at origin
            /* tan 22.5 degrees (angle to edge of cube ++at++ 45 degree cube)
            /* this gives correct proportions in conjunction wit texture
            /* matrix and window resolution.
            pfSetVec3(view.xyz, 0, -1.0f - 2.4142136f, 0);
        }
         
        pfChanView(chan, view.xyz, view.hpr);
         
        pfSync();

        /* Update the buffer for the next frame. Here we simply copy an
        ** image from the animation array into the buffer, but DIVO would
        ** initiate a video load into the buffer instead.
        */
        if (!Video)
        {
            /* Divide i by 10 to slow down the speed of the animation. */
            pb = animation + Shared->tvxsize * Shared->tvysize * ((i/10) % NUMANIMFRAMES);
            memcpy(img, pb, Shared->tvxsize * Shared->tvysize * sizeof(int));
            pfTexLoadImage(Shared->vtex, img);
            i++;
        }

        pfFrame();
         
        {
            static pfWSConnection dsp = NULL;
            if (!dsp)
                dsp = pfGetCurWSConnection();
            if (!Shared->XInputInited)
                InitXInput(dsp);
            if (Shared->XInputInited)
                GetXInput(dsp);
        }

    }
    pfExit();
    return 0;
}

/******************************************************************************
 * XInput Handler
 ******************************************************************************
 */

static void
InitXInput(pfWSConnection dsp)
{
    Window w;
     
    /* wait for X Window to exist in Performer shared memory */
    if (w = pfGetPWinWSWindow(Shared->pw))
    {
        XSelectInput(dsp, w, PointerMotionMask |
                        ButtonPressMask | ButtonReleaseMask | KeyPressMask);
        XMapWindow(dsp, w);
        XFlush(dsp);
        Shared->XInputInited = 1;
    }
}

static void
GetXInput(pfWSConnection dsp)
{
    if (XEventsQueued(dsp, QueuedAfterFlush))
    while (XEventsQueued(dsp, QueuedAlready))
    {
        XEvent event;
             
        XNextEvent(dsp, &event);

        switch (event.type)
        {
        case KeyPress:
        {
            char buf[100];
            int rv;
            KeySym ks;
            rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0);
            switch(ks) {
            case XK_Escape:
                Shared->exitFlag = 1;
                exit(0);
                break;
            case XK_space:
                Shared->spin ^= 1;
                break;
            case XK_g:
            case XK_s:
                Shared->stats = !Shared->stats;
                break;
            default:
                break;
            }
        }
        break;
        default:
            break;
        }/* switch */
    }
}

/******************************************************************************
 * data for faked memory video loop
 ******************************************************************************
 */

#define B 0x000000ff
#define W 0xffffffff

unsigned int animation[] = {
    /* frame 0 */
    B,B,W,W,W,W,W,W,
    B,B,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,

    /* frame 1 */
    W,W,W,W,W,W,W,W,
    W,B,B,W,W,W,W,W,
    W,B,B,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,

    /* frame 2 */
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,B,B,W,W,W,W,
    W,W,B,B,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,

    /* frame 3 */
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,B,B,W,W,W,
    W,W,W,B,B,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,

    /* frame 4 */
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,B,B,W,W,
    W,W,W,W,B,B,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,

    /* frame 5 */
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,B,B,W,
    W,W,W,W,W,B,B,W,
    W,W,W,W,W,W,W,W,

    /* frame 6 */
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,W,W,
    W,W,W,W,W,W,B,B,
    W,W,W,W,W,W,B,B,
};

/******************************************************************************
 * cube
 ******************************************************************************
 */

static pfGeoSet *cube( void )
{
    pfVec3 *scoords;
    ushort *sindex;
    pfVec4 *colors;
    pfVec2 *tcoords;
    ushort *tindex;

    pfGeoSet *gset;
    void *arena;

    int i, j, c;

static float v[][3] = {
    { -1., -1., -1. },
    { 1., -1., -1. },
    { 1., 1., -1. },
    { -1., 1., -1. },
    { -1., -1., 1. },
    { 1., -1., 1. },
    { 1., 1., 1. },
    { -1., 1., 1. }
};

static int con[][4] = {
    { 0, 1, 2, 3 },
    { 2, 6, 5, 1 },
    { 4, 5, 6, 7 },
    { 7, 3, 0, 4 },
    { 7, 6, 2, 3 },
    { 0, 1, 5, 4 }
};

    arena = pfGetSharedArena();

    scoords = (pfVec3 *)pfMalloc( 8 * sizeof( pfVec3 ), arena );
    sindex = (ushort *)pfMalloc( 24 * sizeof( ushort ), arena );
    colors = (pfVec4 *)pfMalloc( 4 * sizeof( pfVec4 ), arena );
    tcoords = (pfVec2 *)pfMalloc( 4 * sizeof( pfVec2 ), arena );
    tindex = (ushort *)pfMalloc( 24 * sizeof( ushort ), arena );

    for( i = 0; i < 8; i++ )
            PFSET_VEC3(scoords[i], v[i][0], v[i][1], v[i][2] );

    c = 0;
    for( i = 0; i < 6; i++ )
            for( j = 0; j < 4; j++ )
            {
                    sindex[c++] = con[i][j];
            }
     
    PFSET_VEC4(colors[0], 1, 1, 1, 1 );
    PFSET_VEC4(colors[1], 1, 0, 0, 1 );
    PFSET_VEC4(colors[2], 0, 1, 0, 1 );
    PFSET_VEC4(colors[3], 0, 0, 1, 0 );
     
    PFSET_VEC2(tcoords[0], 0.0, 0.0 );
    PFSET_VEC2(tcoords[1], 1.0, 0.0 );
    PFSET_VEC2(tcoords[2], 1.0, 1.0 );
    PFSET_VEC2(tcoords[3], 0.0, 1.0 );
     
    c = 0;
    for( i = 0; i < 6; i++ )
            for( j = 0; j < 4; j++ )
                    tindex[c++] = (ushort)j;

    gset = pfNewGSet(arena);
    pfGSetAttr(gset, PFGS_COORD3, PFGS_PER_VERTEX, scoords, sindex);
    pfGSetAttr(gset, PFGS_TEXCOORD2, PFGS_PER_VERTEX, tcoords, tindex);
    pfGSetAttr(gset, PFGS_COLOR4, PFGS_OVERALL, colors, tindex);
    pfGSetPrimType(gset, PFGS_QUADS);
    pfGSetNumPrims(gset, 6);
     
    return gset;
}

#else /* IRISGL */

#include <stdio.h>
main(int argc, char **argv)
{
    fprintf(stderr, "Sorry, this program is OPENGL-only.\n");
    return 1;
}

#endif /* IRISGL */


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Tue Aug 31 1999 - 17:46:40 PDT

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