Annotation of quake2/linux/rw_x11.c, revision 1.1.1.1

1.1       root        1: /*
                      2: ** RW_X11.C
                      3: **
                      4: ** This file contains ALL Linux specific stuff having to do with the
                      5: ** software refresh.  When a port is being made the following functions
                      6: ** must be implemented by the port:
                      7: **
                      8: ** SWimp_EndFrame
                      9: ** SWimp_Init
                     10: ** SWimp_InitGraphics
                     11: ** SWimp_SetPalette
                     12: ** SWimp_Shutdown
                     13: ** SWimp_SwitchFullscreen
                     14: */
                     15: 
                     16: #include <ctype.h>
                     17: #include <sys/time.h>
                     18: #include <sys/types.h>
                     19: #include <unistd.h>
                     20: #include <signal.h>
                     21: #include <stdlib.h>
                     22: #include <stdio.h>
                     23: #include <string.h>
                     24: #include <sys/ipc.h>
                     25: #include <sys/shm.h>
                     26: 
                     27: #include <X11/Xlib.h>
                     28: #include <X11/Xutil.h>
                     29: #include <X11/Xatom.h>
                     30: #include <X11/keysym.h>
                     31: #include <X11/extensions/XShm.h>
                     32: 
                     33: #include "../ref_soft/r_local.h"
                     34: #include "../client/keys.h"
                     35: #include "../linux/rw_linux.h"
                     36: 
                     37: /*****************************************************************************/
                     38: 
                     39: static qboolean                        doShm;
                     40: static Display                 *x_disp;
                     41: static Colormap                        x_cmap;
                     42: static Window                  x_win;
                     43: static GC                              x_gc;
                     44: static Visual                  *x_vis;
                     45: static XVisualInfo             *x_visinfo;
                     46: //static XImage                        *x_image;
                     47: 
                     48: #define STD_EVENT_MASK (StructureNotifyMask | KeyPressMask \
                     49:             | KeyReleaseMask | ExposureMask | PointerMotionMask | \
                     50:             ButtonPressMask | ButtonReleaseMask)
                     51: 
                     52: static int                             x_shmeventtype;
                     53: //static XShmSegmentInfo       x_shminfo;
                     54: 
                     55: static qboolean                        oktodraw = false;
                     56: static qboolean                        X11_active = false;
                     57: 
                     58: int XShmQueryExtension(Display *);
                     59: int XShmGetEventBase(Display *);
                     60: 
                     61: int current_framebuffer;
                     62: static XImage                  *x_framebuffer[2] = { 0, 0 };
                     63: static XShmSegmentInfo x_shminfo[2];
                     64: 
                     65: struct
                     66: {
                     67:        int key;
                     68:        int down;
                     69: } keyq[64];
                     70: int keyq_head=0;
                     71: int keyq_tail=0;
                     72: 
                     73: int config_notify=0;
                     74: int config_notify_width;
                     75: int config_notify_height;
                     76:                                                      
                     77: typedef unsigned short PIXEL;
                     78: 
                     79: // Console variables that we need to access from this module
                     80: 
                     81: /*****************************************************************************/
                     82: /* MOUSE                                                                     */
                     83: /*****************************************************************************/
                     84: 
                     85: // this is inside the renderer shared lib, so these are called from vid_so
                     86: 
                     87: static qboolean        mouse_avail;
                     88: static int     mouse_buttonstate;
                     89: static int     mouse_oldbuttonstate;
                     90: static int   mouse_x, mouse_y;
                     91: static int     old_mouse_x, old_mouse_y;
                     92: static int             mx, my;
                     93: static float old_windowed_mouse;
                     94: static int p_mouse_x, p_mouse_y;
                     95: 
                     96: static cvar_t  *_windowed_mouse;
                     97: static cvar_t  *m_filter;
                     98: static cvar_t  *in_mouse;
                     99: 
                    100: static qboolean        mlooking;
                    101: 
                    102: // state struct passed in Init
                    103: static in_state_t      *in_state;
                    104: 
                    105: static cvar_t *sensitivity;
                    106: static cvar_t *lookstrafe;
                    107: static cvar_t *m_side;
                    108: static cvar_t *m_yaw;
                    109: static cvar_t *m_pitch;
                    110: static cvar_t *m_forward;
                    111: static cvar_t *freelook;
                    112: 
                    113: static void Force_CenterView_f (void)
                    114: {
                    115:        in_state->viewangles[PITCH] = 0;
                    116: }
                    117: 
                    118: static void RW_IN_MLookDown (void) 
                    119: { 
                    120:        mlooking = true; 
                    121: }
                    122: 
                    123: static void RW_IN_MLookUp (void) 
                    124: {
                    125:        mlooking = false;
                    126:        in_state->IN_CenterView_fp ();
                    127: }
                    128: 
                    129: void RW_IN_Init(in_state_t *in_state_p)
                    130: {
                    131:        int mtype;
                    132:        int i;
                    133: 
                    134:        in_state = in_state_p;
                    135: 
                    136:        // mouse variables
                    137:        _windowed_mouse = ri.Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE);
                    138:        m_filter = ri.Cvar_Get ("m_filter", "0", 0);
                    139:     in_mouse = ri.Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE);
                    140:        freelook = ri.Cvar_Get( "freelook", "0", 0 );
                    141:        lookstrafe = ri.Cvar_Get ("lookstrafe", "0", 0);
                    142:        sensitivity = ri.Cvar_Get ("sensitivity", "3", 0);
                    143:        m_pitch = ri.Cvar_Get ("m_pitch", "0.022", 0);
                    144:        m_yaw = ri.Cvar_Get ("m_yaw", "0.022", 0);
                    145:        m_forward = ri.Cvar_Get ("m_forward", "1", 0);
                    146:        m_side = ri.Cvar_Get ("m_side", "0.8", 0);
                    147: 
                    148:        ri.Cmd_AddCommand ("+mlook", RW_IN_MLookDown);
                    149:        ri.Cmd_AddCommand ("-mlook", RW_IN_MLookUp);
                    150: 
                    151:        ri.Cmd_AddCommand ("force_centerview", Force_CenterView_f);
                    152: 
                    153:        mouse_x = mouse_y = 0.0;
                    154:        mouse_avail = true;
                    155: }
                    156: 
                    157: void RW_IN_Shutdown(void)
                    158: {
                    159:        mouse_avail = false;
                    160: }
                    161: 
                    162: /*
                    163: ===========
                    164: IN_Commands
                    165: ===========
                    166: */
                    167: void RW_IN_Commands (void)
                    168: {
                    169:        int i;
                    170:    
                    171:        if (!mouse_avail) 
                    172:                return;
                    173:    
                    174:        for (i=0 ; i<3 ; i++) {
                    175:                if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
                    176:                        in_state->Key_Event_fp (K_MOUSE1 + i, true);
                    177: 
                    178:                if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
                    179:                        in_state->Key_Event_fp (K_MOUSE1 + i, false);
                    180:        }
                    181:        mouse_oldbuttonstate = mouse_buttonstate;
                    182: }
                    183: 
                    184: /*
                    185: ===========
                    186: IN_Move
                    187: ===========
                    188: */
                    189: void RW_IN_Move (usercmd_t *cmd)
                    190: {
                    191:        if (!mouse_avail)
                    192:                return;
                    193:    
                    194:        if (m_filter->value)
                    195:        {
                    196:                mouse_x = (mx + old_mouse_x) * 0.5;
                    197:                mouse_y = (my + old_mouse_y) * 0.5;
                    198:        } else {
                    199:                mouse_x = mx;
                    200:                mouse_y = my;
                    201:        }
                    202: 
                    203:        old_mouse_x = mx;
                    204:        old_mouse_y = my;
                    205: 
                    206:        if (!mouse_x && !mouse_y)
                    207:                return;
                    208: 
                    209:        mouse_x *= sensitivity->value;
                    210:        mouse_y *= sensitivity->value;
                    211: 
                    212: // add mouse X/Y movement to cmd
                    213:        if ( (*in_state->in_strafe_state & 1) || 
                    214:                (lookstrafe->value && mlooking ))
                    215:                cmd->sidemove += m_side->value * mouse_x;
                    216:        else
                    217:                in_state->viewangles[YAW] -= m_yaw->value * mouse_x;
                    218: 
                    219:        if ( (mlooking || freelook->value) && 
                    220:                !(*in_state->in_strafe_state & 1))
                    221:        {
                    222:                in_state->viewangles[PITCH] += m_pitch->value * mouse_y;
                    223:        }
                    224:        else
                    225:        {
                    226:                cmd->forwardmove -= m_forward->value * mouse_y;
                    227:        }
                    228:        mx = my = 0;
                    229: }
                    230: 
                    231: void RW_IN_Frame (void)
                    232: {
                    233: }
                    234: 
                    235: void RW_IN_Activate(void)
                    236: {
                    237: }
                    238: 
                    239: /*****************************************************************************/
                    240: 
                    241: static PIXEL st2d_8to16table[256];
                    242: static int shiftmask_fl=0;
                    243: static long r_shift,g_shift,b_shift;
                    244: static unsigned long r_mask,g_mask,b_mask;
                    245: 
                    246: void shiftmask_init()
                    247: {
                    248:     unsigned int x;
                    249:     r_mask=x_vis->red_mask;
                    250:     g_mask=x_vis->green_mask;
                    251:     b_mask=x_vis->blue_mask;
                    252:     for(r_shift=-8,x=1;x<r_mask;x=x<<1)r_shift++;
                    253:     for(g_shift=-8,x=1;x<g_mask;x=x<<1)g_shift++;
                    254:     for(b_shift=-8,x=1;x<b_mask;x=x<<1)b_shift++;
                    255:     shiftmask_fl=1;
                    256: }
                    257: 
                    258: PIXEL xlib_rgb(int r,int g,int b)
                    259: {
                    260:     PIXEL p;
                    261:     if(shiftmask_fl==0) shiftmask_init();
                    262:     p=0;
                    263: 
                    264:     if(r_shift>0) {
                    265:         p=(r<<(r_shift))&r_mask;
                    266:     } else if(r_shift<0) {
                    267:         p=(r>>(-r_shift))&r_mask;
                    268:     } else p|=(r&r_mask);
                    269: 
                    270:     if(g_shift>0) {
                    271:         p|=(g<<(g_shift))&g_mask;
                    272:     } else if(g_shift<0) {
                    273:         p|=(g>>(-g_shift))&g_mask;
                    274:     } else p|=(g&g_mask);
                    275: 
                    276:     if(b_shift>0) {
                    277:         p|=(b<<(b_shift))&b_mask;
                    278:     } else if(b_shift<0) {
                    279:         p|=(b>>(-b_shift))&b_mask;
                    280:     } else p|=(b&b_mask);
                    281: 
                    282:     return p;
                    283: }
                    284: 
                    285: void st2_fixup( XImage *framebuf, int x, int y, int width, int height)
                    286: {
                    287:        int xi,yi;
                    288:        unsigned char *src;
                    289:        PIXEL *dest;
                    290: 
                    291:        if( (x<0)||(y<0) )return;
                    292: 
                    293:        for (yi = y; yi < (y+height); yi++) {
                    294:                src = &framebuf->data [yi * framebuf->bytes_per_line];
                    295:                dest = (PIXEL*)src;
                    296:                for(xi = (x+width-1); xi >= x; xi -= 8) {
                    297:                        dest[xi  ] = st2d_8to16table[src[xi  ]];
                    298:                        dest[xi-1] = st2d_8to16table[src[xi-1]];
                    299:                        dest[xi-2] = st2d_8to16table[src[xi-2]];
                    300:                        dest[xi-3] = st2d_8to16table[src[xi-3]];
                    301:                        dest[xi-4] = st2d_8to16table[src[xi-4]];
                    302:                        dest[xi-5] = st2d_8to16table[src[xi-5]];
                    303:                        dest[xi-6] = st2d_8to16table[src[xi-6]];
                    304:                        dest[xi-7] = st2d_8to16table[src[xi-7]];
                    305:                }
                    306:        }
                    307: }
                    308: 
                    309: // ========================================================================
                    310: // makes a null cursor
                    311: // ========================================================================
                    312: 
                    313: static Cursor CreateNullCursor(Display *display, Window root)
                    314: {
                    315:     Pixmap cursormask; 
                    316:     XGCValues xgc;
                    317:     GC gc;
                    318:     XColor dummycolour;
                    319:     Cursor cursor;
                    320: 
                    321:     cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
                    322:     xgc.function = GXclear;
                    323:     gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
                    324:     XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
                    325:     dummycolour.pixel = 0;
                    326:     dummycolour.red = 0;
                    327:     dummycolour.flags = 04;
                    328:     cursor = XCreatePixmapCursor(display, cursormask, cursormask,
                    329:           &dummycolour,&dummycolour, 0,0);
                    330:     XFreePixmap(display,cursormask);
                    331:     XFreeGC(display,gc);
                    332:     return cursor;
                    333: }
                    334: 
                    335: void ResetFrameBuffer(void)
                    336: {
                    337:        int mem;
                    338:        int pwidth;
                    339: 
                    340:        if (x_framebuffer[0])
                    341:        {
                    342:                free(x_framebuffer[0]->data);
                    343:                free(x_framebuffer[0]);
                    344:        }
                    345: 
                    346: // alloc an extra line in case we want to wrap, and allocate the z-buffer
                    347:        pwidth = x_visinfo->depth / 8;
                    348:        if (pwidth == 3) pwidth = 4;
                    349:        mem = ((vid.width*pwidth+7)&~7) * vid.height;
                    350: 
                    351:        x_framebuffer[0] = XCreateImage(        x_disp,
                    352:                x_vis,
                    353:                x_visinfo->depth,
                    354:                ZPixmap,
                    355:                0,
                    356:                malloc(mem),
                    357:                vid.width, vid.height,
                    358:                32,
                    359:                0);
                    360: 
                    361:        if (!x_framebuffer[0])
                    362:                Sys_Error("VID: XCreateImage failed\n");
                    363: 
                    364:        vid.buffer = (byte*) (x_framebuffer[0]);
                    365: }
                    366: 
                    367: void ResetSharedFrameBuffers(void)
                    368: {
                    369:        int size;
                    370:        int key;
                    371:        int minsize = getpagesize();
                    372:        int frm;
                    373: 
                    374:        for (frm=0 ; frm<2 ; frm++)
                    375:        {
                    376:        // free up old frame buffer memory
                    377:                if (x_framebuffer[frm])
                    378:                {
                    379:                        XShmDetach(x_disp, &x_shminfo[frm]);
                    380:                        free(x_framebuffer[frm]);
                    381:                        shmdt(x_shminfo[frm].shmaddr);
                    382:                }
                    383: 
                    384:        // create the image
                    385:                x_framebuffer[frm] = XShmCreateImage(   x_disp,
                    386:                                                x_vis,
                    387:                                                x_visinfo->depth,
                    388:                                                ZPixmap,
                    389:                                                0,
                    390:                                                &x_shminfo[frm],
                    391:                                                vid.width,
                    392:                                                vid.height );
                    393: 
                    394:        // grab shared memory
                    395: 
                    396:                size = x_framebuffer[frm]->bytes_per_line
                    397:                        * x_framebuffer[frm]->height;
                    398:                if (size < minsize)
                    399:                        Sys_Error("VID: Window must use at least %d bytes\n", minsize);
                    400: 
                    401:                key = random();
                    402:                x_shminfo[frm].shmid = shmget((key_t)key, size, IPC_CREAT|0777);
                    403:                if (x_shminfo[frm].shmid==-1)
                    404:                        Sys_Error("VID: Could not get any shared memory\n");
                    405: 
                    406:                // attach to the shared memory segment
                    407:                x_shminfo[frm].shmaddr =
                    408:                        (void *) shmat(x_shminfo[frm].shmid, 0, 0);
                    409: 
                    410:                ri.Con_Printf(PRINT_ALL, 
                    411:                        "MITSHM shared memory (id=%d, addr=0x%lx)\n", 
                    412:                        x_shminfo[frm].shmid,
                    413:                        (long) x_shminfo[frm].shmaddr);
                    414: 
                    415:                x_framebuffer[frm]->data = x_shminfo[frm].shmaddr;
                    416: 
                    417:        // get the X server to attach to it
                    418: 
                    419:                if (!XShmAttach(x_disp, &x_shminfo[frm]))
                    420:                        Sys_Error("VID: XShmAttach() failed\n");
                    421:                XSync(x_disp, 0);
                    422:                shmctl(x_shminfo[frm].shmid, IPC_RMID, 0);
                    423:        }
                    424: 
                    425: }
                    426: 
                    427: // ========================================================================
                    428: // Tragic death handler
                    429: // ========================================================================
                    430: 
                    431: void TragicDeath(int signal_num)
                    432: {
                    433:        XAutoRepeatOn(x_disp);
                    434:        XCloseDisplay(x_disp);
                    435:        Sys_Error("This death brought to you by the number %d\n", signal_num);
                    436: }
                    437: 
                    438: int XLateKey(XKeyEvent *ev)
                    439: {
                    440: 
                    441:        int key;
                    442:        char buf[64];
                    443:        KeySym keysym;
                    444: 
                    445:        key = 0;
                    446: 
                    447:        XLookupString(ev, buf, sizeof buf, &keysym, 0);
                    448: 
                    449:        switch(keysym)
                    450:        {
                    451:                case XK_KP_Page_Up:      key = K_KP_PGUP; break;
                    452:                case XK_Page_Up:         key = K_PGUP; break;
                    453: 
                    454:                case XK_KP_Page_Down: key = K_KP_PGDN; break;
                    455:                case XK_Page_Down:       key = K_PGDN; break;
                    456: 
                    457:                case XK_KP_Home: key = K_KP_HOME; break;
                    458:                case XK_Home:    key = K_HOME; break;
                    459: 
                    460:                case XK_KP_End:  key = K_KP_END; break;
                    461:                case XK_End:     key = K_END; break;
                    462: 
                    463:                case XK_KP_Left: key = K_KP_LEFTARROW; break;
                    464:                case XK_Left:    key = K_LEFTARROW; break;
                    465: 
                    466:                case XK_KP_Right: key = K_KP_RIGHTARROW; break;
                    467:                case XK_Right:  key = K_RIGHTARROW;             break;
                    468: 
                    469:                case XK_KP_Down: key = K_KP_DOWNARROW; break;
                    470:                case XK_Down:    key = K_DOWNARROW; break;
                    471: 
                    472:                case XK_KP_Up:   key = K_KP_UPARROW; break;
                    473:                case XK_Up:              key = K_UPARROW;        break;
                    474: 
                    475:                case XK_Escape: key = K_ESCAPE;         break;
                    476: 
                    477:                case XK_KP_Enter: key = K_KP_ENTER;     break;
                    478:                case XK_Return: key = K_ENTER;           break;
                    479: 
                    480:                case XK_Tab:            key = K_TAB;                     break;
                    481: 
                    482:                case XK_F1:              key = K_F1;                            break;
                    483: 
                    484:                case XK_F2:              key = K_F2;                            break;
                    485: 
                    486:                case XK_F3:              key = K_F3;                            break;
                    487: 
                    488:                case XK_F4:              key = K_F4;                            break;
                    489: 
                    490:                case XK_F5:              key = K_F5;                            break;
                    491: 
                    492:                case XK_F6:              key = K_F6;                            break;
                    493: 
                    494:                case XK_F7:              key = K_F7;                            break;
                    495: 
                    496:                case XK_F8:              key = K_F8;                            break;
                    497: 
                    498:                case XK_F9:              key = K_F9;                            break;
                    499: 
                    500:                case XK_F10:            key = K_F10;                     break;
                    501: 
                    502:                case XK_F11:            key = K_F11;                     break;
                    503: 
                    504:                case XK_F12:            key = K_F12;                     break;
                    505: 
                    506:                case XK_BackSpace: key = K_BACKSPACE; break;
                    507: 
                    508:                case XK_KP_Delete: key = K_KP_DEL; break;
                    509:                case XK_Delete: key = K_DEL; break;
                    510: 
                    511:                case XK_Pause:  key = K_PAUSE;           break;
                    512: 
                    513:                case XK_Shift_L:
                    514:                case XK_Shift_R:        key = K_SHIFT;          break;
                    515: 
                    516:                case XK_Execute: 
                    517:                case XK_Control_L: 
                    518:                case XK_Control_R:      key = K_CTRL;            break;
                    519: 
                    520:                case XK_Alt_L:  
                    521:                case XK_Meta_L: 
                    522:                case XK_Alt_R:  
                    523:                case XK_Meta_R: key = K_ALT;                    break;
                    524: 
                    525:                case XK_KP_Begin: key = K_KP_5; break;
                    526: 
                    527:                case XK_Insert:key = K_INS; break;
                    528:                case XK_KP_Insert: key = K_KP_INS; break;
                    529: 
                    530:                case XK_KP_Multiply: key = '*'; break;
                    531:                case XK_KP_Add:  key = K_KP_PLUS; break;
                    532:                case XK_KP_Subtract: key = K_KP_MINUS; break;
                    533:                case XK_KP_Divide: key = K_KP_SLASH; break;
                    534: 
                    535: #if 0
                    536:                case 0x021: key = '1';break;/* [!] */
                    537:                case 0x040: key = '2';break;/* [@] */
                    538:                case 0x023: key = '3';break;/* [#] */
                    539:                case 0x024: key = '4';break;/* [$] */
                    540:                case 0x025: key = '5';break;/* [%] */
                    541:                case 0x05e: key = '6';break;/* [^] */
                    542:                case 0x026: key = '7';break;/* [&] */
                    543:                case 0x02a: key = '8';break;/* [*] */
                    544:                case 0x028: key = '9';;break;/* [(] */
                    545:                case 0x029: key = '0';break;/* [)] */
                    546:                case 0x05f: key = '-';break;/* [_] */
                    547:                case 0x02b: key = '=';break;/* [+] */
                    548:                case 0x07c: key = '\'';break;/* [|] */
                    549:                case 0x07d: key = '[';break;/* [}] */
                    550:                case 0x07b: key = ']';break;/* [{] */
                    551:                case 0x022: key = '\'';break;/* ["] */
                    552:                case 0x03a: key = ';';break;/* [:] */
                    553:                case 0x03f: key = '/';break;/* [?] */
                    554:                case 0x03e: key = '.';break;/* [>] */
                    555:                case 0x03c: key = ',';break;/* [<] */
                    556: #endif
                    557: 
                    558:                default:
                    559:                        key = *(unsigned char*)buf;
                    560:                        if (key >= 'A' && key <= 'Z')
                    561:                                key = key - 'A' + 'a';
                    562:                        break;
                    563:        } 
                    564: 
                    565:        return key;
                    566: }
                    567: 
                    568: void GetEvent(void)
                    569: {
                    570:        XEvent x_event;
                    571:        int b;
                    572:    
                    573:        XNextEvent(x_disp, &x_event);
                    574:        switch(x_event.type) {
                    575:        case KeyPress:
                    576:                keyq[keyq_head].key = XLateKey(&x_event.xkey);
                    577:                keyq[keyq_head].down = true;
                    578:                keyq_head = (keyq_head + 1) & 63;
                    579:                break;
                    580:        case KeyRelease:
                    581:                keyq[keyq_head].key = XLateKey(&x_event.xkey);
                    582:                keyq[keyq_head].down = false;
                    583:                keyq_head = (keyq_head + 1) & 63;
                    584:                break;
                    585: 
                    586:        case MotionNotify:
                    587:                if (_windowed_mouse->value) {
                    588:                        mx += ((int)x_event.xmotion.x - (int)(vid.width/2));
                    589:                        my += ((int)x_event.xmotion.y - (int)(vid.height/2));
                    590: 
                    591:                        /* move the mouse to the window center again */
                    592:                        XSelectInput(x_disp,x_win, STD_EVENT_MASK & ~PointerMotionMask);
                    593:                        XWarpPointer(x_disp,None,x_win,0,0,0,0, 
                    594:                                (vid.width/2),(vid.height/2));
                    595:                        XSelectInput(x_disp,x_win, STD_EVENT_MASK);
                    596:                } else {
                    597:                        mx = ((int)x_event.xmotion.x - (int)p_mouse_x);
                    598:                        my = ((int)x_event.xmotion.y - (int)p_mouse_y);
                    599:                        p_mouse_x=x_event.xmotion.x;
                    600:                        p_mouse_y=x_event.xmotion.y;
                    601:                }
                    602:                break;
                    603: 
                    604:        case ButtonPress:
                    605:                b=-1;
                    606:                if (x_event.xbutton.button == 1)
                    607:                        b = 0;
                    608:                else if (x_event.xbutton.button == 2)
                    609:                        b = 2;
                    610:                else if (x_event.xbutton.button == 3)
                    611:                        b = 1;
                    612:                if (b>=0)
                    613:                        mouse_buttonstate |= 1<<b;
                    614:                break;
                    615: 
                    616:        case ButtonRelease:
                    617:                b=-1;
                    618:                if (x_event.xbutton.button == 1)
                    619:                        b = 0;
                    620:                else if (x_event.xbutton.button == 2)
                    621:                        b = 2;
                    622:                else if (x_event.xbutton.button == 3)
                    623:                        b = 1;
                    624:                if (b>=0)
                    625:                        mouse_buttonstate &= ~(1<<b);
                    626:                break;
                    627:        
                    628:        case ConfigureNotify:
                    629:                config_notify_width = x_event.xconfigure.width;
                    630:                config_notify_height = x_event.xconfigure.height;
                    631:                config_notify = 1;
                    632:                break;
                    633: 
                    634:        default:
                    635:                if (doShm && x_event.type == x_shmeventtype)
                    636:                        oktodraw = true;
                    637:        }
                    638:    
                    639:        if (old_windowed_mouse != _windowed_mouse->value) {
                    640:                old_windowed_mouse = _windowed_mouse->value;
                    641: 
                    642:                if (!_windowed_mouse->value) {
                    643:                        /* ungrab the pointer */
                    644:                        XUngrabPointer(x_disp,CurrentTime);
                    645:                } else {
                    646:                        /* grab the pointer */
                    647:                        XGrabPointer(x_disp,x_win,True,0,GrabModeAsync,
                    648:                                GrabModeAsync,x_win,None,CurrentTime);
                    649:                }
                    650:        }
                    651: }
                    652: 
                    653: /*****************************************************************************/
                    654: 
                    655: /*
                    656: ** SWimp_Init
                    657: **
                    658: ** This routine is responsible for initializing the implementation
                    659: ** specific stuff in a software rendering subsystem.
                    660: */
                    661: int SWimp_Init( void *hInstance, void *wndProc )
                    662: {
                    663: // open the display
                    664:        x_disp = XOpenDisplay(0);
                    665:        if (!x_disp)
                    666:        {
                    667:                if (getenv("DISPLAY"))
                    668:                        Sys_Error("VID: Could not open display [%s]\n",
                    669:                                getenv("DISPLAY"));
                    670:                else
                    671:                        Sys_Error("VID: Could not open local display\n");
                    672:        }
                    673: 
                    674: // catch signals so i can turn on auto-repeat
                    675: 
                    676:        {
                    677:                struct sigaction sa;
                    678:                sigaction(SIGINT, 0, &sa);
                    679:                sa.sa_handler = TragicDeath;
                    680:                sigaction(SIGINT, &sa, 0);
                    681:                sigaction(SIGTERM, &sa, 0);
                    682:        }
                    683: 
                    684:        return true;
                    685: }
                    686: 
                    687: /*
                    688: ** SWimp_InitGraphics
                    689: **
                    690: ** This initializes the software refresh's implementation specific
                    691: ** graphics subsystem.  In the case of Windows it creates DIB or
                    692: ** DDRAW surfaces.
                    693: **
                    694: ** The necessary width and height parameters are grabbed from
                    695: ** vid.width and vid.height.
                    696: */
                    697: static qboolean SWimp_InitGraphics( qboolean fullscreen )
                    698: {
                    699:        int pnum, i;
                    700:        XVisualInfo template;
                    701:        int num_visuals;
                    702:        int template_mask;
                    703: 
                    704:        srandom(getpid());
                    705: 
                    706:        // free resources in use
                    707:        SWimp_Shutdown ();
                    708: 
                    709:        // let the sound and input subsystems know about the new window
                    710:        ri.Vid_NewWindow (vid.width, vid.height);
                    711: 
                    712:        XAutoRepeatOff(x_disp);
                    713: 
                    714: // for debugging only
                    715:        XSynchronize(x_disp, True);
                    716: 
                    717: // check for command-line window size
                    718:        template_mask = 0;
                    719: 
                    720: #if 0
                    721: // specify a visual id
                    722:        if ((pnum=COM_CheckParm("-visualid")))
                    723:        {
                    724:                if (pnum >= com_argc-1)
                    725:                        Sys_Error("VID: -visualid <id#>\n");
                    726:                template.visualid = Q_atoi(com_argv[pnum+1]);
                    727:                template_mask = VisualIDMask;
                    728:        }
                    729: 
                    730: // If not specified, use default visual
                    731:        else
                    732: #endif
                    733:        {
                    734:                int screen;
                    735:                screen = XDefaultScreen(x_disp);
                    736:                template.visualid =
                    737:                        XVisualIDFromVisual(XDefaultVisual(x_disp, screen));
                    738:                template_mask = VisualIDMask;
                    739:        }
                    740: 
                    741: // pick a visual- warn if more than one was available
                    742:        x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals);
                    743:        if (num_visuals > 1)
                    744:        {
                    745:                printf("Found more than one visual id at depth %d:\n", template.depth);
                    746:                for (i=0 ; i<num_visuals ; i++)
                    747:                        printf("        -visualid %d\n", (int)(x_visinfo[i].visualid));
                    748:        }
                    749:        else if (num_visuals == 0)
                    750:        {
                    751:                if (template_mask == VisualIDMask)
                    752:                        Sys_Error("VID: Bad visual id %d\n", template.visualid);
                    753:                else
                    754:                        Sys_Error("VID: No visuals at depth %d\n", template.depth);
                    755:        }
                    756: 
                    757: #if 0
                    758:        if (verbose)
                    759:        {
                    760:                printf("Using visualid %d:\n", (int)(x_visinfo->visualid));
                    761:                printf("        screen %d\n", x_visinfo->screen);
                    762:                printf("        red_mask 0x%x\n", (int)(x_visinfo->red_mask));
                    763:                printf("        green_mask 0x%x\n", (int)(x_visinfo->green_mask));
                    764:                printf("        blue_mask 0x%x\n", (int)(x_visinfo->blue_mask));
                    765:                printf("        colormap_size %d\n", x_visinfo->colormap_size);
                    766:                printf("        bits_per_rgb %d\n", x_visinfo->bits_per_rgb);
                    767:        }
                    768: #endif
                    769: 
                    770:        x_vis = x_visinfo->visual;
                    771: 
                    772: // setup attributes for main window
                    773:        {
                    774:           int attribmask = CWEventMask  | CWColormap | CWBorderPixel;
                    775:           XSetWindowAttributes attribs;
                    776:           Colormap tmpcmap;
                    777:           
                    778:           tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp,
                    779:                                                         x_visinfo->screen), x_vis, AllocNone);
                    780:           
                    781:           attribs.event_mask = STD_EVENT_MASK;
                    782:           attribs.border_pixel = 0;
                    783:           attribs.colormap = tmpcmap;
                    784: 
                    785: // create the main window
                    786:                x_win = XCreateWindow(  x_disp,
                    787:                        XRootWindow(x_disp, x_visinfo->screen),
                    788:                        0, 0,   // x, y
                    789:                        vid.width, vid.height,
                    790:                        0, // borderwidth
                    791:                        x_visinfo->depth,
                    792:                        InputOutput,
                    793:                        x_vis,
                    794:                        attribmask,
                    795:                        &attribs );
                    796:                XStoreName(x_disp, x_win, "Quake II");
                    797: 
                    798:                if (x_visinfo->class != TrueColor)
                    799:                        XFreeColormap(x_disp, tmpcmap);
                    800:        }
                    801: 
                    802:        if (x_visinfo->depth == 8)
                    803:        {
                    804:        // create and upload the palette
                    805:                if (x_visinfo->class == PseudoColor)
                    806:                {
                    807:                        x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll);
                    808:                        XSetWindowColormap(x_disp, x_win, x_cmap);
                    809:                }
                    810: 
                    811:        }
                    812: 
                    813: // inviso cursor
                    814:        XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win));
                    815: 
                    816: // create the GC
                    817:        {
                    818:                XGCValues xgcvalues;
                    819:                int valuemask = GCGraphicsExposures;
                    820:                xgcvalues.graphics_exposures = False;
                    821:                x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues );
                    822:        }
                    823: 
                    824: // map the window
                    825:        XMapWindow(x_disp, x_win);
                    826: 
                    827: // wait for first exposure event
                    828:        {
                    829:                XEvent event;
                    830:                do
                    831:                {
                    832:                        XNextEvent(x_disp, &event);
                    833:                        if (event.type == Expose && !event.xexpose.count)
                    834:                                oktodraw = true;
                    835:                } while (!oktodraw);
                    836:        }
                    837: // now safe to draw
                    838: 
                    839: // even if MITSHM is available, make sure it's a local connection
                    840:        if (XShmQueryExtension(x_disp))
                    841:        {
                    842:                char *displayname;
                    843:                doShm = true;
                    844:                displayname = (char *) getenv("DISPLAY");
                    845:                if (displayname)
                    846:                {
                    847:                        char *d = displayname;
                    848:                        while (*d && (*d != ':')) d++;
                    849:                        if (*d) *d = 0;
                    850:                        if (!(!strcasecmp(displayname, "unix") || !*displayname))
                    851:                                doShm = false;
                    852:                }
                    853:        }
                    854: 
                    855:        if (doShm)
                    856:        {
                    857:                x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion;
                    858:                ResetSharedFrameBuffers();
                    859:        }
                    860:        else
                    861:                ResetFrameBuffer();
                    862: 
                    863:        current_framebuffer = 0;
                    864:        vid.rowbytes = x_framebuffer[0]->bytes_per_line;
                    865:        vid.buffer = x_framebuffer[0]->data;
                    866: 
                    867: //     XSynchronize(x_disp, False);
                    868: 
                    869:        X11_active = true;
                    870: 
                    871:        return true;
                    872: }
                    873: 
                    874: /*
                    875: ** SWimp_EndFrame
                    876: **
                    877: ** This does an implementation specific copy from the backbuffer to the
                    878: ** front buffer.  In the Win32 case it uses BitBlt or BltFast depending
                    879: ** on whether we're using DIB sections/GDI or DDRAW.
                    880: */
                    881: void SWimp_EndFrame (void)
                    882: {
                    883: // if the window changes dimension, skip this frame
                    884: #if 0
                    885:        if (config_notify)
                    886:        {
                    887:                fprintf(stderr, "config notify\n");
                    888:                config_notify = 0;
                    889:                vid.width = config_notify_width & ~7;
                    890:                vid.height = config_notify_height;
                    891:                if (doShm)
                    892:                        ResetSharedFrameBuffers();
                    893:                else
                    894:                        ResetFrameBuffer();
                    895:                vid.rowbytes = x_framebuffer[0]->bytes_per_line;
                    896:                vid.buffer = x_framebuffer[current_framebuffer]->data;
                    897:                vid.recalc_refdef = 1;                          // force a surface cache flush
                    898:                Con_CheckResize();
                    899:                Con_Clear_f();
                    900:                return;
                    901:        }
                    902: #endif
                    903: 
                    904:        if (doShm)
                    905:        {
                    906: 
                    907:                if (x_visinfo->depth != 8)
                    908:                        st2_fixup( x_framebuffer[current_framebuffer], 
                    909:                                0, 0, vid.width, vid.height);   
                    910:                if (!XShmPutImage(x_disp, x_win, x_gc,
                    911:                        x_framebuffer[current_framebuffer], 0, 0,
                    912:                        0, 0, vid.width, vid.height, True))
                    913:                                Sys_Error("VID_Update: XShmPutImage failed\n");
                    914:                oktodraw = false;
                    915:                while (!oktodraw) 
                    916:                        GetEvent();
                    917:                current_framebuffer = !current_framebuffer;
                    918:                vid.buffer = x_framebuffer[current_framebuffer]->data;
                    919:                XSync(x_disp, False);
                    920:        }
                    921:        else
                    922:        {
                    923:                if (x_visinfo->depth != 8)
                    924:                        st2_fixup( x_framebuffer[current_framebuffer], 
                    925:                                0, 0, vid.width, vid.height);
                    926:                XPutImage(x_disp, x_win, x_gc, x_framebuffer[0],
                    927:                        0, 0, 0, 0, vid.width, vid.height);
                    928:                XSync(x_disp, False);
                    929:        }
                    930: }
                    931: 
                    932: /*
                    933: ** SWimp_SetMode
                    934: */
                    935: rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
                    936: {
                    937:        rserr_t retval = rserr_ok;
                    938: 
                    939:        ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode );
                    940: 
                    941:        if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) )
                    942:        {
                    943:                ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
                    944:                return rserr_invalid_mode;
                    945:        }
                    946: 
                    947:        ri.Con_Printf( PRINT_ALL, " %d %d\n", *pwidth, *pheight);
                    948: 
                    949:        if ( !SWimp_InitGraphics( false ) ) {
                    950:                // failed to set a valid mode in windowed mode
                    951:                return rserr_invalid_mode;
                    952:        }
                    953: 
                    954:        R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
                    955: 
                    956:        return retval;
                    957: }
                    958: 
                    959: /*
                    960: ** SWimp_SetPalette
                    961: **
                    962: ** System specific palette setting routine.  A NULL palette means
                    963: ** to use the existing palette.  The palette is expected to be in
                    964: ** a padded 4-byte xRGB format.
                    965: */
                    966: void SWimp_SetPalette( const unsigned char *palette )
                    967: {
                    968:        int i;
                    969:        XColor colors[256];
                    970: 
                    971:        if (!X11_active)
                    972:                return;
                    973: 
                    974:     if ( !palette )
                    975:         palette = ( const unsigned char * ) sw_state.currentpalette;
                    976:  
                    977:        for(i=0;i<256;i++)
                    978:                st2d_8to16table[i]= xlib_rgb(palette[i*4],
                    979:                        palette[i*4+1],palette[i*4+2]);
                    980: 
                    981:        if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8)
                    982:        {
                    983:                for (i=0 ; i<256 ; i++)
                    984:                {
                    985:                        colors[i].pixel = i;
                    986:                        colors[i].flags = DoRed|DoGreen|DoBlue;
                    987:                        colors[i].red = palette[i*4] * 257;
                    988:                        colors[i].green = palette[i*4+1] * 257;
                    989:                        colors[i].blue = palette[i*4+2] * 257;
                    990:                }
                    991:                XStoreColors(x_disp, x_cmap, colors, 256);
                    992:        }
                    993: }
                    994: 
                    995: /*
                    996: ** SWimp_Shutdown
                    997: **
                    998: ** System specific graphics subsystem shutdown routine.  Destroys
                    999: ** DIBs or DDRAW surfaces as appropriate.
                   1000: */
                   1001: void SWimp_Shutdown( void )
                   1002: {
                   1003:        int i;
                   1004: 
                   1005:        if (!X11_active)
                   1006:                return;
                   1007: 
                   1008:        if (doShm) {
                   1009:                for (i = 0; i < 2; i++)
                   1010:                        if (x_framebuffer[i]) {
                   1011:                                XShmDetach(x_disp, &x_shminfo[i]);
                   1012:                                free(x_framebuffer[i]);
                   1013:                                shmdt(x_shminfo[i].shmaddr);
                   1014:                                x_framebuffer[i] = NULL;
                   1015:                        }
                   1016:        } else if (x_framebuffer[0]) {
                   1017:                free(x_framebuffer[0]->data);
                   1018:                free(x_framebuffer[0]);
                   1019:                x_framebuffer[0] = NULL;
                   1020:        }
                   1021: 
                   1022:        XDestroyWindow( x_disp, x_win );
                   1023: 
                   1024:        XAutoRepeatOn(x_disp);
                   1025: //     XCloseDisplay(x_disp);
                   1026: 
                   1027:        X11_active = false;
                   1028: }
                   1029: 
                   1030: /*
                   1031: ** SWimp_AppActivate
                   1032: */
                   1033: void SWimp_AppActivate( qboolean active )
                   1034: {
                   1035: }
                   1036: 
                   1037: //===============================================================================
                   1038: 
                   1039: /*
                   1040: ================
                   1041: Sys_MakeCodeWriteable
                   1042: ================
                   1043: */
                   1044: void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
                   1045: {
                   1046: 
                   1047:        int r;
                   1048:        unsigned long addr;
                   1049:        int psize = getpagesize();
                   1050: 
                   1051:        addr = (startaddr & ~(psize-1)) - psize;
                   1052: 
                   1053: //     fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
                   1054: //                     addr, startaddr+length, length);
                   1055: 
                   1056:        r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
                   1057: 
                   1058:        if (r < 0)
                   1059:                Sys_Error("Protection change failed\n");
                   1060: 
                   1061: }
                   1062: 
                   1063: /*****************************************************************************/
                   1064: /* KEYBOARD                                                                  */
                   1065: /*****************************************************************************/
                   1066: 
                   1067: Key_Event_fp_t Key_Event_fp;
                   1068: 
                   1069: void KBD_Init(Key_Event_fp_t fp)
                   1070: {
                   1071:        Key_Event_fp = fp;
                   1072: }
                   1073: 
                   1074: void KBD_Update(void)
                   1075: {
                   1076: // get events from x server
                   1077:        if (x_disp)
                   1078:        {
                   1079:                while (XPending(x_disp)) 
                   1080:                        GetEvent();
                   1081:                while (keyq_head != keyq_tail)
                   1082:                {
                   1083:                        Key_Event_fp(keyq[keyq_tail].key, keyq[keyq_tail].down);
                   1084:                        keyq_tail = (keyq_tail + 1) & 63;
                   1085:                }
                   1086:        }
                   1087: }
                   1088: 
                   1089: void KBD_Close(void)
                   1090: {
                   1091: }
                   1092: 
                   1093: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.