i_video.c 22 KB

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