ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhd_x11.c
Revision: 3.10
Committed: Fri Dec 5 09:38:55 1997 UTC (26 years, 4 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.9: +0 -1 lines
Log Message:
removed unnecessary assignment of qtDepthEps

File Contents

# User Rev Content
1 gregl 3.1 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ SGI";
5     #endif
6    
7     /*
8     * X11 driver for holodeck display.
9     * Based on rview driver.
10     */
11    
12     #include "standard.h"
13     #include "rhd_qtree.h"
14    
15     #include <X11/Xlib.h>
16     #include <X11/cursorfont.h>
17     #include <X11/Xutil.h>
18    
19     #include "x11icon.h"
20    
21 gregl 3.2 #define CTRL(c) ((c)-'@')
22    
23 gregl 3.1 #define GAMMA 2.2 /* default gamma correction */
24    
25 gregl 3.2 #define MOVPCT 10 /* percent distance to move */
26     #define MOVDIR(b) ((b)==Button1 ? 1 : (b)==Button2 ? 0 : -1)
27    
28 gregl 3.1 #define MINWIDTH 480 /* minimum graphics window width */
29     #define MINHEIGHT 400 /* minimum graphics window height */
30    
31     #define VIEWDIST 356 /* assumed viewing distance (mm) */
32    
33     #define BORWIDTH 5 /* border width */
34    
35     #define ourscreen DefaultScreen(ourdisplay)
36     #define ourroot RootWindow(ourdisplay,ourscreen)
37     #define ourmask (StructureNotifyMask|ExposureMask|KeyPressMask|\
38 gregl 3.2 ButtonPressMask|ButtonReleaseMask)
39 gregl 3.1
40     #define levptr(etype) ((etype *)&currentevent)
41    
42     struct driver odev; /* global device driver structure */
43    
44     static XEvent currentevent; /* current event */
45    
46     static int ncolors = 0; /* color table size */
47     static int mapped = 0; /* window is mapped? */
48     static unsigned long *pixval = NULL; /* allocated pixels */
49     static unsigned long ourblack=0, ourwhite=1;
50    
51     static Display *ourdisplay = NULL; /* our display */
52     static XVisualInfo ourvinfo; /* our visual information */
53     static Window gwind = 0; /* our graphics window */
54     static GC ourgc = 0; /* our graphics context for drawing */
55     static Colormap ourmap = 0; /* our color map */
56    
57     static double pwidth, pheight; /* pixel dimensions (mm) */
58    
59     static int inpresflags; /* input result flags */
60    
61 gregl 3.2 static int headlocked = 0; /* lock vertical motion */
62 gregl 3.1
63     static int getpixels(), xnewcolr(), freepixels(), resizewindow(),
64 gregl 3.2 getevent(), getkey(), moveview(), getmove(), fixwindow();
65 gregl 3.1 static unsigned long true_pixel();
66    
67    
68     static int
69     mytmflags() /* figure out tone mapping flags */
70     {
71     extern char *progname;
72     register char *cp, *tail;
73     /* find basic name */
74     for (cp = tail = progname; *cp; cp++)
75     if (*cp == '/')
76     tail = cp+1;
77     for (cp = tail; *cp && *cp != '.'; cp++)
78     ;
79     if (cp-tail == 3 && !strncmp(tail, "x11", 3))
80     return(TM_F_CAMERA);
81     if (cp-tail == 4 && !strncmp(tail, "x11h", 4))
82     return(TM_F_HUMAN);
83     error(USER, "illegal driver name");
84     }
85    
86    
87     dev_open(id) /* initialize X11 driver */
88     char *id;
89     {
90     extern char *getenv();
91     char *gv;
92     double gamval = GAMMA;
93     int nplanes;
94     XSetWindowAttributes ourwinattr;
95     XWMHints ourxwmhints;
96     XSizeHints oursizhints;
97 gregl 3.2 /* set quadtree globals */
98 gregl 3.4 qtMinNodesiz = 2;
99 gregl 3.1 /* open display server */
100     ourdisplay = XOpenDisplay(NULL);
101     if (ourdisplay == NULL)
102     error(USER, "cannot open X-windows; DISPLAY variable set?\n");
103     /* find a usable visual */
104     nplanes = DisplayPlanes(ourdisplay, ourscreen);
105     if (XMatchVisualInfo(ourdisplay,ourscreen,
106     nplanes>12?nplanes:24,TrueColor,&ourvinfo) ||
107     XMatchVisualInfo(ourdisplay,ourscreen,
108     nplanes>12?nplanes:24,DirectColor,&ourvinfo)) {
109     ourblack = 0;
110     ourwhite = ourvinfo.red_mask |
111     ourvinfo.green_mask |
112     ourvinfo.blue_mask ;
113     } else {
114     if (nplanes < 4)
115     error(INTERNAL, "not enough colors\n");
116     if (!XMatchVisualInfo(ourdisplay,ourscreen,
117     nplanes,PseudoColor,&ourvinfo) &&
118     !XMatchVisualInfo(ourdisplay,ourscreen,
119     nplanes,GrayScale,&ourvinfo))
120     error(INTERNAL, "unsupported visual type\n");
121     ourblack = BlackPixel(ourdisplay,ourscreen);
122     ourwhite = WhitePixel(ourdisplay,ourscreen);
123     }
124     /* set gamma and tone mapping */
125     if ((gv = XGetDefault(ourdisplay, "radiance", "gamma")) != NULL
126     || (gv = getenv("DISPLAY_GAMMA")) != NULL)
127     gamval = atof(gv);
128     if (tmInit(mytmflags(), stdprims, gamval) == NULL)
129     error(SYSTEM, "not enough memory in dev_open");
130     /* open window */
131     ourwinattr.background_pixel = ourblack;
132     ourwinattr.border_pixel = ourblack;
133     ourwinattr.event_mask = ourmask;
134     /* this is stupid */
135     ourwinattr.colormap = XCreateColormap(ourdisplay, ourroot,
136     ourvinfo.visual, AllocNone);
137     gwind = XCreateWindow(ourdisplay, ourroot, 0, 0,
138     DisplayWidth(ourdisplay,ourscreen)-2*BORWIDTH,
139     DisplayHeight(ourdisplay,ourscreen)-2*BORWIDTH,
140     BORWIDTH, ourvinfo.depth, InputOutput, ourvinfo.visual,
141     CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &ourwinattr);
142     if (gwind == 0)
143     error(SYSTEM, "cannot create window\n");
144     XStoreName(ourdisplay, gwind, id);
145     /* get graphics context */
146     ourgc = XCreateGC(ourdisplay, gwind, 0, NULL);
147     /* set window manager hints */
148     ourxwmhints.flags = InputHint|IconPixmapHint;
149     ourxwmhints.input = True;
150     ourxwmhints.icon_pixmap = XCreateBitmapFromData(ourdisplay,
151     gwind, x11icon_bits, x11icon_width, x11icon_height);
152     XSetWMHints(ourdisplay, gwind, &ourxwmhints);
153     oursizhints.min_width = MINWIDTH;
154     oursizhints.min_height = MINHEIGHT;
155     oursizhints.flags = PMinSize;
156     XSetNormalHints(ourdisplay, gwind, &oursizhints);
157     /* map the window and get its size */
158     XMapWindow(ourdisplay, gwind);
159     dev_input();
160 gregl 3.2 /* allocate our leaf pile */
161     if (!qtAllocLeaves(DisplayWidth(ourdisplay,ourscreen) *
162     DisplayHeight(ourdisplay,ourscreen) /
163     (qtMinNodesiz*qtMinNodesiz)))
164     error(SYSTEM, "insufficient memory for leaf storage");
165    
166 gregl 3.1 /* figure out sensible view */
167     pwidth = (double)DisplayWidthMM(ourdisplay, ourscreen) /
168     DisplayWidth(ourdisplay, ourscreen);
169     pheight = (double)DisplayHeightMM(ourdisplay, ourscreen) /
170     DisplayHeight(ourdisplay, ourscreen);
171     copystruct(&odev.v, &stdview);
172     odev.name = id;
173     odev.v.type = VT_PER;
174     odev.v.horiz = 2.*180./PI * atan(0.5/VIEWDIST*pwidth*odev.hres);
175     odev.v.vert = 2.*180./PI * atan(0.5/VIEWDIST*pheight*odev.vres);
176     odev.ifd = ConnectionNumber(ourdisplay);
177     }
178    
179    
180     dev_close() /* close our display */
181     {
182     freepixels();
183     XFreeGC(ourdisplay, ourgc);
184     XDestroyWindow(ourdisplay, gwind);
185     gwind = 0;
186     ourgc = 0;
187     XCloseDisplay(ourdisplay);
188     ourdisplay = NULL;
189     qtFreeLeaves();
190     tmDone(NULL);
191     odev.v.type = 0;
192     odev.hres = odev.vres = 0;
193     odev.ifd = -1;
194     }
195    
196    
197     dev_view(nv) /* assign new driver view */
198     VIEW *nv;
199     {
200     if (nv != &odev.v)
201     copystruct(&odev.v, nv);
202     qtReplant();
203     }
204    
205    
206     int
207     dev_input() /* get X11 input */
208     {
209     inpresflags = 0;
210 gregl 3.5
211 gregl 3.1 do
212     getevent();
213    
214     while (XQLength(ourdisplay) > 0);
215    
216     return(inpresflags);
217     }
218    
219    
220     dev_paintr(rgb, xmin, ymin, xmax, ymax) /* fill a rectangle */
221     BYTE rgb[3];
222     int xmin, ymin, xmax, ymax;
223     {
224     unsigned long pixel;
225    
226     if (!mapped)
227     return;
228     if (ncolors > 0)
229     pixel = pixval[get_pixel(rgb, xnewcolr)];
230     else
231     pixel = true_pixel(rgb);
232     XSetForeground(ourdisplay, ourgc, pixel);
233     XFillRectangle(ourdisplay, gwind,
234     ourgc, xmin, odev.vres-ymax, xmax-xmin, ymax-ymin);
235     }
236    
237    
238     int
239     dev_flush() /* flush output */
240     {
241     qtUpdate();
242     return(XPending(ourdisplay));
243     }
244    
245    
246     static
247     xnewcolr(ndx, r, g, b) /* enter a color into hardware table */
248     int ndx;
249     int r, g, b;
250     {
251     XColor xcolor;
252    
253     xcolor.pixel = pixval[ndx];
254     xcolor.red = r << 8;
255     xcolor.green = g << 8;
256     xcolor.blue = b << 8;
257     xcolor.flags = DoRed|DoGreen|DoBlue;
258    
259     XStoreColor(ourdisplay, ourmap, &xcolor);
260     }
261    
262    
263     static int
264     getpixels() /* get the color map */
265     {
266     XColor thiscolor;
267     register int i, j;
268    
269     if (ncolors > 0)
270     return(ncolors);
271     if (ourvinfo.visual == DefaultVisual(ourdisplay,ourscreen)) {
272     ourmap = DefaultColormap(ourdisplay,ourscreen);
273     goto loop;
274     }
275     newmap:
276     ourmap = XCreateColormap(ourdisplay,gwind,ourvinfo.visual,AllocNone);
277     loop:
278     for (ncolors = ourvinfo.colormap_size;
279     ncolors > ourvinfo.colormap_size/3;
280     ncolors = ncolors*.937) {
281     pixval = (unsigned long *)malloc(ncolors*sizeof(unsigned long));
282     if (pixval == NULL)
283     return(ncolors = 0);
284     if (XAllocColorCells(ourdisplay,ourmap,0,NULL,0,pixval,ncolors))
285     break;
286     free((char *)pixval);
287     pixval = NULL;
288     }
289     if (pixval == NULL) {
290     if (ourmap == DefaultColormap(ourdisplay,ourscreen))
291     goto newmap; /* try it with our map */
292     else
293     return(ncolors = 0); /* failed */
294     }
295     if (ourmap != DefaultColormap(ourdisplay,ourscreen))
296     for (i = 0; i < ncolors; i++) { /* reset black and white */
297     if (pixval[i] != ourblack && pixval[i] != ourwhite)
298     continue;
299     thiscolor.pixel = pixval[i];
300     thiscolor.flags = DoRed|DoGreen|DoBlue;
301     XQueryColor(ourdisplay,
302     DefaultColormap(ourdisplay,ourscreen),
303     &thiscolor);
304     XStoreColor(ourdisplay, ourmap, &thiscolor);
305     for (j = i; j+1 < ncolors; j++)
306     pixval[j] = pixval[j+1];
307     ncolors--;
308     i--;
309     }
310     XSetWindowColormap(ourdisplay, gwind, ourmap);
311     return(ncolors);
312     }
313    
314    
315     static
316     freepixels() /* free our pixels */
317     {
318     if (ncolors == 0)
319     return;
320     XFreeColors(ourdisplay,ourmap,pixval,ncolors,0L);
321     free((char *)pixval);
322     pixval = NULL;
323     ncolors = 0;
324     if (ourmap != DefaultColormap(ourdisplay,ourscreen))
325     XFreeColormap(ourdisplay, ourmap);
326     ourmap = 0;
327     }
328    
329    
330     static unsigned long
331     true_pixel(rgb) /* return true pixel value for color */
332     register BYTE rgb[3];
333     {
334     register unsigned long rval;
335    
336     rval = ourvinfo.red_mask*rgb[RED]/255 & ourvinfo.red_mask;
337     rval |= ourvinfo.green_mask*rgb[GRN]/255 & ourvinfo.green_mask;
338     rval |= ourvinfo.blue_mask*rgb[BLU]/255 & ourvinfo.blue_mask;
339     return(rval);
340     }
341    
342    
343     static
344     getevent() /* get next event */
345     {
346     XNextEvent(ourdisplay, levptr(XEvent));
347     switch (levptr(XEvent)->type) {
348     case ConfigureNotify:
349     resizewindow(levptr(XConfigureEvent));
350     break;
351     case UnmapNotify:
352     mapped = 0;
353     freepixels();
354     break;
355     case MapNotify:
356     if (ourvinfo.class == PseudoColor ||
357     ourvinfo.class == GrayScale) {
358     if (getpixels() == 0)
359     error(SYSTEM, "cannot allocate colors\n");
360     new_ctab(ncolors);
361     }
362     mapped = 1;
363     break;
364     case Expose:
365     fixwindow(levptr(XExposeEvent));
366     break;
367     case KeyPress:
368     getkey(levptr(XKeyPressedEvent));
369     break;
370     case ButtonPress:
371 gregl 3.2 getmove(levptr(XButtonPressedEvent));
372 gregl 3.1 break;
373     }
374     }
375    
376    
377     static
378 gregl 3.9 ilclip(dp, wp) /* clip world coordinates to device */
379     int dp[2][2];
380     FVECT wp[2];
381     {
382     static FVECT vmin = {0.,0.,0.}, vmax = {1.,1.,FHUGE};
383     FVECT ip[2];
384     /* not exactly right, but who cares? */
385     viewloc(ip[0], &odev.v, wp[0]);
386     viewloc(ip[1], &odev.v, wp[1]);
387     if (!clip(ip[0], ip[1], vmin, vmax))
388     return(0);
389     dp[0][0] = ip[0][0]*odev.hres;
390     dp[0][1] = ip[0][1]*odev.vres;
391     dp[1][0] = ip[1][0]*odev.hres;
392     dp[1][1] = ip[1][1]*odev.vres;
393     return(1);
394     }
395    
396    
397     static
398     draw3dline(wp) /* draw 3d line in world coordinates */
399     FVECT wp[2];
400     {
401     int dp[2][2];
402    
403     if (!ilclip(dp, wp))
404     return;
405     XDrawLine(ourdisplay, gwind, ourgc,
406     dp[0][0], odev.vres-1 - dp[0][1],
407     dp[1][0], odev.vres-1 - dp[1][1]);
408     }
409    
410    
411     static
412     draw_grids() /* draw holodeck section grids */
413     {
414     static BYTE gridrgb[3] = {0x0, 0xff, 0xff};
415     unsigned long pixel;
416    
417     if (!mapped || odev.v.type != VT_PER)
418     return;
419     if (ncolors > 0)
420     pixel = pixval[get_pixel(gridrgb, xnewcolr)];
421     else
422     pixel = true_pixel(gridrgb);
423     XSetForeground(ourdisplay, ourgc, pixel);
424     /* draw each grid line */
425     gridlines(draw3dline);
426     }
427    
428    
429     static
430 gregl 3.2 moveview(dx, dy, move) /* move our view */
431     int dx, dy, move;
432     {
433     VIEW nv;
434     double d;
435 gregl 3.4 register int i, li;
436 gregl 3.2 /* start with old view */
437     copystruct(&nv, &odev.v);
438     /* change view direction */
439     if (move) {
440 gregl 3.4 if ((li = qtFindLeaf(dx, dy)) < 0)
441 gregl 3.2 return(0); /* not on window */
442     for (i = 0; i < 3; i++)
443 gregl 3.4 nv.vdir[i] = qtL.wp[li][i] - nv.vp[i];
444 gregl 3.2 } else {
445     if (viewray(nv.vp, nv.vdir, &odev.v,
446     (dx+.5)/odev.hres, (dy+.5)/odev.vres) < -FTINY)
447     return(0); /* outside view */
448     }
449     /* move viewpoint */
450     if (move > 0)
451     for (i = 0; i < 3; i++)
452     nv.vp[i] += MOVPCT/100. * nv.vdir[i];
453     else if (move < 0)
454     for (i = 0; i < 3; i++)
455     nv.vp[i] -= MOVPCT/100. * nv.vdir[i];
456     if (move && headlocked) {
457     d = 0; /* bring head back to same height */
458     for (i = 0; i < 3; i++)
459     d += odev.v.vup[i] * (odev.v.vp[i] - nv.vp[i]);
460     for (i = 0; i < 3; i++)
461     nv.vp[i] += d * odev.v.vup[i];
462     }
463     if (setview(&nv) != NULL)
464     return(0); /* illegal view */
465     dev_view(&nv);
466     inpresflags |= DEV_NEWVIEW;
467     return(1);
468     }
469    
470    
471     static
472     getmove(ebut) /* get view change */
473     XButtonPressedEvent *ebut;
474     {
475     int whichbutton = ebut->button;
476     int oldnodesiz = qtMinNodesiz;
477     Window rootw, childw;
478     int rootx, rooty, wx, wy;
479     unsigned int statemask;
480    
481     qtMinNodesiz = 16; /* for quicker update */
482 gregl 3.9 XNoOp(ourdisplay);
483 gregl 3.2
484 gregl 3.9 while (!XCheckMaskEvent(ourdisplay,
485     ButtonReleaseMask, levptr(XEvent))) {
486    
487 gregl 3.2 if (!XQueryPointer(ourdisplay, gwind, &rootw, &childw,
488     &rootx, &rooty, &wx, &wy, &statemask))
489     break; /* on another screen */
490    
491 gregl 3.9 if (!moveview(wx, odev.vres-1-wy, MOVDIR(whichbutton))) {
492 gregl 3.2 sleep(1);
493 gregl 3.9 continue;
494     }
495     XClearWindow(ourdisplay, gwind);
496     qtUpdate();
497     draw_grids();
498     }
499 gregl 3.2 if (!(inpresflags & DEV_NEWVIEW)) { /* do final motion */
500     whichbutton = levptr(XButtonReleasedEvent)->button;
501     wx = levptr(XButtonReleasedEvent)->x;
502     wy = levptr(XButtonReleasedEvent)->y;
503     moveview(wx, odev.vres-1-wy, MOVDIR(whichbutton));
504     }
505 gregl 3.9 dev_flush();
506 gregl 3.2
507     qtMinNodesiz = oldnodesiz; /* restore quadtree resolution */
508     }
509    
510    
511     static
512 gregl 3.1 getkey(ekey) /* get input key */
513     register XKeyPressedEvent *ekey;
514     {
515     int n;
516     char buf[8];
517    
518     n = XLookupString(ekey, buf, sizeof(buf), NULL, NULL);
519     if (n != 1)
520     return;
521     switch (buf[0]) {
522     case 'h': /* turn on height motion lock */
523 gregl 3.2 headlocked = 1;
524 gregl 3.1 return;
525     case 'H': /* turn off height motion lock */
526 gregl 3.2 headlocked = 0;
527 gregl 3.1 return;
528 gregl 3.5 case CTRL('S'):
529 gregl 3.2 case 'p': /* pause computation */
530     inpresflags |= DEV_WAIT;
531     return;
532 gregl 3.7 case 'v': /* spit out view */
533     fputs(VIEWSTR, stderr);
534     fprintview(&odev.v, stderr);
535     fputc('\n', stderr);
536     return;
537 gregl 3.5 case CTRL('Q'):
538 gregl 3.2 case '\n':
539 gregl 3.5 case '\r': /* resume computation */
540     inpresflags |= DEV_RESUME;
541 gregl 3.2 return;
542 gregl 3.7 case CTRL('R'): /* redraw screen */
543     if (ncolors > 0)
544     new_ctab(ncolors);
545     qtRedraw(0, 0, odev.hres, odev.vres);
546     return;
547     case CTRL('L'): /* refresh from server */
548 gregl 3.8 if (inpresflags & DEV_REDRAW)
549     return;
550 gregl 3.7 XClearWindow(ourdisplay, gwind);
551 gregl 3.9 draw_grids();
552 gregl 3.8 XFlush(ourdisplay);
553 gregl 3.6 qtCompost(100); /* unload the old tree */
554 gregl 3.3 if (ncolors > 0)
555     new_ctab(ncolors);
556 gregl 3.6 inpresflags |= DEV_REDRAW; /* resend values from server */
557 gregl 3.3 return;
558 gregl 3.2 case CTRL('D'):
559 gregl 3.1 case 'Q':
560     case 'q': /* quit the program */
561     inpresflags |= DEV_SHUTDOWN;
562     return;
563     default:
564     XBell(ourdisplay, 0);
565     return;
566     }
567     }
568    
569    
570     static
571     fixwindow(eexp) /* repair damage to window */
572     register XExposeEvent *eexp;
573     {
574     if (odev.hres == 0 || odev.vres == 0) { /* first exposure */
575     odev.hres = eexp->width;
576     odev.vres = eexp->height;
577     inpresflags |= DEV_NEWSIZE;
578     }
579     qtRedraw(eexp->x, odev.vres - eexp->y - eexp->height,
580     eexp->x + eexp->width, odev.vres - eexp->y);
581     }
582    
583    
584     static
585     resizewindow(ersz) /* resize window */
586     register XConfigureEvent *ersz;
587     {
588     if (ersz->width == odev.hres && ersz->height == odev.vres)
589     return;
590    
591     if (odev.hres != 0 && odev.vres != 0) {
592     odev.v.horiz = 2.*180./PI * atan(
593     tan(PI/180./2.*odev.v.horiz) * ersz->width/odev.hres );
594     odev.v.vert = 2.*180./PI * atan(
595     tan(PI/180./2.*odev.v.vert) * ersz->height/odev.vres );
596     inpresflags |= DEV_NEWVIEW;
597     }
598     odev.hres = ersz->width;
599     odev.vres = ersz->height;
600    
601     inpresflags |= DEV_NEWSIZE;
602     }