|
|
1.1 root 1: // Emacs style mode select -*- C++ -*-
2: //-----------------------------------------------------------------------------
3: //
4: // $Id:$
5: //
6: // Copyright (C) 1993-1996 by id Software, Inc.
7: //
8: // This program is free software; you can redistribute it and/or
9: // modify it under the terms of the GNU General Public License
10: // as published by the Free Software Foundation; either version 2
11: // of the License, or (at your option) any later version.
12: //
13: // This program is distributed in the hope that it will be useful,
14: // but WITHOUT ANY WARRANTY; without even the implied warranty of
15: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: // GNU General Public License for more details.
17: //
18: // $Log:$
19: //
20: // DESCRIPTION:
21: // DOOM graphics stuff for X11, UNIX.
22: //
23: //-----------------------------------------------------------------------------
24:
25: static const char
26: rcsid[] = "$Id: i_x.c,v 1.6 1997/02/03 22:45:10 b1 Exp $";
27:
28: #include <stdlib.h>
29: #include <unistd.h>
30: #include <sys/ipc.h>
31: #include <sys/shm.h>
32:
33: #include <X11/Xlib.h>
34: #include <X11/Xutil.h>
35: #include <X11/keysym.h>
36:
37: #include <X11/extensions/XShm.h>
38: // Had to dig up XShm.c for this one.
39: // It is in the libXext, but not in the XFree86 headers.
40: #ifdef LINUX
41: int XShmGetEventBase( Display* dpy ); // problems with g++?
42: #endif
43:
44: #include <stdarg.h>
45: #include <sys/time.h>
46: #include <sys/types.h>
47: #include <sys/socket.h>
48:
49: #include <netinet/in.h>
50: #include <errnos.h>
51: #include <signal.h>
52:
53: #include "doomstat.h"
54: #include "i_system.h"
55: #include "v_video.h"
56: #include "m_argv.h"
57: #include "d_main.h"
58:
59: #include "doomdef.h"
60:
61: #define POINTER_WARP_COUNTDOWN 1
62:
63: Display* X_display=0;
64: Window X_mainWindow;
65: Colormap X_cmap;
66: Visual* X_visual;
67: GC X_gc;
68: XEvent X_event;
69: int X_screen;
70: XVisualInfo X_visualinfo;
71: XImage* image;
72: int X_width;
73: int X_height;
74:
75: // MIT SHared Memory extension.
76: boolean doShm;
77:
78: XShmSegmentInfo X_shminfo;
79: int X_shmeventtype;
80:
81: // Fake mouse handling.
82: // This cannot work properly w/o DGA.
83: // Needs an invisible mouse cursor at least.
84: boolean grabMouse;
85: int doPointerWarp = POINTER_WARP_COUNTDOWN;
86:
87: // Blocky mode,
88: // replace each 320x200 pixel with multiply*multiply pixels.
89: // According to Dave Taylor, it still is a bonehead thing
90: // to use ....
91: static int multiply=1;
92:
93:
94: //
95: // Translates the key currently in X_event
96: //
97:
98: int xlatekey(void)
99: {
100:
101: int rc;
102:
103: switch(rc = XKeycodeToKeysym(X_display, X_event.xkey.keycode, 0))
104: {
105: case XK_Left: rc = KEY_LEFTARROW; break;
106: case XK_Right: rc = KEY_RIGHTARROW; break;
107: case XK_Down: rc = KEY_DOWNARROW; break;
108: case XK_Up: rc = KEY_UPARROW; break;
109: case XK_Escape: rc = KEY_ESCAPE; break;
110: case XK_Return: rc = KEY_ENTER; break;
111: case XK_Tab: rc = KEY_TAB; break;
112: case XK_F1: rc = KEY_F1; break;
113: case XK_F2: rc = KEY_F2; break;
114: case XK_F3: rc = KEY_F3; break;
115: case XK_F4: rc = KEY_F4; break;
116: case XK_F5: rc = KEY_F5; break;
117: case XK_F6: rc = KEY_F6; break;
118: case XK_F7: rc = KEY_F7; break;
119: case XK_F8: rc = KEY_F8; break;
120: case XK_F9: rc = KEY_F9; break;
121: case XK_F10: rc = KEY_F10; break;
122: case XK_F11: rc = KEY_F11; break;
123: case XK_F12: rc = KEY_F12; break;
124:
125: case XK_BackSpace:
126: case XK_Delete: rc = KEY_BACKSPACE; break;
127:
128: case XK_Pause: rc = KEY_PAUSE; break;
129:
130: case XK_KP_Equal:
131: case XK_equal: rc = KEY_EQUALS; break;
132:
133: case XK_KP_Subtract:
134: case XK_minus: rc = KEY_MINUS; break;
135:
136: case XK_Shift_L:
137: case XK_Shift_R:
138: rc = KEY_RSHIFT;
139: break;
140:
141: case XK_Control_L:
142: case XK_Control_R:
143: rc = KEY_RCTRL;
144: break;
145:
146: case XK_Alt_L:
147: case XK_Meta_L:
148: case XK_Alt_R:
149: case XK_Meta_R:
150: rc = KEY_RALT;
151: break;
152:
153: default:
154: if (rc >= XK_space && rc <= XK_asciitilde)
155: rc = rc - XK_space + ' ';
156: if (rc >= 'A' && rc <= 'Z')
157: rc = rc - 'A' + 'a';
158: break;
159: }
160:
161: return rc;
162:
163: }
164:
165: void I_ShutdownGraphics(void)
166: {
167: // Detach from X server
168: if (!XShmDetach(X_display, &X_shminfo))
169: I_Error("XShmDetach() failed in I_ShutdownGraphics()");
170:
171: // Release shared memory.
172: shmdt(X_shminfo.shmaddr);
173: shmctl(X_shminfo.shmid, IPC_RMID, 0);
174:
175: // Paranoia.
176: image->data = NULL;
177: }
178:
179:
180:
181: //
182: // I_StartFrame
183: //
184: void I_StartFrame (void)
185: {
186: // er?
187:
188: }
189:
190: static int lastmousex = 0;
191: static int lastmousey = 0;
192: boolean mousemoved = false;
193: boolean shmFinished;
194:
195: void I_GetEvent(void)
196: {
197:
198: event_t event;
199:
200: // put event-grabbing stuff in here
201: XNextEvent(X_display, &X_event);
202: switch (X_event.type)
203: {
204: case KeyPress:
205: event.type = ev_keydown;
206: event.data1 = xlatekey();
207: D_PostEvent(&event);
208: // fprintf(stderr, "k");
209: break;
210: case KeyRelease:
211: event.type = ev_keyup;
212: event.data1 = xlatekey();
213: D_PostEvent(&event);
214: // fprintf(stderr, "ku");
215: break;
216: case ButtonPress:
217: event.type = ev_mouse;
218: event.data1 =
219: (X_event.xbutton.state & Button1Mask)
220: | (X_event.xbutton.state & Button2Mask ? 2 : 0)
221: | (X_event.xbutton.state & Button3Mask ? 4 : 0)
222: | (X_event.xbutton.button == Button1)
223: | (X_event.xbutton.button == Button2 ? 2 : 0)
224: | (X_event.xbutton.button == Button3 ? 4 : 0);
225: event.data2 = event.data3 = 0;
226: D_PostEvent(&event);
227: // fprintf(stderr, "b");
228: break;
229: case ButtonRelease:
230: event.type = ev_mouse;
231: event.data1 =
232: (X_event.xbutton.state & Button1Mask)
233: | (X_event.xbutton.state & Button2Mask ? 2 : 0)
234: | (X_event.xbutton.state & Button3Mask ? 4 : 0);
235: // suggest parentheses around arithmetic in operand of |
236: event.data1 =
237: event.data1
238: ^ (X_event.xbutton.button == Button1 ? 1 : 0)
239: ^ (X_event.xbutton.button == Button2 ? 2 : 0)
240: ^ (X_event.xbutton.button == Button3 ? 4 : 0);
241: event.data2 = event.data3 = 0;
242: D_PostEvent(&event);
243: // fprintf(stderr, "bu");
244: break;
245: case MotionNotify:
246: event.type = ev_mouse;
247: event.data1 =
248: (X_event.xmotion.state & Button1Mask)
249: | (X_event.xmotion.state & Button2Mask ? 2 : 0)
250: | (X_event.xmotion.state & Button3Mask ? 4 : 0);
251: event.data2 = (X_event.xmotion.x - lastmousex) << 2;
252: event.data3 = (lastmousey - X_event.xmotion.y) << 2;
253:
254: if (event.data2 || event.data3)
255: {
256: lastmousex = X_event.xmotion.x;
257: lastmousey = X_event.xmotion.y;
258: if (X_event.xmotion.x != X_width/2 &&
259: X_event.xmotion.y != X_height/2)
260: {
261: D_PostEvent(&event);
262: // fprintf(stderr, "m");
263: mousemoved = false;
264: } else
265: {
266: mousemoved = true;
267: }
268: }
269: break;
270:
271: case Expose:
272: case ConfigureNotify:
273: break;
274:
275: default:
276: if (doShm && X_event.type == X_shmeventtype) shmFinished = true;
277: break;
278: }
279:
280: }
281:
282: Cursor
283: createnullcursor
284: ( Display* display,
285: Window root )
286: {
287: Pixmap cursormask;
288: XGCValues xgc;
289: GC gc;
290: XColor dummycolour;
291: Cursor cursor;
292:
293: cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
294: xgc.function = GXclear;
295: gc = XCreateGC(display, cursormask, GCFunction, &xgc);
296: XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
297: dummycolour.pixel = 0;
298: dummycolour.red = 0;
299: dummycolour.flags = 04;
300: cursor = XCreatePixmapCursor(display, cursormask, cursormask,
301: &dummycolour,&dummycolour, 0,0);
302: XFreePixmap(display,cursormask);
303: XFreeGC(display,gc);
304: return cursor;
305: }
306:
307: //
308: // I_StartTic
309: //
310: void I_StartTic (void)
311: {
312:
313: if (!X_display)
314: return;
315:
316: while (XPending(X_display))
317: I_GetEvent();
318:
319: // Warp the pointer back to the middle of the window
320: // or it will wander off - that is, the game will
321: // loose input focus within X11.
322: if (grabMouse)
323: {
324: if (!--doPointerWarp)
325: {
326: XWarpPointer( X_display,
327: None,
328: X_mainWindow,
329: 0, 0,
330: 0, 0,
331: X_width/2, X_height/2);
332:
333: doPointerWarp = POINTER_WARP_COUNTDOWN;
334: }
335: }
336:
337: mousemoved = false;
338:
339: }
340:
341:
342: //
343: // I_UpdateNoBlit
344: //
345: void I_UpdateNoBlit (void)
346: {
347: // what is this?
348: }
349:
350: //
351: // I_FinishUpdate
352: //
353: void I_FinishUpdate (void)
354: {
355:
356: static int lasttic;
357: int tics;
358: int i;
359: // UNUSED static unsigned char *bigscreen=0;
360:
361: // draws little dots on the bottom of the screen
362: if (devparm)
363: {
364:
365: i = I_GetTime();
366: tics = i - lasttic;
367: lasttic = i;
368: if (tics > 20) tics = 20;
369:
370: for (i=0 ; i<tics*2 ; i+=2)
371: screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0xff;
372: for ( ; i<20*2 ; i+=2)
373: screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0x0;
374:
375: }
376:
377: // scales the screen size before blitting it
378: if (multiply == 2)
379: {
380: unsigned int *olineptrs[2];
381: unsigned int *ilineptr;
382: int x, y, i;
383: unsigned int twoopixels;
384: unsigned int twomoreopixels;
385: unsigned int fouripixels;
386:
387: ilineptr = (unsigned int *) (screens[0]);
388: for (i=0 ; i<2 ; i++)
389: olineptrs[i] = (unsigned int *) &image->data[i*X_width];
390:
391: y = SCREENHEIGHT;
392: while (y--)
393: {
394: x = SCREENWIDTH;
395: do
396: {
397: fouripixels = *ilineptr++;
398: twoopixels = (fouripixels & 0xff000000)
399: | ((fouripixels>>8) & 0xffff00)
400: | ((fouripixels>>16) & 0xff);
401: twomoreopixels = ((fouripixels<<16) & 0xff000000)
402: | ((fouripixels<<8) & 0xffff00)
403: | (fouripixels & 0xff);
404: #ifdef __BIG_ENDIAN__
405: *olineptrs[0]++ = twoopixels;
406: *olineptrs[1]++ = twoopixels;
407: *olineptrs[0]++ = twomoreopixels;
408: *olineptrs[1]++ = twomoreopixels;
409: #else
410: *olineptrs[0]++ = twomoreopixels;
411: *olineptrs[1]++ = twomoreopixels;
412: *olineptrs[0]++ = twoopixels;
413: *olineptrs[1]++ = twoopixels;
414: #endif
415: } while (x-=4);
416: olineptrs[0] += X_width/4;
417: olineptrs[1] += X_width/4;
418: }
419:
420: }
421: else if (multiply == 3)
422: {
423: unsigned int *olineptrs[3];
424: unsigned int *ilineptr;
425: int x, y, i;
426: unsigned int fouropixels[3];
427: unsigned int fouripixels;
428:
429: ilineptr = (unsigned int *) (screens[0]);
430: for (i=0 ; i<3 ; i++)
431: olineptrs[i] = (unsigned int *) &image->data[i*X_width];
432:
433: y = SCREENHEIGHT;
434: while (y--)
435: {
436: x = SCREENWIDTH;
437: do
438: {
439: fouripixels = *ilineptr++;
440: fouropixels[0] = (fouripixels & 0xff000000)
441: | ((fouripixels>>8) & 0xff0000)
442: | ((fouripixels>>16) & 0xffff);
443: fouropixels[1] = ((fouripixels<<8) & 0xff000000)
444: | (fouripixels & 0xffff00)
445: | ((fouripixels>>8) & 0xff);
446: fouropixels[2] = ((fouripixels<<16) & 0xffff0000)
447: | ((fouripixels<<8) & 0xff00)
448: | (fouripixels & 0xff);
449: #ifdef __BIG_ENDIAN__
450: *olineptrs[0]++ = fouropixels[0];
451: *olineptrs[1]++ = fouropixels[0];
452: *olineptrs[2]++ = fouropixels[0];
453: *olineptrs[0]++ = fouropixels[1];
454: *olineptrs[1]++ = fouropixels[1];
455: *olineptrs[2]++ = fouropixels[1];
456: *olineptrs[0]++ = fouropixels[2];
457: *olineptrs[1]++ = fouropixels[2];
458: *olineptrs[2]++ = fouropixels[2];
459: #else
460: *olineptrs[0]++ = fouropixels[2];
461: *olineptrs[1]++ = fouropixels[2];
462: *olineptrs[2]++ = fouropixels[2];
463: *olineptrs[0]++ = fouropixels[1];
464: *olineptrs[1]++ = fouropixels[1];
465: *olineptrs[2]++ = fouropixels[1];
466: *olineptrs[0]++ = fouropixels[0];
467: *olineptrs[1]++ = fouropixels[0];
468: *olineptrs[2]++ = fouropixels[0];
469: #endif
470: } while (x-=4);
471: olineptrs[0] += 2*X_width/4;
472: olineptrs[1] += 2*X_width/4;
473: olineptrs[2] += 2*X_width/4;
474: }
475:
476: }
477: else if (multiply == 4)
478: {
479: // Broken. Gotta fix this some day.
480: void Expand4(unsigned *, double *);
481: Expand4 ((unsigned *)(screens[0]), (double *) (image->data));
482: }
483:
484: if (doShm)
485: {
486:
487: if (!XShmPutImage( X_display,
488: X_mainWindow,
489: X_gc,
490: image,
491: 0, 0,
492: 0, 0,
493: X_width, X_height,
494: True ))
495: I_Error("XShmPutImage() failed\n");
496:
497: // wait for it to finish and processes all input events
498: shmFinished = false;
499: do
500: {
501: I_GetEvent();
502: } while (!shmFinished);
503:
504: }
505: else
506: {
507:
508: // draw the image
509: XPutImage( X_display,
510: X_mainWindow,
511: X_gc,
512: image,
513: 0, 0,
514: 0, 0,
515: X_width, X_height );
516:
517: // sync up with server
518: XSync(X_display, False);
519:
520: }
521:
522: }
523:
524:
525: //
526: // I_ReadScreen
527: //
528: void I_ReadScreen (byte* scr)
529: {
530: memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT);
531: }
532:
533:
534: //
535: // Palette stuff.
536: //
537: static XColor colors[256];
538:
539: void UploadNewPalette(Colormap cmap, byte *palette)
540: {
541:
542: register int i;
543: register int c;
544: static boolean firstcall = true;
545:
546: #ifdef __cplusplus
547: if (X_visualinfo.c_class == PseudoColor && X_visualinfo.depth == 8)
548: #else
549: if (X_visualinfo.class == PseudoColor && X_visualinfo.depth == 8)
550: #endif
551: {
552: // initialize the colormap
553: if (firstcall)
554: {
555: firstcall = false;
556: for (i=0 ; i<256 ; i++)
557: {
558: colors[i].pixel = i;
559: colors[i].flags = DoRed|DoGreen|DoBlue;
560: }
561: }
562:
563: // set the X colormap entries
564: for (i=0 ; i<256 ; i++)
565: {
566: c = gammatable[usegamma][*palette++];
567: colors[i].red = (c<<8) + c;
568: c = gammatable[usegamma][*palette++];
569: colors[i].green = (c<<8) + c;
570: c = gammatable[usegamma][*palette++];
571: colors[i].blue = (c<<8) + c;
572: }
573:
574: // store the colors to the current colormap
575: XStoreColors(X_display, cmap, colors, 256);
576:
577: }
578: }
579:
580: //
581: // I_SetPalette
582: //
583: void I_SetPalette (byte* palette)
584: {
585: UploadNewPalette(X_cmap, palette);
586: }
587:
588:
589: //
590: // This function is probably redundant,
591: // if XShmDetach works properly.
592: // ddt never detached the XShm memory,
593: // thus there might have been stale
594: // handles accumulating.
595: //
596: void grabsharedmemory(int size)
597: {
598:
599: int key = ('d'<<24) | ('o'<<16) | ('o'<<8) | 'm';
600: struct shmid_ds shminfo;
601: int minsize = 320*200;
602: int id;
603: int rc;
604: // UNUSED int done=0;
605: int pollution=5;
606:
607: // try to use what was here before
608: do
609: {
610: id = shmget((key_t) key, minsize, 0777); // just get the id
611: if (id != -1)
612: {
613: rc=shmctl(id, IPC_STAT, &shminfo); // get stats on it
614: if (!rc)
615: {
616: if (shminfo.shm_nattch)
617: {
618: fprintf(stderr, "User %d appears to be running "
619: "DOOM. Is that wise?\n", shminfo.shm_cpid);
620: key++;
621: }
622: else
623: {
624: if (getuid() == shminfo.shm_perm.cuid)
625: {
626: rc = shmctl(id, IPC_RMID, 0);
627: if (!rc)
628: fprintf(stderr,
629: "Was able to kill my old shared memory\n");
630: else
631: I_Error("Was NOT able to kill my old shared memory");
632:
633: id = shmget((key_t)key, size, IPC_CREAT|0777);
634: if (id==-1)
635: I_Error("Could not get shared memory");
636:
637: rc=shmctl(id, IPC_STAT, &shminfo);
638:
639: break;
640:
641: }
642: if (size >= shminfo.shm_segsz)
643: {
644: fprintf(stderr,
645: "will use %d's stale shared memory\n",
646: shminfo.shm_cpid);
647: break;
648: }
649: else
650: {
651: fprintf(stderr,
652: "warning: can't use stale "
653: "shared memory belonging to id %d, "
654: "key=0x%x\n",
655: shminfo.shm_cpid, key);
656: key++;
657: }
658: }
659: }
660: else
661: {
662: I_Error("could not get stats on key=%d", key);
663: }
664: }
665: else
666: {
667: id = shmget((key_t)key, size, IPC_CREAT|0777);
668: if (id==-1)
669: {
670: extern int errno;
671: fprintf(stderr, "errno=%d\n", errno);
672: I_Error("Could not get any shared memory");
673: }
674: break;
675: }
676: } while (--pollution);
677:
678: if (!pollution)
679: {
680: I_Error("Sorry, system too polluted with stale "
681: "shared memory segments.\n");
682: }
683:
684: X_shminfo.shmid = id;
685:
686: // attach to the shared memory segment
687: image->data = X_shminfo.shmaddr = shmat(id, 0, 0);
688:
689: fprintf(stderr, "shared memory id=%d, addr=0x%x\n", id,
690: (int) (image->data));
691: }
692:
693: void I_InitGraphics(void)
694: {
695:
696: char* displayname;
697: char* d;
698: int n;
699: int pnum;
700: int x=0;
701: int y=0;
702:
703: // warning: char format, different type arg
704: char xsign=' ';
705: char ysign=' ';
706:
707: int oktodraw;
708: unsigned long attribmask;
709: XSetWindowAttributes attribs;
710: XGCValues xgcvalues;
711: int valuemask;
712: static int firsttime=1;
713:
714: if (!firsttime)
715: return;
716: firsttime = 0;
717:
718: signal(SIGINT, (void (*)(int)) I_Quit);
719:
720: if (M_CheckParm("-2"))
721: multiply = 2;
722:
723: if (M_CheckParm("-3"))
724: multiply = 3;
725:
726: if (M_CheckParm("-4"))
727: multiply = 4;
728:
729: X_width = SCREENWIDTH * multiply;
730: X_height = SCREENHEIGHT * multiply;
731:
732: // check for command-line display name
733: if ( (pnum=M_CheckParm("-disp")) ) // suggest parentheses around assignment
734: displayname = myargv[pnum+1];
735: else
736: displayname = 0;
737:
738: // check if the user wants to grab the mouse (quite unnice)
739: grabMouse = !!M_CheckParm("-grabmouse");
740:
741: // check for command-line geometry
742: if ( (pnum=M_CheckParm("-geom")) ) // suggest parentheses around assignment
743: {
744: // warning: char format, different type arg 3,5
745: n = sscanf(myargv[pnum+1], "%c%d%c%d", &xsign, &x, &ysign, &y);
746:
747: if (n==2)
748: x = y = 0;
749: else if (n==6)
750: {
751: if (xsign == '-')
752: x = -x;
753: if (ysign == '-')
754: y = -y;
755: }
756: else
757: I_Error("bad -geom parameter");
758: }
759:
760: // open the display
761: X_display = XOpenDisplay(displayname);
762: if (!X_display)
763: {
764: if (displayname)
765: I_Error("Could not open display [%s]", displayname);
766: else
767: I_Error("Could not open display (DISPLAY=[%s])", getenv("DISPLAY"));
768: }
769:
770: // use the default visual
771: X_screen = DefaultScreen(X_display);
772: if (!XMatchVisualInfo(X_display, X_screen, 8, PseudoColor, &X_visualinfo))
773: I_Error("xdoom currently only supports 256-color PseudoColor screens");
774: X_visual = X_visualinfo.visual;
775:
776: // check for the MITSHM extension
777: doShm = XShmQueryExtension(X_display);
778:
779: // even if it's available, make sure it's a local connection
780: if (doShm)
781: {
782: if (!displayname) displayname = (char *) getenv("DISPLAY");
783: if (displayname)
784: {
785: d = displayname;
786: while (*d && (*d != ':')) d++;
787: if (*d) *d = 0;
788: if (!(!strcasecmp(displayname, "unix") || !*displayname)) doShm = false;
789: }
790: }
791:
792: fprintf(stderr, "Using MITSHM extension\n");
793:
794: // create the colormap
795: X_cmap = XCreateColormap(X_display, RootWindow(X_display,
796: X_screen), X_visual, AllocAll);
797:
798: // setup attributes for main window
799: attribmask = CWEventMask | CWColormap | CWBorderPixel;
800: attribs.event_mask =
801: KeyPressMask
802: | KeyReleaseMask
803: // | PointerMotionMask | ButtonPressMask | ButtonReleaseMask
804: | ExposureMask;
805:
806: attribs.colormap = X_cmap;
807: attribs.border_pixel = 0;
808:
809: // create the main window
810: X_mainWindow = XCreateWindow( X_display,
811: RootWindow(X_display, X_screen),
812: x, y,
813: X_width, X_height,
814: 0, // borderwidth
815: 8, // depth
816: InputOutput,
817: X_visual,
818: attribmask,
819: &attribs );
820:
821: XDefineCursor(X_display, X_mainWindow,
822: createnullcursor( X_display, X_mainWindow ) );
823:
824: // create the GC
825: valuemask = GCGraphicsExposures;
826: xgcvalues.graphics_exposures = False;
827: X_gc = XCreateGC( X_display,
828: X_mainWindow,
829: valuemask,
830: &xgcvalues );
831:
832: // map the window
833: XMapWindow(X_display, X_mainWindow);
834:
835: // wait until it is OK to draw
836: oktodraw = 0;
837: while (!oktodraw)
838: {
839: XNextEvent(X_display, &X_event);
840: if (X_event.type == Expose
841: && !X_event.xexpose.count)
842: {
843: oktodraw = 1;
844: }
845: }
846:
847: // grabs the pointer so it is restricted to this window
848: if (grabMouse)
849: XGrabPointer(X_display, X_mainWindow, True,
850: ButtonPressMask|ButtonReleaseMask|PointerMotionMask,
851: GrabModeAsync, GrabModeAsync,
852: X_mainWindow, None, CurrentTime);
853:
854: if (doShm)
855: {
856:
857: X_shmeventtype = XShmGetEventBase(X_display) + ShmCompletion;
858:
859: // create the image
860: image = XShmCreateImage( X_display,
861: X_visual,
862: 8,
863: ZPixmap,
864: 0,
865: &X_shminfo,
866: X_width,
867: X_height );
868:
869: grabsharedmemory(image->bytes_per_line * image->height);
870:
871:
872: // UNUSED
873: // create the shared memory segment
874: // X_shminfo.shmid = shmget (IPC_PRIVATE,
875: // image->bytes_per_line * image->height, IPC_CREAT | 0777);
876: // if (X_shminfo.shmid < 0)
877: // {
878: // perror("");
879: // I_Error("shmget() failed in InitGraphics()");
880: // }
881: // fprintf(stderr, "shared memory id=%d\n", X_shminfo.shmid);
882: // attach to the shared memory segment
883: // image->data = X_shminfo.shmaddr = shmat(X_shminfo.shmid, 0, 0);
884:
885:
886: if (!image->data)
887: {
888: perror("");
889: I_Error("shmat() failed in InitGraphics()");
890: }
891:
892: // get the X server to attach to it
893: if (!XShmAttach(X_display, &X_shminfo))
894: I_Error("XShmAttach() failed in InitGraphics()");
895:
896: }
897: else
898: {
899: image = XCreateImage( X_display,
900: X_visual,
901: 8,
902: ZPixmap,
903: 0,
904: (char*)malloc(X_width * X_height),
905: X_width, X_height,
906: 8,
907: X_width );
908:
909: }
910:
911: if (multiply == 1)
912: screens[0] = (unsigned char *) (image->data);
913: else
914: screens[0] = (unsigned char *) malloc (SCREENWIDTH * SCREENHEIGHT);
915:
916: }
917:
918:
919: unsigned exptable[256];
920:
921: void InitExpand (void)
922: {
923: int i;
924:
925: for (i=0 ; i<256 ; i++)
926: exptable[i] = i | (i<<8) | (i<<16) | (i<<24);
927: }
928:
929: double exptable2[256*256];
930:
931: void InitExpand2 (void)
932: {
933: int i;
934: int j;
935: // UNUSED unsigned iexp, jexp;
936: double* exp;
937: union
938: {
939: double d;
940: unsigned u[2];
941: } pixel;
942:
943: printf ("building exptable2...\n");
944: exp = exptable2;
945: for (i=0 ; i<256 ; i++)
946: {
947: pixel.u[0] = i | (i<<8) | (i<<16) | (i<<24);
948: for (j=0 ; j<256 ; j++)
949: {
950: pixel.u[1] = j | (j<<8) | (j<<16) | (j<<24);
951: *exp++ = pixel.d;
952: }
953: }
954: printf ("done.\n");
955: }
956:
957: int inited;
958:
959: void
960: Expand4
961: ( unsigned* lineptr,
962: double* xline )
963: {
964: double dpixel;
965: unsigned x;
966: unsigned y;
967: unsigned fourpixels;
968: unsigned step;
969: double* exp;
970:
971: exp = exptable2;
972: if (!inited)
973: {
974: inited = 1;
975: InitExpand2 ();
976: }
977:
978:
979: step = 3*SCREENWIDTH/2;
980:
981: y = SCREENHEIGHT-1;
982: do
983: {
984: x = SCREENWIDTH;
985:
986: do
987: {
988: fourpixels = lineptr[0];
989:
990: dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
991: xline[0] = dpixel;
992: xline[160] = dpixel;
993: xline[320] = dpixel;
994: xline[480] = dpixel;
995:
996: dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
997: xline[1] = dpixel;
998: xline[161] = dpixel;
999: xline[321] = dpixel;
1000: xline[481] = dpixel;
1001:
1002: fourpixels = lineptr[1];
1003:
1004: dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
1005: xline[2] = dpixel;
1006: xline[162] = dpixel;
1007: xline[322] = dpixel;
1008: xline[482] = dpixel;
1009:
1010: dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
1011: xline[3] = dpixel;
1012: xline[163] = dpixel;
1013: xline[323] = dpixel;
1014: xline[483] = dpixel;
1015:
1016: fourpixels = lineptr[2];
1017:
1018: dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
1019: xline[4] = dpixel;
1020: xline[164] = dpixel;
1021: xline[324] = dpixel;
1022: xline[484] = dpixel;
1023:
1024: dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
1025: xline[5] = dpixel;
1026: xline[165] = dpixel;
1027: xline[325] = dpixel;
1028: xline[485] = dpixel;
1029:
1030: fourpixels = lineptr[3];
1031:
1032: dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
1033: xline[6] = dpixel;
1034: xline[166] = dpixel;
1035: xline[326] = dpixel;
1036: xline[486] = dpixel;
1037:
1038: dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
1039: xline[7] = dpixel;
1040: xline[167] = dpixel;
1041: xline[327] = dpixel;
1042: xline[487] = dpixel;
1043:
1044: lineptr+=4;
1045: xline+=8;
1046: } while (x-=16);
1047: xline += step;
1048: } while (y--);
1049: }
1050:
1051:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.