Annotation of quake2/linux/rw_x11.c, revision 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.