rust/cargo-c: update to 0.10.7+cargo-0.84.0
[oi-userland.git] / components / x11 / libdga / src / dga_db.c
blob1fbc6092feb9a205146d6ba3ae50c7e79929045b
1 /* Copyright (c) 1993, 1999, Oracle and/or its affiliates. All rights reserved.
3 * Permission is hereby granted, free of charge, to any person obtaining a
4 * copy of this software and associated documentation files (the "Software"),
5 * to deal in the Software without restriction, including without limitation
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 * and/or sell copies of the Software, and to permit persons to whom the
8 * Software is furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice (including the next
11 * paragraph) shall be included in all copies or substantial portions of the
12 * Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
24 /*
25 * dga_db.c - the client side code for DGA double buffering
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <sys/mman.h>
32 #include <X11/Xlib.h>
34 #include <sys/fbio.h>
36 #ifndef FBIOVRTOFFSET
37 #ifdef SVR4
38 #define FBIOVRTOFFSET (FIOC | 38)
39 #else
40 #define FBIOVRTOFFSET _IOR(F, 38, int)
41 #endif
42 #endif
44 #include <netdb.h>
45 #include <sys/stat.h>
46 #include <unistd.h>
48 #include "dga_incls.h"
50 #define DGA_WIN_LOCK_NOMODIF(win) \
51 { \
52 if ((((_Dga_window)(win))->w_lockcnt)++ == 0) { \
53 DGA_LOCK(win); \
54 } \
57 #define DGA_WIN_UNLOCK_NOMODIF(win) \
58 { \
59 if (--(((_Dga_window)(win))->w_lockcnt) == 0) \
60 DGA_UNLOCK(win); \
63 extern void *_dga_is_X_window(Dga_token token, Display **dpyp, Window *winp);
65 #ifdef _LP64
66 static int _dga_db_vrtfunc_internal(Dga_window);
67 #else /* _LP64 */
68 #if defined(__STDC__)
69 static int _dga_db_vrtfunc_internal(Dga_window);
70 #else
71 static int _dga_db_vrtfunc_internal();
72 #endif
73 #endif /* _LP64 */
75 static u_int *dga_vrt_access();
76 static void dga_vrt_release();
78 int
79 dga_db_access(wg_clientpi)
80 Dga_window wg_clientpi ;
82 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
83 WXINFO *infop = wx_infop(wg_clientp) ;
84 u_int *cpage;
85 u_int *dga_vrt_access();
87 if (wg_clientp->db_enabled)
88 return 0;
89 if (infop->wx_dbuf.number_buffers < 2)
90 return 1;
92 cpage = dga_vrt_access(wg_clientp->w_devfd);
94 if (cpage)
96 wg_clientp->db_enabled = 1;
97 wg_clientp->db_vrtcntrp = cpage;
98 wg_clientp->db_lastvrtcntr = *cpage;
99 wg_clientp->db_swapint = 1;
100 wg_clientp->vrt_func = _dga_db_vrtfunc_internal ;
101 if ((infop->wx_dbuf.display_buffer < 0) ||
102 (infop->wx_dbuf.display_buffer > (infop->wx_dbuf.number_buffers - 1)))
103 infop->wx_dbuf.display_buffer = 0;
104 if ((infop->wx_dbuf.read_buffer < 0) ||
105 (infop->wx_dbuf.read_buffer > (infop->wx_dbuf.number_buffers - 1)))
106 infop->wx_dbuf.read_buffer = 1;
107 if ((infop->wx_dbuf.write_buffer < 0) ||
108 (infop->wx_dbuf.write_buffer > (infop->wx_dbuf.number_buffers - 1)))
109 infop->wx_dbuf.write_buffer = 1;
110 return(0);
112 else
113 return(1);
116 void
117 dga_db_release(wg_clientpi)
118 Dga_window wg_clientpi ;
120 void dga_vrt_release();
121 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
123 if (wg_clientp->db_vrtcntrp)
124 dga_vrt_release(wg_clientp->db_vrtcntrp);
125 wg_clientp->db_enabled = 0;
130 void
131 dga_db_write(wg_clientpi,buffer,writefunc,data)
132 Dga_window wg_clientpi ;
133 int buffer;
134 #ifdef _LP64
135 int (*writefunc)(void*, Dga_window, int);
136 #else /* _LP64 */
137 #if defined (__STDC__)
138 int (*writefunc)(void*, Dga_window, int);
139 #else
140 int (*writefunc)();
141 #endif
142 #endif /* _LP64 */
143 void* data;
145 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
147 DGA_WIN_LOCK_NOMODIF(wg_clientp);
148 if (writefunc)
149 (*writefunc) (data,wg_clientpi,buffer);
150 wx_infop(wg_clientp)->wx_dbuf.write_buffer = buffer;
151 DGA_WIN_UNLOCK_NOMODIF(wg_clientp);
154 void
155 dga_db_read(wg_clientpi,buffer,readfunc,data)
156 Dga_window wg_clientpi ;
157 int buffer;
158 #ifdef _LP64
159 int (*readfunc)(void*, Dga_window, int);
160 #else /* _LP64 */
161 #if defined (__STDC__)
162 int (*readfunc)(void*, Dga_window, int);
163 #else
164 int (*readfunc)();
165 #endif
166 #endif /* _LP64 */
167 void* data;
169 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
171 DGA_WIN_LOCK_NOMODIF(wg_clientp);
172 wx_infop(wg_clientp)->wx_dbuf.read_buffer = buffer;
173 if (readfunc)
174 (*readfunc) (data,wg_clientpi,buffer);
175 DGA_WIN_UNLOCK_NOMODIF(wg_clientp);
179 void
180 dga_db_display(wg_clientpi,buffer,visfunc,data)
181 Dga_window wg_clientpi ;
182 int buffer;
183 #ifdef _LP64
184 int (*visfunc)(void*, Dga_window, int);
185 #else /* _LP64 */
186 #if defined (__STDC__)
187 int (*visfunc)(void*, Dga_window, int);
188 #else
189 int (*visfunc)();
190 #endif
191 #endif /* _LP64 */
192 void* data;
194 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
196 if (!dga_db_interval_check(wg_clientpi))
197 dga_db_interval_wait(wg_clientpi);
198 if (visfunc)
199 (*visfunc)(data, wg_clientpi, buffer);
200 if (wg_clientp->db_vrtcntrp)
201 wg_clientp->db_lastvrtcntr = *wg_clientp->db_vrtcntrp;
202 wx_infop(wg_clientp)->wx_dbuf.display_buffer = buffer;
205 void
206 dga_db_interval(wg_clientpi,interval)
207 Dga_window wg_clientpi ;
208 int interval; /* number of milliseconds */
210 int ref_rate;
211 float rr;
212 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
214 ref_rate = wx_infop(wg_clientp)->w_refresh_period;
215 if (ref_rate == 0) ref_rate = 66000;
217 if (interval < 0)
218 interval = 0;
219 if (interval > ref_rate)
220 interval = ref_rate;
221 rr = ((float)ref_rate)* 0.001;
222 wg_clientp->db_swapint = rr * ((float)interval* 0.001);
224 if (wg_clientp->db_swapint == 0)
225 wg_clientp->db_swapint = 1;
229 void
230 dga_db_interval_wait(wg_clientpi)
231 Dga_window wg_clientpi ;
233 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
234 u_int *counter = wg_clientp->db_vrtcntrp;
236 /* Do a block if necessary and if vrt_func has been supplied */
238 if (!wg_clientp->vrt_func || !wg_clientp->db_vrtcntrp) return;
240 while (((u_int) (*counter - wg_clientp->db_lastvrtcntr))
241 < wg_clientp->db_swapint)
243 if ((*(wg_clientp->vrt_func))(wg_clientpi) < 0) return ;;
245 return;
249 dga_db_interval_check(wg_clientpi)
250 Dga_window wg_clientpi ;
252 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
253 u_int *counter = wg_clientp->db_vrtcntrp;
255 if ((wg_clientp->db_vrtcntrp) &&
256 ((u_int) (*counter - wg_clientp->db_lastvrtcntr))
257 < wg_clientp->db_swapint)
258 return(0);
259 else
260 return(1);
264 dga_db_write_inquire(wg_clientpi)
265 Dga_window wg_clientpi ;
267 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
268 return(wx_infop(wg_clientp)->wx_dbuf.write_buffer);
272 dga_db_read_inquire(wg_clientpi)
273 Dga_window wg_clientpi ;
275 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
277 return(wx_infop(wg_clientp)->wx_dbuf.read_buffer);
281 dga_db_display_inquire(wg_clientpi)
282 Dga_window wg_clientpi ;
284 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
285 return(wx_infop(wg_clientp)->wx_dbuf.display_buffer);
288 /* INTERNAL INTERFACE */
290 dga_db_display_complete(wg_clientpi, flag)
291 Dga_window wg_clientpi ;
292 int flag;
294 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
295 if (wg_clientp->db_vrtcntrp &&
296 (wg_clientp->db_lastvrtcntr != *(wg_clientp->db_vrtcntrp)))
297 return 1;
298 if (flag == 0)
299 return 0;
300 if (ioctl(wg_clientp->w_devfd,FBIOVERTICAL,0) < 0)
301 return 0;
302 return 1;
305 /* INTERNAL INTERFACE */
306 static u_int
307 *dga_vrt_access(devfd)
308 int devfd;
310 u_int *cpage;
311 u_int dev_offset;
312 u_int pagesize;
314 dev_offset = 0;
315 if (ioctl(devfd, FBIOVRTOFFSET, &dev_offset) < 0)
316 return (NULL);
318 #ifdef SVR4
319 pagesize = sysconf(_SC_PAGESIZE);
320 #else
321 pagesize = getpagesize();
322 #endif
325 * the driver provides the dev_offset into the mmaped page
326 * where the vertical retrace counter word is.
327 * We will mmap a shared memory page that is on a
328 * page boundary then modify the pointer to the
329 * vertical retrace counter to reflect the exact
330 * location where the counter word exists
333 cpage = (u_int *) mmap((char *)0,
334 pagesize,
335 PROT_READ | PROT_WRITE,
336 MAP_SHARED | _MAP_NEW,
337 devfd,
338 (off_t) (dev_offset & ~(pagesize - 1)));
340 /* if the mmap failed then return NULL otherwide return
341 * the computed address of the vertical retract counter
342 * by adding the beginning of the mmaped page to the
343 * dev_offset into the page returned by the device driver
346 if (cpage == (u_int *) -1)
347 return NULL;
349 return ((u_int *) ((int) cpage | (dev_offset & (pagesize - 1))));
352 static void
353 dga_vrt_release(counter)
354 u_int *counter;
356 char *counter_page;
357 int pagesize;
359 #ifdef SVR4
360 pagesize = sysconf(_SC_PAGESIZE);
361 #else
362 pagesize = getpagesize();
363 #endif
365 /* Unmap the page for this client.
366 * remove the offset computation and munmap the
367 * vertical retrace counter page. we remove the
368 * offset by simply setting the lower bits of
369 * the address to 0
372 counter_page = (char *) (((int) counter) & (~(pagesize - 1)));
373 munmap(counter_page, pagesize) ;
374 return;
377 /* New routines that will be exposed to the public */
379 int
380 dga_db_display_done(wg_clientpi,flag, display_done_func)
381 Dga_window wg_clientpi;
382 int flag;
383 #ifdef _LP64
384 int (*display_done_func)(Dga_window);
386 int (*vrt_func)(Dga_window);
387 #else /* _LP64 */
388 #if defined (__STDC__)
389 int (*display_done_func)(Dga_window);
390 #else
391 int (*display_done_func)();
392 #endif
394 #if defined (__STDC__)
395 int (*vrt_func)(Dga_window);
396 #else
397 int (*vrt_func)();
398 #endif
399 #endif /* _LP64 */
400 _Dga_window wg_clientp = (struct dga_window *)wg_clientpi;
401 int ret_val;
403 /* Return 1 = done, 0 = not done, -1 = error */
404 ret_val = (*display_done_func)(wg_clientpi);
406 /* If the user does not want to block or if the
407 * display_done_func() returned a non-zero, we return
408 * else we try till success after each vrt_retrace()
410 if ((!flag) || (ret_val != 0))
411 return (ret_val);
413 vrt_func = wg_clientp->vrt_func;
414 if (!vrt_func) return 1;
416 while((ret_val = (*display_done_func)(wg_clientpi)) == 0)
417 if (vrt_func(wg_clientpi) < 0) return -1;
418 return (ret_val);
421 /* Returns 0 on fail and non-zero on success */
423 dga_db_grab(clientpi, nbuffers, vrtfunc, vrtcounterp)
424 Dga_window clientpi;
425 int nbuffers;
426 #ifdef _LP64
427 int (*vrtfunc)(Dga_window);
428 #else /* _LP64 */
429 #if defined (__STDC__)
430 int (*vrtfunc)(Dga_window);
431 #else
432 int (*vrtfunc)();
433 #endif
434 #endif /* _LP64 */
435 u_int *vrtcounterp;
437 Display *dpy;
438 Window win;
441 * Check for an invalid Dga_window
443 _Dga_window clientp = (struct dga_window *)clientpi;
444 WXINFO *infop;
446 if ((clientp == (_Dga_window) NULL)) {
447 #ifdef DEBUG
448 (void) fprintf(stderr, "dga_db_grab: passed null pointer\n");
449 #endif
450 return (0);
454 * If the buffers has already been grabbed. Don't
455 * do anything.
457 if (clientp->db_enabled)
458 return (1);
461 * Find out if this is an X window. If so get the Display and window
462 * id.
464 if (!_dga_is_X_window(clientp->w_token, &dpy, &win)) {
465 #ifdef DEBUG
466 (void) fprintf(stderr, "dga_db_grab: Unsupported window type\n");
467 #endif
468 return (0);
472 * Request the server to allow DGA to the buffers associated
473 * with this Dga_window.
475 if (!XDgaGrabBuffers(dpy, win, nbuffers)) {
476 #ifdef DEBUG
477 (void) fprintf(stderr, "dga_db_grab: XDgaGrabBuffers failed\n");
478 #endif
479 return (0);
482 /* Now if they supplied vrtfunc, update the clientp
485 infop =wx_infop(clientp) ;
486 clientp->vrt_func = vrtfunc;
488 /* Now update the clientp pointer with other info */
489 if (vrtcounterp) {
490 clientp->db_enabled = 1;
491 clientp->db_vrtcntrp = (u_int *)vrtcounterp;
492 clientp->db_lastvrtcntr = *vrtcounterp;
493 clientp->db_swapint = 1;
494 if ((infop->wx_dbuf.display_buffer < 0) ||
495 (infop->wx_dbuf.display_buffer > (infop->wx_dbuf.number_buffers - 1)))
496 infop->wx_dbuf.display_buffer = 0;
497 if ((infop->wx_dbuf.read_buffer < 0) ||
498 (infop->wx_dbuf.read_buffer > (infop->wx_dbuf.number_buffers - 1)))
499 infop->wx_dbuf.read_buffer = 1;
500 if ((infop->wx_dbuf.write_buffer < 0) ||
501 (infop->wx_dbuf.write_buffer > (infop->wx_dbuf.number_buffers - 1)))
502 infop->wx_dbuf.write_buffer = 1;
503 return(1);
504 } else {
506 /* Even though they have not supplied vrtp we allow the db_grab
507 * to succeed but we null out vrtfunc and set vrtcntrp to point
508 * to itself!
510 clientp->db_enabled = 1;
511 clientp->vrt_func = NULL;
512 clientp->db_vrtcntrp = NULL;
513 return(1);
518 /* Returns 0 on failure and non-zero on success */
520 dga_db_ungrab(clientpi)
521 Dga_window clientpi;
523 _Dga_window clientp = (struct dga_window *)clientpi;
524 Display *dpy;
525 Window win;
526 int status = -1;
529 * Check for an invalid Dga_window
531 if ((clientp == (Dga_window) NULL)) {
532 #ifdef DEBUG
533 (void) fprintf(stderr, "dga_db_ungrab: passed null pointer\n");
534 #endif
535 return (0);
538 /* If it wasm't grabbed in the first place. don't do anything */
539 if (!clientp->db_enabled)
540 return 1;
544 * Find out if this is an X window. If so get the Display and window
545 * id.
547 if (!_dga_is_X_window(clientp->w_token, &dpy, &win)) {
548 #ifdef DEBUG
549 (void) fprintf(stderr, "dga_db_ungrab: Unsupported window type\n");
550 #endif
551 return (0);
553 /* Mark the window as single buffered */
554 clientp->db_enabled = 0;
556 /* Tell server t ungrab */
557 return (XDgaUnGrabBuffers(dpy, win));
561 /* This is just for internal use */
562 static int
563 _dga_db_vrtfunc_internal(wg_clientp)
564 Dga_window wg_clientp;
566 ( ioctl(((_Dga_window)wg_clientp)->w_devfd,FBIOVERTICAL,0));
567 return(1);