Sharon Fischler (srf++at++rose)
Mon, 10 Jan 1994 12:52:03 -0800
This often means ortho() was sent some impossible arguments.
You could try using gldebug() to see what commands and values
are being sent to the graphics pipeline.
->
-> twice, once when I called pfConfig, and again when I called XtRealizeWidget.
->Can you tell me what conditions generate this error?
->
-> I am running Performer 1.0 and Motif 1.1 on an IRIS 4D/440 Reality Engine
->with IRIX 4.0.5G. Thanks.
Performer 1.2 supports running under GLX (and thus motif) very
well. Please forgive my previous mail that described 1.2.
You can certainly make GLX work in Performer 1.0/1.1, but it takes
a bit more work on your part.
srf.
FYI: this is a 1.0/1.1 compatible complex-glx.c
/*
* complex-glx.c
*
* IRIS Performer example using mixed model (GLX) and
* cull and draw process callbacks. Mouse and
* keyboard input are read through X in the application
* process to reduce overhead in the draw process.
* Also demonstrates use of overlay planes with GLX.
*
* $Revision: 1.1 $
* $Date: 93/07/13 08:18:11 $
*
* Run-time controls:
* ESC-key: exits
* F1-key: profile
* Left-mouse: advance
* Middle-mouse: stop
* Right-mouse: retreat
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <gl/glws.h>
#include <X11/keysym.h>
#include "pf.h"
#include "pfflt.h"
#include "pfsgi.h"
static void CullChannel(pfChannel *chan, void *data);
static void DrawChannel(pfChannel *chan, void *data);
static void OpenPipeline(pfPipe *p);
static void DrawOverlay(void);
static void UpdateView(void);
static void GetXInput(void);
static void usage(void);
#define HISPEED 0.1f
#define LOSPEED 0.001f
/*
* structure that resides in shared memory so that the
* application, cull, and draw processes can access it.
*/
typedef struct
{
long exitFlag;
long inWindow;
float mouseX;
float mouseY;
long mouseButtons;
long winOriginX;
long winOriginY;
long winSizeX;
long winSizeY;
pfCoord view;
float sceneSize;
int drawStats;
Window xWin;
Window glWin;
Window overWin;
long redrawOverlay;
} SharedData;
static SharedData *Shared;
/*
* X Display for opening window and input. In MP mode, each
* process separately opens the display.
*/
static Display *XDpy = NULL;
/* light source created and updated in draw-process */
static pfLight *Sun;
/*
* main() -- program entry point. this procedure
* is executed in the application process.
*/
int
main (int argc, char *argv[])
{
int arg;
int found;
pfNode *root;
pfChannel *chan;
pfScene *scene;
pfPipe *p;
pfEarthSky *eSky;
pfBox bbox;
pfCoord view;
float far = 10000.0f;
if (argc < 2)
usage();
pfInit();
pfMultiprocess(PFMP_APPCULLDRAW);
/* allocate shared before fork()'ing parallel processes */
Shared = (SharedData*)pfMalloc(sizeof(SharedData), pfGetSharedArena());
Shared->inWindow = 0;
Shared->exitFlag = 0;
Shared->drawStats = 0;
Shared->redrawOverlay = 1;
/* initiate multi-processing mode set in pfMultiprocess call */
pfConfig();
scene = pfNewScene();
/* specify directories where geometry and textures exist */
if (pfGetFilePath() == NULL)
pfFilePath(
"."
":./data"
":../data"
":../../data"
":/usr/src/Performer/data"
);
/* load database files named by command line arguments */
for (arg = 1, found = 0; arg < argc; arg++)
{
if ((root = (pfNode *)LoadFlt(argv[arg])) != NULL)
{
pfAddChild(scene, root);
found++;
}
}
/* if no files successfully loaded, terminate program */
if (!found)
usage();
/* determine extent of scene's geometry */
pfGetNodeBBox(scene, &bbox, NULL);
p = pfGetPipe(0);
pfPhase(PFPHASE_FLOAT);
/* Open and configure full screen GL window. */
pfInitPipe(p, OpenPipeline);
pfFrameRate(20.0f);
chan = pfNewChan(p);
pfChanCullFunc(chan, CullChannel);
pfChanDrawFunc(chan, DrawChannel);
pfChanScene(chan, scene);
pfChanNearFar(chan, 0.1f, far);
/* Create an earth/sky model that draws sky/ground/horizon */
eSky = pfNewESky();
pfESkyMode(eSky, PFES_BUFFER_CLEAR, PFES_SKY_GRND);
pfESkyAttr(eSky, PFES_GRND_HT, -10.0f);
pfChanESky(chan, eSky);
/* vertical FOV is matched to window aspect ratio */
pfChanFOV(chan, 45.0f, -1.0f);
{
float sceneSize;
/* Set initial view to be "in front" of scene */
/* view point at center of bbox */
pfAddVec3(Shared->view.xyz, bbox.min, bbox.max);
pfScaleVec3(Shared->view.xyz, 0.5f, view.xyz);
/* find max dimension */
sceneSize = bbox.max[PF_X] - bbox.min[PF_X];
sceneSize = PF_MAX2(sceneSize, bbox.max[PF_Y] - bbox.min[PF_Y]);
sceneSize = PF_MAX2(sceneSize, bbox.max[PF_Z] - bbox.min[PF_Z]);
sceneSize = PF_MIN2(sceneSize, 0.5f * far);
Shared->sceneSize = sceneSize;
/* offset so all is visible */
Shared->view.xyz[PF_Y] -= sceneSize;
Shared->view.xyz[PF_Z] += 0.25f*sceneSize;
pfSetVec3(Shared->view.hpr, 0.0f, 0.0f, 0.0f);
pfChanView(chan, Shared->view.xyz, Shared->view.hpr);
}
/* main simulation loop */
while (!Shared->exitFlag)
{
/* wait until next frame boundary */
pfSync();
/* Set view parameters. */
UpdateView();
pfChanView(chan, Shared->view.xyz, Shared->view.hpr);
/* initiate traversal using current state */
pfFrame();
/* Check the mouse and keyboard */
GetXInput();
}
/* terminate cull and draw processes (if they exist) */
pfExit();
/* exit to operating system */
exit(0);
}
/*
* UpdateView() updates the eyepoint based on the information
* placed in shared memory by GetXInput().
*/
static void
UpdateView(void)
{
static float speed = 0.0f;
static float speedLimit = 4.0f;
pfCoord *view = &Shared->view;
float cp;
if (!Shared->inWindow)
{
speed = 0;
return;
}
switch (Shared->mouseButtons)
{
case Button1Mask: /* LEFTMOUSE: faster forward or slower backward*/
if (speed > 0.0f)
speed *= 1.2f;
else
speed /= 1.2f;
if (PF_ABSLT(speed, LOSPEED * Shared->sceneSize))
speed = LOSPEED * Shared->sceneSize;
else if (speed >= HISPEED * Shared->sceneSize)
speed = HISPEED * Shared->sceneSize;
break;
case Button2Mask: /* MIDDLEMOUSE: stop moving and pick */
speed = 0.0f;
break;
case Button3Mask: /* RIGHTMOUSE: faster backward or slower foreward*/
if (speed < 0.0f)
speed *= 1.2f;
else
speed /= 1.2f;
if (PF_ABSLT(speed, LOSPEED * Shared->sceneSize))
speed = -LOSPEED * Shared->sceneSize;
else if (speed <= -HISPEED * Shared->sceneSize)
speed = -HISPEED * Shared->sceneSize;
break;
}
/* update view direction */
view->hpr[PF_H] -= Shared->mouseX * PF_ABS(Shared->mouseX);
view->hpr[PF_P] = Shared->mouseY * PF_ABS(Shared->mouseY) * 90.0f;
view->hpr[PF_R] = 0.0f;
/* update view position */
cp = cosf(PF_DEG2RAD(view->hpr[PF_P]));
view->xyz[PF_X] += speed*sinf(-PF_DEG2RAD(view->hpr[PF_H])*cp);
view->xyz[PF_Y] += speed*cosf(-PF_DEG2RAD(view->hpr[PF_H])*cp);
view->xyz[PF_Z] += speed*sinf( PF_DEG2RAD(view->hpr[PF_P]));
}
/*
* In Performer1.2: use pfInitGLXGfx() so that
* windows can be automatically repositioned and
* resized as needed.
*/
void
InitGLXGfx(pfPipe *_pipe, ulong _xwin, ulong _glwin, ulong _overwin)
{
long zmin, zmax;
zmin = getgdesc(GD_ZMIN);
zmax = getgdesc(GD_ZMAX);
lsetdepth(zmin, zmax);
zbuffer(TRUE);
subpixel(TRUE);
mmode(MVIEWING);
cpack(0);
clear();
zclear();
swapbuffers();
clear();
zclear();
/* XXX do the "right" thing here or in your own app */
pfEnable(PFEN_TEXTURE);
/*
* Apply default TV_MODULATE environment so geostates can inherit
* for better performance.
*/
pfApplyTEnv(pfNewTEnv(pfGetSharedArena()));
}
/*
* Prototypes for GLX utility code from
* /usr/people/4DGifts/examples/GLX/gl-Xlib/glxh2.c
* which appears at the end of this file
*/
ulong GLXgetvalue(GLXconfig* conf, int buffer, int mode);
GLXconfig* GLXCreateWindow(Display* dpy,Window parent,
int x,int y,
int w,int h,
int borderWidth,
...);
/*
* OpenPipeline() -- create a pipeline: setup the window system,
* the IRIS GL, and IRIS Performer. this procedure is executed in
* the draw process (when there is a separate draw process).
*/
static void
OpenPipeline(pfPipe *p)
{
float xSize = 800;
float ySize = 500;
XSetWindowAttributes swa;
XColor gray;
GLXconfig *config;
if (XDpy == NULL)
{
XDpy = XOpenDisplay(":0.0");
if (!XDpy)
pfNotify(PFNFY_FATAL, PFNFY_RESOURCE,
"OpenPipeline: couldn't open display\n");
}
/*
* First create the top level X window. The background will be
* grey, and the window is only interested in key press events.
*/
gray.red = 0x7fff; gray.green = 0x7fff; gray.blue = 0x7fff;
XAllocColor(XDpy, DefaultColormap(XDpy, DefaultScreen(XDpy)), &gray);
swa.background_pixel = gray.pixel;
Shared->xWin = XCreateWindow(XDpy, RootWindow(XDpy, DefaultScreen(XDpy)),
100, 100, xSize, ySize,
0, CopyFromParent,
InputOutput, CopyFromParent,
CWBackPixel, &swa);
XStoreName(XDpy, Shared->xWin, "Performer GLX Test");
/* create window for GL rendering */
#ifdef VENICE
if (getgdesc(GD_MULTISAMPLE) > 0)
config = GLXCreateWindow(XDpy, Shared->xWin, 0, 0, xSize, ySize, 0,
GLX_NORMAL, GLX_DOUBLE, TRUE,
GLX_NORMAL, GLX_RGB, TRUE,
GLX_NORMAL, GLX_ZSIZE, 0,
GLX_NORMAL, GLX_STENSIZE, 0,
GLX_NORMAL, GLX_MSSAMPLE, 8,
GLX_NORMAL, GLX_MSZSIZE, 24,
GLX_NORMAL, GLX_MSSSIZE, 1,
GLX_OVERLAY, GLX_BUFSIZE, 2,
0, 0, 0);
else
#endif
config = GLXCreateWindow(XDpy, Shared->xWin, 0, 0, xSize, ySize, 0,
GLX_NORMAL, GLX_DOUBLE, TRUE,
GLX_NORMAL, GLX_RGB, TRUE,
GLX_NORMAL, GLX_ZSIZE, GLX_NOCONFIG,
GLX_NORMAL, GLX_STENSIZE, 1,
GLX_OVERLAY, GLX_BUFSIZE, 2,
0, 0, 0);
Shared->glWin = GLXgetvalue(config, GLX_NORMAL, GLX_WINDOW);
Shared->overWin = GLXgetvalue(config, GLX_OVERLAY, GLX_WINDOW);
XMapWindow(XDpy, Shared->glWin);
XMapWindow(XDpy, Shared->xWin);
XFlush(XDpy);
/* initialize Performer for GLX rendering */
InitGLXGfx(p, Shared->xWin, Shared->glWin, Shared->overWin);
/* create a light source in the "south-west" (QIII) */
Sun = pfNewLight(NULL);
pfLightPos(Sun, -0.3f, -0.3f, 1.0f, 0.0f);
/* create a default texture environment */
pfApplyTEnv(pfNewTEnv(NULL));
/* create a default lighting model */
pfApplyLModel(pfNewLModel(NULL));
/* enable culling of back-facing polygons */
pfCullFace(PFCF_BACK);
/*
* These enables should be set to reflect the majority of the
* database. If most geometry is not textured, then texture
* should be disabled. However, you then need to change the
* FLIGHT-format file reader. (pfflt.c)
*/
pfEnable(PFEN_TEXTURE);
pfEnable(PFEN_LIGHTING);
pfEnable(PFEN_FOG);
}
/*
* CullChannel() -- traverse the scene graph and generate a
* display list for the draw process. This procedure is
* executed in the cull process.
*/
static void
CullChannel(pfChannel *channel, void *data)
{
/*
* pfDrawGeoSet or other display listable Performer routines
* could be invoked before or after pfCull()
*/
pfCull();
}
/*
* DrawChannel() -- draw a channel and read input queue. this
* procedure is executed in the draw process (when there is a
* separate draw process).
*/
static void
DrawChannel (pfChannel *channel, void *data)
{
/* rebind light so it stays fixed in position */
pfLightOn(Sun);
/* erase framebuffer and draw Earth-Sky model */
pfClearChan(channel);
/* invoke Performer draw-processing for this frame */
pfDraw();
/* draw Performer throughput statistics */
if (Shared->drawStats)
pfDrawChanStats(channel);
/* read window origin and size (it may have changed) */
pfGetWindowSize(pfGetChanPipe(channel),
&Shared->winSizeX, &Shared->winSizeY);
pfGetWindowOrigin(pfGetChanPipe(channel),
&Shared->winOriginX, &Shared->winOriginY);
if (Shared->redrawOverlay)
{
Shared->redrawOverlay = 0;
DrawOverlay();
}
}
/* leave FocusChange in XINMASK, since doesn't work in GLINMASK */
#define XINMASK (FocusChangeMask)
/*
* want motion and button presses only within GL window area,
* parent X window focus includes window border
*/
#define GLINMASK (KeyPressMask | \
ButtonPressMask | \
ButtonReleaseMask | \
ExposureMask | \
PointerMotionMask)
static void
GetXInput(void)
{
static long first = 1;
XEvent ev;
long newMouse = 0;
long x, y;
/* Display already open in single process mode */
if (XDpy == NULL)
{
XDpy = XOpenDisplay(":0.0");
if (!XDpy)
pfNotify(PFNFY_FATAL, PFNFY_RESOURCE,
"GetXInput: couldn't open display\n");
}
if (first)
{
XSelectInput(XDpy, Shared->glWin, GLINMASK);
XSelectInput(XDpy, Shared->xWin, XINMASK);
first = 0;
}
while (XCheckWindowEvent(XDpy, Shared->glWin, GLINMASK, &ev))
{
switch (ev.type)
{
case Expose:
Shared->redrawOverlay = 1;
break;
case ButtonPress:
switch (ev.xbutton.button)
{
case (1):
Shared->mouseButtons = ev.xbutton.state | Button1Mask;
break;
case (2):
Shared->mouseButtons = ev.xbutton.state | Button2Mask;
break;
case (3):
Shared->mouseButtons = ev.xbutton.state | Button3Mask;
break;
}
break;
case ButtonRelease:
switch (ev.xbutton.button)
{
case (1):
Shared->mouseButtons = ev.xbutton.state & ~Button1Mask;
break;
case (2):
Shared->mouseButtons = ev.xbutton.state & ~Button2Mask;
break;
case (3):
Shared->mouseButtons = ev.xbutton.state & ~Button3Mask;
break;
}
break;
case MotionNotify:
{
newMouse = 1;
x = ev.xmotion.x;
y = ev.xmotion.y;
}
break;
case KeyPress:
{
KeySym ks;
/*
* On a keypress, either rotate and re-display
* or exit.
*/
ks = XLookupKeysym(&ev.xkey, 0);
switch (ks)
{
case XK_F1:
{
Shared->drawStats = !Shared->drawStats;
break;
}
case XK_Escape:
{
Shared->exitFlag = 1;
break;
}
}
break;
}
}
}
while (XCheckWindowEvent(XDpy, Shared->xWin, XINMASK, &ev))
{
switch (ev.type)
{
case FocusIn:
break;
case FocusOut:
Shared->inWindow = 0;
break;
}
}
if (newMouse)
{
long xs, ys;
Shared->mouseX = 2.0f*x/(float)Shared->winSizeX - 1.0f;
Shared->mouseY = -2.0f*y/(float)Shared->winSizeY + 1.0f;
Shared->inWindow = 1;
}
}
static void
DrawOverlay(void)
{
if (GLXwinset(XDpy, Shared->overWin) < 0)
{
pfNotify(PFNFY_WARN, PFNFY_SYSERR,
"GLXwinset for overlay failed\n");
return;
}
pfPushState();
pfBasicState();
zbuffer(FALSE);
pfPushIdentMatrix();
mapcolor(0, 0, 0, 0);
mapcolor(1, 71, 9, 82);
mapcolor(2, 0, 0, 0);
gflush();
color(0);
clear();
ortho2(-0.5, Shared->winSizeX - 0.5, -0.5, Shared->winSizeY - 0.5);
cmov2(2, 2);
color(1);
charstr("GLX Overlay Test");
pfPopMatrix();
zbuffer(TRUE);
pfPopState();
if (GLXwinset(XDpy, Shared->glWin) < 0)
{
pfNotify(PFNFY_WARN, PFNFY_SYSERR,
"GLXwinset for NORMAL window failed\n");
}
}
/*
* usage() -- print usage advice and exit. This procedure
* is executed in the application process.
*/
static void
usage (void)
{
fprintf(stderr, "Usage: complex-glx file.flt ...\n");
pfExit();
exit(1);
}
/*
* /usr/people/4DGifts/examples/GLX/gl-Xlib/glxh2.c
*
* This file (companion to mix2.c) provides the helper function
* "GLXCreateWindow", which does all the necessary magic to create
* an X window suitable for GL drawing to take place within.
* see the definition of GLXCreateWindow for a description of how
* to call it.
*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <gl/glws.h>
#include <stdarg.h>
#include <stdio.h>
/*
** Internal helper routines
*/
/* extract_visual:
* a visual is uniquely identified by a viusal identifier descibing the
* visual and screen. this function is used to get back the
* GLX_NORMAL-GLX_VISUAL and the GLX_NORMAL-GLX_COLORMAP fields out of
* the configuration data for use in creating a window using these data.
* XGetVisualInfo() returns a list of visual structures that match the
* attributes explicitly specified in the template structure.
*/
static XVisualInfo*
extract_visual(Display* D, int S, GLXconfig *conf, int buffer)
{
XVisualInfo template, *v;
int n;
template.screen = S;
template.visualid = GLXgetvalue(conf, buffer, GLX_VISUAL);
return XGetVisualInfo (D, VisualScreenMask|VisualIDMask, &template, &n);
}
/* set_window()
* search thru the current conf GL window structure looking for the
* buffer that matches the mode of GLX_WINDOW so that we can go ahead
* and assign the window W, (created via XCreateWindow below in
* GLXCreateWindow) to the arg element. We do this because in order
* for this stuff to work, the "arg" element of the conf structure
* must have the value field set to the X window id of the window
* which was created.
*/
static void
set_window(GLXconfig* conf, int buffer, Window W)
{
int i;
for (i = 0; conf[i].buffer; i++)
if (conf[i].buffer == buffer && conf[i].mode == GLX_WINDOW)
conf[i].arg = W;
}
/*
** Used to get a value out of the configuration structure returned by
** GLXgetconfig. Scan through the GLX config structure, and, when we
** find the proper buffer-mode combination, return the argument relevant
** for that buffer type.
*/
unsigned long
GLXgetvalue(GLXconfig* conf, int buffer, int mode)
{
int i;
for (i = 0; conf[i].buffer; i++)
if (conf[i].buffer == buffer && conf[i].mode == mode)
return conf[i].arg;
return 0;
}
/*
* GLXCreateWindow(dpy, parent, x, y, w, h, boderWidth, arg_list, ...)
*
* Return value is the filled in config structure
*
* Arguments are:
* dpy The X "Display*" returned by XOpenDisplay
* parent The parent of the newly created window,
* a typical value for this is
* RootWindow(dpy, DefaultScreen(dpy))
* x,y The location of the window to be created,
* y coordinate is measured from the top down.
* w,h size of the new window
* borderWidth the X border size for this window, should probably
* be zero.
* arg_list Arguments to fill in initial config structure
*/
GLXconfig*
GLXCreateWindow(
Display* dpy, Window parent,
int x, int y, int w, int h,
int borderWidth, ...)
{
XSetWindowAttributes init_attr;
XWindowAttributes read_attr;
GLXconfig init_config[50], *cp;
GLXconfig *retconfig;
Window win, normal_win;
va_list ap;
int buf, screen;
XVisualInfo *vis;
/*
** Loop through the remaining arguments, copying all triples
** up to a zero-triple (or just plain zero if there are no
** triples), into the initial config structure.
*/
va_start(ap, borderWidth);
for (cp = init_config; buf = va_arg(ap, int); cp++) {
cp->buffer = buf;
cp->mode = va_arg(ap, int);
cp->arg = va_arg(ap, int);
}
cp->buffer = cp->mode = cp->arg = 0;
/*
** Now that we have the configuration request, call GLXgetconfig to
** get back real configuration information.
*/
XGetWindowAttributes(dpy, parent, &read_attr);
screen = XScreenNumberOfScreen(read_attr.screen);
if ((retconfig = GLXgetconfig(dpy, screen, init_config)) == 0) {
pfNotify(PFNFY_FATAL, PFNFY_RESOURCE,
"Hardware doesn't support that window type\n");
}
/*
** Now we have the information needed to actually create the
** windows. There is always a normal window, so we create that
** one first.
**
** Basically we extract the GLX_NORMAL,GLX_VISUAL and the
** GLX_NORMAL,GLX_COLORMAP fields out of the configuration
* data, and create a window using these data.
** When we are done we save the X ID of the new window in
** the configuration structure (using set_window()). GLXlink,
** and the caller of GLXCreateWindow will be interested in
** this value.
** note the explicit definition of the init_attr.colormap
** element: we aren't sure if our visual is the same as our
** parent's, and we'd like to not care. since our colormap
** and visual MUST be of the same depth and class (else the
** BadMatch error will bite), we pass a colormap which we
** know will match our visual. If we don't do this, we
** inherit from our parent and all bets are off..
*/
vis = extract_visual(dpy, screen, retconfig, GLX_NORMAL);
init_attr.colormap = GLXgetvalue(retconfig, GLX_NORMAL, GLX_COLORMAP);
init_attr.border_pixel = 0; /* Must exist, otherwise BadMatch error */
normal_win = XCreateWindow (dpy, parent, x, y, w, h, borderWidth,
vis->depth, InputOutput, vis->visual,
CWColormap|CWBorderPixel, &init_attr);
set_window(retconfig, GLX_NORMAL, normal_win);
/*
** If overlay planes were requested in the configuration, and
** they are available, the GLX_OVERLAY,GLX_BUFSIZE arg field in
** the returned configuration will be non zero. If this is the
** case, we create another window, in the overlay planes, a child
** of the normal planes window. The size is 2K x 2K so that the
** overlay window will never have to be resized, it will always
** be clipped by the size of its parent.
*/
if (GLXgetvalue(retconfig, GLX_OVERLAY, GLX_BUFSIZE)) {
vis = extract_visual(dpy, screen, retconfig, GLX_OVERLAY);
init_attr.colormap = GLXgetvalue(retconfig,GLX_OVERLAY,GLX_COLORMAP);
win = XCreateWindow (dpy, normal_win, 0, 0, 2000, 2000, 0,
vis->depth, InputOutput, vis->visual,
CWColormap|CWBorderPixel, &init_attr);
XMapWindow(dpy, win);
set_window(retconfig, GLX_OVERLAY, win);
}
/*
** Do exactly the same stuff, but this time for the popup planes
** when we are running on a machine that has no OVERLAY planes.
*/
if (GLXgetvalue(retconfig, GLX_POPUP, GLX_BUFSIZE)) {
vis = extract_visual(dpy, screen, retconfig, GLX_POPUP);
init_attr.colormap = GLXgetvalue(retconfig,GLX_POPUP,GLX_COLORMAP);
win = XCreateWindow (dpy, normal_win, 0, 0, 2000, 2000, 0,
vis->depth, InputOutput, vis->visual,
CWColormap|CWBorderPixel, &init_attr);
XMapWindow(dpy, win);
set_window(retconfig, GLX_POPUP, win);
}
/* now do the final step: configure the X window for GL rendering.
** this informs the GL that we intend to render GL into an X window.
** at this point, the retconfig structure contains all the
** information necessary to ensure that X and GL know about each
** other and will behave in a responsible manner...
*/
if (GLXlink(dpy, retconfig) < 0) {
pfNotify(PFNFY_FATAL, PFNFY_SYSERR, "GLXlink failed\n");
}
/* finally do what winopen() always did: explicitly set the current
** GL window to be this new mixed model window.
*/
GLXwinset(dpy, normal_win);
return retconfig;
}
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sharon Rose Fischler - Silicon Graphics, Advanced Graphics Development srf++at++sgi.com (415) 390 - 1002 FAX: (415) 965 - 2658 MS 7L-590 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:50:08 PDT