|
|
1.1 ! root 1: // vid_x.c -- general x video driver ! 2: ! 3: #include <sys/time.h> ! 4: #include <sys/types.h> ! 5: #include <unistd.h> ! 6: #include <signal.h> ! 7: #include <stdlib.h> ! 8: #include <stdio.h> ! 9: #include <string.h> ! 10: #include <sys/ipc.h> ! 11: #include <sys/shm.h> ! 12: #include <X11/Xlib.h> ! 13: #include <X11/Xutil.h> ! 14: #include <X11/Xatom.h> ! 15: #include <X11/keysym.h> ! 16: #include <X11/extensions/XShm.h> ! 17: #include <GL/gl.h> ! 18: #include <GL/glx.h> ! 19: #include <GL/glu.h> ! 20: ! 21: #include "quakedef.h" ! 22: #include "vid_256.h" ! 23: ! 24: typedef struct ! 25: { ! 26: int input; ! 27: int output; ! 28: } keymap_t; ! 29: ! 30: viddef_t vid; // global video state ! 31: ! 32: int num_shades=32; ! 33: ! 34: static qboolean doShm; ! 35: static Display *x_disp; ! 36: static Colormap x_cmap; ! 37: static Window x_win; ! 38: static GC x_gc; ! 39: static Visual *x_vis; ! 40: static XVisualInfo *x_visinfo=0; ! 41: //static XImage *x_image; ! 42: static int x_screen; ! 43: ! 44: static int x_shmeventtype; ! 45: //static XShmSegmentInfo x_shminfo; ! 46: ! 47: static qboolean oktodraw = false; ! 48: ! 49: static unsigned char *framebuffer=0; ! 50: ! 51: static int verbose=0; ! 52: ! 53: static short *jcspace=0; ! 54: ! 55: static qboolean doGLX; ! 56: static int glX_errorBase, glX_eventBase; ! 57: static GLXContext glX_context; ! 58: ! 59: static qboolean glX_scaled=0; ! 60: static GLfloat glX_scale_width; ! 61: static GLfloat glX_scale_height; ! 62: ! 63: static int config_notify=0; ! 64: static int config_notify_width; ! 65: static int config_notify_height; ! 66: ! 67: int d_con_indirect = 0; ! 68: ! 69: void Scaled_f(void) ! 70: { ! 71: config_notify = 1; ! 72: glX_scaled = 1; ! 73: } ! 74: ! 75: void UnScaled_f(void) ! 76: { ! 77: config_notify = 1; ! 78: glX_scaled = 0; ! 79: } ! 80: ! 81: // ======================================================================== ! 82: // Tragic death handler ! 83: // ======================================================================== ! 84: ! 85: void TragicDeath(int signal_num) ! 86: { ! 87: XAutoRepeatOn(x_disp); ! 88: XCloseDisplay(x_disp); ! 89: I_Error("This death brought to you by the number %d\n", signal_num); ! 90: } ! 91: ! 92: // ======================================================================== ! 93: // makes a null cursor ! 94: // ======================================================================== ! 95: ! 96: static Cursor CreateNullCursor(Display *display, Window root) ! 97: { ! 98: Pixmap cursormask; ! 99: XGCValues xgc; ! 100: GC gc; ! 101: XColor dummycolour; ! 102: Cursor cursor; ! 103: ! 104: cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/); ! 105: xgc.function = GXclear; ! 106: gc = XCreateGC(display, cursormask, GCFunction, &xgc); ! 107: XFillRectangle(display, cursormask, gc, 0, 0, 1, 1); ! 108: dummycolour.pixel = 0; ! 109: dummycolour.red = 0; ! 110: dummycolour.flags = 04; ! 111: cursor = XCreatePixmapCursor(display, cursormask, cursormask, ! 112: &dummycolour,&dummycolour, 0,0); ! 113: XFreePixmap(display,cursormask); ! 114: XFreeGC(display,gc); ! 115: return cursor; ! 116: } ! 117: ! 118: void ResetFrameBuffer(void) ! 119: { ! 120: ! 121: int mem; ! 122: int pwidth; ! 123: ! 124: if (!glX_scaled) ! 125: { ! 126: ! 127: if (framebuffer) ! 128: Z_Free(framebuffer); ! 129: ! 130: pwidth = 4; ! 131: mem = vid.width*4 * vid.height; ! 132: ! 133: framebuffer = Z_Malloc(mem); ! 134: ! 135: vid.rowbytes = 2 * vid.width; ! 136: if (jcspace) Z_Free(jcspace); ! 137: jcspace = Z_Malloc(vid.rowbytes * vid.height); ! 138: vid.buffer = (pixel_t *) jcspace; ! 139: ! 140: glViewport(0, 0, vid.width, vid.height); ! 141: glMatrixMode(GL_PROJECTION); ! 142: glLoadIdentity(); ! 143: gluOrtho2D(0, vid.width, 0, vid.height); ! 144: glMatrixMode(GL_MODELVIEW); ! 145: glLoadIdentity(); ! 146: ! 147: glPixelZoom(1.0, -1.0); ! 148: glRasterPos2i(0, vid.height); ! 149: ! 150: } ! 151: else ! 152: { ! 153: glViewport(0, 0, config_notify_width, config_notify_height); ! 154: glMatrixMode(GL_PROJECTION); ! 155: glLoadIdentity(); ! 156: gluOrtho2D(0, config_notify_width, 0, config_notify_height); ! 157: glMatrixMode(GL_MODELVIEW); ! 158: glLoadIdentity(); ! 159: ! 160: glX_scale_width = (float) config_notify_width / vid.width; ! 161: glX_scale_height = (float) config_notify_height / vid.height; ! 162: glPixelZoom(glX_scale_width, -glX_scale_height); ! 163: ! 164: glRasterPos2i(0, config_notify_height); ! 165: ! 166: } ! 167: ! 168: } ! 169: ! 170: int *lookup24; ! 171: ! 172: void InitLookup24(unsigned char *pal) ! 173: { ! 174: ! 175: int intensity; ! 176: int color; ! 177: int r, g, b; ! 178: ! 179: lookup24 = Z_Malloc(VID_GRADES * 256 * 4); ! 180: ! 181: // intensities go from 0 (bright) to VID_GRADES - 1 (dark) ! 182: ! 183: for (intensity = 0 ; intensity < VID_GRADES ; intensity++) ! 184: { ! 185: for (color = 0 ; color < 256 ; color++) ! 186: { ! 187: r = pal[color*3] * (VID_GRADES - intensity) / VID_GRADES; ! 188: g = pal[color*3+1] * (VID_GRADES - intensity) / VID_GRADES; ! 189: b = pal[color*3+2] * (VID_GRADES - intensity) / VID_GRADES; ! 190: r = (r<<24) + (r<<16) + (r<<8) + r; ! 191: g = (g<<24) + (g<<16) + (g<<8) + g; ! 192: b = (b<<24) + (b<<16) + (b<<8) + b; ! 193: r = r & 0xff000000; ! 194: g = g & 0x00ff0000; ! 195: b = b & 0x0000ff00; ! 196: /* ! 197: r = r & x_visinfo->red_mask; ! 198: g = g & x_visinfo->green_mask; ! 199: b = b & x_visinfo->blue_mask; ! 200: */ ! 201: lookup24[intensity * 256 + color] = r + g + b; ! 202: } ! 203: } ! 204: ! 205: } ! 206: ! 207: void JCSpaceTo24(void) ! 208: { ! 209: ! 210: int rowcount; ! 211: int height; ! 212: short *from; ! 213: int *to; ! 214: ! 215: from = jcspace; ! 216: to = (int*) framebuffer; ! 217: ! 218: for (height = vid.height ; height ; height--) ! 219: { ! 220: for (rowcount = vid.width ; rowcount ; rowcount--) ! 221: { ! 222: *to = lookup24[*from]; ! 223: from++; ! 224: to++; ! 225: } ! 226: } ! 227: ! 228: } ! 229: ! 230: void PickVisual(void) ! 231: { ! 232: ! 233: int attribList1[] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 8, ! 234: GLX_BLUE_SIZE, 8, GLX_GREEN_SIZE, 8, None }; ! 235: int attribList2[] = { GLX_RGBA, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, ! 236: GLX_BLUE_SIZE, 8, None }; ! 237: ! 238: doGLX = glXQueryExtension(x_disp, &glX_errorBase, &glX_eventBase); ! 239: if (!doGLX) I_Error("OpenGL not supported\n"); ! 240: ! 241: x_visinfo = glXChooseVisual(x_disp, x_screen, attribList1); ! 242: if (!x_visinfo) ! 243: x_visinfo = glXChooseVisual(x_disp, x_screen, attribList2); ! 244: else ! 245: printf("double-buffered\n"); ! 246: if (!x_visinfo) ! 247: I_Error("Could not chose an RGB visual. Use X version.\n"); ! 248: else ! 249: printf("single-buffered\n"); ! 250: ! 251: // if (verbose) ! 252: { ! 253: printf("Using visualid %d:\n", (int)(x_visinfo->visualid)); ! 254: printf(" screen %d\n", x_visinfo->screen); ! 255: printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask)); ! 256: printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask)); ! 257: printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask)); ! 258: printf(" colormap_size %d\n", x_visinfo->colormap_size); ! 259: printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb); ! 260: } ! 261: ! 262: x_vis = x_visinfo->visual; ! 263: ! 264: } ! 265: ! 266: void CreateWindow(void) ! 267: { ! 268: ! 269: // setup attributes for main window ! 270: int attribmask = CWEventMask | CWColormap | CWBorderPixel; ! 271: XSetWindowAttributes attribs; ! 272: Colormap tmpcmap; ! 273: ! 274: tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp, ! 275: x_visinfo->screen), x_vis, AllocNone); ! 276: ! 277: attribs.event_mask = StructureNotifyMask | KeyPressMask ! 278: | KeyReleaseMask | ExposureMask; ! 279: attribs.border_pixel = 0; ! 280: attribs.colormap = tmpcmap; ! 281: ! 282: // create the main window ! 283: x_win = XCreateWindow( x_disp, ! 284: XRootWindow(x_disp, x_visinfo->screen), ! 285: 0, 0, // x, y ! 286: vid.width, vid.height, ! 287: 0, // borderwidth ! 288: x_visinfo->depth, ! 289: InputOutput, ! 290: x_vis, ! 291: attribmask, ! 292: &attribs ); ! 293: ! 294: XFreeColormap(x_disp, tmpcmap); ! 295: ! 296: } ! 297: ! 298: // Called at startup to set up translation tables, takes 256 8 bit RGB values ! 299: // the palette data will go away after the call, so it must be copied off if ! 300: // the video driver will need it again ! 301: ! 302: void VID_Init (unsigned char *palette) ! 303: { ! 304: ! 305: int pnum, i; ! 306: int num_visuals; ! 307: ! 308: Cmd_AddCommand("glx_scaled", Scaled_f); ! 309: Cmd_AddCommand("glx_unscaled", UnScaled_f); ! 310: ! 311: vid.width = 320; ! 312: vid.height = 200; ! 313: vid.aspect = 1.0; ! 314: vid.numpages = 1; ! 315: ! 316: srandom(getpid()); ! 317: ! 318: verbose=COM_CheckParm("-verbose"); ! 319: ! 320: // open the display ! 321: x_disp = XOpenDisplay(0); ! 322: if (!x_disp) ! 323: { ! 324: if (getenv("DISPLAY")) ! 325: I_Error("VID: Could not open display [%s]\n", ! 326: getenv("DISPLAY")); ! 327: else ! 328: I_Error("VID: Could not open local display\n"); ! 329: } ! 330: ! 331: x_screen = DefaultScreen(x_disp); ! 332: ! 333: // catch signals so i can turn on auto-repeat ! 334: ! 335: { ! 336: struct sigaction sa; ! 337: sigaction(SIGINT, 0, &sa); ! 338: sa.sa_handler = TragicDeath; ! 339: sigaction(SIGINT, &sa, 0); ! 340: sigaction(SIGTERM, &sa, 0); ! 341: } ! 342: ! 343: XAutoRepeatOff(x_disp); ! 344: ! 345: // for debugging only ! 346: XSynchronize(x_disp, True); ! 347: ! 348: // check for command-line window size ! 349: if ((pnum=COM_CheckParm("-winsize"))) ! 350: { ! 351: if (pnum >= com_argc-2) ! 352: I_Error("VID: -winsize <width> <height>\n"); ! 353: vid.width = Q_atoi(com_argv[pnum+1]); ! 354: vid.height = Q_atoi(com_argv[pnum+2]); ! 355: if (!vid.width || !vid.height) ! 356: I_Error("VID: Bad window width/height\n"); ! 357: } ! 358: ! 359: PickVisual(); ! 360: ! 361: CreateWindow(); ! 362: ! 363: glX_context = glXCreateContext(x_disp, x_visinfo, 0, True); ! 364: glXMakeCurrent(x_disp, x_win, glX_context); ! 365: glPixelZoom(1.0, -1.0); ! 366: ! 367: // create the GC ! 368: { ! 369: XGCValues xgcvalues; ! 370: int valuemask = GCGraphicsExposures; ! 371: xgcvalues.graphics_exposures = False; ! 372: x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues ); ! 373: } ! 374: ! 375: InitLookup24(palette); ! 376: ! 377: // inviso cursor ! 378: XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win)); ! 379: ! 380: // map the window ! 381: XMapWindow(x_disp, x_win); ! 382: ! 383: // wait for first exposure event ! 384: { ! 385: XEvent event; ! 386: do ! 387: { ! 388: XNextEvent(x_disp, &event); ! 389: if (event.type == Expose && !event.xexpose.count) ! 390: oktodraw = true; ! 391: } while (!oktodraw); ! 392: } ! 393: // now safe to draw ! 394: ! 395: ResetFrameBuffer(); ! 396: ! 397: XSynchronize(x_disp, False); ! 398: ! 399: } ! 400: ! 401: void VID_SetPalette(unsigned char *palette) ! 402: { ! 403: ! 404: if (lookup24) ! 405: Z_Free(lookup24); ! 406: InitLookup24(palette); ! 407: ! 408: } ! 409: ! 410: // Called at shutdown ! 411: ! 412: void VID_Shutdown (void) ! 413: { ! 414: I_Printf("VID_Shutdown\n"); ! 415: XAutoRepeatOn(x_disp); ! 416: XCloseDisplay(x_disp); ! 417: } ! 418: ! 419: int XLateKey(XKeyEvent *ev) ! 420: { ! 421: ! 422: int key; ! 423: char buf[64]; ! 424: KeySym keysym; ! 425: ! 426: XLookupString(ev, buf, sizeof buf, &keysym, 0); ! 427: ! 428: switch(keysym) ! 429: { ! 430: case XK_Left: key = K_LEFTARROW; break; ! 431: case XK_Right: key = K_RIGHTARROW; break; ! 432: case XK_Down: key = K_DOWNARROW; break; ! 433: case XK_Up: key = K_UPARROW; break; ! 434: case XK_Escape: key = K_ESCAPE; break; ! 435: case XK_Return: key = K_ENTER; break; ! 436: case XK_Tab: key = K_TAB; break; ! 437: case XK_F1: key = K_F1; break; ! 438: case XK_F2: key = K_F2; break; ! 439: case XK_F3: key = K_F3; break; ! 440: case XK_F4: key = K_F4; break; ! 441: case XK_F5: key = K_F5; break; ! 442: case XK_F6: key = K_F6; break; ! 443: case XK_F7: key = K_F7; break; ! 444: case XK_F8: key = K_F8; break; ! 445: case XK_F9: key = K_F9; break; ! 446: case XK_F10: key = K_F10; break; ! 447: case XK_F11: key = K_F11; break; ! 448: case XK_F12: key = K_F12; break; ! 449: case XK_BackSpace: ! 450: case XK_Delete: key = K_BACKSPACE; break; ! 451: case XK_Pause: key = K_PAUSE; break; ! 452: case XK_Shift_L: ! 453: case XK_Shift_R: key = K_SHIFT; break; ! 454: case XK_Control_L: ! 455: case XK_Control_R: key = K_CTRL; break; ! 456: case XK_Alt_L: ! 457: case XK_Meta_L: ! 458: case XK_Alt_R: ! 459: case XK_Meta_R: key = K_ALT; break; ! 460: default: ! 461: key = *buf; ! 462: break; ! 463: } ! 464: ! 465: return key; ! 466: ! 467: } ! 468: ! 469: void GetEvent(void) ! 470: { ! 471: ! 472: XEvent x_event; ! 473: ! 474: XNextEvent(x_disp, &x_event); ! 475: switch(x_event.type) ! 476: { ! 477: case KeyPress: ! 478: Key_Event(XLateKey(&x_event.xkey), true); ! 479: break; ! 480: case KeyRelease: ! 481: Key_Event(XLateKey(&x_event.xkey), false); ! 482: break; ! 483: case ConfigureNotify: ! 484: // printf("config notify\n"); ! 485: config_notify_width = x_event.xconfigure.width; ! 486: config_notify_height = x_event.xconfigure.height; ! 487: config_notify = 1; ! 488: break; ! 489: } ! 490: ! 491: } ! 492: ! 493: // flushes the given rectangles from the view buffer to the screen ! 494: ! 495: void VID_Update (vrect_t *rects) ! 496: { ! 497: ! 498: // if the window changes dimension, skip this frame ! 499: ! 500: if (config_notify) ! 501: { ! 502: printf("config notify\n"); ! 503: config_notify = 0; ! 504: if (!glX_scaled) ! 505: { ! 506: vid.width = config_notify_width & ~3; ! 507: vid.height = config_notify_height; ! 508: } ! 509: ResetFrameBuffer(); ! 510: return; ! 511: } ! 512: ! 513: // slam that baby ! 514: ! 515: JCSpaceTo24(); ! 516: glDrawPixels(vid.width, vid.height, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer); ! 517: glFlush(); ! 518: glXSwapBuffers(x_disp, x_win); ! 519: ! 520: } ! 521: ! 522: static int dither; ! 523: ! 524: void VID_DitherOn(void) ! 525: { ! 526: if (dither == 0) ! 527: { ! 528: vid.recalc_refdef = 1; ! 529: dither = 1; ! 530: } ! 531: } ! 532: ! 533: void VID_DitherOff(void) ! 534: { ! 535: if (dither) ! 536: { ! 537: vid.recalc_refdef = 1; ! 538: dither = 0; ! 539: } ! 540: } ! 541: ! 542: int I_OpenWindow(void) ! 543: { ! 544: return 0; ! 545: } ! 546: ! 547: void I_EraseWindow(int window) ! 548: { ! 549: } ! 550: ! 551: void I_DrawCircle(int window, int x, int y, int r) ! 552: { ! 553: } ! 554: ! 555: void I_DisplayWindow(int window) ! 556: { ! 557: } ! 558: ! 559: void Sys_SendKeyEvents(void) ! 560: { ! 561: // get events from x server ! 562: while (XPending(x_disp)) GetEvent(); ! 563: } ! 564: ! 565: char *Sys_ConsoleInput (void) ! 566: { ! 567: ! 568: static char text[256]; ! 569: int len; ! 570: fd_set readfds; ! 571: int ready; ! 572: struct timeval timeout; ! 573: ! 574: timeout.tv_sec = 0; ! 575: timeout.tv_usec = 0; ! 576: FD_ZERO(&readfds); ! 577: FD_SET(0, &readfds); ! 578: ready = select(1, &readfds, 0, 0, &timeout); ! 579: ! 580: if (ready>0) ! 581: { ! 582: len = read (0, text, sizeof(text)); ! 583: if (len >= 1) ! 584: { ! 585: text[len-1] = 0; // rip off the /n and terminate ! 586: return text; ! 587: } ! 588: } ! 589: ! 590: return 0; ! 591: ! 592: } ! 593:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.