]> git.sesse.net Git - ccbs/blob - bigscreen/tinyptc/xdga2.c
Reset bigscreen on changed groups, not just changed tournaments.
[ccbs] / bigscreen / tinyptc / xdga2.c
1 /*
2  * TinyPTC x11 v0.7.3 X Direct Graphics Access Extension v2 target
3  * Copyright (C) 2001-2002 Alessandro Gatti <a.gatti@tiscali.it>
4  * 
5  * http://www.sourceforge.net/projects/tinyptc/
6  * 
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  */
22
23 /* #includes */
24
25 #include <X11/Xlib.h>
26 #include <X11/Xutil.h>
27 #include <X11/extensions/xf86dga.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <limits.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include "tinyptc.h"
35
36 #ifdef __PTC_XDGA2__
37
38 #define __PTC_FROM_SOURCE
39
40 #include "xdga2.h"
41
42 /* Open the screen */
43
44 int
45 ptc_open (char *title, int width, int height)
46 {
47   /* Check for the effective UID of the running process */
48   if (geteuid ())
49     {
50       return PTC_FAILURE;
51     }
52   /* Open a display on the current root window */
53   ptc_display = XOpenDisplay (NULL);
54   if (ptc_display == NULL)
55     {
56       return PTC_FAILURE;
57     }
58   /* Get the default screen associated with the previously opened display */
59   ptc_screen = DefaultScreen (ptc_display);
60   /* Get the default visual */
61   ptc_visual = DefaultVisual (ptc_display, ptc_screen);
62
63   /* Check for DGA extension avaliability */
64   if (!XDGAQueryExtension (ptc_display, &ptc_dga_event_base, &ptc_error_base))
65     {
66       XCloseDisplay (ptc_display);
67       return PTC_FAILURE;
68     }
69   /* Check for version 2.x of the extension */
70   ptc_dga_major_version = 0;
71   if (!XDGAQueryVersion
72       (ptc_display, &ptc_dga_major_version, &ptc_dga_minor_version)
73       || (ptc_dga_major_version < 2))
74     {
75       XCloseDisplay (ptc_display);
76       return PTC_FAILURE;
77     }
78   /* Enable framebuffer access */
79   if (!XDGAOpenFramebuffer (ptc_display, ptc_screen))
80     {
81       XCloseDisplay (ptc_display);
82       return PTC_FAILURE;
83     }
84   /* Get all the modelines */
85   ptc_dga_mode = XDGAQueryModes (ptc_display, ptc_screen, &ptc_dga_modes);
86   ptc_dga_emulate_fullscreen = True;
87 #ifdef __PTC_ENABLE_CONVERSIONS__
88   ptc_dga_mode_32 = INT_MIN;
89   ptc_dga_mode_24 = INT_MIN;
90   ptc_dga_mode_16 = INT_MIN;
91   ptc_dga_mode_15 = INT_MIN;
92 #endif /* __PTC_ENABLE_CONVERSIONS__ */
93   ptc_dga_new_mode = INT_MIN;
94   /* Search for desired mode in parameter list */
95   for (ptc_dga_counter = 0; ptc_dga_counter < ptc_dga_modes;
96        ptc_dga_counter++)
97     {
98       if ((ptc_dga_mode[ptc_dga_counter].viewportWidth == width)
99           && (ptc_dga_mode[ptc_dga_counter].viewportHeight == height))
100         {
101 #ifdef __PTC_ENABLE_CONVERSIONS__
102           /* Get the right videomode for each colordepth */
103           if (ptc_dga_mode[ptc_dga_counter].depth == 24)
104             {
105               if (ptc_dga_mode[ptc_dga_counter].bitsPerPixel == 32)
106                 {
107                   ptc_dga_mode_32 = ptc_dga_counter;
108                   ptc_dga_emulate_fullscreen = False;
109                 }
110               if (ptc_dga_mode[ptc_dga_counter].bitsPerPixel == 24)
111                 {
112                   ptc_dga_mode_24 = ptc_dga_counter;
113                   ptc_dga_emulate_fullscreen = False;
114                 }
115             }
116           if (ptc_dga_mode[ptc_dga_counter].bitsPerPixel == 16)
117             {
118               if (ptc_dga_mode[ptc_dga_counter].depth == 15)
119                 {
120                   ptc_dga_mode_15 = ptc_dga_counter;
121                   ptc_dga_emulate_fullscreen = False;
122                 }
123               if (ptc_dga_mode[ptc_dga_counter].depth == 16)
124                 {
125                   ptc_dga_mode_16 = ptc_dga_counter;
126                   ptc_dga_emulate_fullscreen = False;
127                 }
128             }
129 #else
130           /* Get the right videomode */
131           if ((ptc_dga_mode[ptc_dga_counter].bitsPerPixel == 32)
132               && (ptc_dga_mode[ptc_dga_counter].depth == 32))
133             {
134               ptc_dga_new_mode = ptc_dga_counter;
135               ptc_dga_emulate_fullscreen = False;
136               break;
137             }
138 #endif /* __PTC_ENABLE_CONVERSIONS__ */
139         }
140     }
141
142 #ifdef __PTC_ENABLE_CONVERSIONS__
143   /* Simple heuristics for getting the best videomode and the right
144    * converter for that videomode */
145   if (ptc_dga_mode_32 == INT_MIN)
146     {
147       if (ptc_dga_mode_24 == INT_MIN)
148         {
149           if (ptc_dga_mode_16 == INT_MIN)
150             {
151               if (ptc_dga_mode_15 == INT_MIN)
152                 {
153                 }
154               else
155                 {
156                   ptc_convert =
157                     ptc_request_converter (15,
158                                            ptc_dga_mode[ptc_dga_mode_15].
159                                            redMask,
160                                            ptc_dga_mode[ptc_dga_mode_15].
161                                            greenMask,
162                                            ptc_dga_mode[ptc_dga_mode_15].
163                                            blueMask);
164                   if (!ptc_convert)
165                     {
166                       ptc_dga_new_mode = INT_MIN;
167                     }
168                   else
169                     {
170                       ptc_dga_new_mode = ptc_dga_mode_15;
171                       ptc_dga_output_pitch = 2;
172                     }
173                 }
174             }
175           else
176             {
177               ptc_convert =
178                 ptc_request_converter (16,
179                                        ptc_dga_mode[ptc_dga_mode_16].
180                                        redMask,
181                                        ptc_dga_mode[ptc_dga_mode_16].
182                                        greenMask,
183                                        ptc_dga_mode[ptc_dga_mode_16].
184                                        blueMask);
185               if (!ptc_convert)
186                 {
187                   ptc_dga_new_mode = INT_MIN;
188                 }
189               else
190                 {
191                   ptc_dga_new_mode = ptc_dga_mode_16;
192                   ptc_dga_output_pitch = 2;
193                 }
194             }
195         }
196       else
197         {
198           ptc_convert =
199             ptc_request_converter (24, ptc_dga_mode[ptc_dga_mode_24].redMask,
200                                    ptc_dga_mode[ptc_dga_mode_24].greenMask,
201                                    ptc_dga_mode[ptc_dga_mode_24].blueMask);
202           if (!ptc_convert)
203             {
204               ptc_dga_new_mode = INT_MIN;
205             }
206           else
207             {
208               ptc_dga_new_mode = ptc_dga_mode_24;
209               ptc_dga_output_pitch = 3;
210             }
211         }
212     }
213   else
214     {
215       ptc_convert =
216         ptc_request_converter (32, ptc_dga_mode[ptc_dga_mode_32].redMask,
217                                ptc_dga_mode[ptc_dga_mode_32].greenMask,
218                                ptc_dga_mode[ptc_dga_mode_32].blueMask);
219       if (!ptc_convert)
220         {
221           ptc_dga_new_mode = INT_MIN;
222         }
223       else
224         {
225           ptc_dga_new_mode = ptc_dga_mode_32;
226           ptc_dga_output_pitch = 4;
227         }
228     }
229 #else
230   ptc_dga_output_pitch = 4;
231 #endif /* __PTC_ENABLE_CONVERSIONS__ */
232
233 #ifdef __PTC_BEST_VIDEOMODE__
234   /* It works for fullscreen emulation only */
235   if (ptc_dga_emulate_fullscreen)
236     {
237       /* Set up loop */
238 #ifdef __PTC_ENABLE_CONVERSIONS__
239       ptc_dga_32.best_delta = INT_MAX;
240       ptc_dga_24.best_delta = INT_MAX;
241       ptc_dga_16.best_delta = INT_MAX;
242       ptc_dga_15.best_delta = INT_MAX;
243       ptc_dga_32.best_videomode = INT_MIN;
244       ptc_dga_24.best_videomode = INT_MIN;
245       ptc_dga_16.best_videomode = INT_MIN;
246       ptc_dga_15.best_videomode = INT_MIN;
247 #else
248       ptc_dga_best_delta = INT_MAX;
249       ptc_dga_best_videomode = INT_MIN;
250 #endif /* __PTC_ENABLE_CONVERSIONS__ */
251       /* Check for all avaliable modes */
252       for (ptc_dga_counter = 0; ptc_dga_counter < ptc_dga_modes;
253            ptc_dga_counter++)
254         {
255           if ((ptc_dga_mode[ptc_dga_counter].viewportWidth >= width)
256               && (ptc_dga_mode[ptc_dga_counter].viewportHeight >= height))
257             {
258               ptc_dga_best_x_delta =
259                 ptc_dga_mode[ptc_dga_counter].viewportWidth - width;
260               ptc_dga_best_x_delta *= ptc_dga_best_x_delta;
261               ptc_dga_best_y_delta =
262                 ptc_dga_mode[ptc_dga_counter].viewportHeight - height;
263               ptc_dga_best_y_delta *= ptc_dga_best_y_delta;
264
265               /* Check if the mode fits better than the previous one */
266
267 #ifdef __PTC_ENABLE_CONVERSIONS__
268               if (ptc_dga_mode[ptc_dga_counter].depth == 24)
269                 {
270                   if (ptc_dga_mode[ptc_dga_counter].bitsPerPixel == 32)
271                     {
272                       if (ptc_dga_best_x_delta + ptc_dga_best_y_delta <
273                           ptc_dga_32.best_delta)
274                         {
275                           ptc_dga_32.best_delta =
276                             ptc_dga_best_x_delta + ptc_dga_best_y_delta;
277                           ptc_dga_32.best_videomode = ptc_dga_counter;
278                         }
279                     }
280                   if (ptc_dga_mode[ptc_dga_counter].bitsPerPixel == 24)
281                     {
282                       if (ptc_dga_best_x_delta + ptc_dga_best_y_delta <
283                           ptc_dga_24.best_delta)
284                         {
285                           ptc_dga_24.best_delta =
286                             ptc_dga_best_x_delta + ptc_dga_best_y_delta;
287                           ptc_dga_24.best_videomode = ptc_dga_counter;
288                         }
289                     }
290                 }
291               if (ptc_dga_mode[ptc_dga_counter].bitsPerPixel == 16)
292                 {
293                   if (ptc_dga_mode[ptc_dga_counter].depth == 15)
294                     {
295                       if (ptc_dga_best_x_delta + ptc_dga_best_y_delta <
296                           ptc_dga_15.best_delta)
297                         {
298                           ptc_dga_15.best_delta =
299                             ptc_dga_best_x_delta + ptc_dga_best_y_delta;
300                           ptc_dga_15.best_videomode = ptc_dga_counter;
301                         }
302                     }
303                   if (ptc_dga_mode[ptc_dga_counter].depth == 16)
304                     {
305                       if (ptc_dga_best_x_delta + ptc_dga_best_y_delta <
306                           ptc_dga_16.best_delta)
307                         {
308                           ptc_dga_16.best_delta =
309                             ptc_dga_best_x_delta + ptc_dga_best_y_delta;
310                           ptc_dga_16.best_videomode = ptc_dga_counter;
311                         }
312                     }
313                 }
314 #else
315               /* Set up next iteration */
316               ptc_dga_best_delta =
317                 ptc_dga_best_x_delta + ptc_dga_best_y_delta;
318               ptc_dga_best_videomode = ptc_dga_counter;
319 #endif /* __PTC_ENABLE_CONVERSIONS__ */
320             }
321         }
322     }
323
324 #ifdef __PTC_ENABLE_CONVERSIONS__
325   /* Simple heuristics for getting the best videomode and the right
326    * converter for that videomode */
327
328   if (ptc_dga_32.best_videomode == INT_MIN)
329     {
330       if (ptc_dga_24.best_videomode == INT_MIN)
331         {
332           if (ptc_dga_16.best_videomode == INT_MIN)
333             {
334               if (ptc_dga_15.best_videomode == INT_MIN)
335                 {
336                 }
337               else
338                 {
339                   ptc_convert =
340                     ptc_request_converter (15,
341                                            ptc_dga_mode[ptc_dga_15.
342                                                         best_videomode].
343                                            redMask,
344                                            ptc_dga_mode[ptc_dga_15.
345                                                         best_videomode].
346                                            greenMask,
347                                            ptc_dga_mode[ptc_dga_15.
348                                                         best_videomode].
349                                            blueMask);
350                   if (!ptc_convert)
351                     {
352                       ptc_dga_new_mode = INT_MIN;
353                     }
354                   else
355                     {
356                       ptc_dga_new_mode = ptc_dga_15.best_videomode;
357                       ptc_dga_output_pitch = 2;
358                     }
359                 }
360             }
361           else
362             {
363
364               ptc_convert =
365                 ptc_request_converter (16,
366                                        ptc_dga_mode[ptc_dga_16.
367                                                     best_videomode].redMask,
368                                        ptc_dga_mode[ptc_dga_16.
369                                                     best_videomode].greenMask,
370                                        ptc_dga_mode[ptc_dga_16.
371                                                     best_videomode].blueMask);
372               if (!ptc_convert)
373                 {
374                   ptc_dga_new_mode = INT_MIN;
375                 }
376               else
377                 {
378                   ptc_dga_new_mode = ptc_dga_16.best_videomode;
379                   ptc_dga_output_pitch = 2;
380                 }
381             }
382         }
383       else
384         {
385
386           ptc_convert =
387             ptc_request_converter (24,
388                                    ptc_dga_mode[ptc_dga_24.best_videomode].
389                                    redMask,
390                                    ptc_dga_mode[ptc_dga_24.best_videomode].
391                                    greenMask,
392                                    ptc_dga_mode[ptc_dga_24.best_videomode].
393                                    blueMask);
394           if (!ptc_convert)
395             {
396               ptc_dga_new_mode = INT_MIN;
397             }
398           else
399             {
400               ptc_dga_new_mode = ptc_dga_24.best_videomode;
401               ptc_dga_output_pitch = 3;
402             }
403         }
404     }
405   else
406     {
407       ptc_convert =
408         ptc_request_converter (32,
409                                ptc_dga_mode[ptc_dga_32.best_videomode].
410                                redMask,
411                                ptc_dga_mode[ptc_dga_32.best_videomode].
412                                greenMask,
413                                ptc_dga_mode[ptc_dga_32.best_videomode].
414                                blueMask);
415       if (!ptc_convert)
416         {
417           ptc_dga_new_mode = INT_MIN;
418         }
419       else
420         {
421           ptc_dga_new_mode = ptc_dga_32.best_videomode;
422           ptc_dga_output_pitch = 4;
423         }
424     }
425 #else
426   ptc_dga_output_pitch = 4;
427   ptc_dga_new_mode = ptc_dga_best_videomode;
428 #endif /* __PTC_ENABLE_CONVERSIONS__ */
429 #endif /* __PTC_BEST_VIDEOMODE__ */
430
431   /* No suitable mode found */
432   if (ptc_dga_new_mode == INT_MIN)
433     {
434       XFree (ptc_dga_mode);
435       XCloseDisplay (ptc_display);
436       return PTC_FAILURE;
437     }
438   /* Try to switch mode */
439   ptc_dga_device =
440     XDGASetMode (ptc_display, ptc_screen, ptc_dga_mode[ptc_dga_new_mode].num);
441   if (ptc_dga_device == NULL)
442     {
443       XFree (ptc_dga_mode);
444       XCloseDisplay (ptc_display);
445       return PTC_FAILURE;
446     }
447   /* Clear event queue */
448   XFlush (ptc_display);
449   /* Leave root mode */
450   setuid (getuid ());
451   /* Get viewport parameters */
452   ptc_screen_width = ptc_dga_device->mode.viewportWidth;
453   ptc_screen_height = ptc_dga_device->mode.viewportHeight;
454   /* Get framebuffer address */
455   ptc_dga_framebuffer_address = (char *)ptc_dga_device->data;
456
457
458   /* Set fullscreen emulation up */
459   if (ptc_dga_emulate_fullscreen)
460     {
461       /* Get effective framebuffer address */
462       ptc_framebuffer_start =
463         ptc_dga_device->mode.bytesPerScanline *
464         ((ptc_screen_height - height) / 2) +
465         (((ptc_screen_width - width) / 2) * ptc_dga_output_pitch);
466     }
467   else
468     {
469       /* Ignore offsets */
470       ptc_framebuffer_start = 0;
471     }
472   ptc_dga_video_length =
473     ptc_dga_device->mode.bytesPerScanline *
474     ptc_dga_device->mode.viewportHeight;
475
476   ptc_dga_first_page_address = ptc_dga_framebuffer_address + ptc_framebuffer_start;
477   ptc_dga_second_page_address =
478     ptc_dga_first_page_address + ptc_dga_video_length;
479
480   /* Set the final viewport */
481   XDGASetViewport (ptc_display, ptc_screen, 0, 0, XDGAFlipRetrace);
482   /* Select the input events that should be reported */
483   XDGASelectInput (ptc_display, ptc_screen, KeyPressMask | KeyReleaseMask);
484   /* Clear event queue */
485   XFlush (ptc_display);
486   /* Clear video memory */
487   memset (ptc_dga_device->data, 0x00, ptc_dga_video_length * 2);
488   /* Save the buffer size */
489   ptc_viewport_width = width;
490   ptc_viewport_height = height;
491   ptc_dga_first_page = False;
492   return PTC_SUCCESS;
493 }
494
495 /* Update the screen */
496
497 int
498 ptc_update (void *buffer)
499 {
500   char *ptc_vram_pointer;
501
502   /* This is here just to keep the c++ compiler happy */
503   char *ptc_buffer;
504
505   ptc_buffer=(char *)buffer;
506
507   ptc_framebuffer_index = 0;
508 #ifdef __PTC_ENABLE_CONVERSIONS__
509   ptc_source_index = 0;
510   ptc_destination_index = 0;
511 #endif /* __PTC_ENABLE_CONVERSIONS__ */
512
513   /* Get the right memory area to write into */
514   if (ptc_dga_first_page == True)
515     {
516       ptc_vram_pointer = ptc_dga_first_page_address;
517     }
518   else
519     {
520       ptc_vram_pointer = ptc_dga_second_page_address;
521     }
522
523   /* Do the blit line by line */
524   for (ptc_blitcounter = 0; ptc_blitcounter < ptc_viewport_height;
525        ptc_blitcounter++)
526     {
527 #ifdef __PTC_ENABLE_CONVERSIONS__
528       /* Conversion */
529       ptc_convert (ptc_buffer + ptc_source_index,
530                    ptc_vram_pointer + ptc_destination_index,
531                    ptc_viewport_width);
532       /* Pointers update */
533       ptc_source_index += ptc_viewport_width * sizeof (int);
534       ptc_destination_index += ptc_dga_device->mode.bytesPerScanline;
535 #else
536       /* Data copy */
537       memcpy (ptc_vram_pointer + ptc_framebuffer_index, ptc_buffer,
538               ptc_viewport_width * sizeof (int));
539       ptc_buffer += ptc_viewport_width * sizeof (int);
540       /* Set up offsets */
541       ptc_framebuffer_index += ptc_dga_device->mode.bytesPerScanline;
542 #endif /* __PTC_ENABLE_CONVERSIONS__ */
543     }
544
545   /* Wait for retrace */
546   while (XDGAGetViewportStatus (ptc_display, ptc_screen));
547
548   /* Flip the two pages */
549   if (ptc_dga_first_page == True)
550     {
551       XDGASetViewport (ptc_display, ptc_screen, 0, 0, XDGAFlipImmediate);
552     }
553   else
554     {
555       XDGASetViewport (ptc_display, ptc_screen, 0,
556                        ptc_dga_device->mode.viewportHeight,
557                        XDGAFlipImmediate);
558     }
559   ptc_dga_first_page = !ptc_dga_first_page;
560
561   /* Process incoming events */
562   if (ptc_process_events ())
563     {
564 #ifdef __PTC_CLEANUP_CALLBACK__
565       ptc_cleanup_callback ();
566 #endif /* __PTC_CLEANUP_CALLBACK__ */
567       ptc_close ();
568       exit (0);
569     }
570   return PTC_SUCCESS;
571 }
572
573 /* Process events */
574
575 int
576 ptc_process_events (void)
577 {
578   XDGAEvent ptc_dga_event;
579   KeySym ptc_keysym;
580   XKeyEvent ptc_dga_keyevent;
581   /* Check if there are events waiting in the display's queue */
582   if (XPending (ptc_display))
583     {
584       /* Get the next event in queue */
585       XNextEvent (ptc_display, (XEvent *) & ptc_dga_event);
586       ptc_dga_event.type -= ptc_dga_event_base;
587
588       /* Check if it's a keypress event */
589       if (ptc_dga_event.type == KeyPress)
590         {
591           /* Translate the event */
592           XDGAKeyEventToXKeyEvent (&ptc_dga_event.xkey, &ptc_dga_keyevent);
593           /* Get the keysym */
594           ptc_keysym = XLookupKeysym (&ptc_dga_keyevent, 0);
595           /* Check if the key pressed was a function one */
596           if ((ptc_keysym >> 8) == __PTC_FUNCTION_KEY__)
597             {
598               /* Check if it was the escape key */
599               if ((ptc_keysym & 0xFF) == __PTC_ESCAPE_KEY__)
600                 {
601                   return PTC_SUCCESS;
602                 }
603             }
604         }
605     }
606   return PTC_FAILURE;
607 }
608
609 /* Close the screen */
610
611 void
612 ptc_close (void)
613 {
614   /* Switch back to the previous video mode */
615   XDGASetMode (ptc_display, ptc_screen, 0);
616   /* Disable framebuffer access */
617   XDGACloseFramebuffer (ptc_display, ptc_screen);
618   /* Close the display */
619   XCloseDisplay (ptc_display);
620   /* Deallocate the buffer */
621   if (ptc_buffer)
622     {
623       free (ptc_buffer);
624     }
625 }
626
627 #endif /* __PTC_XDGA2__ */