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

1.1       root        1: /*
                      2: Copyright (C) 1997-2001 Id Software, Inc.
                      3: 
                      4: This program is free software; you can redistribute it and/or
                      5: modify it under the terms of the GNU General Public License
                      6: as published by the Free Software Foundation; either version 2
                      7: of the License, or (at your option) any later version.
                      8: 
                      9: This program is distributed in the hope that it will be useful,
                     10: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
                     12: 
                     13: See the GNU General Public License for more details.
                     14: 
                     15: You should have received a copy of the GNU General Public License
                     16: along with this program; if not, write to the Free Software
                     17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
                     18: 
                     19: */
                     20: /*
                     21: ** GLW_IMP.C
                     22: **
                     23: ** This file contains ALL Linux specific stuff having to do with the
                     24: ** OpenGL refresh.  When a port is being made the following functions
                     25: ** must be implemented by the port:
                     26: **
                     27: ** GLimp_EndFrame
                     28: ** GLimp_Init
                     29: ** GLimp_Shutdown
                     30: ** GLimp_SwitchFullscreen
                     31: **
                     32: */
                     33: 
                     34: #include <termios.h>
                     35: #include <sys/ioctl.h>
                     36: #include <sys/stat.h>
                     37: #include <sys/vt.h>
                     38: #include <stdarg.h>
                     39: #include <stdio.h>
                     40: #include <signal.h>
                     41: 
                     42: #include "../ref_gl/gl_local.h"
                     43: 
                     44: #include "../client/keys.h"
                     45: 
                     46: #include "../linux/rw_linux.h"
                     47: #include "../linux/glw_linux.h"
                     48: 
                     49: #include <GL/glx.h>
                     50: 
                     51: #include <X11/keysym.h>
                     52: #include <X11/cursorfont.h>
                     53: 
                     54: #include <X11/extensions/xf86dga.h>
                     55: #include <X11/extensions/xf86vmode.h>
                     56: 
                     57: glwstate_t glw_state;
                     58: 
                     59: static Display *dpy = NULL;
                     60: static int scrnum;
                     61: static Window win;
                     62: static GLXContext ctx = NULL;
                     63: 
                     64: #define KEY_MASK (KeyPressMask | KeyReleaseMask)
                     65: #define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \
                     66:                    PointerMotionMask | ButtonMotionMask )
                     67: #define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask )
                     68: 
                     69: /*****************************************************************************/
                     70: /* MOUSE                                                                     */
                     71: /*****************************************************************************/
                     72: 
                     73: // this is inside the renderer shared lib, so these are called from vid_so
                     74: 
                     75: static qboolean        mouse_avail;
                     76: static int   mx, my;
                     77: static int     old_mouse_x, old_mouse_y;
                     78: 
                     79: static int win_x, win_y;
                     80: 
                     81: static cvar_t  *m_filter;
                     82: static cvar_t  *in_mouse;
                     83: static cvar_t  *in_dgamouse;
                     84: 
                     85: static cvar_t  *r_fakeFullscreen;
                     86: 
                     87: static XF86VidModeModeInfo **vidmodes;
                     88: static int default_dotclock_vidmode;
                     89: static int num_vidmodes;
                     90: static qboolean vidmode_active = false;
                     91: 
                     92: static qboolean        mlooking;
                     93: 
                     94: static qboolean mouse_active = false;
                     95: static qboolean dgamouse = false;
                     96: static qboolean vidmode_ext = false;
                     97: 
                     98: // state struct passed in Init
                     99: static in_state_t      *in_state;
                    100: 
                    101: static cvar_t *sensitivity;
                    102: static cvar_t *lookstrafe;
                    103: static cvar_t *m_side;
                    104: static cvar_t *m_yaw;
                    105: static cvar_t *m_pitch;
                    106: static cvar_t *m_forward;
                    107: static cvar_t *freelook;
                    108: 
                    109: static Cursor CreateNullCursor(Display *display, Window root)
                    110: {
                    111:     Pixmap cursormask; 
                    112:     XGCValues xgc;
                    113:     GC gc;
                    114:     XColor dummycolour;
                    115:     Cursor cursor;
                    116: 
                    117:     cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
                    118:     xgc.function = GXclear;
                    119:     gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
                    120:     XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
                    121:     dummycolour.pixel = 0;
                    122:     dummycolour.red = 0;
                    123:     dummycolour.flags = 04;
                    124:     cursor = XCreatePixmapCursor(display, cursormask, cursormask,
                    125:           &dummycolour,&dummycolour, 0,0);
                    126:     XFreePixmap(display,cursormask);
                    127:     XFreeGC(display,gc);
                    128:     return cursor;
                    129: }
                    130: 
                    131: static void install_grabs(void)
                    132: {
                    133: 
                    134: // inviso cursor
                    135:        XDefineCursor(dpy, win, CreateNullCursor(dpy, win));
                    136: 
                    137:        XGrabPointer(dpy, win,
                    138:                                 True,
                    139:                                 0,
                    140:                                 GrabModeAsync, GrabModeAsync,
                    141:                                 win,
                    142:                                 None,
                    143:                                 CurrentTime);
                    144: 
                    145:        if (in_dgamouse->value) {
                    146:                int MajorVersion, MinorVersion;
                    147: 
                    148:                if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) { 
                    149:                        // unable to query, probalby not supported
                    150:                        ri.Con_Printf( PRINT_ALL, "Failed to detect XF86DGA Mouse\n" );
                    151:                        ri.Cvar_Set( "in_dgamouse", "0" );
                    152:                } else {
                    153:                        dgamouse = true;
                    154:                        XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse);
                    155:                        XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
                    156:                }
                    157:        } else {
                    158:                XWarpPointer(dpy, None, win,
                    159:                                         0, 0, 0, 0,
                    160:                                         vid.width / 2, vid.height / 2);
                    161:        }
                    162: 
                    163:        XGrabKeyboard(dpy, win,
                    164:                                  False,
                    165:                                  GrabModeAsync, GrabModeAsync,
                    166:                                  CurrentTime);
                    167: 
                    168:        mouse_active = true;
                    169: 
                    170: //     XSync(dpy, True);
                    171: }
                    172: 
                    173: static void uninstall_grabs(void)
                    174: {
                    175:        if (!dpy || !win)
                    176:                return;
                    177: 
                    178:        if (dgamouse) {
                    179:                dgamouse = false;
                    180:                XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0);
                    181:        }
                    182: 
                    183:        XUngrabPointer(dpy, CurrentTime);
                    184:        XUngrabKeyboard(dpy, CurrentTime);
                    185: 
                    186: // inviso cursor
                    187:        XUndefineCursor(dpy, win);
                    188: 
                    189:        mouse_active = false;
                    190: }
                    191: 
                    192: static void Force_CenterView_f (void)
                    193: {
                    194:        in_state->viewangles[PITCH] = 0;
                    195: }
                    196: 
                    197: static void RW_IN_MLookDown (void) 
                    198: { 
                    199:        mlooking = true; 
                    200: }
                    201: 
                    202: static void RW_IN_MLookUp (void) 
                    203: {
                    204:        mlooking = false;
                    205:        in_state->IN_CenterView_fp ();
                    206: }
                    207: 
                    208: void RW_IN_Init(in_state_t *in_state_p)
                    209: {
                    210:        int mtype;
                    211:        int i;
                    212: 
                    213:        in_state = in_state_p;
                    214: 
                    215:        // mouse variables
                    216:        m_filter = ri.Cvar_Get ("m_filter", "0", 0);
                    217:     in_mouse = ri.Cvar_Get ("in_mouse", "1", CVAR_ARCHIVE);
                    218:     in_dgamouse = ri.Cvar_Get ("in_dgamouse", "1", CVAR_ARCHIVE);
                    219:        freelook = ri.Cvar_Get( "freelook", "0", 0 );
                    220:        lookstrafe = ri.Cvar_Get ("lookstrafe", "0", 0);
                    221:        sensitivity = ri.Cvar_Get ("sensitivity", "3", 0);
                    222:        m_pitch = ri.Cvar_Get ("m_pitch", "0.022", 0);
                    223:        m_yaw = ri.Cvar_Get ("m_yaw", "0.022", 0);
                    224:        m_forward = ri.Cvar_Get ("m_forward", "1", 0);
                    225:        m_side = ri.Cvar_Get ("m_side", "0.8", 0);
                    226: 
                    227:        ri.Cmd_AddCommand ("+mlook", RW_IN_MLookDown);
                    228:        ri.Cmd_AddCommand ("-mlook", RW_IN_MLookUp);
                    229: 
                    230:        ri.Cmd_AddCommand ("force_centerview", Force_CenterView_f);
                    231: 
                    232:        mx = my = 0.0;
                    233:        mouse_avail = true;
                    234: }
                    235: 
                    236: void RW_IN_Shutdown(void)
                    237: {
                    238:        mouse_avail = false;
                    239: }
                    240: 
                    241: /*
                    242: ===========
                    243: IN_Commands
                    244: ===========
                    245: */
                    246: void RW_IN_Commands (void)
                    247: {
                    248: }
                    249: 
                    250: /*
                    251: ===========
                    252: IN_Move
                    253: ===========
                    254: */
                    255: void RW_IN_Move (usercmd_t *cmd)
                    256: {
                    257:        if (!mouse_avail)
                    258:                return;
                    259:    
                    260:        if (m_filter->value)
                    261:        {
                    262:                mx = (mx + old_mouse_x) * 0.5;
                    263:                my = (my + old_mouse_y) * 0.5;
                    264:        }
                    265: 
                    266:        old_mouse_x = mx;
                    267:        old_mouse_y = my;
                    268: 
                    269:        mx *= sensitivity->value;
                    270:        my *= sensitivity->value;
                    271: 
                    272: // add mouse X/Y movement to cmd
                    273:        if ( (*in_state->in_strafe_state & 1) || 
                    274:                (lookstrafe->value && mlooking ))
                    275:                cmd->sidemove += m_side->value * mx;
                    276:        else
                    277:                in_state->viewangles[YAW] -= m_yaw->value * mx;
                    278: 
                    279:        if ( (mlooking || freelook->value) && 
                    280:                !(*in_state->in_strafe_state & 1))
                    281:        {
                    282:                in_state->viewangles[PITCH] += m_pitch->value * my;
                    283:        }
                    284:        else
                    285:        {
                    286:                cmd->forwardmove -= m_forward->value * my;
                    287:        }
                    288: 
                    289:        mx = my = 0;
                    290: }
                    291: 
                    292: static void IN_DeactivateMouse( void ) 
                    293: {
                    294:        if (!mouse_avail || !dpy || !win)
                    295:                return;
                    296: 
                    297:        if (mouse_active) {
                    298:                uninstall_grabs();
                    299:                mouse_active = false;
                    300:        }
                    301: }
                    302: 
                    303: static void IN_ActivateMouse( void ) 
                    304: {
                    305:        if (!mouse_avail || !dpy || !win)
                    306:                return;
                    307: 
                    308:        if (!mouse_active) {
                    309:                mx = my = 0; // don't spazz
                    310:                install_grabs();
                    311:                mouse_active = true;
                    312:        }
                    313: }
                    314: 
                    315: void RW_IN_Frame (void)
                    316: {
                    317: }
                    318: 
                    319: void RW_IN_Activate(qboolean active)
                    320: {
                    321:        if (active || vidmode_active)
                    322:                IN_ActivateMouse();
                    323:        else
                    324:                IN_DeactivateMouse ();
                    325: }
                    326: 
                    327: /*****************************************************************************/
                    328: /* KEYBOARD                                                                  */
                    329: /*****************************************************************************/
                    330: 
                    331: static int XLateKey(XKeyEvent *ev)
                    332: {
                    333: 
                    334:        int key;
                    335:        char buf[64];
                    336:        KeySym keysym;
                    337: 
                    338:        key = 0;
                    339: 
                    340:        XLookupString(ev, buf, sizeof buf, &keysym, 0);
                    341: 
                    342:        switch(keysym)
                    343:        {
                    344:                case XK_KP_Page_Up:      key = K_KP_PGUP; break;
                    345:                case XK_Page_Up:         key = K_PGUP; break;
                    346: 
                    347:                case XK_KP_Page_Down: key = K_KP_PGDN; break;
                    348:                case XK_Page_Down:       key = K_PGDN; break;
                    349: 
                    350:                case XK_KP_Home: key = K_KP_HOME; break;
                    351:                case XK_Home:    key = K_HOME; break;
                    352: 
                    353:                case XK_KP_End:  key = K_KP_END; break;
                    354:                case XK_End:     key = K_END; break;
                    355: 
                    356:                case XK_KP_Left: key = K_KP_LEFTARROW; break;
                    357:                case XK_Left:    key = K_LEFTARROW; break;
                    358: 
                    359:                case XK_KP_Right: key = K_KP_RIGHTARROW; break;
                    360:                case XK_Right:  key = K_RIGHTARROW;             break;
                    361: 
                    362:                case XK_KP_Down: key = K_KP_DOWNARROW; break;
                    363:                case XK_Down:    key = K_DOWNARROW; break;
                    364: 
                    365:                case XK_KP_Up:   key = K_KP_UPARROW; break;
                    366:                case XK_Up:              key = K_UPARROW;        break;
                    367: 
                    368:                case XK_Escape: key = K_ESCAPE;         break;
                    369: 
                    370:                case XK_KP_Enter: key = K_KP_ENTER;     break;
                    371:                case XK_Return: key = K_ENTER;           break;
                    372: 
                    373:                case XK_Tab:            key = K_TAB;                     break;
                    374: 
                    375:                case XK_F1:              key = K_F1;                            break;
                    376: 
                    377:                case XK_F2:              key = K_F2;                            break;
                    378: 
                    379:                case XK_F3:              key = K_F3;                            break;
                    380: 
                    381:                case XK_F4:              key = K_F4;                            break;
                    382: 
                    383:                case XK_F5:              key = K_F5;                            break;
                    384: 
                    385:                case XK_F6:              key = K_F6;                            break;
                    386: 
                    387:                case XK_F7:              key = K_F7;                            break;
                    388: 
                    389:                case XK_F8:              key = K_F8;                            break;
                    390: 
                    391:                case XK_F9:              key = K_F9;                            break;
                    392: 
                    393:                case XK_F10:            key = K_F10;                     break;
                    394: 
                    395:                case XK_F11:            key = K_F11;                     break;
                    396: 
                    397:                case XK_F12:            key = K_F12;                     break;
                    398: 
                    399:                case XK_BackSpace: key = K_BACKSPACE; break;
                    400: 
                    401:                case XK_KP_Delete: key = K_KP_DEL; break;
                    402:                case XK_Delete: key = K_DEL; break;
                    403: 
                    404:                case XK_Pause:  key = K_PAUSE;           break;
                    405: 
                    406:                case XK_Shift_L:
                    407:                case XK_Shift_R:        key = K_SHIFT;          break;
                    408: 
                    409:                case XK_Execute: 
                    410:                case XK_Control_L: 
                    411:                case XK_Control_R:      key = K_CTRL;            break;
                    412: 
                    413:                case XK_Alt_L:  
                    414:                case XK_Meta_L: 
                    415:                case XK_Alt_R:  
                    416:                case XK_Meta_R: key = K_ALT;                    break;
                    417: 
                    418:                case XK_KP_Begin: key = K_KP_5; break;
                    419: 
                    420:                case XK_Insert:key = K_INS; break;
                    421:                case XK_KP_Insert: key = K_KP_INS; break;
                    422: 
                    423:                case XK_KP_Multiply: key = '*'; break;
                    424:                case XK_KP_Add:  key = K_KP_PLUS; break;
                    425:                case XK_KP_Subtract: key = K_KP_MINUS; break;
                    426:                case XK_KP_Divide: key = K_KP_SLASH; break;
                    427: 
                    428: #if 0
                    429:                case 0x021: key = '1';break;/* [!] */
                    430:                case 0x040: key = '2';break;/* [@] */
                    431:                case 0x023: key = '3';break;/* [#] */
                    432:                case 0x024: key = '4';break;/* [$] */
                    433:                case 0x025: key = '5';break;/* [%] */
                    434:                case 0x05e: key = '6';break;/* [^] */
                    435:                case 0x026: key = '7';break;/* [&] */
                    436:                case 0x02a: key = '8';break;/* [*] */
                    437:                case 0x028: key = '9';;break;/* [(] */
                    438:                case 0x029: key = '0';break;/* [)] */
                    439:                case 0x05f: key = '-';break;/* [_] */
                    440:                case 0x02b: key = '=';break;/* [+] */
                    441:                case 0x07c: key = '\'';break;/* [|] */
                    442:                case 0x07d: key = '[';break;/* [}] */
                    443:                case 0x07b: key = ']';break;/* [{] */
                    444:                case 0x022: key = '\'';break;/* ["] */
                    445:                case 0x03a: key = ';';break;/* [:] */
                    446:                case 0x03f: key = '/';break;/* [?] */
                    447:                case 0x03e: key = '.';break;/* [>] */
                    448:                case 0x03c: key = ',';break;/* [<] */
                    449: #endif
                    450: 
                    451:                default:
                    452:                        key = *(unsigned char*)buf;
                    453:                        if (key >= 'A' && key <= 'Z')
                    454:                                key = key - 'A' + 'a';
                    455:                        break;
                    456:        } 
                    457: 
                    458:        return key;
                    459: }
                    460: 
                    461: 
                    462: static void HandleEvents(void)
                    463: {
                    464:        XEvent event;
                    465:        int b;
                    466:        qboolean dowarp = false;
                    467:        int mwx = vid.width/2;
                    468:        int mwy = vid.height/2;
                    469:    
                    470:        if (!dpy)
                    471:                return;
                    472: 
                    473:        while (XPending(dpy)) {
                    474: 
                    475:                XNextEvent(dpy, &event);
                    476: 
                    477:                switch(event.type) {
                    478:                case KeyPress:
                    479:                case KeyRelease:
                    480:                        if (in_state && in_state->Key_Event_fp)
                    481:                                in_state->Key_Event_fp (XLateKey(&event.xkey), event.type == KeyPress);
                    482:                        break;
                    483: 
                    484:                case MotionNotify:
                    485:                        if (mouse_active) {
                    486:                                if (dgamouse) {
                    487:                                        mx += (event.xmotion.x + win_x) * 2;
                    488:                                        my += (event.xmotion.y + win_y) * 2;
                    489:                                } 
                    490:                                else 
                    491:                                {
                    492:                                        mx += ((int)event.xmotion.x - mwx) * 2;
                    493:                                        my += ((int)event.xmotion.y - mwy) * 2;
                    494:                                        mwx = event.xmotion.x;
                    495:                                        mwy = event.xmotion.y;
                    496: 
                    497:                                        if (mx || my)
                    498:                                                dowarp = true;
                    499:                                }
                    500:                        }
                    501:                        break;
                    502: 
                    503: 
                    504:                case ButtonPress:
                    505:                        b=-1;
                    506:                        if (event.xbutton.button == 1)
                    507:                                b = 0;
                    508:                        else if (event.xbutton.button == 2)
                    509:                                b = 2;
                    510:                        else if (event.xbutton.button == 3)
                    511:                                b = 1;
                    512:                        if (b>=0 && in_state && in_state->Key_Event_fp)
                    513:                                in_state->Key_Event_fp (K_MOUSE1 + b, true);
                    514:                        break;
                    515: 
                    516:                case ButtonRelease:
                    517:                        b=-1;
                    518:                        if (event.xbutton.button == 1)
                    519:                                b = 0;
                    520:                        else if (event.xbutton.button == 2)
                    521:                                b = 2;
                    522:                        else if (event.xbutton.button == 3)
                    523:                                b = 1;
                    524:                        if (b>=0 && in_state && in_state->Key_Event_fp)
                    525:                                in_state->Key_Event_fp (K_MOUSE1 + b, false);
                    526:                        break;
                    527: 
                    528:                case CreateNotify :
                    529:                        win_x = event.xcreatewindow.x;
                    530:                        win_y = event.xcreatewindow.y;
                    531:                        break;
                    532: 
                    533:                case ConfigureNotify :
                    534:                        win_x = event.xconfigure.x;
                    535:                        win_y = event.xconfigure.y;
                    536:                        break;
                    537:                }
                    538:        }
                    539:           
                    540:        if (dowarp) {
                    541:                /* move the mouse to the window center again */
                    542:                XWarpPointer(dpy,None,win,0,0,0,0, vid.width/2,vid.height/2);
                    543:        }
                    544: }
                    545: 
                    546: Key_Event_fp_t Key_Event_fp;
                    547: 
                    548: void KBD_Init(Key_Event_fp_t fp)
                    549: {
                    550:        Key_Event_fp = fp;
                    551: }
                    552: 
                    553: void KBD_Update(void)
                    554: {
                    555: // get events from x server
                    556:        HandleEvents();
                    557: }
                    558: 
                    559: void KBD_Close(void)
                    560: {
                    561: }
                    562: 
                    563: /*****************************************************************************/
                    564: 
                    565: static qboolean GLimp_SwitchFullscreen( int width, int height );
                    566: qboolean GLimp_InitGL (void);
                    567: 
                    568: static void signal_handler(int sig)
                    569: {
                    570:        printf("Received signal %d, exiting...\n", sig);
                    571:        GLimp_Shutdown();
                    572:        _exit(0);
                    573: }
                    574: 
                    575: static void InitSig(void)
                    576: {
                    577:        signal(SIGHUP, signal_handler);
                    578:        signal(SIGQUIT, signal_handler);
                    579:        signal(SIGILL, signal_handler);
                    580:        signal(SIGTRAP, signal_handler);
                    581:        signal(SIGIOT, signal_handler);
                    582:        signal(SIGBUS, signal_handler);
                    583:        signal(SIGFPE, signal_handler);
                    584:        signal(SIGSEGV, signal_handler);
                    585:        signal(SIGTERM, signal_handler);
                    586: }
                    587: 
                    588: /*
                    589: ** GLimp_SetMode
                    590: */
                    591: int GLimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
                    592: {
                    593:        int width, height;
                    594:        int attrib[] = {
                    595:                GLX_RGBA,
                    596:                GLX_RED_SIZE, 1,
                    597:                GLX_GREEN_SIZE, 1,
                    598:                GLX_BLUE_SIZE, 1,
                    599:                GLX_DOUBLEBUFFER,
                    600:                GLX_DEPTH_SIZE, 1,
                    601:                None
                    602:        };
                    603:        Window root;
                    604:        XVisualInfo *visinfo;
                    605:        XSetWindowAttributes attr;
                    606:        unsigned long mask;
                    607:        int MajorVersion, MinorVersion;
                    608:        int actualWidth, actualHeight;
                    609:        int i;
                    610: 
                    611:        r_fakeFullscreen = ri.Cvar_Get( "r_fakeFullscreen", "0", CVAR_ARCHIVE);
                    612: 
                    613:        ri.Con_Printf( PRINT_ALL, "Initializing OpenGL display\n");
                    614: 
                    615:        if (fullscreen)
                    616:                ri.Con_Printf (PRINT_ALL, "...setting fullscreen mode %d:", mode );
                    617:        else
                    618:                ri.Con_Printf (PRINT_ALL, "...setting mode %d:", mode );
                    619: 
                    620:        if ( !ri.Vid_GetModeInfo( &width, &height, mode ) )
                    621:        {
                    622:                ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
                    623:                return rserr_invalid_mode;
                    624:        }
                    625: 
                    626:        ri.Con_Printf( PRINT_ALL, " %d %d\n", width, height );
                    627: 
                    628:        // destroy the existing window
                    629:        GLimp_Shutdown ();
                    630: 
                    631:        // Mesa VooDoo hacks
                    632:        if (fullscreen)
                    633:                putenv("MESA_GLX_FX=fullscreen");
                    634:        else
                    635:                putenv("MESA_GLX_FX=window");
                    636: 
                    637:        if (!(dpy = XOpenDisplay(NULL))) {
                    638:                fprintf(stderr, "Error couldn't open the X display\n");
                    639:                return rserr_invalid_mode;
                    640:        }
                    641: 
                    642:        scrnum = DefaultScreen(dpy);
                    643:        root = RootWindow(dpy, scrnum);
                    644: 
                    645:        // Get video mode list
                    646:        MajorVersion = MinorVersion = 0;
                    647:        if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) { 
                    648:                vidmode_ext = false;
                    649:        } else {
                    650:                ri.Con_Printf(PRINT_ALL, "Using XFree86-VidModeExtension Version %d.%d\n",
                    651:                        MajorVersion, MinorVersion);
                    652:                vidmode_ext = true;
                    653:        }
                    654: 
                    655:        visinfo = qglXChooseVisual(dpy, scrnum, attrib);
                    656:        if (!visinfo) {
                    657:                fprintf(stderr, "Error couldn't get an RGB, Double-buffered, Depth visual\n");
                    658:                return rserr_invalid_mode;
                    659:        }
                    660: 
                    661:        if (vidmode_ext) {
                    662:                int best_fit, best_dist, dist, x, y;
                    663:                
                    664:                XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
                    665: 
                    666:                // Are we going fullscreen?  If so, let's change video mode
                    667:                if (fullscreen && !r_fakeFullscreen->value) {
                    668:                        best_dist = 9999999;
                    669:                        best_fit = -1;
                    670: 
                    671:                        for (i = 0; i < num_vidmodes; i++) {
                    672:                                if (width > vidmodes[i]->hdisplay ||
                    673:                                        height > vidmodes[i]->vdisplay)
                    674:                                        continue;
                    675: 
                    676:                                x = width - vidmodes[i]->hdisplay;
                    677:                                y = height - vidmodes[i]->vdisplay;
                    678:                                dist = (x * x) + (y * y);
                    679:                                if (dist < best_dist) {
                    680:                                        best_dist = dist;
                    681:                                        best_fit = i;
                    682:                                }
                    683:                        }
                    684: 
                    685:                        if (best_fit != -1) {
                    686:                                actualWidth = vidmodes[best_fit]->hdisplay;
                    687:                                actualHeight = vidmodes[best_fit]->vdisplay;
                    688: 
                    689:                                // change to the mode
                    690:                                XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
                    691:                                vidmode_active = true;
                    692: 
                    693:                                // Move the viewport to top left
                    694:                                XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
                    695:                        } else
                    696:                                fullscreen = 0;
                    697:                }
                    698:        }
                    699: 
                    700:        /* window attributes */
                    701:        attr.background_pixel = 0;
                    702:        attr.border_pixel = 0;
                    703:        attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
                    704:        attr.event_mask = X_MASK;
                    705:        if (vidmode_active) {
                    706:                mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | 
                    707:                        CWEventMask | CWOverrideRedirect;
                    708:                attr.override_redirect = True;
                    709:                attr.backing_store = NotUseful;
                    710:                attr.save_under = False;
                    711:        } else
                    712:                mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
                    713: 
                    714:        win = XCreateWindow(dpy, root, 0, 0, width, height,
                    715:                                                0, visinfo->depth, InputOutput,
                    716:                                                visinfo->visual, mask, &attr);
                    717:        XMapWindow(dpy, win);
                    718: 
                    719:        if (vidmode_active) {
                    720:                XMoveWindow(dpy, win, 0, 0);
                    721:                XRaiseWindow(dpy, win);
                    722:                XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
                    723:                XFlush(dpy);
                    724:                // Move the viewport to top left
                    725:                XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
                    726:        }
                    727: 
                    728:        XFlush(dpy);
                    729: 
                    730:        ctx = qglXCreateContext(dpy, visinfo, NULL, True);
                    731: 
                    732:        qglXMakeCurrent(dpy, win, ctx);
                    733: 
                    734:        *pwidth = width;
                    735:        *pheight = height;
                    736: 
                    737:        // let the sound and input subsystems know about the new window
                    738:        ri.Vid_NewWindow (width, height);
                    739: 
                    740:        qglXMakeCurrent(dpy, win, ctx);
                    741: 
                    742:        return rserr_ok;
                    743: }
                    744: 
                    745: /*
                    746: ** GLimp_Shutdown
                    747: **
                    748: ** This routine does all OS specific shutdown procedures for the OpenGL
                    749: ** subsystem.  Under OpenGL this means NULLing out the current DC and
                    750: ** HGLRC, deleting the rendering context, and releasing the DC acquired
                    751: ** for the window.  The state structure is also nulled out.
                    752: **
                    753: */
                    754: void GLimp_Shutdown( void )
                    755: {
                    756:        uninstall_grabs();
                    757:        mouse_active = false;
                    758:        dgamouse = false;
                    759: 
                    760:        if (dpy) {
                    761:                if (ctx)
                    762:                        qglXDestroyContext(dpy, ctx);
                    763:                if (win)
                    764:                        XDestroyWindow(dpy, win);
                    765:                if (vidmode_active)
                    766:                        XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]);
                    767:                XCloseDisplay(dpy);
                    768:        }
                    769:        ctx = NULL;
                    770:        dpy = NULL;
                    771:        win = 0;
                    772:        ctx = NULL;
                    773: }
                    774: 
                    775: /*
                    776: ** GLimp_Init
                    777: **
                    778: ** This routine is responsible for initializing the OS specific portions
                    779: ** of OpenGL.  
                    780: */
                    781: int GLimp_Init( void *hinstance, void *wndproc )
                    782: {
                    783:        InitSig();
                    784: 
                    785:        return true;
                    786: }
                    787: 
                    788: /*
                    789: ** GLimp_BeginFrame
                    790: */
                    791: void GLimp_BeginFrame( float camera_seperation )
                    792: {
                    793: }
                    794: 
                    795: /*
                    796: ** GLimp_EndFrame
                    797: ** 
                    798: ** Responsible for doing a swapbuffers and possibly for other stuff
                    799: ** as yet to be determined.  Probably better not to make this a GLimp
                    800: ** function and instead do a call to GLimp_SwapBuffers.
                    801: */
                    802: void GLimp_EndFrame (void)
                    803: {
                    804:        qglFlush();
                    805:        qglXSwapBuffers(dpy, win);
                    806: }
                    807: 
                    808: /*
                    809: ** GLimp_AppActivate
                    810: */
                    811: void GLimp_AppActivate( qboolean active )
                    812: {
                    813: }
                    814: 
                    815: void Fake_glColorTableEXT( GLenum target, GLenum internalformat,
                    816:                              GLsizei width, GLenum format, GLenum type,
                    817:                              const GLvoid *table )
                    818: {
                    819:        byte temptable[256][4];
                    820:        byte *intbl;
                    821:        int i;
                    822: 
                    823:        for (intbl = (byte *)table, i = 0; i < 256; i++) {
                    824:                temptable[i][2] = *intbl++;
                    825:                temptable[i][1] = *intbl++;
                    826:                temptable[i][0] = *intbl++;
                    827:                temptable[i][3] = 255;
                    828:        }
                    829:        qgl3DfxSetPaletteEXT((GLuint *)temptable);
                    830: }
                    831: 
                    832: 
                    833: /*------------------------------------------------*/
                    834: /* X11 Input Stuff
                    835: /*------------------------------------------------*/
                    836: 

unix.superglobalmegacorp.com

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