2 * TinyPTC x11 v0.7.3 X Direct Graphics Access Extension v1 target
3 * Copyright (C) 2000-2002 Alessandro Gatti <a.gatti@tiscali.it>
5 * http://www.sourceforge.net/projects/tinyptc/
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.
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.
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
26 #include <X11/Xutil.h>
27 #include <X11/extensions/xf86dga.h>
28 #include <X11/extensions/xf86vmode.h>
34 #include <sys/types.h>
39 #define __PTC_FROM_SOURCE
46 ptc_open (char *title, int width, int height)
48 /* Check for the effective UID of the running process */
53 /* Open a display on the current root window */
54 ptc_display = XOpenDisplay (NULL);
55 if (ptc_display == NULL)
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 */
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;
72 if (ptc_depth == ptc_pixmap_formats[ptc_pixmap_counter].depth)
74 /* Set the right value */
76 ptc_pixmap_formats[ptc_pixmap_counter].bits_per_pixel;
79 XFree (ptc_pixmap_formats);
80 #ifdef __PTC_ENABLE_CONVERSIONS__
81 /* Check if a converter is avaliable */
83 ptc_request_converter (ptc_converter_depth, ptc_visual->red_mask,
84 ptc_visual->green_mask, ptc_visual->blue_mask);
87 /* Close the display */
88 XCloseDisplay (ptc_display);
91 /* Get the actual bytes-per-pixel value */
92 switch (ptc_converter_depth)
101 ptc_output_pitch = 2;
104 ptc_output_pitch = 3;
107 ptc_output_pitch = 4;
110 /* Allocate the temporary buffer */
111 ptc_buffer = (char *) malloc (width * height * ptc_output_pitch);
112 if (ptc_buffer == NULL)
114 XCloseDisplay (ptc_display);
118 /* It runs only on a 32bpp display if no conversions were activated */
119 if (ptc_converter_depth != 32)
121 XCloseDisplay (ptc_display);
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))
129 XCloseDisplay (ptc_display);
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)
139 XCloseDisplay (ptc_display);
142 /* Check for VidMode extension avaliability */
143 if (!XF86VidModeQueryExtension
144 (ptc_display, &ptc_event_base, &ptc_error_base))
146 XCloseDisplay (ptc_display);
149 /* Get all the mode parameters */
150 XF86VidModeGetAllModeLines (ptc_display, ptc_screen, &ptc_totalmodes,
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;
159 if ((ptc_currentmodeline.hdisplay ==
160 ptc_modeinfodata[ptc_modecounter]->hdisplay)
161 && (ptc_currentmodeline.vdisplay ==
162 ptc_modeinfodata[ptc_modecounter]->vdisplay))
164 /* Save the parameters */
165 ptc_previousmode_number = ptc_modecounter;
166 ptc_screen_width = ptc_currentmodeline.hdisplay;
167 ptc_screen_height = ptc_currentmodeline.vdisplay;
171 ptc_emulate_fullscreen = True;
172 /* Search for desired mode in parameter list */
173 for (ptc_modecounter = 0; ptc_modecounter < ptc_totalmodes;
176 if ((ptc_modeinfodata[ptc_modecounter]->hdisplay == width)
177 && (ptc_modeinfodata[ptc_modecounter]->vdisplay == height))
179 /* Try to switch mode */
180 if (!XF86VidModeSwitchToMode
181 (ptc_display, ptc_screen, ptc_modeinfodata[ptc_modecounter]))
183 XFree (ptc_modeinfodata);
184 XCloseDisplay (ptc_display);
187 ptc_emulate_fullscreen = False;
191 #ifdef __PTC_BEST_VIDEOMODE__
192 /* It works for fullscreen emulation only */
193 if (ptc_emulate_fullscreen)
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;
202 if ((ptc_modeinfodata[ptc_modecounter]->hdisplay >= width)
203 && (ptc_modeinfodata[ptc_modecounter]->vdisplay >= height))
205 /* If it fits, get delta parameters */
207 ptc_modeinfodata[ptc_modecounter]->hdisplay - width;
208 ptc_best_x_delta *= ptc_best_x_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)
215 /* Set up next iteration */
216 ptc_best_delta = ptc_best_x_delta + ptc_best_y_delta;
217 ptc_best_videomode = ptc_modecounter;
221 /* Try to switch mode */
222 if (!XF86VidModeSwitchToMode
223 (ptc_display, ptc_screen, ptc_modeinfodata[ptc_best_videomode]))
225 XFree (ptc_modeinfodata);
226 XCloseDisplay (ptc_display);
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 */
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)
251 /* Get effective framebuffer address */
252 #ifdef __PTC_ENABLE_CONVERSIONS__
253 ptc_framebuffer_start =
254 ptc_framebuffer_width * ((ptc_screen_height - height) / 2) *
256 ((ptc_screen_width - width) / 2) * ptc_output_pitch;
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__ */
266 ptc_framebuffer_start = 0;
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))
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);
288 /* Initialize DGA video access */
289 XF86DGADirectVideo (ptc_display, ptc_screen,
290 XF86DGADirectGraphics | XF86DGADirectKeyb |
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;
308 /* Update the screen */
311 ptc_update (void *buffer)
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;
325 #ifdef __PTC_ENABLE_CONVERSIONS__
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;
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);
340 ptc_framebuffer_index += ptc_framebuffer_pitch;
341 #endif /* __PTC_ENABLE_CONVERSIONS__ */
343 /* Process incoming events */
344 if (ptc_process_events ())
346 #ifdef __PTC_CLEANUP_CALLBACK__
347 ptc_cleanup_callback ();
348 #endif /* __PTC_CLEANUP_CALLBACK__ */
358 ptc_process_events (void)
362 /* Check if there are events waiting in the display's queue */
363 if (XPending (ptc_display))
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)
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__)
375 /* Check if it was the escape key */
376 if ((ptc_keysym & 0xFF) == __PTC_ESCAPE_KEY__)
386 /* Close the screen */
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 */
411 #endif /* __PTC_XDGA1__ */