]> git.sesse.net Git - ccbs/blob - bigscreen/tinyptc/xdga1.c
Import TinyPTC 0.7.3 sources, switch from OpenGL to TinyPTC for now.
[ccbs] / bigscreen / tinyptc / xdga1.c
1 /*
2  * TinyPTC x11 v0.7.3 X Direct Graphics Access Extension v1 target
3  * Copyright (C) 2000-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 <X11/extensions/xf86vmode.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <limits.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include "tinyptc.h"
36
37 #ifdef __PTC_XDGA1__
38
39 #define __PTC_FROM_SOURCE
40
41 #include "xdga1.h"
42
43 /* Open the screen */
44
45 int
46 ptc_open (char *title, int width, int height)
47 {
48   /* Check for the effective UID of the running process */
49   if (geteuid ())
50     {
51       return PTC_FAILURE;
52     }
53   /* Open a display on the current root window */
54   ptc_display = XOpenDisplay (NULL);
55   if (ptc_display == NULL)
56     {
57       return PTC_FAILURE;
58     }
59   /* Get the default screen associated with the previously opened display */
60   ptc_screen = DefaultScreen (ptc_display);
61   /* Get the default visual */
62   ptc_visual = DefaultVisual (ptc_display, ptc_screen);
63   /* Get screen bitdepth */
64   ptc_depth = DefaultDepth (ptc_display, ptc_screen);
65   /* Get a pointer to the supported pixmap formats */
66   ptc_pixmap_formats =
67     XListPixmapFormats (ptc_display, &ptc_pixmap_format_count);
68   /* Check if there's one that's suitable */
69   for (ptc_pixmap_counter = 0; ptc_pixmap_counter < ptc_pixmap_format_count;
70        ptc_pixmap_counter++)
71     {
72       if (ptc_depth == ptc_pixmap_formats[ptc_pixmap_counter].depth)
73         {
74           /* Set the right value */
75           ptc_converter_depth =
76             ptc_pixmap_formats[ptc_pixmap_counter].bits_per_pixel;
77         }
78     }
79   XFree (ptc_pixmap_formats);
80 #ifdef __PTC_ENABLE_CONVERSIONS__
81   /* Check if a converter is avaliable */
82   ptc_convert =
83     ptc_request_converter (ptc_converter_depth, ptc_visual->red_mask,
84                            ptc_visual->green_mask, ptc_visual->blue_mask);
85   if (!ptc_convert)
86     {
87       /* Close the display */
88       XCloseDisplay (ptc_display);
89       return 0;
90     }
91   /* Get the actual bytes-per-pixel value */
92   switch (ptc_converter_depth)
93     {
94     case 8:
95       ptc_output_pitch = 1;
96       break;
97     case 15:
98       ptc_output_pitch = 2;
99       break;
100     case 16:
101       ptc_output_pitch = 2;
102       break;
103     case 24:
104       ptc_output_pitch = 3;
105       break;
106     case 32:
107       ptc_output_pitch = 4;
108       break;
109     }
110   /* Allocate the temporary buffer */
111   ptc_buffer = (char *) malloc (width * height * ptc_output_pitch);
112   if (ptc_buffer == NULL)
113     {
114       XCloseDisplay (ptc_display);
115       return PTC_FAILURE;
116     }
117 #else
118   /* It runs only on a 32bpp display if no conversions were activated */
119   if (ptc_converter_depth != 32)
120     {
121       XCloseDisplay (ptc_display);
122       return PTC_FAILURE;
123     }
124   ptc_output_pitch = sizeof (int);
125 #endif /* __PTC_ENABLE_CONVERSIONS__ */
126   /* Check for DGA extension avaliability */
127   if (!XF86DGAQueryExtension (ptc_display, &ptc_event_base, &ptc_error_base))
128     {
129       XCloseDisplay (ptc_display);
130       return PTC_FAILURE;
131     }
132   /* Get framebuffer parameters */
133   XF86DGAGetVideo (ptc_display, ptc_screen, &ptc_framebuffer_address,
134                    &ptc_framebuffer_width, &ptc_framebuffer_banksize,
135                    &ptc_framebuffer_memory);
136   /* Check if the mode is banked */
137   if (ptc_framebuffer_banksize < ptc_framebuffer_memory)
138     {
139       XCloseDisplay (ptc_display);
140       return PTC_FAILURE;
141     }
142   /* Check for VidMode extension avaliability */
143   if (!XF86VidModeQueryExtension
144       (ptc_display, &ptc_event_base, &ptc_error_base))
145     {
146       XCloseDisplay (ptc_display);
147       return PTC_FAILURE;
148     }
149   /* Get all the mode parameters */
150   XF86VidModeGetAllModeLines (ptc_display, ptc_screen, &ptc_totalmodes,
151                               &ptc_modeinfodata);
152   /* Get current mode parameters */
153   XF86VidModeGetModeLine (ptc_display, ptc_screen, &ptc_dotclock,
154                           &ptc_currentmodeline);
155   /* Search for current mode in parameter list */
156   for (ptc_modecounter = 0; ptc_modecounter < ptc_totalmodes;
157        ptc_modecounter++)
158     {
159       if ((ptc_currentmodeline.hdisplay ==
160            ptc_modeinfodata[ptc_modecounter]->hdisplay)
161           && (ptc_currentmodeline.vdisplay ==
162               ptc_modeinfodata[ptc_modecounter]->vdisplay))
163         {
164           /* Save the parameters */
165           ptc_previousmode_number = ptc_modecounter;
166           ptc_screen_width = ptc_currentmodeline.hdisplay;
167           ptc_screen_height = ptc_currentmodeline.vdisplay;
168           break;
169         }
170     }
171   ptc_emulate_fullscreen = True;
172   /* Search for desired mode in parameter list */
173   for (ptc_modecounter = 0; ptc_modecounter < ptc_totalmodes;
174        ptc_modecounter++)
175     {
176       if ((ptc_modeinfodata[ptc_modecounter]->hdisplay == width)
177           && (ptc_modeinfodata[ptc_modecounter]->vdisplay == height))
178         {
179           /* Try to switch mode */
180           if (!XF86VidModeSwitchToMode
181               (ptc_display, ptc_screen, ptc_modeinfodata[ptc_modecounter]))
182             {
183               XFree (ptc_modeinfodata);
184               XCloseDisplay (ptc_display);
185               return PTC_FAILURE;
186             }
187           ptc_emulate_fullscreen = False;
188           break;
189         }
190     }
191 #ifdef __PTC_BEST_VIDEOMODE__
192   /* It works for fullscreen emulation only */
193   if (ptc_emulate_fullscreen)
194     {
195       /* Set up loop */
196       ptc_best_delta = INT_MAX;
197       ptc_best_videomode = 0;
198       /* Check for all avaliable modes */
199       for (ptc_modecounter = 0; ptc_modecounter < ptc_totalmodes;
200            ptc_modecounter++)
201         {
202           if ((ptc_modeinfodata[ptc_modecounter]->hdisplay >= width)
203               && (ptc_modeinfodata[ptc_modecounter]->vdisplay >= height))
204             {
205               /* If it fits, get delta parameters */
206               ptc_best_x_delta =
207                 ptc_modeinfodata[ptc_modecounter]->hdisplay - width;
208               ptc_best_x_delta *= ptc_best_x_delta;
209               ptc_best_y_delta =
210                 ptc_modeinfodata[ptc_modecounter]->vdisplay - height;
211               ptc_best_y_delta *= ptc_best_y_delta;
212               /* Check if the mode was fitting better than the previous one */
213               if (ptc_best_x_delta + ptc_best_y_delta < ptc_best_delta)
214                 {
215                   /* Set up next iteration */
216                   ptc_best_delta = ptc_best_x_delta + ptc_best_y_delta;
217                   ptc_best_videomode = ptc_modecounter;
218                 }
219             }
220         }
221       /* Try to switch mode */
222       if (!XF86VidModeSwitchToMode
223           (ptc_display, ptc_screen, ptc_modeinfodata[ptc_best_videomode]))
224         {
225           XFree (ptc_modeinfodata);
226           XCloseDisplay (ptc_display);
227           return PTC_FAILURE;
228         }
229     }
230 #endif /* __PTC_BEST_VIDEOMODE__ */
231   /* Clear event queue */
232   XFlush (ptc_display);
233   /* Get the root window */
234   ptc_root_window = XRootWindow (ptc_display, ptc_screen);
235   /* Get exclusive keyboard access */
236   XGrabKeyboard (ptc_display, ptc_root_window, False, GrabModeAsync,
237                  GrabModeAsync, CurrentTime);
238   /* Get exclusive mouse access */
239   XGrabPointer (ptc_display, ptc_root_window, True,
240                 PointerMotionMask | ButtonPressMask | ButtonReleaseMask,
241                 GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
242   /* Leave root mode */
243   setuid (getuid ());
244   /* Get viewport parameters */
245   XF86DGAGetViewPortSize (ptc_display, ptc_screen,
246                           (int *) (&ptc_screen_width),
247                           (int *) (&ptc_screen_height));
248   /* Set fullscreen emulation up */
249   if (ptc_emulate_fullscreen)
250     {
251       /* Get effective framebuffer address */
252 #ifdef __PTC_ENABLE_CONVERSIONS__
253       ptc_framebuffer_start =
254         ptc_framebuffer_width * ((ptc_screen_height - height) / 2) *
255         ptc_output_pitch +
256         ((ptc_screen_width - width) / 2) * ptc_output_pitch;
257 #else
258       ptc_framebuffer_start =
259         ptc_framebuffer_width * ((ptc_screen_height - height) / 2) *
260         sizeof (int) + ((ptc_screen_width - width) / 2) * sizeof (int);
261 #endif /* __PTC_ENABLE_CONVERSIONS__ */
262     }
263   else
264     {
265       /* Ignore offsets */
266       ptc_framebuffer_start = 0;
267     }
268   /* Get the pitch value */
269   ptc_framebuffer_pitch = ptc_framebuffer_width * ptc_output_pitch;
270   /* Do a safety fork */
271   if (XF86DGAForkApp (ptc_screen))
272     {
273       /* Exit DGA mode */
274       XF86DGADirectVideo (ptc_display, ptc_screen, False);
275       /* Switch back to the previous video mode */
276       XF86VidModeSwitchToMode (ptc_display, ptc_screen,
277                                ptc_modeinfodata[ptc_previousmode_number]);
278       /* Free modeinfo data */
279       XFree (ptc_modeinfodata);
280       /* Leave exclusive keyboard access */
281       XUngrabKeyboard (ptc_display, CurrentTime);
282       /* Leave exclusive mouse access */
283       XUngrabPointer (ptc_display, CurrentTime);
284       /* Close the display */
285       XCloseDisplay (ptc_display);
286       return PTC_FAILURE;
287     }
288   /* Initialize DGA video access */
289   XF86DGADirectVideo (ptc_display, ptc_screen,
290                       XF86DGADirectGraphics | XF86DGADirectKeyb |
291                       XF86DGADirectMouse);
292   /* Clear the screen */
293   memset (ptc_framebuffer_address, 0x00,
294           ptc_framebuffer_width * ptc_screen_height * ptc_output_pitch);
295   /* Select the input events that should be reported */
296   XSelectInput (ptc_display, DefaultRootWindow (ptc_display),
297                 KeyPressMask | KeyReleaseMask);
298   /* Set the final viewport */
299   XF86DGASetViewPort (ptc_display, ptc_screen, 0, 0);
300   /* Clear event queue */
301   XFlush (ptc_display);
302   /* Save the buffer size */
303   ptc_viewport_width = width;
304   ptc_viewport_height = height;
305   return PTC_SUCCESS;
306 }
307
308 /* Update the screen */
309
310 int
311 ptc_update (void *buffer)
312 {
313   char *ptc_buffer;
314
315   ptc_buffer=(char *)buffer;
316   ptc_framebuffer_index = 0;
317 #ifdef __PTC_ENABLE_CONVERSIONS__
318   ptc_source_index = 0;
319   ptc_destination_index = 0;
320 #endif /* __PTC_ENABLE_CONVERSIONS__ */
321   /* Do the blit line by line */
322   for (ptc_blitcounter = 0; ptc_blitcounter < ptc_viewport_height;
323        ptc_blitcounter++)
324     {
325 #ifdef __PTC_ENABLE_CONVERSIONS__
326       /* Conversion */
327       ptc_convert (ptc_buffer + ptc_source_index,
328                    ptc_framebuffer_address + ptc_framebuffer_start +
329                    ptc_destination_index, ptc_viewport_width);
330       /* Pointers update */
331       ptc_source_index += ptc_viewport_width * sizeof (int);
332       ptc_destination_index += ptc_framebuffer_pitch;
333 #else
334       /* Copy the data */
335       memcpy (ptc_framebuffer_address + ptc_framebuffer_start +
336               ptc_framebuffer_index, ptc_buffer,
337               ptc_viewport_width * sizeof (int));
338       ptc_buffer += ptc_viewport_width * sizeof (int);
339       /* Set up offsets */
340       ptc_framebuffer_index += ptc_framebuffer_pitch;
341 #endif /* __PTC_ENABLE_CONVERSIONS__ */
342     }
343   /* Process incoming events */
344   if (ptc_process_events ())
345     {
346 #ifdef __PTC_CLEANUP_CALLBACK__
347       ptc_cleanup_callback ();
348 #endif /* __PTC_CLEANUP_CALLBACK__ */
349       ptc_close ();
350       exit (0);
351     }
352   return PTC_SUCCESS;
353 }
354
355 /* Process events */
356
357 int
358 ptc_process_events (void)
359 {
360   XEvent ptc_xevent;
361   KeySym ptc_keysym;
362   /* Check if there are events waiting in the display's queue */
363   if (XPending (ptc_display))
364     {
365       /* Get the next event in queue */
366       XNextEvent (ptc_display, &ptc_xevent);
367       /* Check if it's a keypress event */
368       if (ptc_xevent.type == KeyPress)
369         {
370           /* Get the keysym */
371           ptc_keysym = XLookupKeysym (&ptc_xevent.xkey, 0);
372           /* Check if the key pressed was a function one */
373           if ((ptc_keysym >> 8) == __PTC_FUNCTION_KEY__)
374             {
375               /* Check if it was the escape key */
376               if ((ptc_keysym & 0xFF) == __PTC_ESCAPE_KEY__)
377                 {
378                   return PTC_SUCCESS;
379                 }
380             }
381         }
382     }
383   return PTC_FAILURE;
384 }
385
386 /* Close the screen */
387
388 void
389 ptc_close (void)
390 {
391   /* Exit from DGA mode */
392   XF86DGADirectVideo (ptc_display, ptc_screen, False);
393   /* Switch back to the previous video mode */
394   XF86VidModeSwitchToMode (ptc_display, ptc_screen,
395                            ptc_modeinfodata[ptc_previousmode_number]);
396   /* Free modeinfo data */
397   XFree (ptc_modeinfodata);
398   /* Leave exclusive keyboard access */
399   XUngrabKeyboard (ptc_display, CurrentTime);
400   /* Leave exclusive mouse access */
401   XUngrabPointer (ptc_display, CurrentTime);
402   /* Close the display */
403   XCloseDisplay (ptc_display);
404   /* Deallocate the buffer */
405   if (ptc_buffer)
406     {
407       free (ptc_buffer);
408     }
409 }
410
411 #endif /* __PTC_XDGA1__ */