1 /* Copyright (c) 1993, 1998, 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
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.
27 * @@@@ @@@@@ @ @ @@@@ @@@@ @@@ @@@@
28 * @ @ @ @@ @ @ @ @ @ @ @ @
29 * @@@@ @ @ @ @ @ @@@ @@@@ @@@@@ @@@@
30 * @ @ @ @ @@ @ @ @ @ @ @ @ @
31 * @ @ @ @ @ @@@@@ @@@@ @ @ @ @ @@@@
33 * DGA shared retained window access routines
36 * dga_rtn_active(clientp)
40 * dga_rtn_cached(clientp)
44 * dga_rtn_devinfo(clientp)
48 * dga_rtn_devtype(clientp, type, name)
54 * dga_rtn_dimensions(clientp, width, height, linebytes)
61 * dga_rtn_grab(clientp)
65 * dga_rtn_pixels(clientp)
69 * dga_rtn_ungrab(clientp)
73 * _dga_rtn_map(clientp)
77 * _dga_rtn_unmap(clientp)
84 #include <sys/types.h>
89 #include "windowstr.h"
90 #include "dga_externaldefs.h"
91 #include "dga/dgawinstr.h"
100 #include <sys/param.h>
103 #include <X11/Xlib.h>
104 #endif /* SERVER_DGA */
106 #include "dga_incls.h"
107 #include "rtn_grab.h"
109 int dgai_rtn_ungrab_common();
110 extern int dgai_win_check_multiple_grab(_Dga_window clientp
, int drawableGrabber
);
111 extern void *_dga_is_X_window(Dga_token token
, Display
**dpyp
, Window
*winp
);
117 * DGA Retained Windows Active. This function is called to determine
118 * if DGA to the retained portion of the specified dga_window is currently
119 * active. Since the server can drop support for this functionality at
120 * any time, the client should always call this function when a change has
121 * been has been recorded in the retained window information. This function
122 * should be called prior to accessing any other retained window information.
123 * The function returns a non-zero result if DGA to the retained portion
124 * of the window is active. A zero result is returned if support has
127 * Inputs: Dga_window - Pointer to the client structure.
129 * Outputs: 0 - DGA Retained window support has been dropped.
130 * -1 - DGA Retained window support continues.
138 dga_rtn_active(clientpi
)
141 _Dga_window clientp
= (struct dga_window
*)clientpi
;
143 if ((clientp
->rtn_flags
& RTN_MAPPED
))
153 * DGA Retained HW Cache status. This function returns a non-zero
154 * value if the retained raster is cached in hardware. If set to
155 * DGA_RTN_NEW_DEV then the server has re-cached the retained
156 * raster from one device to another. If set to DGA_RTN_SAME_DEV
157 * the raster remains cached in the same device as previously
158 * recorded. If the retained raster is not cached in hw then the
159 * function returns DGA_RTN_NOT_CACHED (0).
161 * Inputs: Dga_window - Pointer to the client structure.
163 * Outputs: DGA_RTN_NOT_CACHED - not cached in hw
164 * DGA_RTN_SAME_DEV - cached in the same hw device
165 * DGA_RTN_NEW_DEV - cached in the new hw device
169 * Externals: RTN_INFOP() Internal MACRO
174 dga_rtn_cached(clientpi
)
177 _Dga_window clientp
= (struct dga_window
*)clientpi
;
179 if (RTN_INFOP(clientp
)->cached
)
180 if (clientp
->c_rtncachseq
!= *(clientp
->s_rtncachseq_p
)) {
181 clientp
->c_rtncachseq
= *(clientp
->s_rtncachseq_p
);
182 return (DGA_RTN_NEW_DEV
);
185 return (DGA_RTN_SAME_DEV
);
187 return (DGA_RTN_NOT_CACHED
);
192 * dga_rtn_devinfop() <---external interface just to be consistent
195 * DGA Retained Device Info. This function returns a pointer to
196 * the shared device specific retained raster information when
197 * the retained raster is cached in hw. The pointer is invalid
198 * if the retained raster isn't cached in hw.
200 * Inputs: Dga_window - Pointer to the client structure.
202 * Outputs: void * - Pointer to the device specific information
206 * Externals: RTN_INFOP() Internal MACRO
210 dga_rtn_devinfo(clientpi
)
213 /* This is the internal interface */
214 _Dga_window clientp
= (struct dga_window
*)clientpi
;
216 return (((char *)clientp
->rtn_info
) + RTN_INFOP(clientp
)->device_offset
);
220 dga_rtn_devinfop(clientpi
)
223 _Dga_window clientp
= (struct dga_window
*)clientpi
;
225 return (((char *)clientp
->rtn_info
) + RTN_INFOP(clientp
)->device_offset
);
232 * DGA Retained Device Type. This function is used to obtain
233 * the retained raster hardware cache device type and name.
235 * Inputs: Dga_window - Pointer to the client structure.
236 * Unsign8 * - Pointer to location to store device type.
237 * char ** - Pointer to location to store name string pointer.
243 * Externals: RTN_INFOP() Internal MACRO
247 dga_rtn_devtype(clientpi
, type
, name
)
252 _Dga_window clientp
= (struct dga_window
*)clientpi
;
254 *type
= RTN_INFOP(clientp
)->device
;
255 *name
= (char *) RTN_INFOP(clientp
)->scr_name
;
260 * dga_rtn_dimensions()
262 * DGA Retained Raster Dimensions. This function is used to obtain
263 * the retained raster's dimensions.
265 * Inputs: Dga_window - Pointer to the client structure.
266 * short * - Pointer to location to store the width.
267 * short * - Pointer to location to store the height.
268 * u_int * - Pointer to the location to store the linebytes.
274 * Externals: RTN_INFOP() Internal MACRO
278 dga_rtn_dimensions(clientpi
, width
, height
, linebytes
)
284 _Dga_window clientp
= (struct dga_window
*)clientpi
;
286 *width
= RTN_INFOP(clientp
)->width
;
287 *height
= RTN_INFOP(clientp
)->height
;
288 *linebytes
= RTN_INFOP(clientp
)->linebytes
;
292 dga_rtn_bitsperpixel(Dga_window clientpi
)
294 _Dga_window clientp
= (struct dga_window
*)clientpi
;
296 return(RTN_INFOP(clientp
)->bitsperpixel
);
303 * DGA Retained Window Grab. This function creates the shared memory
304 * interface to allow the calling process Direct Graphics Access (DGA)
305 * to the retained raster associated with the specified DGA window.
306 * A request to allow DGA access to the retained raster is sent to the
307 * X/NeWS server. Should the server honor this request, shared memory
308 * mappings within the calling process's address space are then created.
309 * Should any of these steps fail, 0 is returned and the calling process
310 * is not allowed DGA to the retained raster. A non-zero result is
311 * returned upon success.
313 * Inputs: Dga_window - Pointer to the Dga_window for which DGA
314 * to the retained raster is desired.
316 * Outputs: 0 - failed
321 * Externals: XDgaGrabRetainedWindow()
322 * XDgaUnGrabRetainedWindow()
325 * fprintf() DEBUG ONLY
329 dga_rtn_grab(clientpi
)
337 #endif /* SERVER_DGA */
340 * Check for an invalid Dga_window
342 _Dga_window clientp
= (struct dga_window
*)clientpi
;
344 if ((clientp
== (_Dga_window
) NULL
)) {
346 (void) fprintf(stderr
, "dga_rtn_grab: passed null pointer\n");
352 /* Determine the window associated with this clientp */
353 infop
= (WXINFO
*) clientp
->w_info
;
354 pWin
= (((WDEV
*)(infop
->wdev
))->pWin
);
356 /* Check to see if backing store has been turned on for thw window */
357 if (pWin
->backingStore
== NotUseful
)
361 if (!DgaSharedRetained(pWin
, 1, pWin
->drawable
.id
)) {
364 /* Map the shared memory into the calling process's address space.*/
365 if (!_dga_rtn_map(clientp
)) {
367 /* Ungrab the retained raster */
368 (void) DgaSharedRetained(pWin
, 0, pWin
->drawable
.id
);
373 * If the retained raster has already been grabbed. Don't
376 if (clientp
->rtn_flags
& RTN_GRABBED
)
380 * Find out if this is an X window. If so get the Display and window
381 * id. These are used to determine the name of the shared retained
382 * info file. NOTE: DGA to retained rasters are currently supported
383 * only for X windows.
385 if (!_dga_is_X_window(clientp
->w_token
, &dpy
, &win
)) {
387 (void) fprintf(stderr
, "dga_rtn_grab: Unsupported window type\n");
391 /* Check to see if backing store is turned on for this window; if not
395 XWindowAttributes attr
;
396 XGetWindowAttributes(dpy
,win
,&attr
);
397 if (attr
.backing_store
== NotUseful
) {
399 (void) fprintf(stderr
,"dga_rtn_grab: Window has no backing store\n");
407 * Request the server to allow DGA to the retained raster associated
408 * with this Dga_window.
410 if (!XDgaGrabRetainedWindow(dpy
, win
)) {
412 (void) fprintf(stderr
, "dga_rtn_grab: XDgaGrabRetainedWindow failed\n");
417 * Now map the shared memory into the calling process's address
420 if (!_dga_rtn_map(clientp
)) {
422 (void) fprintf(stderr
, "dga_rtn_grab: unable to map shared info\n");
425 * Ungrab the retained raster
427 (void) XDgaUnGrabRetainedWindow(dpy
, win
);
430 #endif /* SERVER_DGA */
431 clientp
->rtn_flags
|= RTN_GRABBED
;
439 * DGA Retained Pixel Memory . This function returns a pointer
440 * to the shared retained pixel memory.
442 * Inputs: Dga_window - Pointer to the client structure.
444 * Outputs: u_char * - Pointer to retained pixel memory.
453 dga_rtn_pixels(clientpi
)
456 _Dga_window clientp
= (struct dga_window
*)clientpi
;
458 return ((void *)clientp
->rtn_pixels
);
465 * DGA Retained Window Ungrab. This function frees the resources
466 * associated with a DGA retained retained raster. The shared
467 * memory mappings in the calling process's address space are
468 * unmapped, the shared info file is closed, and the server is
469 * notified through a protocol extension to free all its resources
470 * associated with the DGA retained raster. Should any of these
471 * steps fail, 0 is returned. A non-zero result is returned upon
474 * Inputs: Dga_window - Pointer to the Dga_window for which DGA
475 * to the retained raster is desired.
477 * Outputs: 0 - failed
482 * Externals: DisplayString() X11 MACRO
483 * XDgaUnGrabRetainedWindow()
486 * fprintf() DEBUG ONLY
490 dga_rtn_ungrab(clientpi
)
493 _Dga_window clientp
= (struct dga_window
*)clientpi
;
495 return (dgai_rtn_ungrab_common(clientp
, 0));
499 dgai_rtn_ungrab_common(clientp
, drawableGrabber
)
510 #endif /* SERVER_DGA */
513 * Check for an invalid Dga_window
515 if ((clientp
== (Dga_window
) NULL
)) {
517 (void) fprintf(stderr
, "dga_rtn_ungrab: passed null pointer\n");
523 * If the retained window has not been grabbed then don't
526 if ((clientp
->rtn_flags
& RTN_GRABBED
) == 0)
530 * Unmap the calling process's resources if present.
532 status
&= _dga_rtn_unmap(clientp
);
535 * Set the dga_window retained window server sequence counter pointer
536 * to reflect that the retained raster has NOT been grabbed.
538 clientp
->s_rtnseq_p
= &(clientp
->c_rtnseq
);
541 /* Determine the window associated with this clientp */
542 infop
= (WXINFO
*) clientp
->w_info
;
543 pWin
= (((WDEV
*)(infop
->wdev
))->pWin
);
545 status
&= DgaSharedRetained(pWin
, 0, pWin
->drawable
.id
);
548 * Find out if this is an X window. If so get the Display and window
549 * id. These are used to determine the name of the shared retained
550 * info file. NOTE: DGA to retained rasters is currently supported
551 * only for X windows.
553 if (!_dga_is_X_window(clientp
->w_token
, &dpy
, &win
)) {
555 (void) fprintf(stderr
, "dga_rtn_grab: Unsupported window type\n");
561 * Tell the server to deallocate its retained window
562 * resources.if there are no other clients grabbing this window
564 if (!dgai_win_check_multiple_grab(clientp
,drawableGrabber
))
565 status
&= XDgaUnGrabRetainedWindow(dpy
, win
);
567 #endif /* SERVER_DGA */
569 clientp
->rtn_flags
= 0;
581 * DGA Retained Window Map. This function maps the retained window
582 * shared memory into the clients address space after determining
583 * the path to the retained window information file. The shared
584 * retained info structure is mapped followed by the actual pixel
585 * array used when the pixels are not cached in hardware. The
586 * address of the shared retained info structure is then place in
587 * the dga_window structure along with the client dependent information.
588 * Should any operation fail, a NULL pointer is placed in the dga_window
589 * structure and 0 is returned.
591 * Inputs: Dga_window - Pointer to the dga_window structure
593 * Outputs: 0 - failed
598 * Externals: DisplayString() X11 MACRO
599 * XDgaGetRetainedPath()
602 * fprintf() DEBUG ONLY
604 * getpagesize() SUNOS ONLY
613 * sysconf() SVR4 ONLY
618 _dga_rtn_map(clientp
)
621 SHARED_RETAINED_INFO
*infop
;
635 char host
[MAXHOSTNAMELEN
];
636 #endif /* SERVER_DGA */
639 * Check for a non-zero pointer.
641 if (clientp
== (_Dga_window
) NULL
) {
643 (void) fprintf(stderr
, "_dga_rtn_map: dga_window pointer (NULL)\n");
649 * If the shared retained information has already been mapped don't
652 if ((clientp
->rtn_flags
& RTN_MAPPED
))
656 /* Determine the window associated with this clientp */
657 winfop
= (WXINFO
*) clientp
->w_info
;
658 infop
= (SHARED_RETAINED_INFO
*)winfop
->w_srtndlink
;
660 /* Initialise clientp's retained info structure - refer dga.h */
661 clientp
->rtn_fd
= 0; /* I don't think that it is needed any more */
662 clientp
->rtn_size
= infop
->s_size
;
663 clientp
->c_rtnseq
= 0;
664 clientp
->s_rtnseq_p
= (u_int
*)&(infop
->s_modified
);
665 clientp
->c_rtncachseq
= 0;
666 clientp
->s_rtncachseq_p
= (u_int
*)&(infop
->s_cacheseq
);
667 clientp
->rtn_info
= (caddr_t
)infop
;
668 clientp
->rtn_pixels
= (caddr_t
)(infop
->s_pixels
);
669 clientp
->rtn_flags
|= RTN_MAPPED
;
672 #else /* SERVER_DGA */
674 * Find out if this is an X window. If so get the Display and window
675 * id. These are used to determine the name of the shared retained
676 * info file. NOTE: DGA to retained rasters are currently supported
677 * only for X windows.
679 if (!_dga_is_X_window(clientp
->w_token
, &dpy
, &win
)) {
681 (void) fprintf(stderr
, "_dga_rtn_map: Unsupported window type\n");
687 * Now locate the shared retained info file within the file system.
688 * This file is located in /tmp by default, but through a server
689 * command line option, can be located anywhere on the system in
690 * question. Get the path from the server using the protocol
691 * extension. Then create the filename using the display string
692 * and the port number.
694 if (!XDgaGetRetainedPath(dpy
, win
, path
)) {
696 (void) fprintf(stderr
, "_dga_rtn_map: XDgaGetRetainedPath failed\n");
702 * If the path is equal to "", then use the default directory
706 (void) strcpy(path
, "/tmp");
707 else if (strlen(path
) > RTN_MAXPATH
) {
709 (void) fprintf(stderr
, "_dga_rtn_map: path longer than supported\n");
713 (void) strcat(path
, RTN_FILE
);
716 * Now get the port number for this display
718 dpystr
= DisplayString(dpy
);
719 if (dpystr
[0] == ':')
720 (void) sscanf(dpystr
, ":%u", &port
);
722 (void) sscanf(dpystr
, "%[^:]:%u", host
, &port
);
725 * Combine the port number and the window id with the path
729 (void) sprintf(path
+size
, "%01x.%08x", port
, win
);
731 if ((filefd
= open(path
,O_RDWR
,0666))<0) {
733 (void) fprintf(stderr
, "_dga_rtn_map: unable to open file %s\n",
740 * Now unlink the file to guarantee that it will disappear
741 * should the client or server crash.
746 pagesize
= sysconf(_SC_PAGESIZE
);
748 pagesize
= getpagesize();
752 * Check the state of the file. If the size of the file
753 * is insufficient to contain the first page of the shared
754 * retained info structure (ie < pagesize) report a failure.
756 if (fstat(filefd
, &rstat
) < 0) {
758 (void) fprintf(stderr
, "_dga_rtn_map: unable get file status\n");
760 (void) close(filefd
);
763 if (rstat
.st_size
< pagesize
) {
765 (void) fprintf(stderr
, "_dga_rtn_map: file not correct size, %ld\n",
768 (void) close(filefd
);
773 * Map the SHARED_RETAINED_INFO structure
775 infop
= (SHARED_RETAINED_INFO
*) mmap(0,
777 PROT_READ
|PROT_WRITE
,
782 if (infop
== (SHARED_RETAINED_INFO
*) -1) {
784 (void) fprintf(stderr
, "_dga_rtn_map: unable to mmap file %s\n",
787 (void) close(filefd
);
792 * If the file is not actually a shared retained information file
793 * or its the wrong version, unmap the shared memory, close the
794 * file and return the error status.
796 if ((infop
->magic
!= RTN_MAGIC
) || (infop
->version
> RTN_VERS
)) {
798 (void) fprintf(stderr
, "_dga_rtn_map: contents of file %s incorrect\n",
801 (void) munmap((caddr_t
) infop
, pagesize
);
802 (void) close(filefd
);
809 pixels
= (u_char
*) mmap(0,
811 PROT_READ
|PROT_WRITE
,
814 (off_t
)infop
->first_mmap_offset
);
816 if (pixels
== (u_char
*) -1) {
818 (void) fprintf(stderr
, "_dga_rtn_map: unable to mmap pixel area\n");
820 (void) munmap((caddr_t
) infop
, pagesize
);
821 (void) close(filefd
);
826 * Set the fields of the client information.
828 clientp
->rtn_fd
= filefd
;
829 clientp
->rtn_size
= infop
->s_size
;
830 clientp
->c_rtnseq
= 0;
831 clientp
->s_rtnseq_p
= &(infop
->s_modified
);
832 clientp
->c_rtncachseq
= 0;
833 clientp
->s_rtncachseq_p
= &(infop
->s_cacheseq
);
834 clientp
->rtn_info
= (void *) infop
;
835 clientp
->rtn_pixels
= (void *) pixels
;
836 clientp
->rtn_flags
|= RTN_MAPPED
;
839 _dga_rtn_dump(infop
);
843 #endif /* SERVER_DGA */
850 * DGA Retained Window Unmap. This function unmaps the retained window
851 * shared memory from the clients address space given the pointer to the
852 * dga_window structure. The pixel array associated with the retained info
853 * structure is unmapped first followed by the shared retained info
854 * structure. The pointer to the shared memory info structure within the
855 * dga_window structure is set to NULL and the shared memory file is then
856 * closed. Should any operation fail zero is returned.
858 * Inputs: Dga_window - Pointer to the dga_window structure for which
859 * the the shared retained info structure is to
862 * Outputs: 0 - failed
868 * fprintf() DEBUG ONLY
869 * getpagesize() SUNOS ONLY
871 * sysconf() SVR4 ONLY
876 _dga_rtn_unmap(clientp
)
882 if ((clientp
->rtn_flags
& RTN_MAPPED
) == 0)
887 pagesize
= sysconf(_SC_PAGESIZE
);
889 pagesize
= getpagesize();
892 if (munmap(clientp
->rtn_pixels
, clientp
->rtn_size
)) {
894 (void) fprintf(stderr
, "_dga_rtn_unmap: pixel unmap failed\n");
898 if (munmap(clientp
->rtn_info
, pagesize
)) {
900 (void) fprintf(stderr
, "_dga_rtn_unmap: info page unmap failed\n");
904 #endif /*SERVER_DGA */
905 clientp
->rtn_info
= (void *) NULL
;
906 clientp
->c_rtnseq
= 0;
907 clientp
->s_rtnseq_p
= (u_int
*) &(clientp
->s_rtnseq_p
);
908 clientp
->c_rtncachseq
= 0;
909 clientp
->s_rtncachseq_p
= &(clientp
->c_rtncachseq
);
910 clientp
->rtn_pixels
= (void*) NULL
;
911 (void) close(clientp
->rtn_fd
);
912 clientp
->rtn_fd
= -1;
913 clientp
->rtn_flags
&= ~(RTN_MAPPED
);
914 clientp
->rtn_flags
|= RTN_MAPCHG
;
926 * DGA Retained Info Structure Dump. This function prints out the contents
927 * of the shared retained info structure found at the specified address.
929 * Inputs: SHARED_RETAINED_INFO * - Pointer to the structure to dump.
935 * Externals: printf()
940 SHARED_RETAINED_INFO
*infop
;
943 if (infop
== (SHARED_RETAINED_INFO
*) NULL
)
944 (void) printf("NULL info pointer passed to _dga_rtn_dump\n");
946 (void) printf("Retained window info page is %p\n", infop
);
947 (void) printf("\tmagic =\t\t%u\n", infop
->magic
);
948 (void) printf("\tversion =\t%u\n", infop
->version
);
949 (void) printf("\tobsolete =\t%u\n", infop
->obsolete
);
950 (void) printf("\tdevice =\t%u\n", infop
->device
);
951 (void) printf("\tcached =\t%u\n", infop
->cached
);
952 (void) printf("\ts_cacheseq =\t%u\n", infop
->s_cacheseq
);
953 (void) printf("\ts_modified =\t%u\n", infop
->s_modified
);
954 (void) printf("\ts_wxlink =\t%p\n", infop
->s_wxlink
);
955 (void) printf("\tfirst_mmap_offset =\t%u\n", infop
->first_mmap_offset
);
956 (void) printf("\tdevice_offset =\t%u\n", infop
->device_offset
);
957 (void) printf("\twidth =\t\t%d\n", infop
->width
);
958 (void) printf("\theight =\t%d\n", infop
->height
);
959 (void) printf("\tlineybtes =\t%u\n", infop
->linebytes
);
960 (void) printf("\ts_fd =\t\t%d\n", infop
->s_fd
);
961 (void) printf("\ts_size =\t%u\n", infop
->s_size
);
962 (void) printf("\ts_pixels =\t%p\n", infop
->s_pixels
);
963 (void) printf("\tfn = \t\t%s\n", infop
->fn
);
964 (void) printf("\tscr_name = \t%s\n", infop
->scr_name
);
965 (void) printf("\tc_fd =\t\t%d\n", infop
->c_fd
);
966 (void) printf("\tc_size =\t%u\n", infop
->c_size
);
967 (void) printf("\tc_pixels =\t%p\n", infop
->c_pixels
);
968 (void) printf("\tc_modified =\t%u\n", infop
->c_modified
);
969 (void) printf("\tc_cacheseq =\t%u\n", infop
->c_cacheseq
);
976 dga_win_bboxinfop(clientpi
)
979 _Dga_window clientp
= (struct dga_window
*)clientpi
;
980 WXINFO
*infop
= (WXINFO
*) clientp
->w_info
;
982 if (infop
->w_version
< 2)
984 return (void *) &(infop
->w_window_boundary
);