1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * X interface
5 *
6 * Copyright 1995, 1996 Bernd Schmidt
7 * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste
8 * Copyright 1998 Marcus Sundberg
9 * DGA support by Kai Kollmorgen
10 * X11/DGA merge, hotkeys and grabmouse by Marcus Sundberg
11 * Copyright 2003-2007 Richard Drummond
12 */
13
14 #include "sysconfig.h"
15 #include "sysdeps.h"
16
17 #include <X11/Xlib.h>
18 #include <X11/Xutil.h>
19 #include <X11/keysym.h>
20 #include <X11/cursorfont.h>
21
22 #include <ctype.h>
23
24 #include "cfgfile.h"
25 #include "uae.h"
26 #include "memory_uae.h"
27 #include "xwin.h"
28 #include "custom.h"
29 #include "drawing.h"
30 #include "newcpu.h"
31 #include "keyboard.h"
32 #include "keybuf.h"
33 #include "gui.h"
34 #include "debug.h"
35 #include "picasso96.h"
36 #include "inputdevice.h"
37 #include "hotkeys.h"
38 #include "keymap/keymap.h"
39 #include "keymap/keymap_all.h"
40
41 #ifdef __cplusplus
42 #define VI_CLASS c_class
43 #else
44 #define VI_CLASS class
45 #endif
46
47 #ifdef USE_DGA_EXTENSION
48
49 #ifdef USE_VIDMODE_EXTENSION
50 #include <X11/extensions/xf86vmode.h>
51 #define VidMode_MINMAJOR 0
52 #define VidMode_MINMINOR 0
53 #endif
54
55 #include <X11/extensions/Xxf86dga.h>
56 #define DGA_MINMAJOR 0
57 #define DGA_MINMINOR 0
58
59 #endif /* USE_DGA_EXTENSION */
60
61 #if SHM_SUPPORT_LINKS == 1
62
63 #include <sys/ipc.h>
64 #include <sys/shm.h>
65 #include <X11/extensions/XShm.h>
66
67 #define DO_PUTIMAGE(IMG, SRCX, SRCY, DSTX, DSTY, WIDTH, HEIGHT) \
68 do { \
69 if (currprefs.x11_use_mitshm && shmavail) \
70 XShmPutImage (display, mywin, mygc, (IMG), (SRCX), (SRCY), (DSTX), (DSTY), (WIDTH), (HEIGHT), 0); \
71 else \
72 XPutImage (display, mywin, mygc, (IMG), (SRCX), (SRCY), (DSTX), (DSTY), (WIDTH), (HEIGHT)); \
73 } while (0)
74 #else
75 #define DO_PUTIMAGE(IMG, SRCX, SRCY, DSTX, DSTY, WIDTH, HEIGHT) \
76 XPutImage (display, mywin, mygc, (IMG), (SRCX), (SRCY), (DSTX), (DSTY), (WIDTH), (HEIGHT))
77 #endif
78
79 /* internal types */
80 struct disp_info {
81 XImage *ximg;
82 char *image_mem;
83 #if SHM_SUPPORT_LINKS == 1
84 XShmSegmentInfo shminfo;
85 #endif
86 };
87
88
89 /* internal members */
90 static Display *display;
91 static int screen;
92 static Window rootwin, mywin;
93 static Atom delete_win;
94
95 static GC mygc;
96 static XColor black, white;
97 static Colormap cmap, cmap2;
98 static int red_bits, green_bits, blue_bits;
99 static int red_shift, green_shift, blue_shift;
100
101 #ifdef USE_DGA_EXTENSION
102 /* Kludge-O-Matic.
103 * Unfortunately the X server loses colormap changes in DGA mode. Switching
104 * back and forth between two identical colormaps fixes this problem. */
105 static int dga_colormap_installed;
106 #endif
107
108 static int need_dither;
109
110 extern int screen_is_picasso;
111 static char picasso_invalid_lines[1201];
112 static int picasso_has_invalid_lines;
113 static int picasso_invalid_start, picasso_invalid_stop;
114 static int picasso_maxw = 0, picasso_maxh = 0;
115
116 static int autorepeatoff = 0;
117 static struct disp_info ami_dinfo, pic_dinfo;
118 static Visual *vis;
119 static XVisualInfo visualInfo;
120 static int bitdepth, bit_unit;
121 static Cursor blankCursor, xhairCursor;
122 static int cursorOn;
123 static int inverse_byte_order = 0;
124
125 static int current_width, current_height;
126
127 static int x11_init_ok;
128 static int dgaavail = 0, vidmodeavail = 0, shmavail = 0;
129 static int dgamode;
130 static int grabbed;
131 static int mousehack;
132
133 static int rawkeys_available;
134 static struct uae_input_device_kbr_default *raw_keyboard;
135
136 void toggle_mousegrab (void);
137 int xkeysym2amiga (int);
138 struct uae_hotkeyseq *get_x11_default_hotkeys (void);
139 const char *get_xkb_keycodes (Display *display);
140
141 static int oldx, oldy;
142 static int inwindow;
143
144 #define EVENTMASK (KeyPressMask|KeyReleaseMask|ButtonPressMask \
145 |ButtonReleaseMask|PointerMotionMask \
146 |FocusChangeMask|EnterWindowMask \
147 |ExposureMask |LeaveWindowMask)
148 #define DGA_EVENTMASK (KeyPressMask|KeyReleaseMask|ButtonPressMask \
149 |ButtonReleaseMask|PointerMotionMask)
150
151 #if SHM_SUPPORT_LINKS == 1
152 /* Hack to detect shm-failure, probably due to displaying on a
153 * remote server. */
154 static int shmerror;
155
156
157 /* internal prototypes */
158 int mousehack_allowed (void);
159 void setmaintitle(void);
160 void gfx_save_options (FILE *, const struct uae_prefs *);
161 int gfx_parse_option (struct uae_prefs *, const char *, const char *);
162 void gfx_default_options (struct uae_prefs *);
163 int is_vsync (void);
164 void gfx_save_options (FILE *, const struct uae_prefs *);
165 int gfx_parse_option (struct uae_prefs *, const char *, const char *);
166 void gfx_default_options (struct uae_prefs *);
167 static int (*oldshmerrorhandler) (Display *, XErrorEvent *);
168
169
170 /* implementations */
shmerrorhandler(Display * dsp,XErrorEvent * ev)171 static int shmerrorhandler (Display *dsp, XErrorEvent *ev)
172 {
173 if (ev->error_code == BadAccess)
174 shmerror=1;
175 else
176 (*oldshmerrorhandler) (dsp, ev);
177 return 0;
178 }
179 #endif
180
get_image(int w,int h,struct disp_info * dispi)181 static void get_image (int w, int h, struct disp_info *dispi)
182 {
183 XImage *new_img;
184 char *p;
185
186 #if SHM_SUPPORT_LINKS == 1
187 if (currprefs.x11_use_mitshm && shmavail) {
188 XShmSegmentInfo *shminfo = &dispi->shminfo;
189
190 new_img = XShmCreateImage (display, vis, bitdepth, ZPixmap, 0, shminfo, w, h);
191
192 shminfo->shmid = shmget (IPC_PRIVATE, h * new_img->bytes_per_line,
193 IPC_CREAT | 0777);
194 shminfo->shmaddr = new_img->data = (char *)shmat (shminfo->shmid, 0, 0);
195 dispi->image_mem = new_img->data;
196 shminfo->readOnly = False;
197 /* Try to let the Xserver attach */
198 shmerror = 0;
199 oldshmerrorhandler = XSetErrorHandler (shmerrorhandler);
200 XShmAttach (display, shminfo);
201 XSync (display, 0);
202 XSetErrorHandler (oldshmerrorhandler);
203 if (shmerror) {
204 shmdt (shminfo->shmaddr);
205 XDestroyImage (new_img);
206 shminfo->shmid = -1;
207 shmavail = 0;
208 write_log ("MIT-SHM extension failed, trying fallback.\n");
209 } else {
210 /* now deleting means making it temporary */
211 shmctl (shminfo->shmid, IPC_RMID, 0);
212 dispi->ximg = new_img;
213 write_log ("Using MIT-SHM extension.\n");
214 return;
215 }
216 }
217 #endif
218
219 /* Question for people who know about X: Could we allocate the buffer
220 * after creating the image and then do new_img->data = buffer, as above in
221 * the SHM case?
222 */
223 write_log ("Using normal image buffer.\n");
224 p = (char *)xmalloc (char, h * w * ((bit_unit + 7) / 8)); /* ??? */
225 new_img = XCreateImage (display, vis, bitdepth, ZPixmap, 0, p,
226 w, h, 32, 0);
227 if (new_img->bytes_per_line != w * ((bit_unit + 7) / 8))
228 write_log ("Possible bug here... graphics may look strange.\n");
229
230 dispi->image_mem = p;
231 dispi->ximg = new_img;
232 }
233
get_best_visual(Display * display,int screen,XVisualInfo * vi)234 static int get_best_visual (Display *display, int screen, XVisualInfo *vi)
235 {
236 /* try for a 12 bit visual first, then a 16 bit, then a 24 bit, then 8 bit */
237 if (XMatchVisualInfo (display, screen, 12, TrueColor, vi)) {
238 } else if (XMatchVisualInfo (display, screen, 15, TrueColor, vi)) {
239 } else if (XMatchVisualInfo (display, screen, 16, TrueColor, vi)) {
240 } else if (XMatchVisualInfo (display, screen, 24, TrueColor, vi)) {
241 } else if (XMatchVisualInfo (display, screen, 32, TrueColor, vi)) {
242 } else if (XMatchVisualInfo (display, screen, 8, PseudoColor, vi)) {
243 /* for our HP boxes */
244 } else if (XMatchVisualInfo (display, screen, 8, GrayScale, vi)) {
245 } else if (XMatchVisualInfo (display, screen, 4, PseudoColor, vi)) {
246 /* VGA16 server. Argh. */
247 } else if (XMatchVisualInfo (display, screen, 1, StaticGray, vi)) {
248 /* Mono server. Yuk */
249 } else {
250 write_log ("Can't obtain appropriate X visual.\n");
251 return 0;
252 }
253 return 1;
254 }
255
get_visual_bit_unit(XVisualInfo * vi,int bitdepth)256 static int get_visual_bit_unit (XVisualInfo *vi, int bitdepth)
257 {
258 int bit_unit = 0;
259 XPixmapFormatValues *xpfvs;
260 int i,j;
261
262 /* We now have the bitdepth of the display, but that doesn't tell us yet
263 * how many bits to use per pixel. The VGA16 server has a bitdepth of 4,
264 * but uses 1 byte per pixel. */
265 xpfvs = XListPixmapFormats (display, &i);
266 for (j = 0; j < i && xpfvs[j].depth != bitdepth; j++)
267 ;
268 if (j < i)
269 bit_unit = xpfvs[j].bits_per_pixel;
270 XFree (xpfvs);
271 if (j == i) {
272 write_log ("Your X server is feeling ill.\n");
273 }
274
275 return bit_unit;
276 }
277
278 #ifdef USE_VIDMODE_EXTENSION
279 static XF86VidModeModeInfo **allmodes;
280 static int vidmodecount;
281
get_vidmodes(void)282 static int get_vidmodes (void)
283 {
284 return XF86VidModeGetAllModeLines (display, screen, &vidmodecount, &allmodes);
285 }
286 #endif
287
288 #ifdef USE_DGA_EXTENSION
289
290 static int fb_bank, fb_banks, fb_mem;
291 static char *fb_addr;
292 static int fb_width;
293
switch_to_best_mode(void)294 static void switch_to_best_mode (void)
295 {
296 Screen *scr = ScreenOfDisplay (display, screen);
297 int w = WidthOfScreen (scr);
298 int h = HeightOfScreen (scr);
299 int d = DefaultDepthOfScreen (scr);
300 #ifdef USE_VIDMODE_EXTENSION
301 int i, best;
302 if (vidmodeavail) {
303 best = 0;
304 for (i = 1; i < vidmodecount; i++) {
305 if (allmodes[i]->hdisplay >= current_width
306 && allmodes[i]->vdisplay >= current_height
307 && allmodes[i]->hdisplay <= allmodes[best]->hdisplay
308 && allmodes[i]->vdisplay <= allmodes[best]->vdisplay)
309 best = i;
310 }
311 write_log ("entering DGA mode: %dx%d (%d, %d)\n",
312 allmodes[best]->hdisplay, allmodes[best]->vdisplay,
313 current_width, current_height);
314 XF86VidModeSwitchToMode (display, screen, allmodes[best]);
315 XF86VidModeSetViewPort (display, screen, 0, 0);
316 }
317 #endif
318 XMoveWindow (display, mywin, 0, 0);
319 XWarpPointer (display, None, rootwin, 0, 0, 0, 0, 0, 0);
320 XF86DGADirectVideo (display, screen, XF86DGADirectGraphics | XF86DGADirectMouse | XF86DGADirectKeyb);
321 XF86DGASetViewPort (display, screen, 0, 0);
322 memset (fb_addr, 0, (w * h) * (d / 8));
323 }
324
enter_dga_mode(void)325 static void enter_dga_mode (void)
326 {
327 XRaiseWindow (display, mywin);
328
329 /* We want all the key presses */
330 XGrabKeyboard (display, rootwin, 1, GrabModeAsync,
331 GrabModeAsync, CurrentTime);
332
333 /* and all the mouse moves */
334 XGrabPointer (display, rootwin, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
335 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
336
337 switch_to_best_mode ();
338
339 gfxvidinfo.rowbytes = fb_width*gfxvidinfo.pixbytes;
340 gfxvidinfo.bufmem = (unsigned char*)fb_addr;
341 gfxvidinfo.linemem = 0;
342 gfxvidinfo.emergmem = malloc (gfxvidinfo.rowbytes);
343 gfxvidinfo.maxblocklines = MAXBLOCKLINES_MAX;
344 }
345
leave_dga_mode(void)346 static void leave_dga_mode (void)
347 {
348 XF86DGADirectVideo (display, screen, 0);
349 XUngrabPointer (display, CurrentTime);
350 XUngrabKeyboard (display, CurrentTime);
351 #ifdef USE_VIDMODE_EXTENSION
352 if (vidmodeavail)
353 XF86VidModeSwitchToMode (display, screen, allmodes[0]);
354 #endif
355 }
356 #endif
357
358
359 /*
360 * Dummy buffer methods.
361 */
x11_lock(struct vidbuf_description * gfxinfo)362 static int x11_lock (struct vidbuf_description *gfxinfo)
363 {
364 return 1;
365 }
366
x11_unlock(struct vidbuf_description * gfxinfo)367 static void x11_unlock (struct vidbuf_description *gfxinfo)
368 {
369 }
370
371 /*
372 * Flush screen method
373 */
x11_flush_screen(struct vidbuf_description * gfxinfo,int first_line,int last_line)374 static void x11_flush_screen (struct vidbuf_description *gfxinfo, int first_line, int last_line)
375 {
376 XSync (display, 0);
377 }
378
379 /*
380 * Template for flush_line() buffer method in low-bandwidth mode
381 *
382 * In low-bandwidth mode, we don't flush the complete line. For each line we try
383 * to find the smallest line segment that contains modified pixels and flush only
384 * that segment.
385 */
386
387 #define x11_flush_line_lbw(gfxinfo, line_no, pixbytes, pixtype, mitshm) \
388 \
389 char *src; \
390 char *dst; \
391 int xs = 0; \
392 int xe = gfxinfo->inwidth - 1; \
393 int len; \
394 pixtype *newp = (pixtype *)gfxinfo->linemem; \
395 pixtype *oldp = (pixtype *)((uae_u8 *)ami_dinfo.image_mem + \
396 line_no * ami_dinfo.ximg->bytes_per_line); \
397 \
398 /* Find first modified pixel on this line */ \
399 while (newp[xs] == oldp[xs]) { \
400 if (xs == xe) \
401 return; \
402 xs++; \
403 } \
404 \
405 /* Find last modified pixel */ \
406 while (newp[xe] == oldp[xe]) \
407 xe--; \
408 \
409 dst = (char *)(oldp + xs); \
410 src = (char *)(newp + xs); \
411 len = xe - xs + 1; \
412 \
413 /* Copy changed pixels to buffer */ \
414 memcpy (dst, src, len * pixbytes); \
415 \
416 /* Blit changed pixels to the display */ \
417 if (!mitshm) { \
418 XPutImage (display, mywin, mygc, \
419 ami_dinfo.ximg, \
420 xs, line_no, \
421 xs, line_no, \
422 len, \
423 1); \
424 } else { \
425 XShmPutImage (display, mywin, mygc, \
426 ami_dinfo.ximg, \
427 xs, line_no, \
428 xs, line_no, \
429 len, \
430 1, \
431 0); \
432 }
433
434 /* Expand the above template for various bit depths and for with and without MITSHM */
435
x11_flush_line_lbw_8bit(struct vidbuf_description * gfxinfo,int line_no)436 static void x11_flush_line_lbw_8bit (struct vidbuf_description *gfxinfo, int line_no) { x11_flush_line_lbw (gfxinfo, line_no, 1, uae_u8, 0); }
x11_flush_line_lbw_16bit(struct vidbuf_description * gfxinfo,int line_no)437 static void x11_flush_line_lbw_16bit (struct vidbuf_description *gfxinfo, int line_no) { x11_flush_line_lbw (gfxinfo, line_no, 2, uae_u16, 0); }
x11_flush_line_lbw_32bit(struct vidbuf_description * gfxinfo,int line_no)438 static void x11_flush_line_lbw_32bit (struct vidbuf_description *gfxinfo, int line_no) { x11_flush_line_lbw (gfxinfo, line_no, 4, uae_u32, 0); }
x11_flush_line_lbw_8bit_mitshm(struct vidbuf_description * gfxinfo,int line_no)439 static void x11_flush_line_lbw_8bit_mitshm (struct vidbuf_description *gfxinfo, int line_no) { x11_flush_line_lbw (gfxinfo, line_no, 1, uae_u8, 1); }
x11_flush_line_lbw_16bit_mitshm(struct vidbuf_description * gfxinfo,int line_no)440 static void x11_flush_line_lbw_16bit_mitshm (struct vidbuf_description *gfxinfo, int line_no) { x11_flush_line_lbw (gfxinfo, line_no, 2, uae_u16, 1); }
x11_flush_line_lbw_32bit_mitshm(struct vidbuf_description * gfxinfo,int line_no)441 static void x11_flush_line_lbw_32bit_mitshm (struct vidbuf_description *gfxinfo, int line_no) { x11_flush_line_lbw (gfxinfo, line_no, 4, uae_u32, 1); }
442
443 /*
444 * flush_line() buffer method for dithered mode
445 */
x11_flush_line_dither(struct vidbuf_description * gfxinfo,int line_no)446 static void x11_flush_line_dither (struct vidbuf_description *gfxinfo, int line_no)
447 {
448 DitherLine ((uae_u8 *)ami_dinfo.image_mem + ami_dinfo.ximg->bytes_per_line * line_no,
449 (uae_u16 *)gfxinfo->linemem, 0, line_no, gfxinfo->inwidth, bit_unit);
450
451 DO_PUTIMAGE (ami_dinfo.ximg, 0, line_no, 0, line_no, gfxinfo->inwidth, 1);
452 }
453
454 /*
455 * flush_line() buffer method for dithered mode using DGA
456 */
457 #ifdef USE_DGA_EXTENSION
x11_flush_line_dither_dga(struct vidbuf_description * gfxinfo,int line_no)458 static void x11_flush_line_dither_dga (struct vidbuf_description *gfxinfo, int line_no)
459 {
460 DitherLine ((unsigned char *)(fb_addr + fb_width * line_no),
461 (uae_u16 *)gfxinfo->linemem, 0, line_no, gfxinfo->inwidth, bit_unit);
462
463 }
464 #endif
465
466 /*
467 * flush_block() buffer method for a normal image buffer (no dithering and not low-bandwidth)
468 */
x11_flush_block(struct vidbuf_description * gfxinfo,int first_line,int last_line)469 static void x11_flush_block (struct vidbuf_description *gfxinfo, int first_line, int last_line)
470 {
471 XPutImage (display, mywin, mygc,
472 ami_dinfo.ximg,
473 0, first_line,
474 0, first_line,
475 gfxinfo->inwidth,
476 last_line - first_line + 1);
477 }
478
479 /*
480 * flush_block() buffer method for shm image buffer (no dithering and not low-bandwidth)
481 */
x11_flush_block_mitshm(struct vidbuf_description * gfxinfo,int first_line,int last_line)482 static void x11_flush_block_mitshm (struct vidbuf_description *gfxinfo, int first_line, int last_line)
483 {
484 XShmPutImage (display, mywin, mygc,
485 ami_dinfo.ximg,
486 0, first_line,
487 0, first_line,
488 gfxinfo->inwidth,
489 last_line - first_line + 1,
490 0);
491 }
492
493
bitsInMask(unsigned long mask)494 STATIC_INLINE int bitsInMask (unsigned long mask)
495 {
496 /* count bits in mask */
497 int n = 0;
498 while (mask) {
499 n += mask & 1;
500 mask >>= 1;
501 }
502 return n;
503 }
504
maskShift(unsigned long mask)505 STATIC_INLINE int maskShift (unsigned long mask)
506 {
507 /* determine how far mask is shifted */
508 int n = 0;
509 while (!(mask & 1)) {
510 n++;
511 mask >>= 1;
512 }
513 return n;
514 }
515
516 static unsigned long pixel_return[256];
517 static XColor parsed_xcolors[256];
518 static int ncolors = 0;
519
520 static int blackval = 32767;
521 static int whiteval = 0;
522
get_color(int r,int g,int b,xcolnr * cnp)523 static int get_color (int r, int g, int b, xcolnr *cnp)
524 {
525 XColor *col = parsed_xcolors + ncolors;
526 char str[10];
527
528 sprintf (str, "rgb:%x/%x/%x", r, g, b);
529 XParseColor (display, cmap, str, col);
530 *cnp = col->pixel = pixel_return[ncolors];
531 XStoreColor (display, cmap, col);
532 XStoreColor (display, cmap2, col);
533
534 if (r + g + b < blackval)
535 blackval = r + g + b, black = *col;
536 if (r + g + b > whiteval)
537 whiteval = r + g + b, white = *col;
538
539 ncolors++;
540 return 1;
541 }
542
init_colors(void)543 static int init_colors (void)
544 {
545 if (visualInfo.VI_CLASS == TrueColor) {
546 red_bits = bitsInMask (visualInfo.red_mask);
547 green_bits = bitsInMask (visualInfo.green_mask);
548 blue_bits = bitsInMask (visualInfo.blue_mask);
549 red_shift = maskShift (visualInfo.red_mask);
550 green_shift = maskShift (visualInfo.green_mask);
551 blue_shift = maskShift (visualInfo.blue_mask);
552 }
553
554 if (need_dither) {
555 if (bitdepth == 1)
556 setup_greydither (1, get_color);
557 else
558 setup_dither (bitdepth, get_color);
559 } else {
560 if (bitdepth != 8 && bitdepth != 12 && bitdepth != 15
561 && bitdepth != 16 && bitdepth != 24) {
562 write_log ("Unsupported bit depth (%d)\n", bitdepth);
563 return 0;
564 }
565
566 switch (visualInfo.VI_CLASS) {
567 case TrueColor:
568 alloc_colors64k (red_bits, green_bits, blue_bits, red_shift,
569 green_shift, blue_shift, 0, 0, 0,
570 inverse_byte_order);
571
572 XParseColor (display, cmap, "#000000", &black);
573 if (! XAllocColor (display, cmap, &black))
574 write_log ("Whoops??\n");
575 XParseColor (display, cmap, "#ffffff", &white);
576 if (! XAllocColor (display, cmap, &white))
577 write_log ("Whoops??\n");
578 break;
579
580 case GrayScale:
581 case PseudoColor:
582 alloc_colors256 (get_color);
583 break;
584
585 default:
586 write_log ("Unsupported visual class (%d)\n", visualInfo.VI_CLASS);
587 return 0;
588 }
589 }
590 return 1;
591 }
592
dga_available(void)593 static int dga_available (void)
594 {
595 #ifdef USE_DGA_EXTENSION
596 int MajorVersion, MinorVersion;
597 int EventBase, ErrorBase;
598
599 if (! XF86DGAQueryVersion (display, &MajorVersion, &MinorVersion)) {
600 write_log ("Unable to query video extension version\n");
601 return 0;
602 }
603 if (! XF86DGAQueryExtension (display, &EventBase, &ErrorBase)) {
604 write_log ("Unable to query video extension information\n");
605 return 0;
606 }
607 /* Fail if the extension version in the server is too old */
608 if (MajorVersion < DGA_MINMAJOR
609 || (MajorVersion == DGA_MINMAJOR && MinorVersion < DGA_MINMINOR))
610 {
611 write_log (
612 "Xserver is running an old XFree86-DGA version"
613 " (%d.%d)\n", MajorVersion, MinorVersion);
614 write_log ("Minimum required version is %d.%d\n",
615 DGA_MINMAJOR, DGA_MINMINOR);
616 return 0;
617 }
618 if (geteuid () != 0) {
619 write_log ("UAE is not running as root, DGA extension disabled.\n");
620 return 0;
621 }
622 if (! XF86DGAGetVideo (display, screen, &fb_addr, &fb_width, &fb_bank, &fb_mem)
623 || fb_bank < fb_mem)
624 {
625 write_log ("Problems with DGA - disabling DGA extension.\n");
626 return 0;
627 }
628 write_log ("DGA extension: addr:%X, width %d, bank size %d mem size %d\n",
629 fb_addr, fb_width, fb_bank, fb_mem);
630
631 return 1;
632 #else
633 return 0;
634 #endif
635 }
636
vid_mode_available(void)637 static int vid_mode_available (void)
638 {
639 #ifdef USE_VIDMODE_EXTENSION
640 int MajorVersion, MinorVersion;
641 int EventBase, ErrorBase;
642
643 if (! dgaavail)
644 return 0;
645 if (! XF86VidModeQueryVersion (display, &MajorVersion, &MinorVersion)) {
646 write_log ("Unable to query video extension version\n");
647 return 0;
648 }
649 if (! XF86VidModeQueryExtension (display, &EventBase, &ErrorBase)) {
650 write_log ("Unable to query video extension information\n");
651 return 0;
652 }
653 if (MajorVersion < VidMode_MINMAJOR
654 || (MajorVersion == VidMode_MINMAJOR && MinorVersion < VidMode_MINMINOR)) {
655 /* Fail if the extension version in the server is too old */
656 write_log ("Xserver is running an old XFree86-VidMode version (%d.%d)\n",
657 MajorVersion, MinorVersion);
658 write_log ("Minimum required version is %d.%d\n",
659 VidMode_MINMAJOR, VidMode_MINMINOR);
660 return 0;
661 }
662 if (! get_vidmodes ()) {
663 write_log ("Error getting video mode information\n");
664 return 0;
665 }
666 return 1;
667 #else
668 return 0;
669 #endif
670 }
671
shm_available(void)672 static int shm_available (void)
673 {
674 #if SHM_SUPPORT_LINKS == 1
675 if (XShmQueryExtension (display))
676 return 1;
677 #endif
678 return 0;
679 }
680
graphics_setup(void)681 int graphics_setup (void)
682 {
683 char *display_name = 0;
684 const char *keycodes;
685
686 display = XOpenDisplay (display_name);
687 if (display == 0) {
688 write_log ("Can't connect to X server %s\n", XDisplayName (display_name));
689 return 0;
690 }
691
692 shmavail = shm_available ();
693 dgaavail = dga_available ();
694 vidmodeavail = vid_mode_available ();
695
696 {
697 int local_byte_order;
698 int x = 0x04030201;
699 char *y=(char*)&x;
700
701 local_byte_order = y[0] == 0x04 ? MSBFirst : LSBFirst;
702 if (ImageByteOrder(display) != local_byte_order)
703 inverse_byte_order = 1;
704 }
705
706 screen = XDefaultScreen (display);
707 rootwin = XRootWindow (display, screen);
708
709 if (!get_best_visual (display, screen, &visualInfo))
710 return 0;
711
712 vis = visualInfo.visual;
713 bitdepth = visualInfo.depth;
714 if (!(bit_unit = get_visual_bit_unit (&visualInfo, bitdepth))) return 0;
715
716 write_log ("X11GFX: Initialized.\n");
717
718 rawkeys_available = 0;
719
720 #if 0
721 #ifdef USE_XKB
722 keycodes = get_xkb_keycodes (display);
723
724 if (keycodes) {
725 /* We only support xfree86 keycodes for now */
726 if (strncmp (keycodes, "xfree86", 7) == 0) {
727 rawkeys_available = 1;
728 raw_keyboard = uaekey_make_default_kbr (x11pc_keymap);
729 write_log ("X11GFX: Keyboard uses xfree86 keycodes\n");
730 }
731 }
732 #endif
733 #endif
734
735 return 1;
736 }
737
lock_window_size(void)738 static void lock_window_size (void)
739 {
740 XSizeHints hint;
741
742 hint.flags = PMinSize | PMaxSize;
743 hint.min_width = current_width;
744 hint.min_height = current_height;
745 hint.max_width = current_width;
746 hint.max_height = current_height;
747 XSetWMNormalHints (display, mywin, &hint);
748 }
749
init_dispinfo(struct disp_info * disp)750 static void init_dispinfo (struct disp_info *disp)
751 {
752 #if SHM_SUPPORT_LINKS == 1
753 disp->shminfo.shmid = -1;
754 #endif
755 disp->ximg = 0;
756 }
757
graphics_subinit(void)758 static void graphics_subinit (void)
759 {
760 XSetWindowAttributes wattr;
761 XClassHint classhint;
762 XWMHints *hints;
763 unsigned long valuemask;
764
765 dgamode = currprefs.gfx_apmode[screen_is_picasso ? APMODE_RTG : APMODE_NATIVE].gfx_fullscreen;
766 // dgamode = screen_is_picasso ? currprefs.gfx_pfullscreen : currprefs.gfx_afullscreen;
767 dgamode = dgamode && dgaavail;
768
769 wattr.background_pixel = /*black.pixel*/0;
770 wattr.backing_store = Always;
771 wattr.backing_planes = bitdepth;
772 wattr.border_pixmap = None;
773 wattr.border_pixel = /*black.pixel*/0;
774 wattr.colormap = cmap;
775 valuemask = (CWEventMask | CWBackPixel | CWBorderPixel
776 | CWBackingStore | CWBackingPlanes | CWColormap);
777
778 if (dgamode) {
779 wattr.event_mask = DGA_EVENTMASK;
780 wattr.override_redirect = 1;
781 valuemask |= CWOverrideRedirect;
782 } else
783 wattr.event_mask = EVENTMASK;
784
785 XSync (display, 0);
786
787 delete_win = XInternAtom(display, "WM_DELETE_WINDOW", False);
788 mywin = XCreateWindow (display, rootwin, 0, 0, current_width, current_height,
789 0, bitdepth, InputOutput, vis, valuemask, &wattr);
790 gfxvidinfo.width_allocated = current_width;
791 gfxvidinfo.height_allocated = current_height;
792 XSetWMProtocols (display, mywin, &delete_win, 1);
793 XSync (display, 0);
794 XStoreName (display, mywin, PACKAGE_NAME);
795 XSetIconName (display, mywin, PACKAGE_NAME);
796
797 /* set class hint */
798 classhint.res_name = (char *)"UAE";
799 classhint.res_class = (char *)"UAEScreen";
800 XSetClassHint(display, mywin, &classhint);
801
802 hints = XAllocWMHints();
803 /* Set window group leader to self to become an application
804 * that can be hidden by e.g. WindowMaker.
805 * Would be more useful if we could find out what the
806 * (optional) GTK+ window ID is :-/ */
807 hints->window_group = mywin;
808 hints->flags = WindowGroupHint;
809 XSetWMHints(display, mywin, hints);
810
811 XMapRaised (display, mywin);
812 XSync (display, 0);
813 mygc = XCreateGC (display, mywin, 0, 0);
814
815 if (dgamode) {
816 #ifdef USE_DGA_EXTENSION
817 enter_dga_mode ();
818 /*setuid(getuid());*/
819 picasso_vidinfo.rowbytes = fb_width * picasso_vidinfo.pixbytes;
820 #endif
821 } else {
822 get_image (current_width, current_height, &ami_dinfo);
823 if (screen_is_picasso) {
824 get_image (current_width, current_height, &pic_dinfo);
825 picasso_vidinfo.rowbytes = pic_dinfo.ximg->bytes_per_line;
826 }
827 }
828
829 picasso_vidinfo.extra_mem = 1;
830
831 gfxvidinfo.flush_screen = x11_flush_screen;
832 gfxvidinfo.lockscr = x11_lock;
833 gfxvidinfo.unlockscr = x11_unlock;
834
835
836 if (need_dither) {
837 gfxvidinfo.maxblocklines = 0;
838 gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * currprefs.gfx_size_win.width;
839 gfxvidinfo.linemem = malloc (gfxvidinfo.rowbytes);
840 gfxvidinfo.flush_line = x11_flush_line_dither;
841 } else if (! dgamode) {
842 gfxvidinfo.emergmem = 0;
843 gfxvidinfo.linemem = 0;
844 gfxvidinfo.bufmem = (uae_u8 *)ami_dinfo.image_mem;
845 gfxvidinfo.rowbytes = ami_dinfo.ximg->bytes_per_line;
846 if (currprefs.x11_use_low_bandwidth) {
847 write_log ("Doing low-bandwidth output.\n");
848 gfxvidinfo.maxblocklines = 0;
849 gfxvidinfo.rowbytes = ami_dinfo.ximg->bytes_per_line;
850 gfxvidinfo.linemem = malloc (gfxvidinfo.rowbytes);
851
852 if (shmavail && currprefs.x11_use_mitshm) {
853 switch (gfxvidinfo.pixbytes) {
854 case 4 : gfxvidinfo.flush_line = x11_flush_line_lbw_32bit_mitshm; break;
855 case 2 : gfxvidinfo.flush_line = x11_flush_line_lbw_16bit_mitshm; break;
856 default : gfxvidinfo.flush_line = x11_flush_line_lbw_8bit_mitshm; break;
857 }
858 } else {
859 switch (gfxvidinfo.pixbytes) {
860 case 4 : gfxvidinfo.flush_line = x11_flush_line_lbw_32bit; break;
861 case 2 : gfxvidinfo.flush_line = x11_flush_line_lbw_16bit; break;
862 default : gfxvidinfo.flush_line = x11_flush_line_lbw_8bit; break;
863 }
864 }
865 } else {
866 gfxvidinfo.maxblocklines = MAXBLOCKLINES_MAX;
867
868 if (shmavail && currprefs.x11_use_mitshm)
869 gfxvidinfo.flush_block = x11_flush_block_mitshm;
870 else
871 gfxvidinfo.flush_block = x11_flush_block;
872 }
873 }
874
875 if (visualInfo.VI_CLASS != TrueColor && ! screen_is_picasso) {
876 int i;
877 for (i = 0; i < 256; i++)
878 XStoreColor (display, cmap, parsed_xcolors + i);
879 }
880
881 #ifdef USE_DGA_EXTENSION
882 if (dgamode) {
883 dga_colormap_installed = 0;
884 XF86DGAInstallColormap (display, screen, cmap2);
885 XF86DGAInstallColormap (display, screen, cmap);
886 }
887 #endif
888
889 if (! dgamode) {
890 if (!currprefs.hide_cursor)
891 XDefineCursor (display, mywin, xhairCursor);
892 else
893 XDefineCursor (display, mywin, blankCursor);
894 cursorOn = 1;
895 }
896
897 mousehack = !dgamode;
898
899 if (screen_is_picasso) {
900 picasso_has_invalid_lines = 0;
901 picasso_invalid_start = picasso_vidinfo.height + 1;
902 picasso_invalid_stop = -1;
903 memset (picasso_invalid_lines, 0, sizeof picasso_invalid_lines);
904 } else
905 reset_drawing ();
906
907 inwindow = 0;
908 inputdevice_release_all_keys ();
909 reset_hotkeys ();
910 }
911
graphics_init(void)912 int graphics_init (void)
913 {
914 if (currprefs.x11_use_mitshm && ! shmavail) {
915 write_log ("MIT-SHM extension not supported by X server.\n");
916 }
917 if (currprefs.color_mode > 5)
918 write_log ("Bad color mode selected. Using default.\n"), currprefs.color_mode = 0;
919
920 x11_init_ok = 0;
921 need_dither = 0;
922 screen_is_picasso = 0;
923 dgamode = 0;
924
925 init_dispinfo (&ami_dinfo);
926 init_dispinfo (&pic_dinfo);
927
928 write_log ("Using %d bit visual, %d bits per pixel\n", bitdepth, bit_unit);
929
930 fixup_prefs_dimensions (&currprefs);
931
932 gfxvidinfo.inwidth = currprefs.gfx_size_win.width;
933 gfxvidinfo.inheight = currprefs.gfx_size_win.height;
934 current_width = currprefs.gfx_size_win.width;
935 current_height = currprefs.gfx_size_win.height;
936
937 cmap = XCreateColormap (display, rootwin, vis, AllocNone);
938 cmap2 = XCreateColormap (display, rootwin, vis, AllocNone);
939 if (visualInfo.VI_CLASS == GrayScale || visualInfo.VI_CLASS == PseudoColor) {
940 XAllocColorCells (display, cmap, 0, 0, 0, pixel_return, 1 << bitdepth);
941 XAllocColorCells (display, cmap2, 0, 0, 0, pixel_return, 1 << bitdepth);
942 }
943
944 if (bitdepth < 8 || (bitdepth == 8 && currprefs.color_mode == 3)) {
945 gfxvidinfo.pixbytes = 2;
946 currprefs.x11_use_low_bandwidth = 0;
947 need_dither = 1;
948 } else {
949 gfxvidinfo.pixbytes = bit_unit >> 3;
950 }
951
952 if (! init_colors ())
953 return 0;
954
955 blankCursor = XCreatePixmapCursor (display,
956 XCreatePixmap (display, rootwin, 1, 1, 1),
957 XCreatePixmap (display, rootwin, 1, 1, 1),
958 &black, &white, 0, 0);
959 xhairCursor = XCreateFontCursor (display, XC_crosshair);
960
961 graphics_subinit ();
962
963 grabbed = 0;
964
965 return x11_init_ok = 1;
966 }
967
destroy_dinfo(struct disp_info * dinfo)968 static void destroy_dinfo (struct disp_info *dinfo)
969 {
970 if (dinfo->ximg == NULL)
971 return;
972 #if SHM_SUPPORT_LINKS == 1
973 if (dinfo->shminfo.shmid != -1)
974 shmdt (dinfo->shminfo.shmaddr);
975 dinfo->shminfo.shmid = -1;
976 #endif
977 XDestroyImage (dinfo->ximg);
978 dinfo->ximg = NULL;
979 }
980
graphics_subshutdown(void)981 static void graphics_subshutdown (void)
982 {
983 XSync (display, 0);
984 #ifdef USE_DGA_EXTENSION
985 if (dgamode)
986 leave_dga_mode ();
987 #endif
988
989 destroy_dinfo (&ami_dinfo);
990 destroy_dinfo (&pic_dinfo);
991
992 if (mywin) {
993 XDestroyWindow (display, mywin);
994 mywin = 0;
995 }
996
997 xfree (gfxvidinfo.linemem);
998 xfree (gfxvidinfo.emergmem);
999
1000 mousehack = 0;
1001 }
1002
graphics_leave(void)1003 void graphics_leave (void)
1004 {
1005 if (! x11_init_ok)
1006 return;
1007
1008 graphics_subshutdown ();
1009
1010 if (autorepeatoff)
1011 XAutoRepeatOn (display);
1012
1013 XFlush (display);
1014 XSync (display, 0);
1015
1016 XFreeColormap (display, cmap);
1017 XFreeColormap (display, cmap2);
1018
1019 XCloseDisplay (display);
1020
1021 dumpcustom ();
1022 }
1023
1024 static struct timeval lastMotionTime;
1025
1026 static int refresh_necessary = 0;
1027
graphics_notify_state(int state)1028 void graphics_notify_state (int state)
1029 {
1030 }
1031
handle_events(void)1032 bool handle_events (void)
1033 {
1034 for (;;) {
1035 XEvent event;
1036 #if 0
1037 if (! XCheckMaskEvent (display, eventmask, &event))
1038 break;
1039 #endif
1040 if (! XPending (display))
1041 break;
1042
1043 XNextEvent (display, &event);
1044
1045 switch (event.type) {
1046 case KeyPress:
1047 case KeyRelease: {
1048 int state = (event.type == KeyPress);
1049
1050 #if 0 // map_raw_keys is marked "if 0" in options.h
1051 if (currprefs.map_raw_keys) {
1052 unsigned int keycode = ((XKeyEvent *)&event)->keycode;
1053 unsigned int ievent;
1054
1055 if ((ievent = match_hotkey_sequence (keycode, state)))
1056 handle_hotkey_event (ievent, state);
1057 else
1058 inputdevice_translatekeycode (0, keycode, state);
1059 } else {
1060 #endif // 0
1061 KeySym keysym;
1062 int index = 0;
1063 int ievent, amiga_keycode;
1064 do {
1065 keysym = XLookupKeysym ((XKeyEvent *)&event, index);
1066 if ((ievent = match_hotkey_sequence (keysym, state))) {
1067 handle_hotkey_event (ievent, state);
1068 break;
1069 } else
1070 if ((amiga_keycode = xkeysym2amiga (keysym)) >= 0) {
1071 inputdevice_do_keyboard (amiga_keycode, state);
1072 break;
1073 }
1074 index++;
1075 } while (keysym != NoSymbol);
1076 #if 0 // from removal above
1077 }
1078 #endif // 0
1079 break;
1080 }
1081 case ButtonPress:
1082 case ButtonRelease: {
1083 int state = (event.type == ButtonPress);
1084 int buttonno = -1;
1085 switch ((int)((XButtonEvent *)&event)->button) {
1086 case 1: buttonno = 0; break;
1087 case 2: buttonno = 2; break;
1088 case 3: buttonno = 1; break;
1089 /* buttons 4 and 5 report mousewheel events */
1090 case 4: if (state) record_key (0x7a << 1); break;
1091 case 5: if (state) record_key (0x7b << 1); break;
1092 }
1093 if (buttonno >=0)
1094 setmousebuttonstate(0, buttonno, state);
1095 break;
1096 }
1097 case MotionNotify:
1098 if (dgamode) {
1099 int tx = ((XMotionEvent *)&event)->x_root;
1100 int ty = ((XMotionEvent *)&event)->y_root;
1101 setmousestate (0, 0, tx, 0);
1102 setmousestate (0, 1, ty, 0);
1103 } else if (grabbed) {
1104 int realmove = 0;
1105 int tx, ty,ttx,tty;
1106
1107 tx = ((XMotionEvent *)&event)->x;
1108 ty = ((XMotionEvent *)&event)->y;
1109
1110 if (! event.xmotion.send_event) {
1111 setmousestate( 0,0,tx-oldx,0);
1112 setmousestate( 0,1,ty-oldy,0);
1113 realmove = 1;
1114 #undef ABS
1115 #define ABS(a) (((a)<0) ? -(a) : (a) )
1116 if (ABS(current_width / 2 - tx) > 3 * current_width / 8
1117 || ABS(current_height / 2 - ty) > 3 * current_height / 8)
1118 {
1119 #undef ABS
1120 XEvent event;
1121 ttx = current_width / 2;
1122 tty = current_height / 2;
1123 event.type = MotionNotify;
1124 event.xmotion.display = display;
1125 event.xmotion.window = mywin;
1126 event.xmotion.x = ttx;
1127 event.xmotion.y = tty;
1128 XSendEvent (display, mywin, False,
1129 PointerMotionMask, &event);
1130 XWarpPointer (display, None, mywin, 0, 0, 0, 0, ttx, tty);
1131 }
1132 } else {
1133 tx=event.xmotion.x;
1134 ty=event.xmotion.y;
1135 }
1136 oldx = tx;
1137 oldy = ty;
1138 } else if (inwindow) {
1139 int tx = ((XMotionEvent *)&event)->x;
1140 int ty = ((XMotionEvent *)&event)->y;
1141 setmousestate(0,0,tx,1);
1142 setmousestate(0,1,ty,1);
1143 if (! cursorOn && !currprefs.hide_cursor) {
1144 XDefineCursor(display, mywin, xhairCursor);
1145 cursorOn = 1;
1146 }
1147 gettimeofday(&lastMotionTime, NULL);
1148 }
1149 break;
1150 case EnterNotify:
1151 {
1152 int tx = ((XCrossingEvent *)&event)->x;
1153 int ty = ((XCrossingEvent *)&event)->y;
1154 setmousestate(0,0,tx,1);
1155 setmousestate(0,1,ty,1);
1156 }
1157 inwindow = 1;
1158 break;
1159 case LeaveNotify:
1160 inwindow = 0;
1161 break;
1162 case FocusIn:
1163 if (! autorepeatoff)
1164 XAutoRepeatOff (display);
1165 autorepeatoff = 1;
1166 break;
1167 case FocusOut:
1168 if (autorepeatoff)
1169 XAutoRepeatOn (display);
1170 autorepeatoff = 0;
1171 inputdevice_release_all_keys ();
1172 break;
1173 case Expose:
1174 refresh_necessary = 1;
1175 break;
1176 case ClientMessage:
1177 if (((Atom)event.xclient.data.l[0]) == delete_win) {
1178 //uae_stop ();
1179 }
1180 break;
1181 }
1182 }
1183
1184 #if defined PICASSO96
1185 if (! dgamode) {
1186 if (screen_is_picasso && refresh_necessary) {
1187 DO_PUTIMAGE (pic_dinfo.ximg, 0, 0, 0, 0,
1188 picasso_vidinfo.width, picasso_vidinfo.height);
1189 XFlush (display);
1190 refresh_necessary = 0;
1191 memset (picasso_invalid_lines, 0, sizeof picasso_invalid_lines);
1192 } else if (screen_is_picasso && picasso_has_invalid_lines) {
1193 int i;
1194 int strt = -1;
1195
1196 picasso_invalid_lines[picasso_vidinfo.height] = 0;
1197 for (i = picasso_invalid_start; i < picasso_invalid_stop + 2; i++) {
1198 if (picasso_invalid_lines[i]) {
1199 picasso_invalid_lines[i] = 0;
1200 if (strt != -1)
1201 continue;
1202 strt = i;
1203 } else {
1204 if (strt == -1)
1205 continue;
1206 DO_PUTIMAGE (pic_dinfo.ximg, 0, strt, 0, strt,
1207 picasso_vidinfo.width, i - strt);
1208 strt = -1;
1209 }
1210 }
1211 XFlush (display);
1212 if (strt != -1)
1213 abort ();
1214 }
1215 }
1216 picasso_has_invalid_lines = 0;
1217 picasso_invalid_start = picasso_vidinfo.height + 1;
1218 picasso_invalid_stop = -1;
1219 #endif
1220
1221 if (! dgamode) {
1222 if (! screen_is_picasso && refresh_necessary) {
1223 DO_PUTIMAGE (ami_dinfo.ximg, 0, 0, 0, 0, current_width, current_height);
1224 refresh_necessary = 0;
1225 }
1226 if (cursorOn && !currprefs.hide_cursor) {
1227 struct timeval now;
1228 int diff;
1229 gettimeofday(&now, NULL);
1230 diff = (now.tv_sec - lastMotionTime.tv_sec) * 1000000 +
1231 (now.tv_usec - lastMotionTime.tv_usec);
1232 if (diff > 1000000) {
1233 XDefineCursor (display, mywin, blankCursor);
1234 cursorOn = 0;
1235 }
1236 }
1237 }
1238 return pause_emulation != 0;
1239 }
1240
check_prefs_changed_gfx(void)1241 int check_prefs_changed_gfx (void)
1242 {
1243 if (changed_prefs.gfx_size_win.width != currprefs.gfx_size_win.width
1244 || changed_prefs.gfx_size_win.height != currprefs.gfx_size_win.height)
1245 fixup_prefs_dimensions (&changed_prefs);
1246
1247 if (changed_prefs.gfx_size_win.width == currprefs.gfx_size_win.width
1248 && changed_prefs.gfx_size_win.height == currprefs.gfx_size_win.height
1249 && changed_prefs.gfx_vresolution == currprefs.gfx_vresolution
1250 && changed_prefs.gfx_xcenter == currprefs.gfx_xcenter
1251 && changed_prefs.gfx_ycenter == currprefs.gfx_ycenter
1252 && changed_prefs.gfx_apmode[APMODE_RTG].gfx_fullscreen == currprefs.gfx_apmode[APMODE_RTG].gfx_fullscreen
1253 && changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_fullscreen == currprefs.gfx_apmode[APMODE_NATIVE].gfx_fullscreen)
1254 return 0;
1255
1256 graphics_subshutdown ();
1257 currprefs.gfx_size_win.width = changed_prefs.gfx_size_win.width;
1258 currprefs.gfx_size_win.height = changed_prefs.gfx_size_win.height;
1259 currprefs.gfx_vresolution = changed_prefs.gfx_vresolution;
1260 currprefs.gfx_xcenter = changed_prefs.gfx_xcenter;
1261 currprefs.gfx_ycenter = changed_prefs.gfx_ycenter;
1262 currprefs.gfx_apmode[APMODE_NATIVE].gfx_fullscreen = changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_fullscreen;
1263 currprefs.gfx_apmode[APMODE_RTG].gfx_fullscreen = changed_prefs.gfx_apmode[APMODE_RTG].gfx_fullscreen;
1264
1265 graphics_subinit ();
1266
1267 if (! inwindow)
1268 XWarpPointer (display, None, mywin, 0, 0, 0, 0,
1269 current_width / 2, current_height / 2);
1270
1271 notice_screen_contents_lost ();
1272 init_row_map ();
1273 if (screen_is_picasso)
1274 picasso_enablescreen (1);
1275 return 0;
1276 }
1277
debuggable(void)1278 int debuggable (void)
1279 {
1280 return 1;
1281 }
1282
mousehack_allowed(void)1283 int mousehack_allowed (void)
1284 {
1285 return mousehack;
1286 }
1287
1288 #ifdef PICASSO96
1289
DX_Invalidate(int first,int last)1290 void DX_Invalidate (int first, int last)
1291 {
1292 if (first > last)
1293 return;
1294
1295 picasso_has_invalid_lines = 1;
1296 if (first < picasso_invalid_start)
1297 picasso_invalid_start = first;
1298 if (last > picasso_invalid_stop)
1299 picasso_invalid_stop = last;
1300
1301 while (first <= last) {
1302 picasso_invalid_lines[first] = 1;
1303 first++;
1304 }
1305 }
1306
1307 static int palette_update_start=256;
1308 static int palette_update_end=0;
1309
DX_SetPalette_real(int start,int count)1310 static void DX_SetPalette_real (int start, int count)
1311 {
1312 if (! screen_is_picasso || picasso96_state.RGBFormat != RGBFB_CHUNKY)
1313 return;
1314
1315 if (picasso_vidinfo.pixbytes != 1) {
1316 /* This is the case when we're emulating a 256 color display. */
1317 while (count-- > 0) {
1318 int r = picasso96_state.CLUT[start].Red;
1319 int g = picasso96_state.CLUT[start].Green;
1320 int b = picasso96_state.CLUT[start].Blue;
1321 picasso_vidinfo.clut[start++] = (doMask256 (r, red_bits, red_shift)
1322 | doMask256 (g, green_bits, green_shift)
1323 | doMask256 (b, blue_bits, blue_shift));
1324 }
1325 return;
1326 }
1327
1328 while (count-- > 0) {
1329 XColor col = parsed_xcolors[start];
1330 col.red = picasso96_state.CLUT[start].Red * 0x0101;
1331 col.green = picasso96_state.CLUT[start].Green * 0x0101;
1332 col.blue = picasso96_state.CLUT[start].Blue * 0x0101;
1333 XStoreColor (display, cmap, &col);
1334 XStoreColor (display, cmap2, &col);
1335 start++;
1336 }
1337 #ifdef USE_DGA_EXTENSION
1338 if (dgamode) {
1339 dga_colormap_installed ^= 1;
1340 if (dga_colormap_installed == 1)
1341 XF86DGAInstallColormap (display, screen, cmap2);
1342 else
1343 XF86DGAInstallColormap (display, screen, cmap);
1344 }
1345 #endif
1346 }
DX_SetPalette(int start,int count)1347 void DX_SetPalette (int start, int count)
1348 {
1349 DX_SetPalette_real (start, count);
1350 }
1351
DX_SetPalette_delayed(int start,int count)1352 static void DX_SetPalette_delayed (int start, int count)
1353 {
1354 if (bit_unit!=8) {
1355 DX_SetPalette_real(start,count);
1356 return;
1357 }
1358 if (start<palette_update_start)
1359 palette_update_start=start;
1360 if (start+count>palette_update_end)
1361 palette_update_end=start+count;
1362 }
1363
DX_SetPalette_vsync(void)1364 void DX_SetPalette_vsync(void)
1365 {
1366 if (palette_update_end>palette_update_start) {
1367 DX_SetPalette_real(palette_update_start,
1368 palette_update_end-palette_update_start);
1369 palette_update_end=0;
1370 palette_update_start=256;
1371 }
1372 }
1373
DX_Fill(int dstx,int dsty,int width,int height,uae_u32 color,RGBFTYPE rgbtype)1374 int DX_Fill (int dstx, int dsty, int width, int height, uae_u32 color, RGBFTYPE rgbtype)
1375 {
1376 /* not implemented yet */
1377 return 0;
1378 }
1379
DX_Blit(int srcx,int srcy,int dstx,int dsty,int width,int height,BLIT_OPCODE opcode)1380 int DX_Blit (int srcx, int srcy, int dstx, int dsty, int width, int height, BLIT_OPCODE opcode)
1381 {
1382 /* not implemented yet */
1383 return 0;
1384 }
1385
1386 #define MAX_SCREEN_MODES 12
1387
1388 static int x_size_table[MAX_SCREEN_MODES] = { 320, 320, 320, 320, 640, 640, 640, 800, 1024, 1152, 1280, 1280 };
1389 static int y_size_table[MAX_SCREEN_MODES] = { 200, 240, 256, 400, 350, 480, 512, 600, 768, 864, 960, 1024 };
1390
set_window_for_picasso(void)1391 static void set_window_for_picasso (void)
1392 {
1393 if (current_width == picasso_vidinfo.width && current_height == picasso_vidinfo.height)
1394 return;
1395
1396 current_width = picasso_vidinfo.width;
1397 current_height = picasso_vidinfo.height;
1398 XResizeWindow (display, mywin, current_width, current_height);
1399 #if defined USE_DGA_EXTENSION && defined USE_VIDMODE_EXTENSION
1400 if (dgamode && vidmodeavail)
1401 switch_to_best_mode ();
1402 #endif
1403 }
1404
gfx_set_picasso_modeinfo(uae_u32 w,uae_u32 h,uae_u32 depth,RGBFTYPE rgbfmt)1405 void gfx_set_picasso_modeinfo (uae_u32 w, uae_u32 h, uae_u32 depth, RGBFTYPE rgbfmt)
1406 {
1407 picasso_vidinfo.width = w;
1408 picasso_vidinfo.height = h;
1409 picasso_vidinfo.depth = depth;
1410 picasso_vidinfo.pixbytes = bit_unit >> 3;
1411
1412 if (screen_is_picasso)
1413 set_window_for_picasso ();
1414 }
1415
gfx_set_picasso_state(int on)1416 void gfx_set_picasso_state (int on)
1417 {
1418 if (on == screen_is_picasso)
1419 return;
1420
1421 /* We can get called by drawing_init() when there's
1422 * no window opened yet... */
1423 if (mywin == 0)
1424 return;
1425
1426 write_log ("set_picasso_state:%d\n", on);
1427 graphics_subshutdown ();
1428 screen_is_picasso = on;
1429 if (on) {
1430 current_width = picasso_vidinfo.width;
1431 current_height = picasso_vidinfo.height;
1432 graphics_subinit ();
1433 } else {
1434 current_width = gfxvidinfo.outwidth;
1435 current_height = gfxvidinfo.outheight;
1436 graphics_subinit ();
1437 reset_drawing ();
1438 }
1439 if (on)
1440 DX_SetPalette_real (0, 256);
1441 }
1442
gfx_lock_picasso(bool fullupdate,bool doclear)1443 uae_u8 *gfx_lock_picasso (bool fullupdate, bool doclear)
1444 {
1445 #ifdef USE_DGA_EXTENSION
1446 if (dgamode)
1447 return (uae_u8 *)fb_addr;
1448 else
1449 #endif
1450 return (uae_u8 *)pic_dinfo.ximg->data;
1451 }
1452
gfx_unlock_picasso(bool dorender)1453 void gfx_unlock_picasso (bool dorender)
1454 {
1455 }
1456 #endif
1457
toggle_mousegrab(void)1458 void toggle_mousegrab (void)
1459 {
1460 if (grabbed) {
1461 XUngrabPointer (display, CurrentTime);
1462 // XUndefineCursor (display, mywin);
1463 grabbed = 0;
1464 mousehack = 1;
1465 write_log ("Ungrabbed mouse\n");
1466 } else if (! dgamode) {
1467 XGrabPointer (display, mywin, 1, 0, GrabModeAsync, GrabModeAsync,
1468 mywin, blankCursor, CurrentTime);
1469 oldx = current_width / 2;
1470 oldy = current_height / 2;
1471 XWarpPointer (display, None, mywin, 0, 0, 0, 0, oldx, oldy);
1472 write_log ("Grabbed mouse\n");
1473 grabbed = 1;
1474 mousehack = 0;
1475 }
1476 }
1477
is_fullscreen(void)1478 int is_fullscreen (void)
1479 {
1480 #ifdef USE_DGA_EXTENSION
1481 return dgamode;
1482 #else
1483 return 0;
1484 #endif
1485 }
1486
is_vsync(void)1487 int is_vsync (void)
1488 {
1489 return 0;
1490 }
1491
toggle_fullscreen(int mode)1492 void toggle_fullscreen (int mode)
1493 {
1494 #ifdef USE_DGA_EXTENSION
1495 changed_prefs.gfx_apmode[APMODE_NATIVE].gfx_fullscreen
1496 = changed_prefs.gfx_apmode[APMODE_RTG].gfx_fullscreen
1497 = !dgamode;
1498 #endif
1499 }
1500
screenshot(int mode,int doprepare)1501 void screenshot (int mode, int doprepare)
1502 {
1503 write_log ("Screenshot not implemented yet\n");
1504 }
1505
1506 /*
1507 * Mouse inputdevice functions
1508 */
1509
1510 /* Hardwire for 3 axes and 3 buttons
1511 * There is no 3rd axis as such - mousewheel events are
1512 * supplied by X on buttons 4 and 5.
1513 */
1514 #define MAX_BUTTONS 3
1515 #define MAX_AXES 3
1516 #define FIRST_AXIS 0
1517 #define FIRST_BUTTON MAX_AXES
1518
init_mouse(void)1519 static int init_mouse (void)
1520 {
1521 return 1;
1522 }
1523
close_mouse(void)1524 static void close_mouse (void)
1525 {
1526 return;
1527 }
1528
acquire_mouse(int num,int flags)1529 static int acquire_mouse (int num, int flags)
1530 {
1531 return 1;
1532 }
1533
unacquire_mouse(int num)1534 static void unacquire_mouse (int num)
1535 {
1536 return;
1537 }
1538
get_mouse_num(void)1539 static int get_mouse_num (void)
1540 {
1541 return 1;
1542 }
1543
get_mouse_friendlyname(int mouse)1544 static TCHAR *get_mouse_friendlyname (int mouse)
1545 {
1546 return "Default mouse";
1547 }
1548
get_mouse_uniquename(int mouse)1549 static TCHAR *get_mouse_uniquename (int mouse)
1550 {
1551 return "DEFMOUSE1";
1552 }
1553
get_mouse_widget_num(int mouse)1554 static int get_mouse_widget_num (int mouse)
1555 {
1556 return MAX_AXES + MAX_BUTTONS;
1557 }
1558
get_mouse_widget_first(int mouse,int type)1559 static int get_mouse_widget_first (int mouse, int type)
1560 {
1561 switch (type) {
1562 case IDEV_WIDGET_BUTTON:
1563 return FIRST_BUTTON;
1564 case IDEV_WIDGET_AXIS:
1565 return FIRST_AXIS;
1566 }
1567 return -1;
1568 }
1569
get_mouse_widget_type(int mouse,int num,TCHAR * name,uae_u32 * code)1570 static int get_mouse_widget_type (int mouse, int num, TCHAR *name, uae_u32 *code)
1571 {
1572 if (num >= MAX_AXES && num < MAX_AXES + MAX_BUTTONS) {
1573 if (name)
1574 sprintf (name, "Button %d", num + 1 + MAX_AXES);
1575 return IDEV_WIDGET_BUTTON;
1576 } else if (num < MAX_AXES) {
1577 if (name)
1578 sprintf (name, "Axis %d", num + 1);
1579 return IDEV_WIDGET_AXIS;
1580 }
1581 return IDEV_WIDGET_NONE;
1582 }
1583
read_mouse(void)1584 static void read_mouse (void)
1585 {
1586 /* We handle mouse input in handle_events() */
1587 }
1588
get_mouse_flags(int num)1589 static int get_mouse_flags (int num)
1590 {
1591 return 0;
1592 }
1593
1594 struct inputdevice_functions inputdevicefunc_mouse = {
1595 init_mouse,
1596 close_mouse,
1597 acquire_mouse,
1598 unacquire_mouse,
1599 read_mouse,
1600 get_mouse_num,
1601 get_mouse_friendlyname,
1602 get_mouse_uniquename,
1603 get_mouse_widget_num,
1604 get_mouse_widget_type,
1605 get_mouse_widget_first,
1606 get_mouse_flags
1607 };
1608
1609 /*
1610 * Keyboard inputdevice functions
1611 */
get_kb_num(void)1612 static int get_kb_num (void)
1613 {
1614 return 1;
1615 }
1616
get_kb_friendlyname(int kb)1617 static TCHAR *get_kb_friendlyname (int kb)
1618 {
1619 return "Default keyboard";
1620 }
1621
get_kb_uniquename(int kb)1622 static TCHAR *get_kb_uniquename (int kb)
1623 {
1624 return "DEFKEYB1";
1625 }
1626
get_kb_widget_num(int kb)1627 static int get_kb_widget_num (int kb)
1628 {
1629 return 255; // fix me
1630 }
1631
get_kb_widget_first(int kb,int type)1632 static int get_kb_widget_first ( int kb, int type)
1633 {
1634 return 0;
1635 }
1636
get_kb_widget_type(int kb,int num,TCHAR * name,uae_u32 * code)1637 static int get_kb_widget_type (int kb, int num, TCHAR *name, uae_u32 *code)
1638 {
1639 // fix me
1640 if(code) *code = num;
1641 return IDEV_WIDGET_KEY;
1642 }
1643
keyhack(int scancode,int pressed,int num)1644 static int keyhack (int scancode, int pressed, int num)
1645 {
1646 return scancode;
1647 }
1648
read_kb(void)1649 static void read_kb (void)
1650 {
1651 }
1652
init_kb(void)1653 static int init_kb (void)
1654 {
1655 #if 0 // map_raw_keys marked "if 0" in options.h
1656 if (currprefs.map_raw_keys) {
1657 if (rawkeys_available) {
1658 // inputdevice_setkeytranslation (raw_keyboard, kbmaps);
1659 set_default_hotkeys (x11pc_hotkeys);
1660 write_log ("X11GFX: Enabling raw key-mapping.\n");
1661 } else {
1662 currprefs.map_raw_keys = 0;
1663 write_log ("X11GFX: Raw key-mapping disabled. Keycodes not supported.\n");
1664 }
1665 } else
1666 #endif // 0
1667 write_log ("X11GFX: Raw key-mapping disabled.\n");
1668
1669 #if 0 // map_raw_keys marked "if 0" in options.h
1670 if (!currprefs.map_raw_keys)
1671 set_default_hotkeys (get_x11_default_hotkeys ());
1672 #endif // 0
1673
1674 return 1;
1675 }
1676
close_kb(void)1677 static void close_kb (void)
1678 {
1679 }
1680
acquire_kb(int num,int flags)1681 static int acquire_kb (int num, int flags)
1682 {
1683 return 1;
1684 }
1685
unacquire_kb(int num)1686 static void unacquire_kb (int num)
1687 {
1688 }
1689
1690 /*
1691 * Default inputdevice config for X11 mouse
1692 */
input_get_default_mouse(struct uae_input_device * uid,int num,int port,int af,bool gp,bool wheel)1693 int input_get_default_mouse (struct uae_input_device *uid, int num, int port, int af, bool gp, bool wheel)
1694 {
1695 /* Supports only one mouse */
1696 uid[0].eventid[ID_AXIS_OFFSET + 0][0] = INPUTEVENT_MOUSE1_HORIZ;
1697 uid[0].eventid[ID_AXIS_OFFSET + 1][0] = INPUTEVENT_MOUSE1_VERT;
1698 uid[0].eventid[ID_AXIS_OFFSET + 2][0] = INPUTEVENT_MOUSE1_WHEEL;
1699 uid[0].eventid[ID_BUTTON_OFFSET + 0][0] = INPUTEVENT_JOY1_FIRE_BUTTON;
1700 uid[0].eventid[ID_BUTTON_OFFSET + 1][0] = INPUTEVENT_JOY1_2ND_BUTTON;
1701 uid[0].eventid[ID_BUTTON_OFFSET + 2][0] = INPUTEVENT_JOY1_3RD_BUTTON;
1702 uid[0].enabled = 1;
1703 return 0;
1704 }
1705
get_kb_flags(int num)1706 static int get_kb_flags (int num)
1707 {
1708 return 0;
1709 }
1710
1711 struct inputdevice_functions inputdevicefunc_keyboard =
1712 {
1713 init_kb,
1714 close_kb,
1715 acquire_kb,
1716 unacquire_kb,
1717 read_kb,
1718 get_kb_num,
1719 get_kb_friendlyname,
1720 get_kb_uniquename,
1721 get_kb_widget_num,
1722 get_kb_widget_type,
1723 get_kb_widget_first,
1724 get_kb_flags
1725 };
1726
getcapslockstate(void)1727 int getcapslockstate (void)
1728 {
1729 return 0;
1730 }
1731
setcapslockstate(int state)1732 void setcapslockstate (int state)
1733 {
1734 }
1735
target_checkcapslock(int scancode,int * state)1736 int target_checkcapslock (int scancode, int *state)
1737 {
1738 if (scancode != DIK_CAPITAL && scancode != DIK_NUMLOCK && scancode != DIK_SCROLL)
1739 return 0;
1740 if (*state == 0)
1741 return -1;
1742
1743 /*
1744 if (scancode == DIK_CAPITAL)
1745 *state = SDL_GetModState() & KMOD_CAPS;
1746 if (scancode == DIK_NUMLOCK)
1747 *state = SDL_GetModState() & KMOD_NUM;
1748 if (scancode == DIK_SCROLL)
1749 *state = host_scrolllockstate;
1750 return 1;
1751 */
1752 return 0;
1753 }
1754
1755 /*
1756 * Handle gfx cfgfile options
1757 */
gfx_save_options(FILE * f,const struct uae_prefs * p)1758 void gfx_save_options (FILE *f, const struct uae_prefs *p)
1759 {
1760 fprintf (f, "x11.low_bandwidth=%s\n", p->x11_use_low_bandwidth ? "true" : "false");
1761 fprintf (f, "x11.use_mitshm=%s\n", p->x11_use_mitshm ? "true" : "false");
1762 #if 0 // map_raw_keys marked "if 0" in options.h
1763 fprintf (f, "x11.map_raw_keys=%s\n", p->map_raw_keys ? "true" : "false");
1764 #endif // 0
1765 }
1766
gfx_parse_option(struct uae_prefs * p,const char * option,const char * value)1767 int gfx_parse_option (struct uae_prefs *p, const char *option, const char *value)
1768 {
1769 return (cfgfile_yesno (option, value, "low_bandwidth", &p->x11_use_low_bandwidth)
1770 || cfgfile_yesno (option, value, "use_mitshm", &p->x11_use_mitshm)
1771 || cfgfile_yesno (option, value, "hide_cursor", &p->hide_cursor) /* Compatibility. This was an X11-specific option. */
1772 #if 0 // map_raw_keys marked "if 0" in options.h
1773 || cfgfile_yesno (option, value, "map_raw_keys", &p->map_raw_keys));
1774 #endif // 0
1775 );
1776 }
1777
gfx_default_options(struct uae_prefs * p)1778 void gfx_default_options (struct uae_prefs *p)
1779 {
1780 p->x11_use_low_bandwidth = 0;
1781 p->x11_use_mitshm = 1;
1782 #if 0 // map_raw_keys marked "if 0" in options.h
1783 p->map_raw_keys = rawkeys_available;
1784 #endif // 0
1785 }
1786
setmaintitle(void)1787 void setmaintitle (void)
1788 {
1789 /* not implemented yet */
1790 }
1791
1792 #if defined PICASSO96
picasso_palette(void)1793 int picasso_palette (void)
1794 {
1795 int i = 0, changed = 0;
1796
1797 for ( ; i < 256; i++) {
1798 int r = picasso96_state.CLUT[i].Red;
1799 int g = picasso96_state.CLUT[i].Green;
1800 int b = picasso96_state.CLUT[i].Blue;
1801 uae_u32 v = (doMask256 (r, red_bits, red_shift)
1802 | doMask256 (g, green_bits, green_shift)
1803 | doMask256 (b, blue_bits, blue_shift));
1804 if (v != picasso_vidinfo.clut[i]) {
1805 picasso_vidinfo.clut[i] = v;
1806 changed = 1;
1807 }
1808 }
1809 return changed;
1810 }
1811
gfx_set_picasso_colors(RGBFTYPE rgbfmt)1812 void gfx_set_picasso_colors (RGBFTYPE rgbfmt)
1813 {
1814 alloc_colors_picasso (red_bits, green_bits, blue_bits, red_shift, green_shift, blue_shift, rgbfmt);
1815 }
1816 #endif // defined
1817