Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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 
27
#include 
28
#include 
29
#include 
30
#include 
31
#include 
32
#include 
33
#include 
34
#include 
35
#include 
36
#include 
37
#include 
38
#include 
39
#include 
40
#include 
41
#include 
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
*/
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
*/
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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  \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 \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
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
 
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
 
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
 
707
void VID_ShiftPalette(unsigned char *p)
708
{
709
	VID_SetPalette(p);
710
}
711
 
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
 
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
 
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
 
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<
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<
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
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
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
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
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
 
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
 
1167
void VID_DitherOn(void)
1168
{
1169
	if (dither == 0) {
1170
		vid.recalc_refdef = 1;
1171
		dither = 1;
1172
	}
1173
}
1174
 
1175
void VID_DitherOff(void)
1176
{
1177
	if (dither) {
1178
		vid.recalc_refdef = 1;
1179
		dither = 0;
1180
	}
1181
}
1182
 
1183
void VID_SetDefaultMode( void )
1184
{
1185
}
1186
 
1187
int I_OpenWindow(void)
1188
{
1189
	return 0;
1190
}
1191
 
1192
void I_EraseWindow(int window)
1193
{
1194
 
1195
}
1196
 
1197
void I_DrawCircle(int window, int x, int y, int r)
1198
{
1199
}
1200
 
1201
void I_DisplayWindow(int window)
1202
{
1203
}
1204
 
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
 
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
 
1227
void IN_Shutdown (void)
1228
{
1229
   mouse_avail = 0;
1230
}
1231
 
1232
void IN_Commands (void)
1233
{
1234
	int i;
1235
 
1236
	if (!mouse_avail) return;
1237
 
1238
	for (i=0 ; i
1239
		if ( (mouse_buttonstate & (1<
1240
			Key_Event (K_MOUSE1 + i, true);
1241
 
1242
		if ( !(mouse_buttonstate & (1<
1243
			Key_Event (K_MOUSE1 + i, false);
1244
	}
1245
	mouse_oldbuttonstate = mouse_buttonstate;
1246
}
1247
 
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