ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/x11.c
Revision: 2.26
Committed: Tue Dec 5 10:54:39 1995 UTC (28 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.25: +2 -2 lines
Log Message:
made initialization work for TrueColor visuals with depths < 24

File Contents

# Content
1 /* Copyright (c) 1995 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * x11.c - driver for X-windows version 11
9 *
10 * Jan 1990
11 */
12
13 #include <stdio.h>
14 #include <math.h>
15 #include <sys/ioctl.h>
16 #include <fcntl.h>
17 #ifdef sparc
18 #include <sys/conf.h>
19 #include <sys/file.h>
20 #include <sys/filio.h>
21 #endif
22 #if !defined(FNDELAY) && defined(O_NONBLOCK)
23 #define FNDELAY O_NONBLOCK
24 #endif
25
26 #include <X11/Xlib.h>
27 #include <X11/cursorfont.h>
28 #include <X11/Xutil.h>
29
30 #include "color.h"
31 #include "driver.h"
32 #include "x11twind.h"
33 #include "x11icon.h"
34
35 #define GAMMA 2.2 /* default exponent correction */
36
37 #define MINWIDTH (32*COMCW) /* minimum graphics window width */
38 #define MINHEIGHT (MINWIDTH/2) /* minimum graphics window height */
39
40 #define BORWIDTH 5 /* border width */
41 #define COMHEIGHT (COMLH*COMCH) /* command line height (pixels) */
42
43 #define COMFN "8x13" /* command line font name */
44 #define COMLH 3 /* number of command lines */
45 #define COMCW 8 /* approx. character width (pixels) */
46 #define COMCH 14 /* approx. character height (pixels) */
47
48 #define ourscreen DefaultScreen(ourdisplay)
49 #define ourroot RootWindow(ourdisplay,ourscreen)
50
51 #define levptr(etype) ((etype *)&currentevent)
52
53 static XEvent currentevent; /* current event */
54
55 static int ncolors = 0; /* color table size */
56 static int mapped = 0; /* window is mapped? */
57 static unsigned long *pixval = NULL; /* allocated pixels */
58 static unsigned long ourblack=0, ourwhite=1;
59
60 static Display *ourdisplay = NULL; /* our display */
61
62 static XVisualInfo ourvinfo; /* our visual information */
63
64 static Window gwind = 0; /* our graphics window */
65
66 static Cursor pickcursor = 0; /* cursor used for picking */
67
68 static int gwidth, gheight; /* graphics window size */
69
70 static int comheight; /* desired comline height */
71 static TEXTWIND *comline = NULL; /* our command line */
72
73 static char c_queue[64]; /* input queue */
74 static int c_first = 0; /* first character in queue */
75 static int c_last = 0; /* last character in queue */
76
77 static GC ourgc = 0; /* our graphics context for drawing */
78
79 static Colormap ourmap = 0; /* our color map */
80
81 #define IC_X11 0
82 #define IC_IOCTL 1
83 #define IC_READ 2
84
85 static int inpcheck; /* whence to check input */
86
87 extern char *malloc();
88
89 static int x11_close(), x11_clear(), x11_paintr(), x11_errout(),
90 x11_getcur(), x11_comout(), x11_comin(), x11_flush();
91
92 static int std_comin(), std_comout();
93
94 static struct driver x11_driver = {
95 x11_close, x11_clear, x11_paintr, x11_getcur,
96 NULL, NULL, x11_flush, 1.0
97 };
98
99 static int getpixels(), xnewcolr(), freepixels(), resizewindow(),
100 getevent(), getkey(), fixwindow(), x11_getc();
101 static unsigned long true_pixel();
102
103
104 struct driver *
105 x11_init(name, id) /* initialize driver */
106 char *name, *id;
107 {
108 extern char *getenv();
109 char *gv;
110 int nplanes;
111 XSetWindowAttributes ourwinattr;
112 XWMHints ourxwmhints;
113 XSizeHints oursizhints;
114 /* open display server */
115 ourdisplay = XOpenDisplay(NULL);
116 if (ourdisplay == NULL) {
117 stderr_v("cannot open X-windows; DISPLAY variable set?\n");
118 return(NULL);
119 }
120 /* find a usable visual */
121 nplanes = DisplayPlanes(ourdisplay, ourscreen);
122 if (XMatchVisualInfo(ourdisplay,ourscreen,
123 nplanes>12?nplanes:24,TrueColor,&ourvinfo) ||
124 XMatchVisualInfo(ourdisplay,ourscreen,
125 nplanes>12?nplanes:24,DirectColor,&ourvinfo)) {
126 ourblack = 0;
127 ourwhite = ourvinfo.red_mask |
128 ourvinfo.green_mask |
129 ourvinfo.blue_mask ;
130 } else {
131 if (nplanes < 4) {
132 stderr_v("not enough colors\n");
133 return(NULL);
134 }
135 if (!XMatchVisualInfo(ourdisplay,ourscreen,
136 nplanes,PseudoColor,&ourvinfo) &&
137 !XMatchVisualInfo(ourdisplay,ourscreen,
138 nplanes,GrayScale,&ourvinfo)) {
139 stderr_v("unsupported visual type\n");
140 return(NULL);
141 }
142 ourblack = BlackPixel(ourdisplay,ourscreen);
143 ourwhite = WhitePixel(ourdisplay,ourscreen);
144 }
145 /* set gamma */
146 if ((gv = XGetDefault(ourdisplay, "radiance", "gamma")) != NULL
147 || (gv = getenv("DISPLAY_GAMMA")) != NULL)
148 make_gmap(atof(gv));
149 else
150 make_gmap(GAMMA);
151 /* X11 command line or no? */
152 if (!strcmp(name, "x11"))
153 comheight = COMHEIGHT;
154 else /* "x11d" */ {
155 comheight = 0;
156 #ifndef FNDELAY
157 stderr_v("warning: x11d driver not fully functional on this machine\n");
158 #endif
159 }
160 /* open window */
161 ourwinattr.background_pixel = ourblack;
162 ourwinattr.border_pixel = ourblack;
163 /* this is stupid */
164 ourwinattr.colormap = XCreateColormap(ourdisplay, ourroot,
165 ourvinfo.visual, AllocNone);
166 gwind = XCreateWindow(ourdisplay, ourroot, 0, 0,
167 DisplayWidth(ourdisplay,ourscreen)-2*BORWIDTH,
168 DisplayHeight(ourdisplay,ourscreen)-2*BORWIDTH,
169 BORWIDTH, ourvinfo.depth, InputOutput, ourvinfo.visual,
170 CWBackPixel|CWBorderPixel|CWColormap, &ourwinattr);
171 if (gwind == 0) {
172 stderr_v("cannot create window\n");
173 return(NULL);
174 }
175 XStoreName(ourdisplay, gwind, id);
176 /* create a cursor */
177 pickcursor = XCreateFontCursor(ourdisplay, XC_diamond_cross);
178 ourgc = XCreateGC(ourdisplay, gwind, 0, NULL);
179 ourxwmhints.flags = InputHint|IconPixmapHint;
180 ourxwmhints.input = True;
181 ourxwmhints.icon_pixmap = XCreateBitmapFromData(ourdisplay,
182 gwind, x11icon_bits, x11icon_width, x11icon_height);
183 XSetWMHints(ourdisplay, gwind, &ourxwmhints);
184 oursizhints.min_width = MINWIDTH;
185 oursizhints.min_height = MINHEIGHT+comheight;
186 oursizhints.flags = PMinSize;
187 XSetNormalHints(ourdisplay, gwind, &oursizhints);
188 XSelectInput(ourdisplay, gwind, ExposureMask);
189 XMapWindow(ourdisplay, gwind);
190 XWindowEvent(ourdisplay, gwind, ExposureMask, levptr(XEvent));
191 gwidth = levptr(XExposeEvent)->width;
192 gheight = levptr(XExposeEvent)->height - comheight;
193 x11_driver.xsiz = gwidth < MINWIDTH ? MINWIDTH : gwidth;
194 x11_driver.ysiz = gheight < MINHEIGHT ? MINHEIGHT : gheight;
195 x11_driver.inpready = 0;
196 mapped = 1;
197 /* set i/o vectors */
198 if (comheight) {
199 x11_driver.comin = x11_comin;
200 x11_driver.comout = x11_comout;
201 cmdvec = x11_comout;
202 if (wrnvec != NULL)
203 wrnvec = x11_errout;
204 inpcheck = IC_X11;
205 } else {
206 x11_driver.comin = std_comin;
207 x11_driver.comout = std_comout;
208 cmdvec = std_comout;
209 inpcheck = IC_IOCTL;
210 }
211 return(&x11_driver);
212 }
213
214
215 static
216 x11_close() /* close our display */
217 {
218 cmdvec = NULL; /* reset error vectors */
219 if (wrnvec != NULL)
220 wrnvec = stderr_v;
221 if (ourdisplay == NULL)
222 return;
223 if (comline != NULL) {
224 xt_close(comline);
225 comline = NULL;
226 }
227 freepixels();
228 XFreeGC(ourdisplay, ourgc);
229 XDestroyWindow(ourdisplay, gwind);
230 gwind = 0;
231 ourgc = 0;
232 XFreeCursor(ourdisplay, pickcursor);
233 XCloseDisplay(ourdisplay);
234 ourdisplay = NULL;
235 }
236
237
238 static
239 x11_clear(xres, yres) /* clear our display */
240 int xres, yres;
241 {
242 /* check limits */
243 if (xres < MINWIDTH)
244 xres = MINWIDTH;
245 if (yres < MINHEIGHT)
246 yres = MINHEIGHT;
247 /* resize window */
248 if (xres != gwidth || yres != gheight) {
249 XSelectInput(ourdisplay, gwind, 0);
250 XResizeWindow(ourdisplay, gwind, xres, yres+comheight);
251 gwidth = xres;
252 gheight = yres;
253 XFlush(ourdisplay);
254 sleep(2); /* wait for window manager */
255 XSync(ourdisplay, 1); /* discard input */
256 }
257 XClearWindow(ourdisplay, gwind);
258 /* reinitialize color table */
259 if (ourvinfo.class == PseudoColor || ourvinfo.class == GrayScale)
260 if (getpixels() == 0)
261 stderr_v("cannot allocate colors\n");
262 else
263 new_ctab(ncolors);
264 /* get new command line */
265 if (comline != NULL)
266 xt_close(comline);
267 if (comheight) {
268 comline = xt_open(ourdisplay, gwind, 0, gheight, gwidth,
269 comheight, 0, ourblack, ourwhite, COMFN);
270 if (comline == NULL) {
271 stderr_v("cannot open command line window\n");
272 quit(1);
273 }
274 XSelectInput(ourdisplay, comline->w, ExposureMask);
275 /* remove earmuffs */
276 XSelectInput(ourdisplay, gwind,
277 StructureNotifyMask|ExposureMask|KeyPressMask|ButtonPressMask);
278 } else /* remove earmuffs */
279 XSelectInput(ourdisplay, gwind,
280 StructureNotifyMask|ExposureMask|ButtonPressMask);
281 }
282
283
284 static
285 x11_paintr(col, xmin, ymin, xmax, ymax) /* fill a rectangle */
286 COLOR col;
287 int xmin, ymin, xmax, ymax;
288 {
289 unsigned long pixel;
290
291 if (!mapped)
292 return;
293 if (ncolors > 0)
294 pixel = pixval[get_pixel(col, xnewcolr)];
295 else
296 pixel = true_pixel(col);
297 XSetForeground(ourdisplay, ourgc, pixel);
298 XFillRectangle(ourdisplay, gwind,
299 ourgc, xmin, gheight-ymax, xmax-xmin, ymax-ymin);
300 }
301
302
303 static
304 x11_flush() /* flush output */
305 {
306 char buf[256];
307 int n;
308 /* check for input */
309 XNoOp(ourdisplay);
310 n = XPending(ourdisplay); /* from X server */
311 while (n-- > 0)
312 getevent();
313 #ifdef FNDELAY
314 if (inpcheck == IC_IOCTL) { /* from stdin */
315 #ifdef FIONREAD
316 if (ioctl(fileno(stdin), FIONREAD, &n) < 0) {
317 #else
318 if (1) {
319 #endif
320 if (fcntl(fileno(stdin), F_SETFL, FNDELAY) < 0) {
321 stderr_v("cannot change input mode\n");
322 quit(1);
323 }
324 inpcheck = IC_READ;
325 } else
326 x11_driver.inpready += n;
327 }
328 if (inpcheck == IC_READ) {
329 n = read(fileno(stdin), buf, sizeof(buf)-1);
330 if (n > 0) {
331 buf[n] = '\0';
332 tocombuf(buf, &x11_driver);
333 }
334 }
335 #endif
336 }
337
338
339 static
340 x11_comin(inp, prompt) /* read in a command line */
341 char *inp, *prompt;
342 {
343 if (prompt != NULL) {
344 x11_flush(); /* make sure we get everything */
345 if (fromcombuf(inp, &x11_driver))
346 return;
347 xt_puts(prompt, comline);
348 }
349 xt_cursor(comline, TBLKCURS);
350 editline(inp, x11_getc, x11_comout);
351 xt_cursor(comline, TNOCURS);
352 }
353
354
355 static
356 x11_comout(outp) /* output a string to command line */
357 char *outp;
358 {
359 if (comline == NULL)
360 return;
361 xt_puts(outp, comline);
362 if (outp[strlen(outp)-1] == '\n')
363 XFlush(ourdisplay);
364 }
365
366
367 static
368 x11_errout(msg) /* output an error message */
369 char *msg;
370 {
371 stderr_v(msg); /* send to stderr also! */
372 x11_comout(msg);
373 }
374
375
376 static
377 std_comin(inp, prompt) /* read in command line from stdin */
378 char *inp, *prompt;
379 {
380 extern char *gets();
381
382 if (prompt != NULL) {
383 if (fromcombuf(inp, &x11_driver))
384 return;
385 if (!x11_driver.inpready)
386 std_comout(prompt);
387 }
388 #ifdef FNDELAY
389 if (inpcheck == IC_READ) { /* turn off FNDELAY */
390 if (fcntl(fileno(stdin), F_SETFL, 0) < 0) {
391 stderr_v("cannot change input mode\n");
392 quit(1);
393 }
394 inpcheck = IC_IOCTL;
395 }
396 #endif
397 if (gets(inp) == NULL) {
398 strcpy(inp, "quit");
399 return;
400 }
401 x11_driver.inpready -= strlen(inp) + 1;
402 if (x11_driver.inpready < 0)
403 x11_driver.inpready = 0;
404 }
405
406
407 static
408 std_comout(outp) /* write out string to stdout */
409 char *outp;
410 {
411 fputs(outp, stdout);
412 fflush(stdout);
413 }
414
415
416 static int
417 x11_getcur(xp, yp) /* get cursor position */
418 int *xp, *yp;
419 {
420 while (XGrabPointer(ourdisplay, gwind, True, ButtonPressMask,
421 GrabModeAsync, GrabModeAsync, None, pickcursor,
422 CurrentTime) != GrabSuccess)
423 sleep(2);
424
425 do
426 getevent();
427 while (c_last <= c_first && levptr(XEvent)->type != ButtonPress);
428 *xp = levptr(XButtonPressedEvent)->x;
429 *yp = gheight-1 - levptr(XButtonPressedEvent)->y;
430 XUngrabPointer(ourdisplay, CurrentTime);
431 XFlush(ourdisplay); /* insure release */
432 if (c_last > c_first) /* key pressed */
433 return(x11_getc());
434 /* button pressed */
435 if (levptr(XButtonPressedEvent)->button == Button1)
436 return(MB1);
437 if (levptr(XButtonPressedEvent)->button == Button2)
438 return(MB2);
439 if (levptr(XButtonPressedEvent)->button == Button3)
440 return(MB3);
441 return(ABORT);
442 }
443
444
445 static
446 xnewcolr(ndx, r, g, b) /* enter a color into hardware table */
447 int ndx;
448 int r, g, b;
449 {
450 XColor xcolor;
451
452 xcolor.pixel = pixval[ndx];
453 xcolor.red = r << 8;
454 xcolor.green = g << 8;
455 xcolor.blue = b << 8;
456 xcolor.flags = DoRed|DoGreen|DoBlue;
457
458 XStoreColor(ourdisplay, ourmap, &xcolor);
459 }
460
461
462 static int
463 getpixels() /* get the color map */
464 {
465 XColor thiscolor;
466 register int i, j;
467
468 if (ncolors > 0)
469 return(ncolors);
470 if (ourvinfo.visual == DefaultVisual(ourdisplay,ourscreen)) {
471 ourmap = DefaultColormap(ourdisplay,ourscreen);
472 goto loop;
473 }
474 newmap:
475 ourmap = XCreateColormap(ourdisplay,gwind,ourvinfo.visual,AllocNone);
476 loop:
477 for (ncolors = ourvinfo.colormap_size;
478 ncolors > ourvinfo.colormap_size/3;
479 ncolors = ncolors*.937) {
480 pixval = (unsigned long *)malloc(ncolors*sizeof(unsigned long));
481 if (pixval == NULL)
482 return(ncolors = 0);
483 if (XAllocColorCells(ourdisplay,ourmap,0,NULL,0,pixval,ncolors))
484 break;
485 free((char *)pixval);
486 pixval = NULL;
487 }
488 if (pixval == NULL) {
489 if (ourmap == DefaultColormap(ourdisplay,ourscreen))
490 goto newmap; /* try it with our map */
491 else
492 return(ncolors = 0); /* failed */
493 }
494 if (ourmap != DefaultColormap(ourdisplay,ourscreen))
495 for (i = 0; i < ncolors; i++) { /* reset black and white */
496 if (pixval[i] != ourblack && pixval[i] != ourwhite)
497 continue;
498 thiscolor.pixel = pixval[i];
499 thiscolor.flags = DoRed|DoGreen|DoBlue;
500 XQueryColor(ourdisplay,
501 DefaultColormap(ourdisplay,ourscreen),
502 &thiscolor);
503 XStoreColor(ourdisplay, ourmap, &thiscolor);
504 for (j = i; j+1 < ncolors; j++)
505 pixval[j] = pixval[j+1];
506 ncolors--;
507 i--;
508 }
509 XSetWindowColormap(ourdisplay, gwind, ourmap);
510 return(ncolors);
511 }
512
513
514 static
515 freepixels() /* free our pixels */
516 {
517 if (ncolors == 0)
518 return;
519 XFreeColors(ourdisplay,ourmap,pixval,ncolors,0L);
520 free((char *)pixval);
521 pixval = NULL;
522 ncolors = 0;
523 if (ourmap != DefaultColormap(ourdisplay,ourscreen))
524 XFreeColormap(ourdisplay, ourmap);
525 ourmap = 0;
526 }
527
528
529 static unsigned long
530 true_pixel(col) /* return true pixel value for color */
531 COLOR col;
532 {
533 unsigned long rval;
534 BYTE rgb[3];
535
536 map_color(rgb, col);
537 rval = ourvinfo.red_mask*rgb[RED]/255 & ourvinfo.red_mask;
538 rval |= ourvinfo.green_mask*rgb[GRN]/255 & ourvinfo.green_mask;
539 rval |= ourvinfo.blue_mask*rgb[BLU]/255 & ourvinfo.blue_mask;
540 return(rval);
541 }
542
543
544 static int
545 x11_getc() /* get a command character */
546 {
547 while (c_last <= c_first) {
548 c_first = c_last = 0; /* reset */
549 getevent(); /* wait for key */
550 }
551 x11_driver.inpready--;
552 return(c_queue[c_first++]);
553 }
554
555
556 static
557 getevent() /* get next event */
558 {
559 XNextEvent(ourdisplay, levptr(XEvent));
560 switch (levptr(XEvent)->type) {
561 case ConfigureNotify:
562 resizewindow(levptr(XConfigureEvent));
563 break;
564 case UnmapNotify:
565 mapped = 0;
566 freepixels();
567 break;
568 case MapNotify:
569 if (ourvinfo.class == PseudoColor ||
570 ourvinfo.class == GrayScale)
571 if (getpixels() == 0)
572 stderr_v("cannot allocate colors\n");
573 else
574 new_ctab(ncolors);
575 mapped = 1;
576 break;
577 case Expose:
578 fixwindow(levptr(XExposeEvent));
579 break;
580 case KeyPress:
581 getkey(levptr(XKeyPressedEvent));
582 break;
583 case ButtonPress:
584 break;
585 }
586 }
587
588
589 static
590 getkey(ekey) /* get input key */
591 register XKeyPressedEvent *ekey;
592 {
593 register int n;
594
595 n = XLookupString(ekey, c_queue+c_last, sizeof(c_queue)-c_last,
596 NULL, NULL);
597 c_last += n;
598 x11_driver.inpready += n;
599 }
600
601
602 static
603 fixwindow(eexp) /* repair damage to window */
604 register XExposeEvent *eexp;
605 {
606 char buf[80];
607
608 if (eexp->window == gwind) {
609 sprintf(buf, "repaint %d %d %d %d\n",
610 eexp->x, gheight - eexp->y - eexp->height,
611 eexp->x + eexp->width, gheight - eexp->y);
612 tocombuf(buf, &x11_driver);
613 } else if (eexp->window == comline->w) {
614 if (eexp->count == 0)
615 xt_redraw(comline);
616 }
617 }
618
619
620 static
621 resizewindow(ersz) /* resize window */
622 register XConfigureEvent *ersz;
623 {
624 if (ersz->width == gwidth && ersz->height-comheight == gheight)
625 return;
626
627 gwidth = ersz->width;
628 gheight = ersz->height-comheight;
629 x11_driver.xsiz = gwidth < MINWIDTH ? MINWIDTH : gwidth;
630 x11_driver.ysiz = gheight < MINHEIGHT ? MINHEIGHT : gheight;
631
632 tocombuf("new\n", &x11_driver);
633 }