1 /************************************************************
3 Copyright 1989, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the 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 THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
25 ********************************************************/
27 /* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */
31 #ifdef HAVE_DIX_CONFIG_H
32 #include <dix-config.h>
35 #include <sys/types.h>
42 #include <X11/Xproto.h>
45 #include "dixstruct.h"
47 #include "scrnintstr.h"
48 #include "windowstr.h"
49 #include "pixmapstr.h"
51 #include "extnsionst.h"
55 #include <X11/extensions/shmproto.h>
56 #include <X11/Xfuncproto.h>
58 #include "protocol-versions.h"
61 /* Needed for Solaris cross-zone shared memory extension */
63 #include <sys/ipc_impl.h>
64 #define SHMSTAT(id, buf) shmctl64(id, IPC_STAT64, buf)
65 #define SHMSTAT_TYPE struct shmid_ds64
66 #define SHMPERM_TYPE struct ipc_perm64
67 #define SHM_PERM(buf) buf.shmx_perm
68 #define SHM_SEGSZ(buf) buf.shmx_segsz
69 #define SHMPERM_UID(p) p->ipcx_uid
70 #define SHMPERM_CUID(p) p->ipcx_cuid
71 #define SHMPERM_GID(p) p->ipcx_gid
72 #define SHMPERM_CGID(p) p->ipcx_cgid
73 #define SHMPERM_MODE(p) p->ipcx_mode
74 #define SHMPERM_ZONEID(p) p->ipcx_zoneid
76 #define SHMSTAT(id, buf) shmctl(id, IPC_STAT, buf)
77 #define SHMSTAT_TYPE struct shmid_ds
78 #define SHMPERM_TYPE struct ipc_perm
79 #define SHM_PERM(buf) buf.shm_perm
80 #define SHM_SEGSZ(buf) buf.shm_segsz
81 #define SHMPERM_UID(p) p->uid
82 #define SHMPERM_CUID(p) p->cuid
83 #define SHMPERM_GID(p) p->gid
84 #define SHMPERM_CGID(p) p->cgid
85 #define SHMPERM_MODE(p) p->mode
89 #include "panoramiX.h"
90 #include "panoramiXsrv.h"
95 typedef struct _ShmScrPrivateRec
{
96 CloseScreenProcPtr CloseScreen
;
98 DestroyPixmapProcPtr destroyPixmap
;
101 static PixmapPtr
fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS
);
102 static int ShmDetachSegment(pointer
/* value */ ,
105 static void ShmResetProc(ExtensionEntry
* /* extEntry */
107 static void SShmCompletionEvent(xShmCompletionEvent
* /* from */ ,
108 xShmCompletionEvent
* /* to */
111 static Bool
ShmDestroyPixmap(PixmapPtr pPixmap
);
113 static unsigned char ShmReqCode
;
114 int ShmCompletionCode
;
117 static ShmDescPtr Shmsegs
;
118 static Bool sharedPixmaps
;
119 static DevPrivateKeyRec shmScrPrivateKeyRec
;
121 #define shmScrPrivateKey (&shmScrPrivateKeyRec)
122 static DevPrivateKeyRec shmPixmapPrivateKeyRec
;
124 #define shmPixmapPrivateKey (&shmPixmapPrivateKeyRec)
125 static ShmFuncs miFuncs
= { NULL
, NULL
};
126 static ShmFuncs fbFuncs
= { fbShmCreatePixmap
, NULL
};
128 #define ShmGetScreenPriv(s) ((ShmScrPrivateRec *)dixLookupPrivate(&(s)->devPrivates, shmScrPrivateKey))
130 #define VERIFY_SHMSEG(shmseg,shmdesc,client) \
133 tmprc = dixLookupResourceByType((pointer *)&(shmdesc), shmseg, ShmSegType, \
134 client, DixReadAccess); \
135 if (tmprc != Success) \
139 #define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \
141 VERIFY_SHMSEG(shmseg, shmdesc, client); \
142 if ((offset & 3) || (offset > shmdesc->size)) \
144 client->errorValue = offset; \
147 if (needwrite && !shmdesc->writable) \
151 #define VERIFY_SHMSIZE(shmdesc,offset,len,client) \
153 if ((offset + len) > shmdesc->size) \
159 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
160 #include <sys/signal.h>
162 static Bool badSysCall
= FALSE
;
165 SigSysHandler(int signo
)
171 CheckForShmSyscall(void)
173 void (*oldHandler
) (int);
176 /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
177 oldHandler
= signal(SIGSYS
, SigSysHandler
);
180 shmid
= shmget(IPC_PRIVATE
, 4096, IPC_CREAT
);
183 /* Successful allocation - clean up */
184 shmctl(shmid
, IPC_RMID
, NULL
);
187 /* Allocation failed */
190 signal(SIGSYS
, oldHandler
);
194 #define MUST_CHECK_FOR_SHM_SYSCALL
199 ShmCloseScreen(ScreenPtr pScreen
)
201 ShmScrPrivateRec
*screen_priv
= ShmGetScreenPriv(pScreen
);
203 pScreen
->CloseScreen
= screen_priv
->CloseScreen
;
204 dixSetPrivate(&pScreen
->devPrivates
, shmScrPrivateKey
, NULL
);
206 return (*pScreen
->CloseScreen
) (pScreen
);
209 static ShmScrPrivateRec
*
210 ShmInitScreenPriv(ScreenPtr pScreen
)
212 ShmScrPrivateRec
*screen_priv
= ShmGetScreenPriv(pScreen
);
215 screen_priv
= calloc(1, sizeof(ShmScrPrivateRec
));
216 screen_priv
->CloseScreen
= pScreen
->CloseScreen
;
217 dixSetPrivate(&pScreen
->devPrivates
, shmScrPrivateKey
, screen_priv
);
218 pScreen
->CloseScreen
= ShmCloseScreen
;
224 ShmRegisterPrivates(void)
226 if (!dixRegisterPrivateKey(&shmScrPrivateKeyRec
, PRIVATE_SCREEN
, 0))
228 if (!dixRegisterPrivateKey(&shmPixmapPrivateKeyRec
, PRIVATE_PIXMAP
, 0))
233 /*ARGSUSED*/ static void
234 ShmResetProc(ExtensionEntry
* extEntry
)
238 for (i
= 0; i
< screenInfo
.numScreens
; i
++)
239 ShmRegisterFuncs(screenInfo
.screens
[i
], NULL
);
243 ShmRegisterFuncs(ScreenPtr pScreen
, ShmFuncsPtr funcs
)
245 if (!ShmRegisterPrivates())
247 ShmInitScreenPriv(pScreen
)->shmFuncs
= funcs
;
251 ShmDestroyPixmap(PixmapPtr pPixmap
)
253 ScreenPtr pScreen
= pPixmap
->drawable
.pScreen
;
254 ShmScrPrivateRec
*screen_priv
= ShmGetScreenPriv(pScreen
);
257 if (pPixmap
->refcnt
== 1) {
260 shmdesc
= (ShmDescPtr
) dixLookupPrivate(&pPixmap
->devPrivates
,
261 shmPixmapPrivateKey
);
263 ShmDetachSegment((pointer
) shmdesc
, pPixmap
->drawable
.id
);
266 pScreen
->DestroyPixmap
= screen_priv
->destroyPixmap
;
267 ret
= (*pScreen
->DestroyPixmap
) (pPixmap
);
268 screen_priv
->destroyPixmap
= pScreen
->DestroyPixmap
;
269 pScreen
->DestroyPixmap
= ShmDestroyPixmap
;
274 ShmRegisterFbFuncs(ScreenPtr pScreen
)
276 ShmRegisterFuncs(pScreen
, &fbFuncs
);
280 ProcShmQueryVersion(ClientPtr client
)
282 xShmQueryVersionReply rep
= {
284 .sharedPixmaps
= sharedPixmaps
,
285 .sequenceNumber
= client
->sequence
,
287 .majorVersion
= SERVER_SHM_MAJOR_VERSION
,
288 .minorVersion
= SERVER_SHM_MINOR_VERSION
,
291 .pixmapFormat
= sharedPixmaps
? ZPixmap
: 0
294 REQUEST_SIZE_MATCH(xShmQueryVersionReq
);
296 if (client
->swapped
) {
297 swaps(&rep
.sequenceNumber
);
299 swaps(&rep
.majorVersion
);
300 swaps(&rep
.minorVersion
);
304 WriteToClient(client
, sizeof(xShmQueryVersionReply
), &rep
);
309 * Simulate the access() system call for a shared memory segement,
310 * using the credentials from the client if available
313 shm_access(ClientPtr client
, SHMPERM_TYPE
* perm
, int readonly
)
317 int uidset
= 0, gidset
= 0;
318 LocalClientCredRec
*lcc
;
320 if (GetLocalClientCreds(client
, &lcc
) != -1) {
322 if (lcc
->fieldsSet
& LCC_UID_SET
) {
326 if (lcc
->fieldsSet
& LCC_GID_SET
) {
331 #if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID)
332 if (((lcc
->fieldsSet
& LCC_ZID_SET
) == 0) || (lcc
->zoneid
== -1)
333 || (lcc
->zoneid
!= SHMPERM_ZONEID(perm
))) {
338 FreeLocalClientCreds(lcc
);
341 /* User id 0 always gets access */
345 /* Check the owner */
346 if (SHMPERM_UID(perm
) == uid
|| SHMPERM_CUID(perm
) == uid
) {
351 return (SHMPERM_MODE(perm
) & mask
) == mask
? 0 : -1;
356 /* Check the group */
357 if (SHMPERM_GID(perm
) == gid
|| SHMPERM_CGID(perm
) == gid
) {
362 return (SHMPERM_MODE(perm
) & mask
) == mask
? 0 : -1;
366 /* Otherwise, check everyone else */
371 return (SHMPERM_MODE(perm
) & mask
) == mask
? 0 : -1;
375 ProcShmAttach(ClientPtr client
)
380 REQUEST(xShmAttachReq
);
382 REQUEST_SIZE_MATCH(xShmAttachReq
);
383 LEGAL_NEW_RESOURCE(stuff
->shmseg
, client
);
384 if ((stuff
->readOnly
!= xTrue
) && (stuff
->readOnly
!= xFalse
)) {
385 client
->errorValue
= stuff
->readOnly
;
388 for (shmdesc
= Shmsegs
; shmdesc
; shmdesc
= shmdesc
->next
) {
389 if (!SHMDESC_IS_FD(shmdesc
) && shmdesc
->shmid
== stuff
->shmid
)
393 if (!stuff
->readOnly
&& !shmdesc
->writable
)
398 shmdesc
= malloc(sizeof(ShmDescRec
));
401 #ifdef SHM_FD_PASSING
402 shmdesc
->is_fd
= FALSE
;
404 shmdesc
->addr
= shmat(stuff
->shmid
, 0,
405 stuff
->readOnly
? SHM_RDONLY
: 0);
406 if ((shmdesc
->addr
== ((char *) -1)) || SHMSTAT(stuff
->shmid
, &buf
)) {
411 /* The attach was performed with root privs. We must
412 * do manual checking of access rights for the credentials
415 if (shm_access(client
, &(SHM_PERM(buf
)), stuff
->readOnly
) == -1) {
416 shmdt(shmdesc
->addr
);
421 shmdesc
->shmid
= stuff
->shmid
;
423 shmdesc
->writable
= !stuff
->readOnly
;
424 shmdesc
->size
= SHM_SEGSZ(buf
);
425 shmdesc
->next
= Shmsegs
;
428 if (!AddResource(stuff
->shmseg
, ShmSegType
, (pointer
) shmdesc
))
433 /*ARGSUSED*/ static int
434 ShmDetachSegment(pointer value
, /* must conform to DeleteType */
437 ShmDescPtr shmdesc
= (ShmDescPtr
) value
;
440 if (--shmdesc
->refcnt
)
443 if (shmdesc
->is_fd
) {
444 if (shmdesc
->busfault
)
445 busfault_unregister(shmdesc
->busfault
);
446 munmap(shmdesc
->addr
, shmdesc
->size
);
449 shmdt(shmdesc
->addr
);
450 for (prev
= &Shmsegs
; *prev
!= shmdesc
; prev
= &(*prev
)->next
);
451 *prev
= shmdesc
->next
;
457 ProcShmDetach(ClientPtr client
)
461 REQUEST(xShmDetachReq
);
463 REQUEST_SIZE_MATCH(xShmDetachReq
);
464 VERIFY_SHMSEG(stuff
->shmseg
, shmdesc
, client
);
465 FreeResource(stuff
->shmseg
, RT_NONE
);
470 * If the given request doesn't exactly match PutImage's constraints,
471 * wrap the image in a scratch pixmap header and let CopyArea sort it out.
474 doShmPutImage(DrawablePtr dst
, GCPtr pGC
,
475 int depth
, unsigned int format
,
476 int w
, int h
, int sx
, int sy
, int sw
, int sh
, int dx
, int dy
,
481 if (format
== ZPixmap
|| (format
== XYPixmap
&& depth
== 1)) {
482 pPixmap
= GetScratchPixmapHeader(dst
->pScreen
, w
, h
, depth
,
484 PixmapBytePad(w
, depth
), data
);
487 pGC
->ops
->CopyArea((DrawablePtr
) pPixmap
, dst
, pGC
, sx
, sy
, sw
, sh
, dx
,
489 FreeScratchPixmapHeader(pPixmap
);
492 GCPtr putGC
= GetScratchGC(depth
, dst
->pScreen
);
497 pPixmap
= (*dst
->pScreen
->CreatePixmap
) (dst
->pScreen
, sw
, sh
, depth
,
498 CREATE_PIXMAP_USAGE_SCRATCH
);
500 FreeScratchGC(putGC
);
503 ValidateGC(&pPixmap
->drawable
, putGC
);
504 (*putGC
->ops
->PutImage
) (&pPixmap
->drawable
, putGC
, depth
, -sx
, -sy
, w
,
506 (format
== XYPixmap
) ? XYPixmap
: ZPixmap
,
508 FreeScratchGC(putGC
);
509 if (format
== XYBitmap
)
510 (void) (*pGC
->ops
->CopyPlane
) (&pPixmap
->drawable
, dst
, pGC
, 0, 0,
513 (void) (*pGC
->ops
->CopyArea
) (&pPixmap
->drawable
, dst
, pGC
, 0, 0,
515 (*pPixmap
->drawable
.pScreen
->DestroyPixmap
) (pPixmap
);
520 ProcShmPutImage(ClientPtr client
)
527 REQUEST(xShmPutImageReq
);
529 REQUEST_SIZE_MATCH(xShmPutImageReq
);
530 VALIDATE_DRAWABLE_AND_GC(stuff
->drawable
, pDraw
, DixWriteAccess
);
531 VERIFY_SHMPTR(stuff
->shmseg
, stuff
->offset
, FALSE
, shmdesc
, client
);
532 if ((stuff
->sendEvent
!= xTrue
) && (stuff
->sendEvent
!= xFalse
))
534 if (stuff
->format
== XYBitmap
) {
535 if (stuff
->depth
!= 1)
537 length
= PixmapBytePad(stuff
->totalWidth
, 1);
539 else if (stuff
->format
== XYPixmap
) {
540 if (pDraw
->depth
!= stuff
->depth
)
542 length
= PixmapBytePad(stuff
->totalWidth
, 1);
543 length
*= stuff
->depth
;
545 else if (stuff
->format
== ZPixmap
) {
546 if (pDraw
->depth
!= stuff
->depth
)
548 length
= PixmapBytePad(stuff
->totalWidth
, stuff
->depth
);
551 client
->errorValue
= stuff
->format
;
556 * There's a potential integer overflow in this check:
557 * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
559 * the version below ought to avoid it
561 if (stuff
->totalHeight
!= 0 &&
562 length
> (shmdesc
->size
- stuff
->offset
) / stuff
->totalHeight
) {
563 client
->errorValue
= stuff
->totalWidth
;
566 if (stuff
->srcX
> stuff
->totalWidth
) {
567 client
->errorValue
= stuff
->srcX
;
570 if (stuff
->srcY
> stuff
->totalHeight
) {
571 client
->errorValue
= stuff
->srcY
;
574 if ((stuff
->srcX
+ stuff
->srcWidth
) > stuff
->totalWidth
) {
575 client
->errorValue
= stuff
->srcWidth
;
578 if ((stuff
->srcY
+ stuff
->srcHeight
) > stuff
->totalHeight
) {
579 client
->errorValue
= stuff
->srcHeight
;
583 if ((((stuff
->format
== ZPixmap
) && (stuff
->srcX
== 0)) ||
584 ((stuff
->format
!= ZPixmap
) &&
585 (stuff
->srcX
< screenInfo
.bitmapScanlinePad
) &&
586 ((stuff
->format
== XYBitmap
) ||
587 ((stuff
->srcY
== 0) &&
588 (stuff
->srcHeight
== stuff
->totalHeight
))))) &&
589 ((stuff
->srcX
+ stuff
->srcWidth
) == stuff
->totalWidth
))
590 (*pGC
->ops
->PutImage
) (pDraw
, pGC
, stuff
->depth
,
591 stuff
->dstX
, stuff
->dstY
,
592 stuff
->totalWidth
, stuff
->srcHeight
,
593 stuff
->srcX
, stuff
->format
,
594 shmdesc
->addr
+ stuff
->offset
+
595 (stuff
->srcY
* length
));
597 doShmPutImage(pDraw
, pGC
, stuff
->depth
, stuff
->format
,
598 stuff
->totalWidth
, stuff
->totalHeight
,
599 stuff
->srcX
, stuff
->srcY
,
600 stuff
->srcWidth
, stuff
->srcHeight
,
601 stuff
->dstX
, stuff
->dstY
, shmdesc
->addr
+ stuff
->offset
);
603 if (stuff
->sendEvent
) {
604 xShmCompletionEvent ev
= {
605 .type
= ShmCompletionCode
,
606 .drawable
= stuff
->drawable
,
607 .minorEvent
= X_ShmPutImage
,
608 .majorEvent
= ShmReqCode
,
609 .shmseg
= stuff
->shmseg
,
610 .offset
= stuff
->offset
612 WriteEventsToClient(client
, 1, (xEvent
*) &ev
);
619 ProcShmGetImage(ClientPtr client
)
622 long lenPer
= 0, length
;
624 xShmGetImageReply xgi
;
626 VisualID visual
= None
;
629 REQUEST(xShmGetImageReq
);
631 REQUEST_SIZE_MATCH(xShmGetImageReq
);
632 if ((stuff
->format
!= XYPixmap
) && (stuff
->format
!= ZPixmap
)) {
633 client
->errorValue
= stuff
->format
;
636 rc
= dixLookupDrawable(&pDraw
, stuff
->drawable
, client
, 0, DixReadAccess
);
639 VERIFY_SHMPTR(stuff
->shmseg
, stuff
->offset
, TRUE
, shmdesc
, client
);
640 if (pDraw
->type
== DRAWABLE_WINDOW
) {
641 if ( /* check for being viewable */
642 !((WindowPtr
) pDraw
)->realized
||
643 /* check for being on screen */
644 pDraw
->x
+ stuff
->x
< 0 ||
645 pDraw
->x
+ stuff
->x
+ (int) stuff
->width
> pDraw
->pScreen
->width
646 || pDraw
->y
+ stuff
->y
< 0 ||
647 pDraw
->y
+ stuff
->y
+ (int) stuff
->height
>
648 pDraw
->pScreen
->height
||
649 /* check for being inside of border */
650 stuff
->x
< -wBorderWidth((WindowPtr
) pDraw
) ||
651 stuff
->x
+ (int) stuff
->width
>
652 wBorderWidth((WindowPtr
) pDraw
) + (int) pDraw
->width
||
653 stuff
->y
< -wBorderWidth((WindowPtr
) pDraw
) ||
654 stuff
->y
+ (int) stuff
->height
>
655 wBorderWidth((WindowPtr
) pDraw
) + (int) pDraw
->height
)
657 visual
= wVisual(((WindowPtr
) pDraw
));
661 stuff
->x
+ (int) stuff
->width
> pDraw
->width
||
662 stuff
->y
< 0 || stuff
->y
+ (int) stuff
->height
> pDraw
->height
)
666 xgi
= (xShmGetImageReply
) {
668 .sequenceNumber
= client
->sequence
,
671 .depth
= pDraw
->depth
673 if (stuff
->format
== ZPixmap
) {
674 length
= PixmapBytePad(stuff
->width
, pDraw
->depth
) * stuff
->height
;
677 lenPer
= PixmapBytePad(stuff
->width
, 1) * stuff
->height
;
678 plane
= ((Mask
) 1) << (pDraw
->depth
- 1);
679 /* only planes asked for */
680 length
= lenPer
* Ones(stuff
->planeMask
& (plane
| (plane
- 1)));
683 VERIFY_SHMSIZE(shmdesc
, stuff
->offset
, length
, client
);
689 else if (stuff
->format
== ZPixmap
) {
690 (*pDraw
->pScreen
->GetImage
) (pDraw
, stuff
->x
, stuff
->y
,
691 stuff
->width
, stuff
->height
,
692 stuff
->format
, stuff
->planeMask
,
693 shmdesc
->addr
+ stuff
->offset
);
697 length
= stuff
->offset
;
698 for (; plane
; plane
>>= 1) {
699 if (stuff
->planeMask
& plane
) {
700 (*pDraw
->pScreen
->GetImage
) (pDraw
,
702 stuff
->width
, stuff
->height
,
703 stuff
->format
, plane
,
704 shmdesc
->addr
+ length
);
710 if (client
->swapped
) {
711 swaps(&xgi
.sequenceNumber
);
716 WriteToClient(client
, sizeof(xShmGetImageReply
), &xgi
);
723 ProcPanoramiXShmPutImage(ClientPtr client
)
725 int j
, result
, orig_x
, orig_y
;
726 PanoramiXRes
*draw
, *gc
;
727 Bool sendEvent
, isRoot
;
729 REQUEST(xShmPutImageReq
);
730 REQUEST_SIZE_MATCH(xShmPutImageReq
);
732 result
= dixLookupResourceByClass((pointer
*) &draw
, stuff
->drawable
,
733 XRC_DRAWABLE
, client
, DixWriteAccess
);
734 if (result
!= Success
)
735 return (result
== BadValue
) ? BadDrawable
: result
;
737 result
= dixLookupResourceByType((pointer
*) &gc
, stuff
->gc
,
738 XRT_GC
, client
, DixReadAccess
);
739 if (result
!= Success
)
742 isRoot
= (draw
->type
== XRT_WINDOW
) && draw
->u
.win
.root
;
744 orig_x
= stuff
->dstX
;
745 orig_y
= stuff
->dstY
;
746 sendEvent
= stuff
->sendEvent
;
747 stuff
->sendEvent
= 0;
750 stuff
->sendEvent
= sendEvent
;
751 stuff
->drawable
= draw
->info
[j
].id
;
752 stuff
->gc
= gc
->info
[j
].id
;
754 stuff
->dstX
= orig_x
- screenInfo
.screens
[j
]->x
;
755 stuff
->dstY
= orig_y
- screenInfo
.screens
[j
]->y
;
757 result
= ProcShmPutImage(client
);
758 if (result
!= Success
)
765 ProcPanoramiXShmGetImage(ClientPtr client
)
768 DrawablePtr
*drawables
;
770 xShmGetImageReply xgi
;
772 int i
, x
, y
, w
, h
, format
, rc
;
773 Mask plane
= 0, planemask
;
774 long lenPer
= 0, length
, widthBytesLine
;
777 REQUEST(xShmGetImageReq
);
779 REQUEST_SIZE_MATCH(xShmGetImageReq
);
781 if ((stuff
->format
!= XYPixmap
) && (stuff
->format
!= ZPixmap
)) {
782 client
->errorValue
= stuff
->format
;
786 rc
= dixLookupResourceByClass((pointer
*) &draw
, stuff
->drawable
,
787 XRC_DRAWABLE
, client
, DixWriteAccess
);
789 return (rc
== BadValue
) ? BadDrawable
: rc
;
791 if (draw
->type
== XRT_PIXMAP
)
792 return ProcShmGetImage(client
);
794 rc
= dixLookupDrawable(&pDraw
, stuff
->drawable
, client
, 0, DixReadAccess
);
798 VERIFY_SHMPTR(stuff
->shmseg
, stuff
->offset
, TRUE
, shmdesc
, client
);
804 format
= stuff
->format
;
805 planemask
= stuff
->planeMask
;
807 isRoot
= (draw
->type
== XRT_WINDOW
) && draw
->u
.win
.root
;
810 if ( /* check for being onscreen */
811 x
< 0 || x
+ w
> PanoramiXPixWidth
||
812 y
< 0 || y
+ h
> PanoramiXPixHeight
)
816 if ( /* check for being onscreen */
817 screenInfo
.screens
[0]->x
+ pDraw
->x
+ x
< 0 ||
818 screenInfo
.screens
[0]->x
+ pDraw
->x
+ x
+ w
> PanoramiXPixWidth
819 || screenInfo
.screens
[0]->y
+ pDraw
->y
+ y
< 0 ||
820 screenInfo
.screens
[0]->y
+ pDraw
->y
+ y
+ h
> PanoramiXPixHeight
822 /* check for being inside of border */
823 x
< -wBorderWidth((WindowPtr
) pDraw
) ||
824 x
+ w
> wBorderWidth((WindowPtr
) pDraw
) + (int) pDraw
->width
||
825 y
< -wBorderWidth((WindowPtr
) pDraw
) ||
826 y
+ h
> wBorderWidth((WindowPtr
) pDraw
) + (int) pDraw
->height
)
830 drawables
= calloc(PanoramiXNumScreens
, sizeof(DrawablePtr
));
834 drawables
[0] = pDraw
;
835 FOR_NSCREENS_FORWARD_SKIP(i
) {
836 rc
= dixLookupDrawable(drawables
+ i
, draw
->info
[i
].id
, client
, 0,
844 xgi
= (xShmGetImageReply
) {
846 .sequenceNumber
= client
->sequence
,
848 .visual
= wVisual(((WindowPtr
) pDraw
)),
849 .depth
= pDraw
->depth
852 if (format
== ZPixmap
) {
853 widthBytesLine
= PixmapBytePad(w
, pDraw
->depth
);
854 length
= widthBytesLine
* h
;
857 widthBytesLine
= PixmapBytePad(w
, 1);
858 lenPer
= widthBytesLine
* h
;
859 plane
= ((Mask
) 1) << (pDraw
->depth
- 1);
860 length
= lenPer
* Ones(planemask
& (plane
| (plane
- 1)));
863 VERIFY_SHMSIZE(shmdesc
, stuff
->offset
, length
, client
);
866 if (length
== 0) { /* nothing to do */
868 else if (format
== ZPixmap
) {
869 XineramaGetImageData(drawables
, x
, y
, w
, h
, format
, planemask
,
870 shmdesc
->addr
+ stuff
->offset
,
871 widthBytesLine
, isRoot
);
875 length
= stuff
->offset
;
876 for (; plane
; plane
>>= 1) {
877 if (planemask
& plane
) {
878 XineramaGetImageData(drawables
, x
, y
, w
, h
,
879 format
, plane
, shmdesc
->addr
+ length
,
880 widthBytesLine
, isRoot
);
887 if (client
->swapped
) {
888 swaps(&xgi
.sequenceNumber
);
893 WriteToClient(client
, sizeof(xShmGetImageReply
), &xgi
);
899 ProcPanoramiXShmCreatePixmap(ClientPtr client
)
901 ScreenPtr pScreen
= NULL
;
902 PixmapPtr pMap
= NULL
;
905 int i
, j
, result
, rc
;
908 REQUEST(xShmCreatePixmapReq
);
909 unsigned int width
, height
, depth
;
911 PanoramiXRes
*newPix
;
913 REQUEST_SIZE_MATCH(xShmCreatePixmapReq
);
914 client
->errorValue
= stuff
->pid
;
916 return BadImplementation
;
917 LEGAL_NEW_RESOURCE(stuff
->pid
, client
);
918 rc
= dixLookupDrawable(&pDraw
, stuff
->drawable
, client
, M_ANY
,
923 VERIFY_SHMPTR(stuff
->shmseg
, stuff
->offset
, TRUE
, shmdesc
, client
);
925 width
= stuff
->width
;
926 height
= stuff
->height
;
927 depth
= stuff
->depth
;
928 if (!width
|| !height
|| !depth
) {
929 client
->errorValue
= 0;
932 if (width
> 32767 || height
> 32767)
935 if (stuff
->depth
!= 1) {
936 pDepth
= pDraw
->pScreen
->allowedDepths
;
937 for (i
= 0; i
< pDraw
->pScreen
->numDepths
; i
++, pDepth
++)
938 if (pDepth
->depth
== stuff
->depth
)
940 client
->errorValue
= stuff
->depth
;
945 size
= PixmapBytePad(width
, depth
) * height
;
946 if (sizeof(size
) == 4 && BitsPerPixel(depth
) > 8) {
947 if (size
< width
* height
)
950 /* thankfully, offset is unsigned */
951 if (stuff
->offset
+ size
< size
)
954 VERIFY_SHMSIZE(shmdesc
, stuff
->offset
, size
, client
);
956 if (!(newPix
= malloc(sizeof(PanoramiXRes
))))
959 newPix
->type
= XRT_PIXMAP
;
960 newPix
->u
.pix
.shared
= TRUE
;
961 panoramix_setup_ids(newPix
, client
, stuff
->pid
);
966 ShmScrPrivateRec
*screen_priv
;
968 pScreen
= screenInfo
.screens
[j
];
970 screen_priv
= ShmGetScreenPriv(pScreen
);
971 pMap
= (*screen_priv
->shmFuncs
->CreatePixmap
) (pScreen
,
979 dixSetPrivate(&pMap
->devPrivates
, shmPixmapPrivateKey
, shmdesc
);
981 pMap
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
982 pMap
->drawable
.id
= newPix
->info
[j
].id
;
983 if (!AddResource(newPix
->info
[j
].id
, RT_PIXMAP
, (pointer
) pMap
)) {
994 if (result
== BadAlloc
) {
996 FreeResource(newPix
->info
[j
].id
, RT_NONE
);
1000 AddResource(stuff
->pid
, XRT_PIXMAP
, newPix
);
1007 fbShmCreatePixmap(ScreenPtr pScreen
,
1008 int width
, int height
, int depth
, char *addr
)
1012 pPixmap
= (*pScreen
->CreatePixmap
) (pScreen
, 0, 0, pScreen
->rootDepth
, 0);
1016 if (!(*pScreen
->ModifyPixmapHeader
) (pPixmap
, width
, height
, depth
,
1017 BitsPerPixel(depth
),
1018 PixmapBytePad(width
, depth
),
1020 (*pScreen
->DestroyPixmap
) (pPixmap
);
1027 ProcShmCreatePixmap(ClientPtr client
)
1034 ShmScrPrivateRec
*screen_priv
;
1036 REQUEST(xShmCreatePixmapReq
);
1037 unsigned int width
, height
, depth
;
1040 REQUEST_SIZE_MATCH(xShmCreatePixmapReq
);
1041 client
->errorValue
= stuff
->pid
;
1043 return BadImplementation
;
1044 LEGAL_NEW_RESOURCE(stuff
->pid
, client
);
1045 rc
= dixLookupDrawable(&pDraw
, stuff
->drawable
, client
, M_ANY
,
1050 VERIFY_SHMPTR(stuff
->shmseg
, stuff
->offset
, TRUE
, shmdesc
, client
);
1052 width
= stuff
->width
;
1053 height
= stuff
->height
;
1054 depth
= stuff
->depth
;
1055 if (!width
|| !height
|| !depth
) {
1056 client
->errorValue
= 0;
1059 if (width
> 32767 || height
> 32767)
1062 if (stuff
->depth
!= 1) {
1063 pDepth
= pDraw
->pScreen
->allowedDepths
;
1064 for (i
= 0; i
< pDraw
->pScreen
->numDepths
; i
++, pDepth
++)
1065 if (pDepth
->depth
== stuff
->depth
)
1067 client
->errorValue
= stuff
->depth
;
1072 size
= PixmapBytePad(width
, depth
) * height
;
1073 if (sizeof(size
) == 4 && BitsPerPixel(depth
) > 8) {
1074 if (size
< width
* height
)
1077 /* thankfully, offset is unsigned */
1078 if (stuff
->offset
+ size
< size
)
1081 VERIFY_SHMSIZE(shmdesc
, stuff
->offset
, size
, client
);
1082 screen_priv
= ShmGetScreenPriv(pDraw
->pScreen
);
1083 pMap
= (*screen_priv
->shmFuncs
->CreatePixmap
) (pDraw
->pScreen
, stuff
->width
,
1084 stuff
->height
, stuff
->depth
,
1088 rc
= XaceHook(XACE_RESOURCE_ACCESS
, client
, stuff
->pid
, RT_PIXMAP
,
1089 pMap
, RT_NONE
, NULL
, DixCreateAccess
);
1090 if (rc
!= Success
) {
1091 pDraw
->pScreen
->DestroyPixmap(pMap
);
1094 dixSetPrivate(&pMap
->devPrivates
, shmPixmapPrivateKey
, shmdesc
);
1096 pMap
->drawable
.serialNumber
= NEXT_SERIAL_NUMBER
;
1097 pMap
->drawable
.id
= stuff
->pid
;
1098 if (AddResource(stuff
->pid
, RT_PIXMAP
, (pointer
) pMap
)) {
1105 #ifdef SHM_FD_PASSING
1108 ShmBusfaultNotify(void *context
)
1110 ShmDescPtr shmdesc
= context
;
1112 ErrorF("shared memory 0x%x truncated by client\n",
1113 (unsigned int) shmdesc
->resource
);
1114 busfault_unregister(shmdesc
->busfault
);
1115 shmdesc
->busfault
= NULL
;
1116 FreeResource (shmdesc
->resource
, RT_NONE
);
1120 ProcShmAttachFd(ClientPtr client
)
1124 REQUEST(xShmAttachFdReq
);
1127 SetReqFds(client
, 1);
1128 REQUEST_SIZE_MATCH(xShmAttachFdReq
);
1129 LEGAL_NEW_RESOURCE(stuff
->shmseg
, client
);
1130 if ((stuff
->readOnly
!= xTrue
) && (stuff
->readOnly
!= xFalse
)) {
1131 client
->errorValue
= stuff
->readOnly
;
1134 fd
= ReadFdFromClient(client
);
1138 if (fstat(fd
, &statb
) < 0 || statb
.st_size
== 0) {
1143 shmdesc
= malloc(sizeof(ShmDescRec
));
1148 shmdesc
->is_fd
= TRUE
;
1149 shmdesc
->addr
= mmap(NULL
, statb
.st_size
,
1150 stuff
->readOnly
? PROT_READ
: PROT_READ
|PROT_WRITE
,
1155 if ((shmdesc
->addr
== ((char *) -1))) {
1160 shmdesc
->refcnt
= 1;
1161 shmdesc
->writable
= !stuff
->readOnly
;
1162 shmdesc
->size
= statb
.st_size
;
1163 shmdesc
->resource
= stuff
->shmseg
;
1165 shmdesc
->busfault
= busfault_register_mmap(shmdesc
->addr
, shmdesc
->size
, ShmBusfaultNotify
, shmdesc
);
1166 if (!shmdesc
->busfault
) {
1167 munmap(shmdesc
->addr
, shmdesc
->size
);
1172 shmdesc
->next
= Shmsegs
;
1175 if (!AddResource(stuff
->shmseg
, ShmSegType
, (pointer
) shmdesc
))
1186 char template[] = SHMDIR
"/shmfd-XXXXXX";
1188 fd
= open(SHMDIR
, O_TMPFILE
|O_RDWR
|O_CLOEXEC
|O_EXCL
, 0666);
1190 ErrorF ("Using O_TMPFILE\n");
1193 ErrorF ("Not using O_TMPFILE\n");
1195 fd
= mkstemp(template);
1199 if (fcntl(fd
, F_GETFD
, &flags
) >= 0) {
1200 flags
|= FD_CLOEXEC
;
1201 (void) fcntl(fd
, F_SETFD
, &flags
);
1210 ProcShmCreateSegment(ClientPtr client
)
1214 REQUEST(xShmCreateSegmentReq
);
1215 xShmCreateSegmentReply rep
= {
1218 .sequenceNumber
= client
->sequence
,
1222 REQUEST_SIZE_MATCH(xShmCreateSegmentReq
);
1223 if ((stuff
->readOnly
!= xTrue
) && (stuff
->readOnly
!= xFalse
)) {
1224 client
->errorValue
= stuff
->readOnly
;
1230 if (ftruncate(fd
, stuff
->size
) < 0) {
1234 shmdesc
= malloc(sizeof(ShmDescRec
));
1239 shmdesc
->is_fd
= TRUE
;
1240 shmdesc
->addr
= mmap(NULL
, stuff
->size
,
1241 stuff
->readOnly
? PROT_READ
: PROT_READ
|PROT_WRITE
,
1245 if ((shmdesc
->addr
== ((char *) -1))) {
1251 shmdesc
->refcnt
= 1;
1252 shmdesc
->writable
= !stuff
->readOnly
;
1253 shmdesc
->size
= stuff
->size
;
1255 shmdesc
->busfault
= busfault_register_mmap(shmdesc
->addr
, shmdesc
->size
, ShmBusfaultNotify
, shmdesc
);
1256 if (!shmdesc
->busfault
) {
1258 munmap(shmdesc
->addr
, shmdesc
->size
);
1263 shmdesc
->next
= Shmsegs
;
1266 if (!AddResource(stuff
->shmseg
, ShmSegType
, (pointer
) shmdesc
)) {
1271 if (WriteFdToClient(client
, fd
, TRUE
) < 0) {
1272 FreeResource(stuff
->shmseg
, RT_NONE
);
1276 WriteToClient(client
, sizeof (xShmCreateSegmentReply
), &rep
);
1279 #endif /* SHM_FD_PASSING */
1282 ProcShmDispatch(ClientPtr client
)
1285 switch (stuff
->data
) {
1286 case X_ShmQueryVersion
:
1287 return ProcShmQueryVersion(client
);
1289 return ProcShmAttach(client
);
1291 return ProcShmDetach(client
);
1294 if (!noPanoramiXExtension
)
1295 return ProcPanoramiXShmPutImage(client
);
1297 return ProcShmPutImage(client
);
1300 if (!noPanoramiXExtension
)
1301 return ProcPanoramiXShmGetImage(client
);
1303 return ProcShmGetImage(client
);
1304 case X_ShmCreatePixmap
:
1306 if (!noPanoramiXExtension
)
1307 return ProcPanoramiXShmCreatePixmap(client
);
1309 return ProcShmCreatePixmap(client
);
1310 #ifdef SHM_FD_PASSING
1312 return ProcShmAttachFd(client
);
1313 case X_ShmCreateSegment
:
1314 return ProcShmCreateSegment(client
);
1322 SShmCompletionEvent(xShmCompletionEvent
* from
, xShmCompletionEvent
* to
)
1324 to
->type
= from
->type
;
1325 cpswaps(from
->sequenceNumber
, to
->sequenceNumber
);
1326 cpswapl(from
->drawable
, to
->drawable
);
1327 cpswaps(from
->minorEvent
, to
->minorEvent
);
1328 to
->majorEvent
= from
->majorEvent
;
1329 cpswapl(from
->shmseg
, to
->shmseg
);
1330 cpswapl(from
->offset
, to
->offset
);
1334 SProcShmQueryVersion(ClientPtr client
)
1336 REQUEST(xShmQueryVersionReq
);
1338 swaps(&stuff
->length
);
1339 return ProcShmQueryVersion(client
);
1343 SProcShmAttach(ClientPtr client
)
1345 REQUEST(xShmAttachReq
);
1346 swaps(&stuff
->length
);
1347 REQUEST_SIZE_MATCH(xShmAttachReq
);
1348 swapl(&stuff
->shmseg
);
1349 swapl(&stuff
->shmid
);
1350 return ProcShmAttach(client
);
1354 SProcShmDetach(ClientPtr client
)
1356 REQUEST(xShmDetachReq
);
1357 swaps(&stuff
->length
);
1358 REQUEST_SIZE_MATCH(xShmDetachReq
);
1359 swapl(&stuff
->shmseg
);
1360 return ProcShmDetach(client
);
1364 SProcShmPutImage(ClientPtr client
)
1366 REQUEST(xShmPutImageReq
);
1367 swaps(&stuff
->length
);
1368 REQUEST_SIZE_MATCH(xShmPutImageReq
);
1369 swapl(&stuff
->drawable
);
1371 swaps(&stuff
->totalWidth
);
1372 swaps(&stuff
->totalHeight
);
1373 swaps(&stuff
->srcX
);
1374 swaps(&stuff
->srcY
);
1375 swaps(&stuff
->srcWidth
);
1376 swaps(&stuff
->srcHeight
);
1377 swaps(&stuff
->dstX
);
1378 swaps(&stuff
->dstY
);
1379 swapl(&stuff
->shmseg
);
1380 swapl(&stuff
->offset
);
1381 return ProcShmPutImage(client
);
1385 SProcShmGetImage(ClientPtr client
)
1387 REQUEST(xShmGetImageReq
);
1388 swaps(&stuff
->length
);
1389 REQUEST_SIZE_MATCH(xShmGetImageReq
);
1390 swapl(&stuff
->drawable
);
1393 swaps(&stuff
->width
);
1394 swaps(&stuff
->height
);
1395 swapl(&stuff
->planeMask
);
1396 swapl(&stuff
->shmseg
);
1397 swapl(&stuff
->offset
);
1398 return ProcShmGetImage(client
);
1402 SProcShmCreatePixmap(ClientPtr client
)
1404 REQUEST(xShmCreatePixmapReq
);
1405 swaps(&stuff
->length
);
1406 REQUEST_SIZE_MATCH(xShmCreatePixmapReq
);
1408 swapl(&stuff
->drawable
);
1409 swaps(&stuff
->width
);
1410 swaps(&stuff
->height
);
1411 swapl(&stuff
->shmseg
);
1412 swapl(&stuff
->offset
);
1413 return ProcShmCreatePixmap(client
);
1416 #ifdef SHM_FD_PASSING
1418 SProcShmAttachFd(ClientPtr client
)
1420 REQUEST(xShmAttachFdReq
);
1421 SetReqFds(client
, 1);
1422 swaps(&stuff
->length
);
1423 REQUEST_SIZE_MATCH(xShmAttachFdReq
);
1424 swapl(&stuff
->shmseg
);
1425 return ProcShmAttachFd(client
);
1429 SProcShmCreateSegment(ClientPtr client
)
1431 REQUEST(xShmCreateSegmentReq
);
1432 swaps(&stuff
->length
);
1433 REQUEST_SIZE_MATCH(xShmCreateSegmentReq
);
1434 swapl(&stuff
->shmseg
);
1435 swapl(&stuff
->size
);
1436 return ProcShmCreateSegment(client
);
1438 #endif /* SHM_FD_PASSING */
1441 SProcShmDispatch(ClientPtr client
)
1444 switch (stuff
->data
) {
1445 case X_ShmQueryVersion
:
1446 return SProcShmQueryVersion(client
);
1448 return SProcShmAttach(client
);
1450 return SProcShmDetach(client
);
1452 return SProcShmPutImage(client
);
1454 return SProcShmGetImage(client
);
1455 case X_ShmCreatePixmap
:
1456 return SProcShmCreatePixmap(client
);
1457 #ifdef SHM_FD_PASSING
1459 return SProcShmAttachFd(client
);
1460 case X_ShmCreateSegment
:
1461 return SProcShmCreateSegment(client
);
1469 ShmExtensionInit(void)
1471 ExtensionEntry
*extEntry
;
1474 #ifdef MUST_CHECK_FOR_SHM_SYSCALL
1475 if (!CheckForShmSyscall()) {
1476 ErrorF("MIT-SHM extension disabled due to lack of kernel support\n");
1481 if (!ShmRegisterPrivates())
1484 sharedPixmaps
= xFalse
;
1486 sharedPixmaps
= xTrue
;
1487 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
1488 ShmScrPrivateRec
*screen_priv
=
1489 ShmInitScreenPriv(screenInfo
.screens
[i
]);
1490 if (!screen_priv
->shmFuncs
)
1491 screen_priv
->shmFuncs
= &miFuncs
;
1492 if (!screen_priv
->shmFuncs
->CreatePixmap
)
1493 sharedPixmaps
= xFalse
;
1496 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
1497 ShmScrPrivateRec
*screen_priv
=
1498 ShmGetScreenPriv(screenInfo
.screens
[i
]);
1499 screen_priv
->destroyPixmap
=
1500 screenInfo
.screens
[i
]->DestroyPixmap
;
1501 screenInfo
.screens
[i
]->DestroyPixmap
= ShmDestroyPixmap
;
1504 ShmSegType
= CreateNewResourceType(ShmDetachSegment
, "ShmSeg");
1506 (extEntry
= AddExtension(SHMNAME
, ShmNumberEvents
, ShmNumberErrors
,
1507 ProcShmDispatch
, SProcShmDispatch
,
1508 ShmResetProc
, StandardMinorOpcode
))) {
1509 ShmReqCode
= (unsigned char) extEntry
->base
;
1510 ShmCompletionCode
= extEntry
->eventBase
;
1511 BadShmSegCode
= extEntry
->errorBase
;
1512 SetResourceTypeErrorValue(ShmSegType
, BadShmSegCode
);
1513 EventSwapVector
[ShmCompletionCode
] = (EventSwapPtr
) SShmCompletionEvent
;