ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhd_x11.c
Revision: 3.1
Committed: Wed Nov 19 18:01:03 1997 UTC (26 years, 4 months ago) by gregl
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

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     #define GAMMA 2.2 /* default gamma correction */
22    
23     #define MINWIDTH 480 /* minimum graphics window width */
24     #define MINHEIGHT 400 /* minimum graphics window height */
25    
26     #define VIEWDIST 356 /* assumed viewing distance (mm) */
27    
28     #define BORWIDTH 5 /* border width */
29    
30     #define ourscreen DefaultScreen(ourdisplay)
31     #define ourroot RootWindow(ourdisplay,ourscreen)
32     #define ourmask (StructureNotifyMask|ExposureMask|KeyPressMask|\
33     ButtonPressMask)
34    
35     #define levptr(etype) ((etype *)&currentevent)
36    
37     struct driver odev; /* global device driver structure */
38    
39     static XEvent currentevent; /* current event */
40    
41     static int ncolors = 0; /* color table size */
42     static int mapped = 0; /* window is mapped? */
43     static unsigned long *pixval = NULL; /* allocated pixels */
44     static unsigned long ourblack=0, ourwhite=1;
45    
46     static Display *ourdisplay = NULL; /* our display */
47    
48     static XVisualInfo ourvinfo; /* our visual information */
49    
50     static Window gwind = 0; /* our graphics window */
51    
52     static GC ourgc = 0; /* our graphics context for drawing */
53    
54     static Colormap ourmap = 0; /* our color map */
55    
56     static double pwidth, pheight; /* pixel dimensions (mm) */
57    
58     static int inpresflags; /* input result flags */
59    
60     static int heightlocked = 0; /* lock vertical motion */
61    
62     static int getpixels(), xnewcolr(), freepixels(), resizewindow(),
63     getevent(), getkey(), fixwindow();
64     static unsigned long true_pixel();
65    
66    
67     static int
68     mytmflags() /* figure out tone mapping flags */
69     {
70     extern char *progname;
71     register char *cp, *tail;
72     /* find basic name */
73     for (cp = tail = progname; *cp; cp++)
74     if (*cp == '/')
75     tail = cp+1;
76     for (cp = tail; *cp && *cp != '.'; cp++)
77     ;
78     if (cp-tail == 3 && !strncmp(tail, "x11", 3))
79     return(TM_F_CAMERA);
80     if (cp-tail == 4 && !strncmp(tail, "x11h", 4))
81     return(TM_F_HUMAN);
82     error(USER, "illegal driver name");
83     }
84    
85    
86     dev_open(id) /* initialize X11 driver */
87     char *id;
88     {
89     extern char *getenv();
90     char *gv;
91     double gamval = GAMMA;
92     int nplanes;
93     int n;
94     XSetWindowAttributes ourwinattr;
95     XWMHints ourxwmhints;
96     XSizeHints oursizhints;
97     /* open display server */
98     ourdisplay = XOpenDisplay(NULL);
99     if (ourdisplay == NULL)
100     error(USER, "cannot open X-windows; DISPLAY variable set?\n");
101     /* find a usable visual */
102     nplanes = DisplayPlanes(ourdisplay, ourscreen);
103     if (XMatchVisualInfo(ourdisplay,ourscreen,
104     nplanes>12?nplanes:24,TrueColor,&ourvinfo) ||
105     XMatchVisualInfo(ourdisplay,ourscreen,
106     nplanes>12?nplanes:24,DirectColor,&ourvinfo)) {
107     ourblack = 0;
108     ourwhite = ourvinfo.red_mask |
109     ourvinfo.green_mask |
110     ourvinfo.blue_mask ;
111     } else {
112     if (nplanes < 4)
113     error(INTERNAL, "not enough colors\n");
114     if (!XMatchVisualInfo(ourdisplay,ourscreen,
115     nplanes,PseudoColor,&ourvinfo) &&
116     !XMatchVisualInfo(ourdisplay,ourscreen,
117     nplanes,GrayScale,&ourvinfo))
118     error(INTERNAL, "unsupported visual type\n");
119     ourblack = BlackPixel(ourdisplay,ourscreen);
120     ourwhite = WhitePixel(ourdisplay,ourscreen);
121     }
122     /* set gamma and tone mapping */
123     if ((gv = XGetDefault(ourdisplay, "radiance", "gamma")) != NULL
124     || (gv = getenv("DISPLAY_GAMMA")) != NULL)
125     gamval = atof(gv);
126     if (tmInit(mytmflags(), stdprims, gamval) == NULL)
127     error(SYSTEM, "not enough memory in dev_open");
128     /* open window */
129     ourwinattr.background_pixel = ourblack;
130     ourwinattr.border_pixel = ourblack;
131     ourwinattr.event_mask = ourmask;
132     /* this is stupid */
133     ourwinattr.colormap = XCreateColormap(ourdisplay, ourroot,
134     ourvinfo.visual, AllocNone);
135     gwind = XCreateWindow(ourdisplay, ourroot, 0, 0,
136     DisplayWidth(ourdisplay,ourscreen)-2*BORWIDTH,
137     DisplayHeight(ourdisplay,ourscreen)-2*BORWIDTH,
138     BORWIDTH, ourvinfo.depth, InputOutput, ourvinfo.visual,
139     CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &ourwinattr);
140     if (gwind == 0)
141     error(SYSTEM, "cannot create window\n");
142     XStoreName(ourdisplay, gwind, id);
143     /* get graphics context */
144     ourgc = XCreateGC(ourdisplay, gwind, 0, NULL);
145     /* set window manager hints */
146     ourxwmhints.flags = InputHint|IconPixmapHint;
147     ourxwmhints.input = True;
148     ourxwmhints.icon_pixmap = XCreateBitmapFromData(ourdisplay,
149     gwind, x11icon_bits, x11icon_width, x11icon_height);
150     XSetWMHints(ourdisplay, gwind, &ourxwmhints);
151     oursizhints.min_width = MINWIDTH;
152     oursizhints.min_height = MINHEIGHT;
153     oursizhints.flags = PMinSize;
154     XSetNormalHints(ourdisplay, gwind, &oursizhints);
155     /* map the window and get its size */
156     XMapWindow(ourdisplay, gwind);
157     dev_input();
158     /* figure out sensible view */
159     pwidth = (double)DisplayWidthMM(ourdisplay, ourscreen) /
160     DisplayWidth(ourdisplay, ourscreen);
161     pheight = (double)DisplayHeightMM(ourdisplay, ourscreen) /
162     DisplayHeight(ourdisplay, ourscreen);
163     copystruct(&odev.v, &stdview);
164     odev.name = id;
165     odev.v.type = VT_PER;
166     odev.v.horiz = 2.*180./PI * atan(0.5/VIEWDIST*pwidth*odev.hres);
167     odev.v.vert = 2.*180./PI * atan(0.5/VIEWDIST*pheight*odev.vres);
168     odev.ifd = ConnectionNumber(ourdisplay);
169     /* allocate our leaf pile */
170     qtDepthEps = 0.02;
171     n = odev.hres < odev.vres ? odev.hres : odev.vres;
172     qtMinNodesiz = 1;
173     if (!qtAllocLeaves(n*n/(qtMinNodesiz*qtMinNodesiz)))
174     error(SYSTEM, "insufficient memory for leaf storage");
175     }
176    
177    
178     dev_close() /* close our display */
179     {
180     freepixels();
181     XFreeGC(ourdisplay, ourgc);
182     XDestroyWindow(ourdisplay, gwind);
183     gwind = 0;
184     ourgc = 0;
185     XCloseDisplay(ourdisplay);
186     ourdisplay = NULL;
187     qtFreeLeaves();
188     tmDone(NULL);
189     odev.v.type = 0;
190     odev.hres = odev.vres = 0;
191     odev.ifd = -1;
192     }
193    
194    
195     dev_view(nv) /* assign new driver view */
196     VIEW *nv;
197     {
198     if (nv != &odev.v)
199     copystruct(&odev.v, nv);
200     qtReplant();
201     }
202    
203    
204     int
205     dev_input() /* get X11 input */
206     {
207     inpresflags = 0;
208     do
209     getevent();
210    
211     while (XQLength(ourdisplay) > 0);
212    
213     return(inpresflags);
214     }
215    
216    
217     dev_paintr(rgb, xmin, ymin, xmax, ymax) /* fill a rectangle */
218     BYTE rgb[3];
219     int xmin, ymin, xmax, ymax;
220     {
221     unsigned long pixel;
222    
223     if (!mapped)
224     return;
225     if (ncolors > 0)
226     pixel = pixval[get_pixel(rgb, xnewcolr)];
227     else
228     pixel = true_pixel(rgb);
229     XSetForeground(ourdisplay, ourgc, pixel);
230     XFillRectangle(ourdisplay, gwind,
231     ourgc, xmin, odev.vres-ymax, xmax-xmin, ymax-ymin);
232     }
233    
234    
235     int
236     dev_flush() /* flush output */
237     {
238     qtUpdate();
239     return(XPending(ourdisplay));
240     }
241    
242    
243     static
244     xnewcolr(ndx, r, g, b) /* enter a color into hardware table */
245     int ndx;
246     int r, g, b;
247     {
248     XColor xcolor;
249    
250     xcolor.pixel = pixval[ndx];
251     xcolor.red = r << 8;
252     xcolor.green = g << 8;
253     xcolor.blue = b << 8;
254     xcolor.flags = DoRed|DoGreen|DoBlue;
255    
256     XStoreColor(ourdisplay, ourmap, &xcolor);
257     }
258    
259    
260     static int
261     getpixels() /* get the color map */
262     {
263     XColor thiscolor;
264     register int i, j;
265    
266     if (ncolors > 0)
267     return(ncolors);
268     if (ourvinfo.visual == DefaultVisual(ourdisplay,ourscreen)) {
269     ourmap = DefaultColormap(ourdisplay,ourscreen);
270     goto loop;
271     }
272     newmap:
273     ourmap = XCreateColormap(ourdisplay,gwind,ourvinfo.visual,AllocNone);
274     loop:
275     for (ncolors = ourvinfo.colormap_size;
276     ncolors > ourvinfo.colormap_size/3;
277     ncolors = ncolors*.937) {
278     pixval = (unsigned long *)malloc(ncolors*sizeof(unsigned long));
279     if (pixval == NULL)
280     return(ncolors = 0);
281     if (XAllocColorCells(ourdisplay,ourmap,0,NULL,0,pixval,ncolors))
282     break;
283     free((char *)pixval);
284     pixval = NULL;
285     }
286     if (pixval == NULL) {
287     if (ourmap == DefaultColormap(ourdisplay,ourscreen))
288     goto newmap; /* try it with our map */
289     else
290     return(ncolors = 0); /* failed */
291     }
292     if (ourmap != DefaultColormap(ourdisplay,ourscreen))
293     for (i = 0; i < ncolors; i++) { /* reset black and white */
294     if (pixval[i] != ourblack && pixval[i] != ourwhite)
295     continue;
296     thiscolor.pixel = pixval[i];
297     thiscolor.flags = DoRed|DoGreen|DoBlue;
298     XQueryColor(ourdisplay,
299     DefaultColormap(ourdisplay,ourscreen),
300     &thiscolor);
301     XStoreColor(ourdisplay, ourmap, &thiscolor);
302     for (j = i; j+1 < ncolors; j++)
303     pixval[j] = pixval[j+1];
304     ncolors--;
305     i--;
306     }
307     XSetWindowColormap(ourdisplay, gwind, ourmap);
308     return(ncolors);
309     }
310    
311    
312     static
313     freepixels() /* free our pixels */
314     {
315     if (ncolors == 0)
316     return;
317     XFreeColors(ourdisplay,ourmap,pixval,ncolors,0L);
318     free((char *)pixval);
319     pixval = NULL;
320     ncolors = 0;
321     if (ourmap != DefaultColormap(ourdisplay,ourscreen))
322     XFreeColormap(ourdisplay, ourmap);
323     ourmap = 0;
324     }
325    
326    
327     static unsigned long
328     true_pixel(rgb) /* return true pixel value for color */
329     register BYTE rgb[3];
330     {
331     register unsigned long rval;
332    
333     rval = ourvinfo.red_mask*rgb[RED]/255 & ourvinfo.red_mask;
334     rval |= ourvinfo.green_mask*rgb[GRN]/255 & ourvinfo.green_mask;
335     rval |= ourvinfo.blue_mask*rgb[BLU]/255 & ourvinfo.blue_mask;
336     return(rval);
337     }
338    
339    
340     static
341     getevent() /* get next event */
342     {
343     XNextEvent(ourdisplay, levptr(XEvent));
344     switch (levptr(XEvent)->type) {
345     case ConfigureNotify:
346     resizewindow(levptr(XConfigureEvent));
347     break;
348     case UnmapNotify:
349     mapped = 0;
350     freepixels();
351     break;
352     case MapNotify:
353     if (ourvinfo.class == PseudoColor ||
354     ourvinfo.class == GrayScale) {
355     if (getpixels() == 0)
356     error(SYSTEM, "cannot allocate colors\n");
357     new_ctab(ncolors);
358     }
359     mapped = 1;
360     break;
361     case Expose:
362     fixwindow(levptr(XExposeEvent));
363     break;
364     case KeyPress:
365     getkey(levptr(XKeyPressedEvent));
366     break;
367     case ButtonPress:
368     /* getmove(levptr(XButtonPressedEvent)); */
369     break;
370     }
371     }
372    
373    
374     static
375     getkey(ekey) /* get input key */
376     register XKeyPressedEvent *ekey;
377     {
378     int n;
379     char buf[8];
380    
381     n = XLookupString(ekey, buf, sizeof(buf), NULL, NULL);
382     if (n != 1)
383     return;
384     switch (buf[0]) {
385     case 'h': /* turn on height motion lock */
386     heightlocked = 1;
387     return;
388     case 'H': /* turn off height motion lock */
389     heightlocked = 0;
390     return;
391     case 'Q':
392     case 'q': /* quit the program */
393     inpresflags |= DEV_SHUTDOWN;
394     return;
395     default:
396     XBell(ourdisplay, 0);
397     return;
398     }
399     }
400    
401    
402     static
403     fixwindow(eexp) /* repair damage to window */
404     register XExposeEvent *eexp;
405     {
406     if (odev.hres == 0 || odev.vres == 0) { /* first exposure */
407     eputs("Resizing window in fixwindow\n");
408     odev.hres = eexp->width;
409     odev.vres = eexp->height;
410     inpresflags |= DEV_NEWSIZE;
411     }
412     qtRedraw(eexp->x, odev.vres - eexp->y - eexp->height,
413     eexp->x + eexp->width, odev.vres - eexp->y);
414     }
415    
416    
417     static
418     resizewindow(ersz) /* resize window */
419     register XConfigureEvent *ersz;
420     {
421     if (ersz->width == odev.hres && ersz->height == odev.vres)
422     return;
423    
424     if (odev.hres != 0 && odev.vres != 0) {
425     odev.v.horiz = 2.*180./PI * atan(
426     tan(PI/180./2.*odev.v.horiz) * ersz->width/odev.hres );
427     odev.v.vert = 2.*180./PI * atan(
428     tan(PI/180./2.*odev.v.vert) * ersz->height/odev.vres );
429     inpresflags |= DEV_NEWVIEW;
430     }
431     odev.hres = ersz->width;
432     odev.vres = ersz->height;
433    
434     inpresflags |= DEV_NEWSIZE;
435     }