• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // vid_sunxil.c -- uses X to setup windows and XIL to copy images (scaled as needed)
21 // 		   to screen
22 
23 #define _BSD
24 #define BYTE_DEFINED 1
25 
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <errno.h>
29 #include <thread.h>
30 #include <unistd.h>
31 #include <signal.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <sys/ipc.h>
36 #include <sys/shm.h>
37 #include <X11/Xlib.h>
38 #include <X11/Xutil.h>
39 #include <X11/Xatom.h>
40 #include <X11/keysym.h>
41 #include <xil/xil.h>
42 
43 #include "quakedef.h"
44 #include "d_local.h"
45 
46 #define MIN_WIDTH 320
47 #define MIN_HEIGHT 200
48 
49 cvar_t		_windowed_mouse = {"_windowed_mouse","0", true};
50 cvar_t		m_filter = {"m_filter","0", true};
51 float old_windowed_mouse;
52 
53 // The following X property format is defined in Motif 1.1's
54 // Xm/MwmUtils.h, but QUAKE should not depend on that header
55 // file. Note: Motif 1.2 expanded this structure with
56 // uninteresting fields (to QUAKE) so just stick with the
57 // smaller Motif 1.1 structure.
58 
59 #define MWM_HINTS_DECORATIONS   2
60 typedef struct
61 {
62 	long flags;
63 	long functions;
64 	long decorations;
65 	long input_mode;
66 } MotifWmHints;
67 
68 #define MAX_COLUMN_SIZE	11
69 
70 #define MAX_MODEDESCS	(MAX_COLUMN_SIZE*3)
71 
72 typedef struct
73 {
74     int		modenum;
75     int		iscur;
76     char	desc[256];
77 } modedesc_t;
78 
79 extern void M_Menu_Options_f (void);
80 extern void M_Print (int cx, int cy, char *str);
81 extern void M_PrintWhite (int cx, int cy, char *str);
82 extern void M_DrawCharacter (int cx, int line, int num);
83 extern void M_DrawTransPic (int x, int y, qpic_t *pic);
84 extern void M_DrawPic (int x, int y, qpic_t *pic);
85 
86 extern int sb_updates;
87 
88 qboolean        mouse_avail;
89 int             mouse_buttons=3;
90 int             mouse_oldbuttonstate;
91 int             mouse_buttonstate;
92 float   mouse_x, mouse_y;
93 float   old_mouse_x, old_mouse_y;
94 int p_mouse_x;
95 int p_mouse_y;
96 
97 typedef struct
98 {
99 	int input;
100 	int output;
101 } keymap_t;
102 
103 viddef_t vid; // global video state
104 unsigned short       d_8to16table[256];
105 
106 int		num_shades=32;
107 
108 int	d_con_indirect = 0;
109 
110 int		vid_buffersize;
111 
112 #define STD_EVENT_MASK \
113 ( \
114 	StructureNotifyMask | \
115 	KeyPressMask | \
116 	KeyReleaseMask | \
117 	ButtonPressMask | \
118 	ButtonReleaseMask | \
119 	ExposureMask | \
120 	PointerMotionMask | \
121 	FocusChangeMask \
122 )
123 
124 int		VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
125 byte	*VGA_pagebase;
126 
127 qboolean			x_fullscreen = true;
128 Display				*x_disp = NULL;
129 int				x_screen, x_screen_width, x_screen_height;
130 int				x_center_width, x_center_height;
131 int				x_std_event_mask = STD_EVENT_MASK;
132 Window				x_win, x_root_win;
133 qboolean			x_focus = true;
134 int				global_dx, global_dy;
135 
136 
137 static Colormap			x_cmap;
138 static GC			x_gc;
139 static Visual			*x_vis;
140 static XVisualInfo		*x_visinfo;
141 static Atom			aHints = NULL;
142 static Atom			aWMDelete = NULL;
143 
144 static qboolean			oktodraw = false;
145 static qboolean			X11_active = false;
146 
147 
148 static int verbose=1;
149 
150 static byte current_palette[768];
151 
152 cvar_t pixel_multiply = {"pixel_multiply", "2", true};
153 int current_pixel_multiply = 2;
154 
155 #define PM(a) (int)((current_pixel_multiply)?((a)*current_pixel_multiply):(a))
156 #define MP(a) (int)((current_pixel_multiply)?((a)/current_pixel_multiply):(a))
157 
158 static int 				render_pipeline[2];
159 static XilSystemState 			state;
160 static XilImage				display_image  = NULL;
161 static XilImage				quake_image  = NULL;
162 static int				use_mt = 0;
163 static int				count_frames = 0;
164 
165 /*
166 ================
167 D_BeginDirectRect
168 ================
169 */
D_BeginDirectRect(int x,int y,byte * pbitmap,int width,int height)170 void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
171 {
172 // direct drawing of the "accessing disk" icon isn't supported under Nextstep
173 }
174 
175 
176 /*
177 ================
178 D_EndDirectRect
179 ================
180 */
D_EndDirectRect(int x,int y,int width,int height)181 void D_EndDirectRect (int x, int y, int width, int height)
182 {
183 // direct drawing of the "accessing disk" icon isnt supported under Nextstep
184 }
185 
186 
187 /*
188 =================
189 VID_Gamma_f
190 
191 Keybinding command
192 =================
193 */
194 
195 byte vid_gamma[256];
196 
VID_Gamma_f(void)197 void VID_Gamma_f (void)
198 {
199 
200 	float	g, f, inf;
201 	int		i;
202 
203 	if (Cmd_Argc () == 2) {
204 		g = Q_atof (Cmd_Argv(1));
205 
206 		for (i=0 ; i<255 ; i++)	{
207 			f = pow ((i+1)/256.0, g);
208 			inf = f*255 + 0.5;
209 			if (inf < 0)
210 				inf = 0;
211 			if (inf > 255)
212 				inf = 255;
213 			vid_gamma[i] = inf;
214 		}
215 
216 		VID_SetPalette (current_palette);
217 
218 		vid.recalc_refdef = 1;				// force a surface cache flush
219 	}
220 
221 }
222 
CheckPixelMultiply(void)223 qboolean CheckPixelMultiply (void)
224 {
225 	int m;
226 	int w, h;
227 	XWindowAttributes wattr;
228 	XWindowChanges chg;
229 	unsigned int value_mask;
230 	int old_pixel;
231 
232 	if ((m = (int)pixel_multiply.value) != current_pixel_multiply) {
233 		if (m < 1)
234 			m = 1;
235 		if (m > 4)
236 			m = 4;
237 
238 		old_pixel = current_pixel_multiply;
239 		current_pixel_multiply = m;
240 		Cvar_SetValue("pixel_multiply", m);
241 
242 		if(XGetWindowAttributes(x_disp, x_win, & wattr) == 0)
243 			return true; // ???
244 
245 		memset(&chg, 0, sizeof(chg));
246 		chg.width = wattr.width/old_pixel * current_pixel_multiply;
247 		chg.height = wattr.height/old_pixel * current_pixel_multiply;
248 
249 		if (chg.width < MIN_WIDTH*current_pixel_multiply)
250 			chg.width = MIN_WIDTH*current_pixel_multiply;
251 		if (chg.height < MIN_HEIGHT*current_pixel_multiply)
252 			chg.height = MIN_HEIGHT*current_pixel_multiply;
253 
254 		XConfigureWindow(x_disp, x_win, CWWidth | CWHeight, &chg);
255 
256 		vid.width = MP(wattr.width) & ~3;
257 		vid.height = MP(wattr.height);
258 
259 		if (vid.width < 320)
260 			vid.width = 320;
261 		if (vid.height < 200)
262 			vid.height = 200;
263 		VID_ResetFramebuffer();
264 
265 		return true;
266 	}
267 	return false;
268 }
269 
270 // ========================================================================
271 // Tragic death handler
272 // ========================================================================
273 
TragicDeath(int signal_num)274 void TragicDeath(int signal_num)
275 {
276 	//XAutoRepeatOn(x_disp);
277 	XCloseDisplay(x_disp);
278 	Sys_Error("This death brought to you by the number %d\n", signal_num);
279 }
280 
281 // ========================================================================
282 // makes a null cursor
283 // ========================================================================
284 
CreateNullCursor(Display * display,Window root)285 static Cursor CreateNullCursor(Display *display, Window root)
286 {
287 	Pixmap cursormask;
288 	XGCValues xgc;
289 	GC gc;
290 	XColor dummycolour;
291 	Cursor cursor;
292 
293 	cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
294 	xgc.function = GXclear;
295 	gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
296 	XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
297 	dummycolour.pixel = 0;
298 	dummycolour.red = 0;
299 	dummycolour.flags = 04;
300 	cursor = XCreatePixmapCursor(display, cursormask, cursormask,
301 				     &dummycolour,&dummycolour, 0,0);
302 	XFreePixmap(display,cursormask);
303 	XFreeGC(display,gc);
304 	return cursor;
305 }
306 
307 
VID_MenuDraw(void)308 void VID_MenuDraw( void )
309 {
310 	qpic_t		*p;
311     char		*ptr;
312     int			i, j, column, row, dup;
313     char		temp[100];
314 
315     p = Draw_CachePic ("gfx/vidmodes.lmp");
316     M_DrawPic ( (320-p->width)/2, 4, p);
317 	M_Print (4*8, 36 + MAX_COLUMN_SIZE * 8 + 8, "Video mode switching unavailable");
318 	M_Print (9*8, 36 + MAX_COLUMN_SIZE * 8 + 8*6, "Press any key...");
319 }
320 
VID_MenuKey(int key)321 void VID_MenuKey( int key ) { M_Menu_Options_f (); }
322 
323 // Called at startup to set up translation tables, takes 256 8 bit RGB values
324 // the palette data will go away after the call, so it must be copied off if
325 // the video driver will need it again
326 
327 byte	surfcache[1024*1024];
328 
329 //
330 // VID_SetWindowTitle - set the window and icon titles
331 //
332 
VID_SetWindowTitle(Window win,char * pszName)333 void VID_SetWindowTitle( Window win, char *pszName )
334 {
335 	XTextProperty	textprop;
336 	XWMHints		*wmHints;
337 
338     // Setup ICCCM properties
339     textprop.value = (unsigned char *)pszName;
340     textprop.encoding = XA_STRING;
341     textprop.format = 8;
342     textprop.nitems = strlen(pszName);
343     wmHints = XAllocWMHints();
344     wmHints->initial_state = NormalState;
345     wmHints->flags = StateHint;
346     XSetWMProperties( x_disp, win, &textprop, &textprop,
347 					  // Only put WM_COMMAND property on first window.
348 					  com_argv, com_argc, NULL, NULL, NULL );
349     XFree( wmHints );
350 
351     aWMDelete = XInternAtom( x_disp, "WM_DELETE_WINDOW", False );
352     XSetWMProtocols( x_disp, win, &aWMDelete, 1 );
353 }
354 
355 //
356 // VID_FullScreen - open the window in full screen mode
357 //
358 
VID_FullScreen(Window win)359 qboolean VID_FullScreen( Window win )
360 {
361 	MotifWmHints    hints;
362 	XWindowChanges  changes;
363 
364 	aHints = XInternAtom( x_disp, "_MOTIF_WM_HINTS", 0 );
365 	if (aHints == None) {
366 		Con_Printf( "Could not intern X atom for _MOTIF_WM_HINTS." );
367 		return( false );
368     }
369 
370 	hints.flags = MWM_HINTS_DECORATIONS;
371 	hints.decorations = 0; // Absolutely no decorations.
372 	XChangeProperty( x_disp, win, aHints, aHints, 32, PropModeReplace, (unsigned char *)&hints, 4 );
373 
374 	changes.x = 0;
375 	changes.y = 0;
376 	changes.width = x_screen_width;
377 	changes.height = x_screen_height;
378 	changes.stack_mode = TopIf;
379 	XConfigureWindow( x_disp, win, CWX | CWY | CWWidth | CWHeight | CWStackMode, &changes);
380 	return( true );
381 }
382 
VID_Init(unsigned char * palette)383 void	VID_Init (unsigned char *palette)
384 {
385 
386 	int pnum, i;
387 	XVisualInfo template;
388 	int num_visuals;
389 	int template_mask;
390 	int w, h;
391 
392 	int desired_width=320, desired_height=200;
393 
394 	Cmd_AddCommand ("gamma", VID_Gamma_f);
395 
396 	Cvar_RegisterVariable (&pixel_multiply);
397 
398 	if (pipe(render_pipeline) < 0)
399 		Sys_Error("VID_Init: pipe");
400 
401 	for (i=0 ; i<256 ; i++)
402 		vid_gamma[i] = i;
403 
404 	vid.width = 320;
405 	vid.height = 200;
406 	vid.aspect = 1.0;
407 	vid.numpages = 2;
408 	vid.colormap = host_colormap;
409 	vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
410 	//vid.cbits = VID_CBITS;
411 	//vid.grades = VID_GRADES;
412 
413 	srandom(getpid());
414 
415 	verbose = COM_CheckParm("-verbose");
416 	count_frames = COM_CheckParm("-count_frames");
417 
418 //
419 // open the display
420 //
421 	x_disp = XOpenDisplay(0);
422 
423 	if (!x_disp) {
424 		if (getenv("DISPLAY"))
425 			Sys_Error("VID: Could not open display [%s]\n",
426 				getenv("DISPLAY"));
427 		else
428 			Sys_Error("VID: Could not open local display\n");
429 	}
430 
431 	x_screen = DefaultScreen( x_disp );
432 	x_screen_width = WidthOfScreen( ScreenOfDisplay( x_disp, x_screen ) );
433 	x_screen_height = HeightOfScreen( ScreenOfDisplay( x_disp, x_screen ) );
434 
435 	x_center_width  = x_screen_width/2;
436 
437 	x_center_height = x_screen_height/2;
438 
439 	Con_Printf( "Using screen %d: %dx%d\n", x_screen, x_screen_width, x_screen_height );
440 
441 	x_root_win = DefaultRootWindow( x_disp);
442 
443 	//XAutoRepeatOff(x_disp);
444 
445 // for debugging only
446 	if (verbose)
447 		XSynchronize(x_disp, True);
448 
449 //
450 // check for command-line window size
451 //
452 	if ((pnum=COM_CheckParm("-winsize"))) {
453 		if (pnum >= com_argc-2)
454 			Sys_Error("VID: -winsize <width> <height>\n");
455 		desired_width = Q_atoi(com_argv[pnum+1]);
456 		desired_height = Q_atoi(com_argv[pnum+2]);
457 		if (desired_width < 1 || desired_height < 1)
458 			Sys_Error("VID: Bad window width/height\n");
459 	}
460 
461 	template_mask = VisualScreenMask; // make sure we get the right one
462 	template.screen = x_screen;
463 //
464 // specify a visual id
465 //
466 	if ((pnum=COM_CheckParm("-visualid"))) {
467 		if (pnum >= com_argc-1)
468 			Sys_Error("VID: -visualid <id#>\n");
469 		template.visualid = Q_atoi(com_argv[pnum+1]);
470 		template_mask |= VisualIDMask;
471 	} else	{
472 		// If not specified, find an 8 bit visual since others don't work
473 //		template.depth = 8;
474 //		template_mask |= VisualDepthMask;
475 		int screen;
476 		screen = XDefaultScreen(x_disp);
477 		template.visualid =
478 			XVisualIDFromVisual(XDefaultVisual(x_disp, screen));
479 		template_mask = VisualIDMask;
480 	}
481 //
482 // pick a visual- warn if more than one was available
483 //
484 	x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals);
485 	if (num_visuals > 1) {
486 		printf("Found more than one visual id at depth %d:\n", template.depth);
487 		for (i=0 ; i<num_visuals ; i++)
488 			printf("	-visualid %d\n", (int)(x_visinfo[i].visualid));
489 	}
490 	else if (num_visuals == 0) {
491 		if (template_mask == VisualIDMask)
492 			Sys_Error("VID: Bad visual id %d\n", template.visualid);
493 		else
494 			Sys_Error("VID: No visuals at depth %d\n", template.depth);
495 	}
496 
497 	if (verbose) {
498 		printf("Using visualid %d:\n", (int)(x_visinfo->visualid));
499 		printf("	screen %d\n", x_visinfo->screen);
500 		printf("	red_mask 0x%x\n", (int)(x_visinfo->red_mask));
501 		printf("	green_mask 0x%x\n", (int)(x_visinfo->green_mask));
502 		printf("	blue_mask 0x%x\n", (int)(x_visinfo->blue_mask));
503 		printf("	colormap_size %d\n", x_visinfo->colormap_size);
504 		printf("	bits_per_rgb %d\n", x_visinfo->bits_per_rgb);
505 	}
506 
507 	x_vis = x_visinfo->visual;
508 //
509 // See if we're going to do pixel multiply
510 //
511 	if (pixel_multiply.value < 1 || pixel_multiply.value > 4)
512 		Cvar_SetValue("pixel_multiply", 2);
513 	current_pixel_multiply = pixel_multiply.value;
514 
515 	w = 320*current_pixel_multiply; // minimum width
516 	h = 200*current_pixel_multiply; // minimum height
517 	if (desired_width < w)
518 		desired_width = w;
519 	if (desired_height < h)
520 		desired_height = h;
521 
522 	vid.width = MP(desired_width);
523 	vid.height = MP(desired_height);
524 
525 	//
526 	// patch things up so game doesn't fail if window is too small
527 	//
528 
529 	if (vid.width < 320)
530 		vid.width = 320;
531 	if (vid.height < 200)
532 		vid.height = 200;
533 
534 //
535 // see if we're going to use threads
536 //
537 	if(((sysconf(_SC_NPROCESSORS_ONLN) > 1) || COM_CheckParm("-mt")) &&
538 		(COM_CheckParm("-no_mt") == 0)) {
539 		use_mt = 1;
540 		printf("VID: Using multiple threads!\n");
541 	}
542 
543 // setup attributes for main window
544 	{
545 		int attribmask = CWEventMask  | CWColormap | CWBorderPixel;
546 		XSetWindowAttributes attribs;
547 		Colormap tmpcmap;
548 
549 		tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp,
550 			x_visinfo->screen), x_vis, AllocNone);
551 
552 		attribs.event_mask = x_std_event_mask;
553 		attribs.border_pixel = 0;
554 		attribs.colormap = tmpcmap;
555 
556 // create the main window
557 		x_win = XCreateWindow(	x_disp,
558 			XRootWindow(x_disp, x_visinfo->screen),
559 			0, 0,	// x, y
560 			desired_width, desired_height,
561 			0, // borderwidth
562 			x_visinfo->depth,
563 			InputOutput,
564 			x_vis,
565 			attribmask,
566 			&attribs );
567 
568 		if (x_visinfo->class != TrueColor)
569 			XFreeColormap(x_disp, tmpcmap);
570 
571 	}
572 
573 	if (x_visinfo->depth == 8) {
574 
575 	// create and upload the palette
576 		if (x_visinfo->class == PseudoColor) {
577 			x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll);
578 			VID_SetPalette(palette);
579 			XSetWindowColormap(x_disp, x_win, x_cmap);
580 		}
581 
582 	}
583 
584 	VID_SetWindowTitle( x_win, "Quake" );
585 
586 // inviso cursor
587 	XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win));
588 
589 // create the GC
590 	{
591 		XGCValues xgcvalues;
592 		int valuemask = GCGraphicsExposures;
593 		xgcvalues.graphics_exposures = False;
594 		x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues );
595 	}
596 
597 // map the window
598 	XMapWindow(x_disp, x_win);
599 	XSync(x_disp, True) ;        /* wait for map */
600 //
601 // wait for first exposure event
602 //
603 	{
604 		XEvent event;
605 		do{
606 			XNextEvent(x_disp, &event);
607 			if (event.type == Expose && !event.xexpose.count)
608 				oktodraw = true;
609 		} while (!oktodraw);
610 	}
611 //
612 // initialize XIL
613 //
614 
615 	state = xil_open();
616 
617 	if(state == NULL) {
618 		//
619 		//  XIL's default error handler will print an error msg on stderr
620 		//
621 		Sys_Error("xil_open failed\n");
622 	}
623 
624 	X11_active = true;
625 
626 	VID_ResetFramebuffer();
627 
628 	D_InitCaches (surfcache, sizeof(surfcache));
629 
630 	vid_menudrawfn = VID_MenuDraw;
631 	vid_menukeyfn = VID_MenuKey;
632 }
633 
VID_ResetFramebuffer()634 VID_ResetFramebuffer()
635 {
636 	XilMemoryStorage storage;
637 
638 	if (use_mt) {
639 		VID_ResetFramebuffer_MT();
640 		return;
641 	}
642 
643 //printf("VID_ResetFramebuffer: vid.width %d, vid.height %d\n", vid.width, vid.height);
644 
645 	xil_destroy(display_image);
646 
647 	xil_destroy(quake_image);
648 
649 	display_image = xil_create_from_window(state, x_disp, x_win);
650 	quake_image = xil_create(state, vid.width, vid.height, 1, XIL_BYTE);
651 
652 	xil_export(quake_image);
653 
654 	if (xil_get_memory_storage(quake_image, &storage) == FALSE)
655 		Sys_Error("xil_get_memory_storage");
656 
657 	xil_import(quake_image, TRUE);
658 	xil_export(quake_image);
659 
660 	if (xil_get_memory_storage(quake_image, &storage) == FALSE)
661 		Sys_Error("xil_get_memory_storage");
662 
663 	vid.rowbytes = storage.byte.scanline_stride;
664 	vid.buffer =   storage.byte.data;
665 	vid.conbuffer = vid.buffer;
666 	vid.conrowbytes = vid.rowbytes;
667 	vid.conwidth = vid.width;
668 	vid.conheight = vid.height;
669 
670 	vid.maxwarpwidth = WARP_WIDTH;
671 	vid.maxwarpheight = WARP_HEIGHT;
672 	vid.recalc_refdef = 1;				// force a surface cache flush
673 
674 	free(d_pzbuffer);
675 
676 	d_pzbuffer = malloc(PM(vid.width)*PM(vid.height)*sizeof(*d_pzbuffer));
677         //Hunk_HighAllocName(PM(vid.width)*PM(vid.height)*sizeof(*d_pzbuffer),"zbuff");
678 }
679 
VID_ResetFramebuffer_MT()680 VID_ResetFramebuffer_MT()
681 {
682 	XilMemoryStorage storage;
683 	XilImage drain_renderpipeline();
684 	XilImage old_display_image;
685 
686 	void * update_thread();
687 
688 	printf("VID_ResetFramebuffer: vid.width %d, vid.height %d\n", vid.width, vid.height);
689 
690 	old_display_image = display_image;
691 
692 	display_image = xil_create_from_window(state, x_disp, x_win);
693 
694 	if (quake_image == NULL)
695 		if (thr_create(NULL, NULL, update_thread, NULL, THR_NEW_LWP, NULL) != 0)
696 			Sys_Error("VID: thr_create");
697 
698 	quake_image = drain_renderpipeline(quake_image);
699 
700 	xil_destroy(old_display_image);
701 
702 	free(d_pzbuffer);
703 
704 	d_pzbuffer = malloc(PM(vid.width)*PM(vid.height)*sizeof(*d_pzbuffer));
705 }
706 
VID_ShiftPalette(unsigned char * p)707 void VID_ShiftPalette(unsigned char *p)
708 {
709 	VID_SetPalette(p);
710 }
711 
VID_SetPalette(unsigned char * palette)712 void VID_SetPalette(unsigned char *palette)
713 {
714 
715 	int i;
716 	XColor colors[256];
717 
718 	if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8) {
719 			if (palette != current_palette)
720 				memcpy(current_palette, palette, 768);
721 			for (i=0 ; i<256 ; i++)
722 				{
723 					colors[i].pixel = i;
724 					colors[i].flags = DoRed|DoGreen|DoBlue;
725 					colors[i].red = vid_gamma[palette[i*3]] * 257;
726 					colors[i].green = vid_gamma[palette[i*3+1]] * 257;
727 					colors[i].blue = vid_gamma[palette[i*3+2]] * 257;
728 				}
729 			XStoreColors(x_disp, x_cmap, colors, 256);
730 		}
731 
732 }
733 
734 // Called at shutdown
735 
VID_Shutdown(void)736 void	VID_Shutdown (void)
737 {
738 	X11_active = false;
739 	Con_Printf("VID_Shutdown\n");
740 	//XAutoRepeatOn(x_disp);
741 	xil_destroy(display_image);
742 	xil_destroy(quake_image);
743 	display_image = NULL;
744 	quake_image = NULL;
745 	XCloseDisplay(x_disp);
746 }
747 
XLateKey(XKeyEvent * ev)748 int XLateKey(XKeyEvent *ev)
749 {
750 
751 	int key;
752 	char buf[64];
753 	KeySym keysym;
754 
755 	XLookupString(ev, buf, sizeof buf, &keysym, 0);
756 
757 	switch(keysym) {
758 		case XK_Page_Up:	 key = K_PGUP; break;
759 		case XK_Page_Down:	 key = K_PGDN; break;
760 		case XK_Home:	 key = K_HOME; break;
761 		case XK_End:	 key = K_END; break;
762 		case XK_Left:	 key = K_LEFTARROW; break;
763 		case XK_Right:	key = K_RIGHTARROW;		break;
764 		case XK_Down:	 key = K_DOWNARROW; break;
765 		case XK_Up:		 key = K_UPARROW;	 break;
766 		case XK_Escape: key = K_ESCAPE;		break;
767 		case XK_Return: key = K_ENTER;		 break;
768 		case XK_Tab:		key = K_TAB;			 break;
769 		case XK_Help:
770 		case XK_F1:		 key = K_F1;				break;
771 		case XK_F2:		 key = K_F2;				break;
772 		case XK_F3:		 key = K_F3;				break;
773 		case XK_F4:		 key = K_F4;				break;
774 		case XK_F5:		 key = K_F5;				break;
775 		case XK_F6:		 key = K_F6;				break;
776 		case XK_F7:		 key = K_F7;				break;
777 		case XK_F8:		 key = K_F8;				break;
778 		case XK_F9:		 key = K_F9;				break;
779 		case XK_F10:		key = K_F10;			 break;
780 		case XK_F11:		key = K_F11;			 break;
781 		case XK_F12:		key = K_F12;			 break;
782 		case XK_BackSpace:
783 		case XK_Delete: key = K_BACKSPACE; break;
784 		case XK_Pause:	key = K_PAUSE;		 break;
785 		case XK_Shift_L:
786 		case XK_Shift_R:		key = K_SHIFT;		break;
787 		case XK_Control_L:
788 		case XK_Control_R:	key = K_CTRL;		 break;
789 		case XK_Alt_L:
790 		case XK_Meta_L:
791 		case XK_Alt_R:
792 		case XK_Meta_R: key = K_ALT;			break;
793 			// various other keys on the keyboard
794 				   case XK_F27: key = K_HOME; break;
795 		case XK_F29: key = K_PGUP; break;
796 		case XK_F33: key = K_END; break;
797 		case XK_F35: key = K_PGDN; break;
798 		case XK_Insert:
799 		case XK_KP_Insert: key = K_INS; break;
800 		case XK_F24: key = '-'; break;
801 		case XK_KP_Add: key = '+'; break;
802 		case XK_KP_Subtract: key = '-'; break;
803 		case XK_F25: key = '/'; break;
804 		case XK_F26: key = '*'; break;
805 
806 		default:
807 			key = (unsigned char)*buf;
808 			break;
809 		}
810 
811 	return key;
812 
813 }
814 
815 struct {
816 	int key;
817 	int down;
818 } keyq[64];
819 
820 int keyq_head=0;
821 int keyq_tail=0;
822 
823 int config_notify=0;
824 int config_notify_width;
825 int config_notify_height;
826 
GetEvent(void)827 void GetEvent(void)
828 {
829 	XEvent x_event;
830 	int b;
831 
832 	XNextEvent(x_disp, &x_event);
833 	switch(x_event.type) {
834 		case KeyPress:
835 			Key_Event(XLateKey(&x_event.xkey), true);
836 			break;
837 		case KeyRelease:
838 			Key_Event(XLateKey(&x_event.xkey), false);
839 			break;
840 
841 		case MotionNotify:
842 
843 			if (_windowed_mouse.value) {
844 				mouse_x = (float) ((int)x_event.xmotion.x - (int)(vid.width/2));
845 				mouse_y = (float) ((int)x_event.xmotion.y - (int)(vid.height/2));
846 	//printf("m: x=%d,y=%d, mx=%3.2f,my=%3.2f\n",
847 	//	x_event.xmotion.x, x_event.xmotion.y, mouse_x, mouse_y);
848 
849 				/* move the mouse to the window center again */
850 				XSelectInput( x_disp, x_win, x_std_event_mask & ~PointerMotionMask );
851 				XWarpPointer(x_disp,None,x_win,0,0,0,0,
852 					(vid.width/2),(vid.height/2));
853 				XSelectInput( x_disp, x_win, x_std_event_mask );
854 			} else {
855 				mouse_x = (float) (x_event.xmotion.x-p_mouse_x);
856 				mouse_y = (float) (x_event.xmotion.y-p_mouse_y);
857 				p_mouse_x=x_event.xmotion.x;
858 				p_mouse_y=x_event.xmotion.y;
859 			}
860 			break;
861 
862 		case ButtonPress:
863 			b=-1;
864 			if (x_event.xbutton.button == 1)
865 				b = 0;
866 			else if (x_event.xbutton.button == 2)
867 				b = 2;
868 			else if (x_event.xbutton.button == 3)
869 				b = 1;
870 			if (b>=0)
871 				mouse_buttonstate |= 1<<b;
872 			break;
873 
874 		case ButtonRelease:
875 			b=-1;
876 			if (x_event.xbutton.button == 1)
877 				b = 0;
878 			else if (x_event.xbutton.button == 2)
879 				b = 2;
880 			else if (x_event.xbutton.button == 3)
881 				b = 1;
882 			if (b>=0)
883 				mouse_buttonstate &= ~(1<<b);
884 			break;
885 
886 		case ConfigureNotify:
887 			//			printf("config notify\n");
888 			config_notify_width = x_event.xconfigure.width;
889 			config_notify_height = x_event.xconfigure.height;
890 			config_notify = 1;
891 			sb_updates = 0;
892 			break;
893 		case Expose:
894 			sb_updates = 0;
895 			break;
896 		case ClientMessage:
897 			if (x_event.xclient.data.l[0] == aWMDelete) Host_Quit_f();
898 			break;
899 #if 0
900 		case FocusIn:
901 			printf("FocusIn...\n");
902 			x_focus = true;
903 			break;
904 		case FocusOut:
905 			printf("FocusOut...\n");
906 			x_focus = false;
907 			break;
908 #endif
909 	}
910 
911 	if (old_windowed_mouse != _windowed_mouse.value) {
912 		old_windowed_mouse = _windowed_mouse.value;
913 
914 		if (!_windowed_mouse.value) {
915 			/* ungrab the pointer */
916 			XUngrabPointer(x_disp,CurrentTime);
917 		} else {
918 			/* grab the pointer */
919 			XGrabPointer(x_disp,x_win,True,0,GrabModeAsync,
920 				GrabModeAsync,x_win,None,CurrentTime);
921 		}
922 	}
923 }
924 
925 // flushes the given rectangles from the view buffer to the screen
926 
927 void
VID_Update(vrect_t * rects)928 VID_Update (vrect_t *rects)
929 {
930 	void VID_Update_MT(vrect_t *);
931 
932 
933 	if (count_frames) {
934 		static int count;
935 		static long long s;
936 		long long gethrtime();
937 
938 		if (count == 0)
939 			s = gethrtime();
940 
941 		if (count++ == 200) {
942 			long long n = gethrtime();
943 			count = 1;
944 			printf("%lf frames/secs\n", 200.0/((double)(n-s) / 1e9));
945 			s = n;
946 		}
947 	}
948 
949 	if (use_mt) {
950 		VID_Update_MT(rects);
951 		return;
952 	}
953 
954 	// if the window changes dimension, skip this frame
955 
956 	if (config_notify) {
957 		int w, h;
958 		XWindowChanges chg;
959 		unsigned int value_mask;
960 
961 		w = 320*current_pixel_multiply; // minimum width
962 		h = 200*current_pixel_multiply; // minimum height
963 
964 		if (config_notify_width < w || config_notify_height < h) {
965 			// We must resize the window
966 			memset(&chg, 0, sizeof(chg));
967 			value_mask = 0;
968 			if (config_notify_width < w) {
969 				config_notify_width = chg.width = w;
970 				value_mask |= CWWidth;
971 			}
972 			if (config_notify_height < h) {
973 				config_notify_height = chg.height = h;
974 				value_mask |= CWHeight;
975 			}
976 			if (value_mask)
977 				XConfigureWindow(x_disp, x_win, value_mask, &chg);
978 		}
979 
980 		config_notify = 0;
981 
982 		vid.width = MP(config_notify_width) & ~3;
983 		vid.height = MP(config_notify_height);
984 
985 		if (vid.width < 320)
986 			vid.width = 320;
987 		if (vid.height < 200)
988 			vid.height = 200;
989 
990 		VID_ResetFramebuffer();
991 
992 		return;
993 	}
994 	// if pixel multiply changed, skip this frame
995 	if (CheckPixelMultiply())
996 		return;
997 
998 	while (rects) { // I've never seen more than one rect?
999 		XilMemoryStorage storage;
1000 
1001 		xil_import(quake_image, TRUE); // let xil control the image
1002 
1003 		if (current_pixel_multiply < 2)
1004 			xil_copy(quake_image, display_image);
1005 		else
1006 			xil_scale(quake_image, display_image, "nearest",
1007 				  (float)current_pixel_multiply, (float)current_pixel_multiply);
1008 
1009 		xil_export(quake_image);  // back to quake
1010 
1011 		if (xil_get_memory_storage(quake_image, &storage) == FALSE)
1012 			Sys_Error("xil_get_memory_storage");
1013 
1014 		vid.buffer =   storage.byte.data;
1015 		vid.conbuffer = vid.buffer;
1016 
1017 		rects = rects->pnext;
1018 	}
1019 }
1020 
1021 void
VID_Update_MT(vrect_t * rects)1022 VID_Update_MT (vrect_t *rects)
1023 {
1024 	XilImage sched_update();
1025 
1026 	// if the window changes dimension, skip this frame
1027 
1028 	if (config_notify) {
1029 		int w, h;
1030 		XWindowChanges chg;
1031 		unsigned int value_mask;
1032 
1033 		w = 320*current_pixel_multiply; // minimum width
1034 		h = 200*current_pixel_multiply; // minimum height
1035 
1036 		if (config_notify_width < w || config_notify_height < h) {
1037 			// We must resize the window
1038 			memset(&chg, 0, sizeof(chg));
1039 			value_mask = 0;
1040 			if (config_notify_width < w) {
1041 				config_notify_width = chg.width = w;
1042 				value_mask |= CWWidth;
1043 			}
1044 			if (config_notify_height < h) {
1045 				config_notify_height = chg.height = h;
1046 				value_mask |= CWHeight;
1047 			}
1048 			if (value_mask)
1049 				XConfigureWindow(x_disp, x_win, value_mask, &chg);
1050 		}
1051 
1052 		config_notify = 0;
1053 
1054 		vid.width = MP(config_notify_width) & ~3;
1055 		vid.height = MP(config_notify_height);
1056 
1057 		if (vid.width < 320)
1058 			vid.width = 320;
1059 		if (vid.height < 200)
1060 			vid.height = 200;
1061 
1062 		VID_ResetFramebuffer_MT();
1063 
1064 		return;
1065 	}
1066 	// if pixel multiply changed, skip this frame
1067 	if (CheckPixelMultiply())
1068 		return;
1069 
1070 	quake_image = sched_update(quake_image);
1071 }
1072 
1073 XilImage
drain_renderpipeline(XilImage old)1074 drain_renderpipeline(XilImage old)
1075 {
1076 	XilImage new;
1077 
1078 	XilMemoryStorage storage;
1079 
1080 	if (old)
1081 		if (read(render_pipeline[1], &new, sizeof(new)) != sizeof (new)) {
1082 			Sys_Error("drain_renderpipeline: read");
1083 			xil_destroy(new);
1084 		}
1085 
1086 	xil_destroy(old);
1087 
1088 
1089 	new = xil_create(state, vid.width, vid.height, 1, XIL_BYTE);
1090 
1091 	if (write(render_pipeline[0], &new, sizeof (new)) != sizeof(new))
1092 		Sys_Error("drain_renderpipeline: write");
1093 
1094 	new = xil_create(state, vid.width, vid.height, 1, XIL_BYTE);
1095 
1096 	xil_export(new);
1097 
1098 	if (xil_get_memory_storage(new, &storage) == FALSE)
1099 		Sys_Error("xil_get_memory_storage");
1100 
1101 	vid.rowbytes = storage.byte.scanline_stride;
1102 	vid.buffer =   storage.byte.data;
1103 	vid.conbuffer = vid.buffer;
1104 	vid.conrowbytes = vid.rowbytes;
1105 	vid.conwidth = vid.width;
1106 	vid.conheight = vid.height;
1107 
1108 	vid.maxwarpwidth = WARP_WIDTH;
1109 	vid.maxwarpheight = WARP_HEIGHT;
1110 	vid.recalc_refdef = 1;				// force a surface cache flush
1111 
1112 	return(new);
1113 
1114 }
1115 
1116 XilImage
sched_update(XilImage image)1117 sched_update(XilImage image)
1118 {
1119 	XilImage new;
1120 	XilMemoryStorage storage;
1121 
1122 	if (write(render_pipeline[1], &image, sizeof(image)) != sizeof (image))
1123 		Sys_Error("sched_update:write");
1124 
1125 	if (read(render_pipeline[1], &new, sizeof(new)) != sizeof (new))
1126 		Sys_Error("sched_update:read");
1127 
1128 	xil_export(new);
1129 
1130 	if (xil_get_memory_storage(new, &storage) == FALSE)
1131 		Sys_Error("xil_get_memory_storage");
1132 
1133 	vid.buffer =   storage.byte.data;
1134 	vid.conbuffer = vid.buffer;
1135 
1136 	return (new);
1137 }
1138 
update_thread()1139 void *update_thread()
1140 {
1141 	XilImage image;
1142 
1143 	if (!X11_active)
1144 		return;
1145 
1146 	while (read(render_pipeline[0], &image, sizeof (image)) == sizeof(image)) {
1147 
1148 		xil_import(image, TRUE); // let xil control the image
1149 
1150 		if (!display_image)
1151 			return;
1152 
1153 		if (current_pixel_multiply < 2)
1154 			xil_copy(image, display_image);
1155 		else
1156 			xil_scale(image, display_image, "nearest",
1157 				  (float)current_pixel_multiply, (float)current_pixel_multiply);
1158 
1159 		if (write(render_pipeline[0], &image, sizeof (image)) != sizeof(image))
1160 			Sys_Error("update_thread: write");
1161 	}
1162 }
1163 
1164 
1165 static int dither;
1166 
VID_DitherOn(void)1167 void VID_DitherOn(void)
1168 {
1169 	if (dither == 0) {
1170 		vid.recalc_refdef = 1;
1171 		dither = 1;
1172 	}
1173 }
1174 
VID_DitherOff(void)1175 void VID_DitherOff(void)
1176 {
1177 	if (dither) {
1178 		vid.recalc_refdef = 1;
1179 		dither = 0;
1180 	}
1181 }
1182 
VID_SetDefaultMode(void)1183 void VID_SetDefaultMode( void )
1184 {
1185 }
1186 
I_OpenWindow(void)1187 int I_OpenWindow(void)
1188 {
1189 	return 0;
1190 }
1191 
I_EraseWindow(int window)1192 void I_EraseWindow(int window)
1193 {
1194 
1195 }
1196 
I_DrawCircle(int window,int x,int y,int r)1197 void I_DrawCircle(int window, int x, int y, int r)
1198 {
1199 }
1200 
I_DisplayWindow(int window)1201 void I_DisplayWindow(int window)
1202 {
1203 }
1204 
Sys_SendKeyEvents(void)1205 void Sys_SendKeyEvents(void)
1206 {
1207 	// get events from x server
1208 		   if (x_disp) {
1209 				   while (XPending(x_disp)) GetEvent();
1210 				   while (keyq_head != keyq_tail) {
1211 						   Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].down);
1212 						   keyq_tail = (keyq_tail + 1) & 63;
1213 					   }
1214 			   }
1215 }
1216 
IN_Init(void)1217 void IN_Init (void)
1218 {
1219 	Cvar_RegisterVariable (&_windowed_mouse);
1220 	Cvar_RegisterVariable (&m_filter);
1221    if ( COM_CheckParm ("-nomouse") )
1222      return;
1223    mouse_x = mouse_y = 0.0;
1224    mouse_avail = 1;
1225 }
1226 
IN_Shutdown(void)1227 void IN_Shutdown (void)
1228 {
1229    mouse_avail = 0;
1230 }
1231 
IN_Commands(void)1232 void IN_Commands (void)
1233 {
1234 	int i;
1235 
1236 	if (!mouse_avail) return;
1237 
1238 	for (i=0 ; i<mouse_buttons ; i++) {
1239 		if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
1240 			Key_Event (K_MOUSE1 + i, true);
1241 
1242 		if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
1243 			Key_Event (K_MOUSE1 + i, false);
1244 	}
1245 	mouse_oldbuttonstate = mouse_buttonstate;
1246 }
1247 
IN_Move(usercmd_t * cmd)1248 void IN_Move (usercmd_t *cmd)
1249 {
1250 	if (!mouse_avail)
1251 		return;
1252 
1253 	if (m_filter.value) {
1254 		mouse_x = (mouse_x + old_mouse_x) * 0.5;
1255 		mouse_y = (mouse_y + old_mouse_y) * 0.5;
1256 	}
1257 
1258 	old_mouse_x = mouse_x;
1259 	old_mouse_y = mouse_y;
1260 
1261 	mouse_x *= sensitivity.value;
1262 	mouse_y *= sensitivity.value;
1263 
1264 	if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
1265 		cmd->sidemove += m_side.value * mouse_x;
1266 	else
1267 		cl.viewangles[YAW] -= m_yaw.value * mouse_x;
1268 	if (in_mlook.state & 1)
1269 		V_StopPitchDrift ();
1270 
1271 	if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) {
1272 		cl.viewangles[PITCH] += m_pitch.value * mouse_y;
1273 		if (cl.viewangles[PITCH] > 80)
1274 			cl.viewangles[PITCH] = 80;
1275 		if (cl.viewangles[PITCH] < -70)
1276 			cl.viewangles[PITCH] = -70;
1277 	} else {
1278 		if ((in_strafe.state & 1) && noclip_anglehack)
1279 			cmd->upmove -= m_forward.value * mouse_y;
1280 		else
1281 			cmd->forwardmove -= m_forward.value * mouse_y;
1282 	}
1283 	mouse_x = mouse_y = 0.0;
1284 }
1285 
1286 //void VID_UnlockBuffer(void) { }
1287 //void VID_LockBuffer(void) { }
1288 
1289