]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - vid_glx.c
Various graphical tweaks (mainly particle related), some code removed.
[xonotic/darkplaces.git] / vid_glx.c
1 /*
2 Copyright (C) 1996-1997 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 #include <termios.h>
21 #include <sys/ioctl.h>
22 #include <sys/stat.h>
23 #include <sys/vt.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <signal.h>
27
28 #include <dlfcn.h>
29
30 #include "quakedef.h"
31
32 #include <GL/glx.h>
33
34 #include <X11/keysym.h>
35 #include <X11/cursorfont.h>
36
37 #include <X11/extensions/xf86dga.h>
38 #include <X11/extensions/xf86vmode.h>
39
40 #define WARP_WIDTH              320
41 #define WARP_HEIGHT             200
42
43 static Display *dpy = NULL;
44 static int scrnum;
45 static Window win;
46 static GLXContext ctx = NULL;
47
48 #define KEY_MASK (KeyPressMask | KeyReleaseMask)
49 #define MOUSE_MASK (ButtonPressMask | ButtonReleaseMask | \
50                     PointerMotionMask | ButtonMotionMask )
51 #define X_MASK (KEY_MASK | MOUSE_MASK | VisibilityChangeMask | StructureNotifyMask )
52
53
54 unsigned short  d_8to16table[256];
55 unsigned                d_8to24table[256];
56 unsigned char   d_15to8table[65536];
57
58 cvar_t  vid_mode = {"vid_mode","0",false};
59  
60 viddef_t        vid;                            // global video state
61
62 static qboolean        mouse_avail;
63 static qboolean        mouse_active;
64 static int   mx, my;
65 static int      old_mouse_x, old_mouse_y;
66
67 static cvar_t in_mouse = {"in_mouse", "1", false};
68 static cvar_t in_dgamouse = {"in_dgamouse", "1", false};
69 static cvar_t m_filter = {"m_filter", "0"};
70
71 qboolean dgamouse = false;
72 qboolean vidmode_ext = false;
73
74 static int win_x, win_y;
75
76 static int scr_width, scr_height;
77
78 static XF86VidModeModeInfo **vidmodes;
79 //static int default_dotclock_vidmode;
80 static int num_vidmodes;
81 static qboolean vidmode_active = false;
82
83 /*-----------------------------------------------------------------------*/
84
85 //int           texture_mode = GL_NEAREST;
86 //int           texture_mode = GL_NEAREST_MIPMAP_NEAREST;
87 //int           texture_mode = GL_NEAREST_MIPMAP_LINEAR;
88 int             texture_mode = GL_LINEAR;
89 //int           texture_mode = GL_LINEAR_MIPMAP_NEAREST;
90 //int           texture_mode = GL_LINEAR_MIPMAP_LINEAR;
91
92 int             texture_extension_number = 1;
93
94 float           gldepthmin, gldepthmax;
95
96 const char *gl_vendor;
97 const char *gl_renderer;
98 const char *gl_version;
99 const char *gl_extensions;
100
101 void (*qglColorTableEXT) (int, int, int, int, int, const void*);
102 void (*qgl3DfxSetPaletteEXT) (GLuint *);
103 void (*qglMTexCoord2f) (GLenum, GLfloat, GLfloat);
104 void (*qglSelectTexture) (GLenum);
105
106 //static float vid_gamma = 1.0;
107
108 // LordHavoc: ARB multitexture support
109 int gl_mtex_enum = 0;
110
111 // LordHavoc: in GLX these are never set, simply provided to make the rest of the code work
112 qboolean is8bit = false;
113 qboolean isPermedia = false;
114 qboolean isATI = false;
115 qboolean isG200 = false;
116 qboolean isRagePro = false;
117 qboolean gl_mtexable = false;
118 qboolean gl_arrays = false;
119
120 /*-----------------------------------------------------------------------*/
121 void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
122 {
123 }
124
125 void D_EndDirectRect (int x, int y, int width, int height)
126 {
127 }
128
129 static int XLateKey(XKeyEvent *ev)
130 {
131
132         int key;
133         char buf[64];
134         KeySym keysym;
135
136         key = 0;
137
138         XLookupString(ev, buf, sizeof buf, &keysym, 0);
139
140         switch(keysym)
141         {
142                 case XK_KP_Page_Up:      
143                 case XK_Page_Up:         key = K_PGUP; break;
144
145                 case XK_KP_Page_Down: 
146                 case XK_Page_Down:       key = K_PGDN; break;
147
148                 case XK_KP_Home: 
149                 case XK_Home:    key = K_HOME; break;
150
151                 case XK_KP_End:  
152                 case XK_End:     key = K_END; break;
153
154                 case XK_KP_Left: 
155                 case XK_Left:    key = K_LEFTARROW; break;
156
157                 case XK_KP_Right: 
158                 case XK_Right:  key = K_RIGHTARROW;             break;
159
160                 case XK_KP_Down: 
161                 case XK_Down:    key = K_DOWNARROW; break;
162
163                 case XK_KP_Up:   
164                 case XK_Up:              key = K_UPARROW;        break;
165
166                 case XK_Escape: key = K_ESCAPE;         break;
167
168                 case XK_KP_Enter: 
169                 case XK_Return: key = K_ENTER;           break;
170
171                 case XK_Tab:            key = K_TAB;                     break;
172
173                 case XK_F1:              key = K_F1;                            break;
174
175                 case XK_F2:              key = K_F2;                            break;
176
177                 case XK_F3:              key = K_F3;                            break;
178
179                 case XK_F4:              key = K_F4;                            break;
180
181                 case XK_F5:              key = K_F5;                            break;
182
183                 case XK_F6:              key = K_F6;                            break;
184
185                 case XK_F7:              key = K_F7;                            break;
186
187                 case XK_F8:              key = K_F8;                            break;
188
189                 case XK_F9:              key = K_F9;                            break;
190
191                 case XK_F10:            key = K_F10;                     break;
192
193                 case XK_F11:            key = K_F11;                     break;
194
195                 case XK_F12:            key = K_F12;                     break;
196
197                 case XK_BackSpace: key = K_BACKSPACE; break;
198
199                 case XK_KP_Delete: 
200                 case XK_Delete: key = K_DEL; break;
201
202                 case XK_Pause:  key = K_PAUSE;           break;
203
204                 case XK_Shift_L:
205                 case XK_Shift_R:        key = K_SHIFT;          break;
206
207                 case XK_Execute: 
208                 case XK_Control_L: 
209                 case XK_Control_R:      key = K_CTRL;            break;
210
211                 case XK_Alt_L:  
212                 case XK_Meta_L: 
213                 case XK_Alt_R:  
214                 case XK_Meta_R: key = K_ALT;                    break;
215
216                 case XK_KP_Begin: key = '5';    break;
217
218                 case XK_KP_Insert: 
219                 case XK_Insert:key = K_INS; break;
220
221                 case XK_KP_Multiply: key = '*'; break;
222                 case XK_KP_Add:  key = '+'; break;
223                 case XK_KP_Subtract: key = '-'; break;
224                 case XK_KP_Divide: key = '/'; break;
225
226 #if 0
227                 case 0x021: key = '1';break;/* [!] */
228                 case 0x040: key = '2';break;/* [@] */
229                 case 0x023: key = '3';break;/* [#] */
230                 case 0x024: key = '4';break;/* [$] */
231                 case 0x025: key = '5';break;/* [%] */
232                 case 0x05e: key = '6';break;/* [^] */
233                 case 0x026: key = '7';break;/* [&] */
234                 case 0x02a: key = '8';break;/* [*] */
235                 case 0x028: key = '9';;break;/* [(] */
236                 case 0x029: key = '0';break;/* [)] */
237                 case 0x05f: key = '-';break;/* [_] */
238                 case 0x02b: key = '=';break;/* [+] */
239                 case 0x07c: key = '\'';break;/* [|] */
240                 case 0x07d: key = '[';break;/* [}] */
241                 case 0x07b: key = ']';break;/* [{] */
242                 case 0x022: key = '\'';break;/* ["] */
243                 case 0x03a: key = ';';break;/* [:] */
244                 case 0x03f: key = '/';break;/* [?] */
245                 case 0x03e: key = '.';break;/* [>] */
246                 case 0x03c: key = ',';break;/* [<] */
247 #endif
248
249                 default:
250                         key = *(unsigned char*)buf;
251                         if (key >= 'A' && key <= 'Z')
252                                 key = key - 'A' + 'a';
253                         break;
254         } 
255
256         return key;
257 }
258
259 static Cursor CreateNullCursor(Display *display, Window root)
260 {
261     Pixmap cursormask; 
262     XGCValues xgc;
263     GC gc;
264     XColor dummycolour;
265     Cursor cursor;
266
267     cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
268     xgc.function = GXclear;
269     gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
270     XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
271     dummycolour.pixel = 0;
272     dummycolour.red = 0;
273     dummycolour.flags = 04;
274     cursor = XCreatePixmapCursor(display, cursormask, cursormask,
275           &dummycolour,&dummycolour, 0,0);
276     XFreePixmap(display,cursormask);
277     XFreeGC(display,gc);
278     return cursor;
279 }
280
281 static void install_grabs(void)
282 {
283
284 // inviso cursor
285         XDefineCursor(dpy, win, CreateNullCursor(dpy, win));
286
287         XGrabPointer(dpy, win,
288                                  True,
289                                  0,
290                                  GrabModeAsync, GrabModeAsync,
291                                  win,
292                                  None,
293                                  CurrentTime);
294
295         if (in_dgamouse.value) {
296                 int MajorVersion, MinorVersion;
297
298                 if (!XF86DGAQueryVersion(dpy, &MajorVersion, &MinorVersion)) { 
299                         // unable to query, probalby not supported
300                         Con_Printf( "Failed to detect XF86DGA Mouse\n" );
301                         in_dgamouse.value = 0;
302                 } else {
303                         dgamouse = true;
304                         XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse);
305                         XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
306                 }
307         } else {
308                 XWarpPointer(dpy, None, win,
309                                          0, 0, 0, 0,
310                                          vid.width / 2, vid.height / 2);
311         }
312
313         XGrabKeyboard(dpy, win,
314                                   False,
315                                   GrabModeAsync, GrabModeAsync,
316                                   CurrentTime);
317
318         mouse_active = true;
319
320 //      XSync(dpy, True);
321 }
322
323 static void uninstall_grabs(void)
324 {
325         if (!dpy || !win)
326                 return;
327
328         if (dgamouse) {
329                 dgamouse = false;
330                 XF86DGADirectVideo(dpy, DefaultScreen(dpy), 0);
331         }
332
333         XUngrabPointer(dpy, CurrentTime);
334         XUngrabKeyboard(dpy, CurrentTime);
335
336 // inviso cursor
337         XUndefineCursor(dpy, win);
338
339         mouse_active = false;
340 }
341
342 static void HandleEvents(void)
343 {
344         XEvent event;
345 //      KeySym ks;
346         int b;
347         qboolean dowarp = false;
348         int mwx = vid.width/2;
349         int mwy = vid.height/2;
350
351         if (!dpy)
352                 return;
353
354         while (XPending(dpy)) {
355                 XNextEvent(dpy, &event);
356
357                 switch (event.type) {
358                 case KeyPress:
359                 case KeyRelease:
360                         Key_Event(XLateKey(&event.xkey), event.type == KeyPress);
361                         break;
362
363                 case MotionNotify:
364                         if (mouse_active) {
365                                 if (dgamouse) {
366                                         mx += (event.xmotion.x + win_x) * 2;
367                                         my += (event.xmotion.y + win_y) * 2;
368                                 } 
369                                 else 
370                                 {
371                                         mx += ((int)event.xmotion.x - mwx) * 2;
372                                         my += ((int)event.xmotion.y - mwy) * 2;
373                                         mwx = event.xmotion.x;
374                                         mwy = event.xmotion.y;
375
376                                         if (mx || my)
377                                                 dowarp = true;
378                                 }
379                         }
380                         break;
381
382                         break;
383
384                 case ButtonPress:
385                         b=-1;
386                         if (event.xbutton.button == 1)
387                                 b = 0;
388                         else if (event.xbutton.button == 2)
389                                 b = 2;
390                         else if (event.xbutton.button == 3)
391                                 b = 1;
392                         if (b>=0)
393                                 Key_Event(K_MOUSE1 + b, true);
394                         break;
395
396                 case ButtonRelease:
397                         b=-1;
398                         if (event.xbutton.button == 1)
399                                 b = 0;
400                         else if (event.xbutton.button == 2)
401                                 b = 2;
402                         else if (event.xbutton.button == 3)
403                                 b = 1;
404                         if (b>=0)
405                                 Key_Event(K_MOUSE1 + b, false);
406                         break;
407
408                 case CreateNotify :
409                         win_x = event.xcreatewindow.x;
410                         win_y = event.xcreatewindow.y;
411                         break;
412
413                 case ConfigureNotify :
414                         win_x = event.xconfigure.x;
415                         win_y = event.xconfigure.y;
416                         break;
417                 }
418         }
419
420         if (dowarp) {
421                 /* move the mouse to the window center again */
422                 XWarpPointer(dpy, None, win, 0, 0, 0, 0, vid.width / 2, vid.height / 2);
423         }
424
425 }
426
427 static void IN_DeactivateMouse( void ) 
428 {
429         if (!mouse_avail || !dpy || !win)
430                 return;
431
432         if (mouse_active) {
433                 uninstall_grabs();
434                 mouse_active = false;
435         }
436 }
437
438 static void IN_ActivateMouse( void ) 
439 {
440         if (!mouse_avail || !dpy || !win)
441                 return;
442
443         if (!mouse_active) {
444                 mx = my = 0; // don't spazz
445                 install_grabs();
446                 mouse_active = true;
447         }
448 }
449
450
451 void VID_Shutdown(void)
452 {
453         if (!ctx || !dpy)
454                 return;
455         IN_DeactivateMouse();
456         if (dpy) {
457                 if (ctx)
458                         glXDestroyContext(dpy, ctx);
459                 if (win)
460                         XDestroyWindow(dpy, win);
461                 if (vidmode_active)
462                         XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[0]);
463                 XCloseDisplay(dpy);
464         }
465         vidmode_active = false;
466         dpy = NULL;
467         win = 0;
468         ctx = NULL;
469 }
470
471 void signal_handler(int sig)
472 {
473         printf("Received signal %d, exiting...\n", sig);
474         Sys_Quit();
475         exit(0);
476 }
477
478 void InitSig(void)
479 {
480         signal(SIGHUP, signal_handler);
481         signal(SIGINT, signal_handler);
482         signal(SIGQUIT, signal_handler);
483         signal(SIGILL, signal_handler);
484         signal(SIGTRAP, signal_handler);
485         signal(SIGIOT, signal_handler);
486         signal(SIGBUS, signal_handler);
487         signal(SIGFPE, signal_handler);
488         signal(SIGSEGV, signal_handler);
489         signal(SIGTERM, signal_handler);
490 }
491
492 /*
493 void (*qglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
494 void (*qglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
495 void (*qglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr);
496 void (*qglArrayElement)(GLint i);
497 void (*qglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
498 void (*qglMTexCoord2f)(GLenum, GLfloat, GLfloat);
499 void (*qglSelectTexture)(GLenum);
500 void (*glColorTableEXT)(int, int, int, int, int, const void*);
501
502 void CheckVertexArrays (void)
503 {
504         void *prjobj;
505         if (COM_CheckParm("-novertex"))
506         {
507                 Con_Printf("...vertex array support disabled\n");
508                 return;
509         }
510         if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL)
511         {
512                 Con_Printf("Unable to open symbol list for main program.\n");
513                 return;
514         }
515         qglMTexCoord2fSGIS = (void *) dlsym(prjobj, "glMTexCoord2fSGIS");
516         if ((qglArrayElement = (void *) dlsym(prjobj, "glArrayElement"))
517          && (qglColorPointer = (void *) dlsym(prjobj, "glColorPointer"))
518 //       && (qglDrawArrays = (void *) dlsym(prjobj, "glDrawArrays"))
519          && (qglDrawElements = (void *) dlsym(prjobj, "glDrawElements"))
520 //       && (qglInterleavedArrays = (void *) dlsym(prjobj, "glInterleavedArrays"))
521          && (qglTexCoordPointer = (void *) dlsym(prjobj, "glTexCoordPointer"))
522          && (qglVertexPointer = (void *) dlsym(prjobj, "glVertexPointer"))
523                 )
524         {
525                 Con_Printf("...vertex array support detected\n");
526                 gl_arrays = true;
527                 dlclose(prjobj);
528                 return;
529         }
530
531         Con_Printf("...vertex array support disabled (not detected - get a better driver)\n");
532         dlclose(prjobj);
533 }
534 */
535
536 void CheckMultiTexture(void) 
537 {
538         void *prjobj;
539         qglMTexCoord2f = NULL;
540         qglSelectTexture = NULL;
541         // Check to see if multitexture is disabled
542         if (COM_CheckParm("-nomtex"))
543         {
544                 Con_Printf("...multitexture disabled\n");
545                 return;
546         }
547         if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL)
548         {
549                 Con_Printf("Unable to open symbol list for main program.\n");
550                 return;
551         }
552         // Test for ARB_multitexture
553         if (!COM_CheckParm("-SGISmtex") && strstr(gl_extensions, "GL_ARB_multitexture "))
554         {
555                 Con_Printf("...using GL_ARB_multitexture\n");
556                 qglMTexCoord2f = (void *) dlsym(prjobj, "glMultiTexCoord2fARB");
557                 qglSelectTexture = (void *) dlsym(prjobj, "glActiveTextureARB");
558                 gl_mtexable = true;
559                 gl_mtex_enum = GL_TEXTURE0_ARB;
560         }
561         else if (strstr(gl_extensions, "GL_SGIS_multitexture ")) // Test for SGIS_multitexture (if ARB_multitexture not found)
562         {
563                 Con_Printf("...using GL_SGIS_multitexture\n");
564                 qglMTexCoord2f = (void *) dlsym(prjobj, "glMTexCoord2fSGIS");
565                 qglSelectTexture = (void *) dlsym(prjobj, "glSelectTextureSGIS");
566                 gl_mtexable = true;
567                 gl_mtex_enum = TEXTURE0_SGIS;
568         }
569         if (!gl_mtexable)
570                 Con_Printf("...multitexture disabled (not detected)\n");
571         dlclose(prjobj);
572 }
573
574 /*
575 ===============
576 GL_Init
577 ===============
578 */
579 extern char *QSG_EXTENSIONS;
580 void GL_Init (void)
581 {
582         gl_vendor = glGetString (GL_VENDOR);
583         Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
584         gl_renderer = glGetString (GL_RENDERER);
585         Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
586
587         gl_version = glGetString (GL_VERSION);
588         Con_Printf ("GL_VERSION: %s\n", gl_version);
589         gl_extensions = glGetString (GL_EXTENSIONS);
590         Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
591
592 //      Con_Printf ("%s %s\n", gl_renderer, gl_version);
593
594         CheckMultiTexture();
595 //      CheckVertexArrays();
596
597         // LordHavoc: report supported extensions
598         Con_Printf ("\nQSG extensions: %s\n", QSG_EXTENSIONS);
599
600 //      glClearColor (1,0,0,0);
601         glCullFace(GL_FRONT);
602 //      glEnable(GL_TEXTURE_2D);
603 //
604 //      glEnable(GL_ALPHA_TEST);
605         glAlphaFunc(GL_GREATER, 0.5);
606 //
607 //      glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
608 //      glShadeModel (GL_FLAT);
609 //
610 //      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
611 //      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
612 //      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
613 //      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
614 //
615 //      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
616 //
617 //      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
618 //      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
619 }
620
621 /*
622 =================
623 GL_BeginRendering
624
625 =================
626 */
627 void GL_BeginRendering (int *x, int *y, int *width, int *height)
628 {
629         *x = *y = 0;
630         *width = scr_width;
631         *height = scr_height;
632
633 //    if (!wglMakeCurrent( maindc, baseRC ))
634 //              Sys_Error ("wglMakeCurrent failed");
635
636 //      glViewport (*x, *y, *width, *height);
637 }
638
639
640 void GL_EndRendering (void)
641 {
642         glFlush();
643         glXSwapBuffers(dpy, win);
644 }
645
646 qboolean VID_Is8bit(void)
647 {
648         return is8bit;
649 }
650
651 void VID_Init8bitPalette(void) 
652 {
653         // Check for 8bit Extensions and initialize them.
654         int i;
655         void *prjobj;
656
657         if (!COM_CheckParm("-8bit"))
658                 return;
659         if ((prjobj = dlopen(NULL, RTLD_LAZY)) == NULL)
660         {
661                 Con_Printf("Unable to open symbol list for main program.\n");
662                 return;
663         }
664
665         if (strstr(gl_extensions, "3DFX_set_global_palette") && (qgl3DfxSetPaletteEXT = dlsym(prjobj, "gl3DfxSetPaletteEXT")) != NULL)
666         {
667                 GLubyte table[256][4];
668                 char *oldpal;
669
670                 Con_SafePrintf("8-bit GL extensions enabled.\n");
671                 glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
672                 oldpal = (char *) d_8to24table; //d_8to24table3dfx;
673                 for (i=0;i<256;i++)
674                 {
675                         table[i][2] = *oldpal++;
676                         table[i][1] = *oldpal++;
677                         table[i][0] = *oldpal++;
678                         table[i][3] = 255;
679                         oldpal++;
680                 }
681                 qgl3DfxSetPaletteEXT((GLuint *)table);
682                 is8bit = true;
683
684         }
685         else if (strstr(gl_extensions, "GL_EXT_shared_texture_palette") && (qglColorTableEXT = dlsym(prjobj, "glColorTableEXT")) != NULL)
686         {
687                 char thePalette[256*3];
688                 char *oldPalette, *newPalette;
689
690                 Con_SafePrintf("8-bit GL extensions enabled.\n");
691                 glEnable( GL_SHARED_TEXTURE_PALETTE_EXT );
692                 oldPalette = (char *) d_8to24table; //d_8to24table3dfx;
693                 newPalette = thePalette;
694                 for (i=0;i<256;i++)
695                 {
696                         *newPalette++ = *oldPalette++;
697                         *newPalette++ = *oldPalette++;
698                         *newPalette++ = *oldPalette++;
699                         oldPalette++;
700                 }
701                 qglColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, (void *) thePalette);
702                 is8bit = true;
703         }
704         
705         dlclose(prjobj);
706 }
707
708 extern void Check_Gamma (unsigned char *pal);
709 void VID_Setup15to8Palette ();
710
711 void VID_Init(unsigned char *palette)
712 {
713         int i;
714         int attrib[] = {
715                 GLX_RGBA,
716                 GLX_RED_SIZE, 1,
717                 GLX_GREEN_SIZE, 1,
718                 GLX_BLUE_SIZE, 1,
719                 GLX_DOUBLEBUFFER,
720                 GLX_DEPTH_SIZE, 1,
721                 None
722         };
723 //      char    gldir[MAX_OSPATH];
724         int width = 640, height = 480;
725         XSetWindowAttributes attr;
726         unsigned long mask;
727         Window root;
728         XVisualInfo *visinfo;
729         qboolean fullscreen = true;
730         int MajorVersion, MinorVersion;
731         int actualWidth, actualHeight;
732
733         Cvar_RegisterVariable (&vid_mode);
734         Cvar_RegisterVariable (&in_mouse);
735         Cvar_RegisterVariable (&in_dgamouse);
736         Cvar_RegisterVariable (&m_filter);
737         
738 // interpret command-line params
739
740 // set vid parameters
741         if ((i = COM_CheckParm("-window")) != 0)
742                 fullscreen = false;
743
744         if ((i = COM_CheckParm("-width")) != 0)
745                 width = atoi(com_argv[i+1]);
746
747         if ((i = COM_CheckParm("-height")) != 0)
748                 height = atoi(com_argv[i+1]);
749
750         if ((i = COM_CheckParm("-conwidth")) != 0)
751                 vid.conwidth = atoi(com_argv[i+1]);
752         else
753                 vid.conwidth = 640;
754
755         vid.conwidth &= 0xfff8; // make it a multiple of eight
756
757         if (vid.conwidth < 320)
758                 vid.conwidth = 320;
759
760         // pick a conheight that matches with correct aspect
761         vid.conheight = vid.conwidth*3 / 4;
762
763         if ((i = COM_CheckParm("-conheight")) != 0)
764                 vid.conheight = atoi(com_argv[i+1]);
765         if (vid.conheight < 200)
766                 vid.conheight = 200;
767
768         if (!(dpy = XOpenDisplay(NULL))) {
769                 fprintf(stderr, "Error couldn't open the X display\n");
770                 exit(1);
771         }
772
773         scrnum = DefaultScreen(dpy);
774         root = RootWindow(dpy, scrnum);
775
776         // Get video mode list
777         MajorVersion = MinorVersion = 0;
778         if (!XF86VidModeQueryVersion(dpy, &MajorVersion, &MinorVersion)) { 
779                 vidmode_ext = false;
780         } else {
781                 Con_Printf("Using XFree86-VidModeExtension Version %d.%d\n", MajorVersion, MinorVersion);
782                 vidmode_ext = true;
783         }
784
785         visinfo = glXChooseVisual(dpy, scrnum, attrib);
786         if (!visinfo) {
787                 fprintf(stderr, "qkHack: Error couldn't get an RGB, Double-buffered, Depth visual\n");
788                 exit(1);
789         }
790
791         if (vidmode_ext) {
792                 int best_fit, best_dist, dist, x, y;
793                 
794                 XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
795
796                 // Are we going fullscreen?  If so, let's change video mode
797                 if (fullscreen) {
798                         best_dist = 9999999;
799                         best_fit = -1;
800
801                         for (i = 0; i < num_vidmodes; i++) {
802                                 if (width > vidmodes[i]->hdisplay ||
803                                         height > vidmodes[i]->vdisplay)
804                                         continue;
805
806                                 x = width - vidmodes[i]->hdisplay;
807                                 y = height - vidmodes[i]->vdisplay;
808                                 dist = (x * x) + (y * y);
809                                 if (dist < best_dist) {
810                                         best_dist = dist;
811                                         best_fit = i;
812                                 }
813                         }
814
815                         if (best_fit != -1) {
816                                 actualWidth = vidmodes[best_fit]->hdisplay;
817                                 actualHeight = vidmodes[best_fit]->vdisplay;
818
819                                 // change to the mode
820                                 XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
821                                 vidmode_active = true;
822
823                                 // Move the viewport to top left
824                                 XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
825                         } else
826                                 fullscreen = 0;
827                 }
828         }
829
830         /* window attributes */
831         attr.background_pixel = 0;
832         attr.border_pixel = 0;
833         attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
834         attr.event_mask = X_MASK;
835         if (vidmode_active) {
836                 mask = CWBackPixel | CWColormap | CWSaveUnder | CWBackingStore | 
837                         CWEventMask | CWOverrideRedirect;
838                 attr.override_redirect = True;
839                 attr.backing_store = NotUseful;
840                 attr.save_under = False;
841         } else
842                 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
843
844         win = XCreateWindow(dpy, root, 0, 0, width, height,
845                                                 0, visinfo->depth, InputOutput,
846                                                 visinfo->visual, mask, &attr);
847         XMapWindow(dpy, win);
848
849         if (vidmode_active) {
850                 XMoveWindow(dpy, win, 0, 0);
851                 XRaiseWindow(dpy, win);
852                 XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0);
853                 XFlush(dpy);
854                 // Move the viewport to top left
855                 XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
856         }
857
858         XFlush(dpy);
859
860         ctx = glXCreateContext(dpy, visinfo, NULL, True);
861
862         glXMakeCurrent(dpy, win, ctx);
863
864         scr_width = width;
865         scr_height = height;
866
867         if (vid.conheight > height)
868                 vid.conheight = height;
869         if (vid.conwidth > width)
870                 vid.conwidth = width;
871         vid.width = vid.conwidth;
872         vid.height = vid.conheight;
873
874         vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
875
876         InitSig(); // trap evil signals
877
878         GL_Init();
879
880 //      sprintf (gldir, "%s/glquake", com_gamedir);
881 //      Sys_mkdir (gldir);
882
883         VID_SetPalette(palette);
884
885         Check_Gamma(palette);
886
887         VID_Init8bitPalette();
888
889         if (is8bit) // LordHavoc: avoid calculating 15to8 table if it won't be used
890                 VID_Setup15to8Palette ();
891
892         Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);
893
894         vid.recalc_refdef = 1;                          // force a surface cache flush
895 }
896
897 void Sys_SendKeyEvents(void)
898 {
899         HandleEvents();
900 }
901
902 void Force_CenterView_f (void)
903 {
904         cl.viewangles[PITCH] = 0;
905 }
906
907 void IN_Init(void)
908 {
909 }
910
911 void IN_Shutdown(void)
912 {
913 }
914
915 /*
916 ===========
917 IN_Commands
918 ===========
919 */
920 void IN_Commands (void)
921 {
922         if (!dpy || !win)
923                 return;
924
925         if (vidmode_active || key_dest == key_game)
926                 IN_ActivateMouse();
927         else
928                 IN_DeactivateMouse ();
929 }
930
931 /*
932 ===========
933 IN_Move
934 ===========
935 */
936 void IN_MouseMove (usercmd_t *cmd)
937 {
938         if (!mouse_avail)
939                 return;
940    
941         if (m_filter.value)
942         {
943                 mx = (mx + old_mouse_x) * 0.5;
944                 my = (my + old_mouse_y) * 0.5;
945         }
946         old_mouse_x = mx;
947         old_mouse_y = my;
948
949         mx *= sensitivity.value;
950         my *= sensitivity.value;
951
952 // add mouse X/Y movement to cmd
953         if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
954                 cmd->sidemove += m_side.value * mx;
955         else
956                 cl.viewangles[YAW] -= m_yaw.value * mx;
957         
958         if (in_mlook.state & 1)
959                 V_StopPitchDrift ();
960                 
961         if ( (in_mlook.state & 1) && !(in_strafe.state & 1))
962         {
963                 cl.viewangles[PITCH] += m_pitch.value * my;
964                 if (cl.viewangles[PITCH] > 80)
965                         cl.viewangles[PITCH] = 80;
966                 if (cl.viewangles[PITCH] < -70)
967                         cl.viewangles[PITCH] = -70;
968         }
969         else
970         {
971                 if ((in_strafe.state & 1) && noclip_anglehack)
972                         cmd->upmove -= m_forward.value * my;
973                 else
974                         cmd->forwardmove -= m_forward.value * my;
975         }
976         mx = my = 0;
977 }
978
979 void IN_Move (usercmd_t *cmd)
980 {
981         IN_MouseMove(cmd);
982 }
983
984