shm.c revision 05b261ec
105b261ecSmrg/************************************************************ 205b261ecSmrg 305b261ecSmrgCopyright 1989, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg 2505b261ecSmrg********************************************************/ 2605b261ecSmrg 2705b261ecSmrg/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ 2805b261ecSmrg 2905b261ecSmrg 3005b261ecSmrg#define SHM 3105b261ecSmrg 3205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3305b261ecSmrg#include <dix-config.h> 3405b261ecSmrg#endif 3505b261ecSmrg 3605b261ecSmrg#include <sys/types.h> 3705b261ecSmrg#ifndef Lynx 3805b261ecSmrg#include <sys/ipc.h> 3905b261ecSmrg#include <sys/shm.h> 4005b261ecSmrg#else 4105b261ecSmrg#include <ipc.h> 4205b261ecSmrg#include <shm.h> 4305b261ecSmrg#endif 4405b261ecSmrg#include <unistd.h> 4505b261ecSmrg#include <sys/stat.h> 4605b261ecSmrg#define NEED_REPLIES 4705b261ecSmrg#define NEED_EVENTS 4805b261ecSmrg#include <X11/X.h> 4905b261ecSmrg#include <X11/Xproto.h> 5005b261ecSmrg#include "misc.h" 5105b261ecSmrg#include "os.h" 5205b261ecSmrg#include "dixstruct.h" 5305b261ecSmrg#include "resource.h" 5405b261ecSmrg#include "scrnintstr.h" 5505b261ecSmrg#include "windowstr.h" 5605b261ecSmrg#include "pixmapstr.h" 5705b261ecSmrg#include "gcstruct.h" 5805b261ecSmrg#include "extnsionst.h" 5905b261ecSmrg#include "servermd.h" 6005b261ecSmrg#define _XSHM_SERVER_ 6105b261ecSmrg#include <X11/extensions/shmstr.h> 6205b261ecSmrg#include <X11/Xfuncproto.h> 6305b261ecSmrg 6405b261ecSmrg#ifdef PANORAMIX 6505b261ecSmrg#include "panoramiX.h" 6605b261ecSmrg#include "panoramiXsrv.h" 6705b261ecSmrg#endif 6805b261ecSmrg 6905b261ecSmrg#include "modinit.h" 7005b261ecSmrg 7105b261ecSmrgtypedef struct _ShmDesc { 7205b261ecSmrg struct _ShmDesc *next; 7305b261ecSmrg int shmid; 7405b261ecSmrg int refcnt; 7505b261ecSmrg char *addr; 7605b261ecSmrg Bool writable; 7705b261ecSmrg unsigned long size; 7805b261ecSmrg} ShmDescRec, *ShmDescPtr; 7905b261ecSmrg 8005b261ecSmrgstatic void miShmPutImage(XSHM_PUT_IMAGE_ARGS); 8105b261ecSmrgstatic void fbShmPutImage(XSHM_PUT_IMAGE_ARGS); 8205b261ecSmrgstatic PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); 8305b261ecSmrgstatic int ShmDetachSegment( 8405b261ecSmrg pointer /* value */, 8505b261ecSmrg XID /* shmseg */ 8605b261ecSmrg ); 8705b261ecSmrgstatic void ShmResetProc( 8805b261ecSmrg ExtensionEntry * /* extEntry */ 8905b261ecSmrg ); 9005b261ecSmrgstatic void SShmCompletionEvent( 9105b261ecSmrg xShmCompletionEvent * /* from */, 9205b261ecSmrg xShmCompletionEvent * /* to */ 9305b261ecSmrg ); 9405b261ecSmrg 9505b261ecSmrgstatic Bool ShmDestroyPixmap (PixmapPtr pPixmap); 9605b261ecSmrg 9705b261ecSmrgstatic DISPATCH_PROC(ProcShmAttach); 9805b261ecSmrgstatic DISPATCH_PROC(ProcShmCreatePixmap); 9905b261ecSmrgstatic DISPATCH_PROC(ProcShmDetach); 10005b261ecSmrgstatic DISPATCH_PROC(ProcShmDispatch); 10105b261ecSmrgstatic DISPATCH_PROC(ProcShmGetImage); 10205b261ecSmrgstatic DISPATCH_PROC(ProcShmPutImage); 10305b261ecSmrgstatic DISPATCH_PROC(ProcShmQueryVersion); 10405b261ecSmrgstatic DISPATCH_PROC(SProcShmAttach); 10505b261ecSmrgstatic DISPATCH_PROC(SProcShmCreatePixmap); 10605b261ecSmrgstatic DISPATCH_PROC(SProcShmDetach); 10705b261ecSmrgstatic DISPATCH_PROC(SProcShmDispatch); 10805b261ecSmrgstatic DISPATCH_PROC(SProcShmGetImage); 10905b261ecSmrgstatic DISPATCH_PROC(SProcShmPutImage); 11005b261ecSmrgstatic DISPATCH_PROC(SProcShmQueryVersion); 11105b261ecSmrg 11205b261ecSmrgstatic unsigned char ShmReqCode; 11305b261ecSmrg_X_EXPORT int ShmCompletionCode; 11405b261ecSmrg_X_EXPORT int BadShmSegCode; 11505b261ecSmrg_X_EXPORT RESTYPE ShmSegType; 11605b261ecSmrgstatic ShmDescPtr Shmsegs; 11705b261ecSmrgstatic Bool sharedPixmaps; 11805b261ecSmrgstatic int pixmapFormat; 11905b261ecSmrgstatic int shmPixFormat[MAXSCREENS]; 12005b261ecSmrgstatic ShmFuncsPtr shmFuncs[MAXSCREENS]; 12105b261ecSmrgstatic DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; 12205b261ecSmrgstatic int shmPixmapPrivate; 12305b261ecSmrgstatic ShmFuncs miFuncs = {NULL, miShmPutImage}; 12405b261ecSmrgstatic ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage}; 12505b261ecSmrg 12605b261ecSmrg#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ 12705b261ecSmrg{ \ 12805b261ecSmrg shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ 12905b261ecSmrg if (!shmdesc) \ 13005b261ecSmrg { \ 13105b261ecSmrg client->errorValue = shmseg; \ 13205b261ecSmrg return BadShmSegCode; \ 13305b261ecSmrg } \ 13405b261ecSmrg} 13505b261ecSmrg 13605b261ecSmrg#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ 13705b261ecSmrg{ \ 13805b261ecSmrg VERIFY_SHMSEG(shmseg, shmdesc, client); \ 13905b261ecSmrg if ((offset & 3) || (offset > shmdesc->size)) \ 14005b261ecSmrg { \ 14105b261ecSmrg client->errorValue = offset; \ 14205b261ecSmrg return BadValue; \ 14305b261ecSmrg } \ 14405b261ecSmrg if (needwrite && !shmdesc->writable) \ 14505b261ecSmrg return BadAccess; \ 14605b261ecSmrg} 14705b261ecSmrg 14805b261ecSmrg#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ 14905b261ecSmrg{ \ 15005b261ecSmrg if ((offset + len) > shmdesc->size) \ 15105b261ecSmrg { \ 15205b261ecSmrg return BadAccess; \ 15305b261ecSmrg } \ 15405b261ecSmrg} 15505b261ecSmrg 15605b261ecSmrg 15705b261ecSmrg#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__) 15805b261ecSmrg#include <sys/signal.h> 15905b261ecSmrg 16005b261ecSmrgstatic Bool badSysCall = FALSE; 16105b261ecSmrg 16205b261ecSmrgstatic void 16305b261ecSmrgSigSysHandler(signo) 16405b261ecSmrgint signo; 16505b261ecSmrg{ 16605b261ecSmrg badSysCall = TRUE; 16705b261ecSmrg} 16805b261ecSmrg 16905b261ecSmrgstatic Bool CheckForShmSyscall() 17005b261ecSmrg{ 17105b261ecSmrg void (*oldHandler)(); 17205b261ecSmrg int shmid = -1; 17305b261ecSmrg 17405b261ecSmrg /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ 17505b261ecSmrg oldHandler = signal(SIGSYS, SigSysHandler); 17605b261ecSmrg 17705b261ecSmrg badSysCall = FALSE; 17805b261ecSmrg shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); 17905b261ecSmrg 18005b261ecSmrg if (shmid != -1) 18105b261ecSmrg { 18205b261ecSmrg /* Successful allocation - clean up */ 18305b261ecSmrg shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); 18405b261ecSmrg } 18505b261ecSmrg else 18605b261ecSmrg { 18705b261ecSmrg /* Allocation failed */ 18805b261ecSmrg badSysCall = TRUE; 18905b261ecSmrg } 19005b261ecSmrg signal(SIGSYS, oldHandler); 19105b261ecSmrg return(!badSysCall); 19205b261ecSmrg} 19305b261ecSmrg 19405b261ecSmrg#define MUST_CHECK_FOR_SHM_SYSCALL 19505b261ecSmrg 19605b261ecSmrg#endif 19705b261ecSmrg 19805b261ecSmrgvoid 19905b261ecSmrgShmExtensionInit(INITARGS) 20005b261ecSmrg{ 20105b261ecSmrg ExtensionEntry *extEntry; 20205b261ecSmrg int i; 20305b261ecSmrg 20405b261ecSmrg#ifdef MUST_CHECK_FOR_SHM_SYSCALL 20505b261ecSmrg if (!CheckForShmSyscall()) 20605b261ecSmrg { 20705b261ecSmrg ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); 20805b261ecSmrg return; 20905b261ecSmrg } 21005b261ecSmrg#endif 21105b261ecSmrg 21205b261ecSmrg sharedPixmaps = xFalse; 21305b261ecSmrg pixmapFormat = 0; 21405b261ecSmrg { 21505b261ecSmrg sharedPixmaps = xTrue; 21605b261ecSmrg pixmapFormat = shmPixFormat[0]; 21705b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) 21805b261ecSmrg { 21905b261ecSmrg if (!shmFuncs[i]) 22005b261ecSmrg shmFuncs[i] = &miFuncs; 22105b261ecSmrg if (!shmFuncs[i]->CreatePixmap) 22205b261ecSmrg sharedPixmaps = xFalse; 22305b261ecSmrg if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat)) 22405b261ecSmrg { 22505b261ecSmrg sharedPixmaps = xFalse; 22605b261ecSmrg pixmapFormat = 0; 22705b261ecSmrg } 22805b261ecSmrg } 22905b261ecSmrg if (!pixmapFormat) 23005b261ecSmrg pixmapFormat = ZPixmap; 23105b261ecSmrg if (sharedPixmaps) 23205b261ecSmrg { 23305b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) 23405b261ecSmrg { 23505b261ecSmrg destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; 23605b261ecSmrg screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; 23705b261ecSmrg } 23805b261ecSmrg shmPixmapPrivate = AllocatePixmapPrivateIndex(); 23905b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) 24005b261ecSmrg { 24105b261ecSmrg if (!AllocatePixmapPrivate(screenInfo.screens[i], 24205b261ecSmrg shmPixmapPrivate, 0)) 24305b261ecSmrg return; 24405b261ecSmrg } 24505b261ecSmrg } 24605b261ecSmrg } 24705b261ecSmrg ShmSegType = CreateNewResourceType(ShmDetachSegment); 24805b261ecSmrg if (ShmSegType && 24905b261ecSmrg (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, 25005b261ecSmrg ProcShmDispatch, SProcShmDispatch, 25105b261ecSmrg ShmResetProc, StandardMinorOpcode))) 25205b261ecSmrg { 25305b261ecSmrg ShmReqCode = (unsigned char)extEntry->base; 25405b261ecSmrg ShmCompletionCode = extEntry->eventBase; 25505b261ecSmrg BadShmSegCode = extEntry->errorBase; 25605b261ecSmrg EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; 25705b261ecSmrg } 25805b261ecSmrg} 25905b261ecSmrg 26005b261ecSmrg/*ARGSUSED*/ 26105b261ecSmrgstatic void 26205b261ecSmrgShmResetProc (extEntry) 26305b261ecSmrgExtensionEntry *extEntry; 26405b261ecSmrg{ 26505b261ecSmrg int i; 26605b261ecSmrg 26705b261ecSmrg for (i = 0; i < MAXSCREENS; i++) 26805b261ecSmrg { 26905b261ecSmrg shmFuncs[i] = (ShmFuncsPtr)NULL; 27005b261ecSmrg shmPixFormat[i] = 0; 27105b261ecSmrg } 27205b261ecSmrg} 27305b261ecSmrg 27405b261ecSmrgvoid 27505b261ecSmrgShmRegisterFuncs( 27605b261ecSmrg ScreenPtr pScreen, 27705b261ecSmrg ShmFuncsPtr funcs) 27805b261ecSmrg{ 27905b261ecSmrg shmFuncs[pScreen->myNum] = funcs; 28005b261ecSmrg} 28105b261ecSmrg 28205b261ecSmrgvoid 28305b261ecSmrgShmSetPixmapFormat( 28405b261ecSmrg ScreenPtr pScreen, 28505b261ecSmrg int format) 28605b261ecSmrg{ 28705b261ecSmrg shmPixFormat[pScreen->myNum] = format; 28805b261ecSmrg} 28905b261ecSmrg 29005b261ecSmrgstatic Bool 29105b261ecSmrgShmDestroyPixmap (PixmapPtr pPixmap) 29205b261ecSmrg{ 29305b261ecSmrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 29405b261ecSmrg Bool ret; 29505b261ecSmrg if (pPixmap->refcnt == 1) 29605b261ecSmrg { 29705b261ecSmrg ShmDescPtr shmdesc; 29805b261ecSmrg shmdesc = (ShmDescPtr) pPixmap->devPrivates[shmPixmapPrivate].ptr; 29905b261ecSmrg if (shmdesc) 30005b261ecSmrg ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); 30105b261ecSmrg } 30205b261ecSmrg 30305b261ecSmrg pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; 30405b261ecSmrg ret = (*pScreen->DestroyPixmap) (pPixmap); 30505b261ecSmrg destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; 30605b261ecSmrg pScreen->DestroyPixmap = ShmDestroyPixmap; 30705b261ecSmrg return ret; 30805b261ecSmrg} 30905b261ecSmrg 31005b261ecSmrgvoid 31105b261ecSmrgShmRegisterFbFuncs(pScreen) 31205b261ecSmrg ScreenPtr pScreen; 31305b261ecSmrg{ 31405b261ecSmrg shmFuncs[pScreen->myNum] = &fbFuncs; 31505b261ecSmrg} 31605b261ecSmrg 31705b261ecSmrgstatic int 31805b261ecSmrgProcShmQueryVersion(client) 31905b261ecSmrg register ClientPtr client; 32005b261ecSmrg{ 32105b261ecSmrg xShmQueryVersionReply rep; 32205b261ecSmrg register int n; 32305b261ecSmrg 32405b261ecSmrg REQUEST_SIZE_MATCH(xShmQueryVersionReq); 32505b261ecSmrg rep.type = X_Reply; 32605b261ecSmrg rep.length = 0; 32705b261ecSmrg rep.sequenceNumber = client->sequence; 32805b261ecSmrg rep.sharedPixmaps = sharedPixmaps; 32905b261ecSmrg rep.pixmapFormat = pixmapFormat; 33005b261ecSmrg rep.majorVersion = SHM_MAJOR_VERSION; 33105b261ecSmrg rep.minorVersion = SHM_MINOR_VERSION; 33205b261ecSmrg rep.uid = geteuid(); 33305b261ecSmrg rep.gid = getegid(); 33405b261ecSmrg if (client->swapped) { 33505b261ecSmrg swaps(&rep.sequenceNumber, n); 33605b261ecSmrg swapl(&rep.length, n); 33705b261ecSmrg swaps(&rep.majorVersion, n); 33805b261ecSmrg swaps(&rep.minorVersion, n); 33905b261ecSmrg swaps(&rep.uid, n); 34005b261ecSmrg swaps(&rep.gid, n); 34105b261ecSmrg } 34205b261ecSmrg WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); 34305b261ecSmrg return (client->noClientException); 34405b261ecSmrg} 34505b261ecSmrg 34605b261ecSmrg/* 34705b261ecSmrg * Simulate the access() system call for a shared memory segement, 34805b261ecSmrg * using the credentials from the client if available 34905b261ecSmrg */ 35005b261ecSmrgstatic int 35105b261ecSmrgshm_access(ClientPtr client, struct ipc_perm *perm, int readonly) 35205b261ecSmrg{ 35305b261ecSmrg int uid, gid; 35405b261ecSmrg mode_t mask; 35505b261ecSmrg 35605b261ecSmrg if (LocalClientCred(client, &uid, &gid) != -1) { 35705b261ecSmrg 35805b261ecSmrg /* User id 0 always gets access */ 35905b261ecSmrg if (uid == 0) { 36005b261ecSmrg return 0; 36105b261ecSmrg } 36205b261ecSmrg /* Check the owner */ 36305b261ecSmrg if (perm->uid == uid || perm->cuid == uid) { 36405b261ecSmrg mask = S_IRUSR; 36505b261ecSmrg if (!readonly) { 36605b261ecSmrg mask |= S_IWUSR; 36705b261ecSmrg } 36805b261ecSmrg return (perm->mode & mask) == mask ? 0 : -1; 36905b261ecSmrg } 37005b261ecSmrg /* Check the group */ 37105b261ecSmrg if (perm->gid == gid || perm->cgid == gid) { 37205b261ecSmrg mask = S_IRGRP; 37305b261ecSmrg if (!readonly) { 37405b261ecSmrg mask |= S_IWGRP; 37505b261ecSmrg } 37605b261ecSmrg return (perm->mode & mask) == mask ? 0 : -1; 37705b261ecSmrg } 37805b261ecSmrg } 37905b261ecSmrg /* Otherwise, check everyone else */ 38005b261ecSmrg mask = S_IROTH; 38105b261ecSmrg if (!readonly) { 38205b261ecSmrg mask |= S_IWOTH; 38305b261ecSmrg } 38405b261ecSmrg return (perm->mode & mask) == mask ? 0 : -1; 38505b261ecSmrg} 38605b261ecSmrg 38705b261ecSmrgstatic int 38805b261ecSmrgProcShmAttach(client) 38905b261ecSmrg register ClientPtr client; 39005b261ecSmrg{ 39105b261ecSmrg struct shmid_ds buf; 39205b261ecSmrg ShmDescPtr shmdesc; 39305b261ecSmrg REQUEST(xShmAttachReq); 39405b261ecSmrg 39505b261ecSmrg REQUEST_SIZE_MATCH(xShmAttachReq); 39605b261ecSmrg LEGAL_NEW_RESOURCE(stuff->shmseg, client); 39705b261ecSmrg if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) 39805b261ecSmrg { 39905b261ecSmrg client->errorValue = stuff->readOnly; 40005b261ecSmrg return(BadValue); 40105b261ecSmrg } 40205b261ecSmrg for (shmdesc = Shmsegs; 40305b261ecSmrg shmdesc && (shmdesc->shmid != stuff->shmid); 40405b261ecSmrg shmdesc = shmdesc->next) 40505b261ecSmrg ; 40605b261ecSmrg if (shmdesc) 40705b261ecSmrg { 40805b261ecSmrg if (!stuff->readOnly && !shmdesc->writable) 40905b261ecSmrg return BadAccess; 41005b261ecSmrg shmdesc->refcnt++; 41105b261ecSmrg } 41205b261ecSmrg else 41305b261ecSmrg { 41405b261ecSmrg shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec)); 41505b261ecSmrg if (!shmdesc) 41605b261ecSmrg return BadAlloc; 41705b261ecSmrg shmdesc->addr = shmat(stuff->shmid, 0, 41805b261ecSmrg stuff->readOnly ? SHM_RDONLY : 0); 41905b261ecSmrg if ((shmdesc->addr == ((char *)-1)) || 42005b261ecSmrg shmctl(stuff->shmid, IPC_STAT, &buf)) 42105b261ecSmrg { 42205b261ecSmrg xfree(shmdesc); 42305b261ecSmrg return BadAccess; 42405b261ecSmrg } 42505b261ecSmrg 42605b261ecSmrg /* The attach was performed with root privs. We must 42705b261ecSmrg * do manual checking of access rights for the credentials 42805b261ecSmrg * of the client */ 42905b261ecSmrg 43005b261ecSmrg if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) { 43105b261ecSmrg shmdt(shmdesc->addr); 43205b261ecSmrg xfree(shmdesc); 43305b261ecSmrg return BadAccess; 43405b261ecSmrg } 43505b261ecSmrg 43605b261ecSmrg shmdesc->shmid = stuff->shmid; 43705b261ecSmrg shmdesc->refcnt = 1; 43805b261ecSmrg shmdesc->writable = !stuff->readOnly; 43905b261ecSmrg shmdesc->size = buf.shm_segsz; 44005b261ecSmrg shmdesc->next = Shmsegs; 44105b261ecSmrg Shmsegs = shmdesc; 44205b261ecSmrg } 44305b261ecSmrg if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) 44405b261ecSmrg return BadAlloc; 44505b261ecSmrg return(client->noClientException); 44605b261ecSmrg} 44705b261ecSmrg 44805b261ecSmrg/*ARGSUSED*/ 44905b261ecSmrgstatic int 45005b261ecSmrgShmDetachSegment(value, shmseg) 45105b261ecSmrg pointer value; /* must conform to DeleteType */ 45205b261ecSmrg XID shmseg; 45305b261ecSmrg{ 45405b261ecSmrg ShmDescPtr shmdesc = (ShmDescPtr)value; 45505b261ecSmrg ShmDescPtr *prev; 45605b261ecSmrg 45705b261ecSmrg if (--shmdesc->refcnt) 45805b261ecSmrg return TRUE; 45905b261ecSmrg shmdt(shmdesc->addr); 46005b261ecSmrg for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) 46105b261ecSmrg ; 46205b261ecSmrg *prev = shmdesc->next; 46305b261ecSmrg xfree(shmdesc); 46405b261ecSmrg return Success; 46505b261ecSmrg} 46605b261ecSmrg 46705b261ecSmrgstatic int 46805b261ecSmrgProcShmDetach(client) 46905b261ecSmrg register ClientPtr client; 47005b261ecSmrg{ 47105b261ecSmrg ShmDescPtr shmdesc; 47205b261ecSmrg REQUEST(xShmDetachReq); 47305b261ecSmrg 47405b261ecSmrg REQUEST_SIZE_MATCH(xShmDetachReq); 47505b261ecSmrg VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); 47605b261ecSmrg FreeResource(stuff->shmseg, RT_NONE); 47705b261ecSmrg return(client->noClientException); 47805b261ecSmrg} 47905b261ecSmrg 48005b261ecSmrgstatic void 48105b261ecSmrgmiShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) 48205b261ecSmrg DrawablePtr dst; 48305b261ecSmrg GCPtr pGC; 48405b261ecSmrg int depth, w, h, sx, sy, sw, sh, dx, dy; 48505b261ecSmrg unsigned int format; 48605b261ecSmrg char *data; 48705b261ecSmrg{ 48805b261ecSmrg PixmapPtr pmap; 48905b261ecSmrg GCPtr putGC; 49005b261ecSmrg 49105b261ecSmrg putGC = GetScratchGC(depth, dst->pScreen); 49205b261ecSmrg if (!putGC) 49305b261ecSmrg return; 49405b261ecSmrg pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth); 49505b261ecSmrg if (!pmap) 49605b261ecSmrg { 49705b261ecSmrg FreeScratchGC(putGC); 49805b261ecSmrg return; 49905b261ecSmrg } 50005b261ecSmrg ValidateGC((DrawablePtr)pmap, putGC); 50105b261ecSmrg (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0, 50205b261ecSmrg (format == XYPixmap) ? XYPixmap : ZPixmap, data); 50305b261ecSmrg FreeScratchGC(putGC); 50405b261ecSmrg if (format == XYBitmap) 50505b261ecSmrg (void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, 50605b261ecSmrg dx, dy, 1L); 50705b261ecSmrg else 50805b261ecSmrg (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh, 50905b261ecSmrg dx, dy); 51005b261ecSmrg (*pmap->drawable.pScreen->DestroyPixmap)(pmap); 51105b261ecSmrg} 51205b261ecSmrg 51305b261ecSmrgstatic void 51405b261ecSmrgfbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) 51505b261ecSmrg DrawablePtr dst; 51605b261ecSmrg GCPtr pGC; 51705b261ecSmrg int depth, w, h, sx, sy, sw, sh, dx, dy; 51805b261ecSmrg unsigned int format; 51905b261ecSmrg char *data; 52005b261ecSmrg{ 52105b261ecSmrg if ((format == ZPixmap) || (depth == 1)) 52205b261ecSmrg { 52305b261ecSmrg PixmapPtr pPixmap; 52405b261ecSmrg 52505b261ecSmrg pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, 52605b261ecSmrg BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data); 52705b261ecSmrg if (!pPixmap) 52805b261ecSmrg return; 52905b261ecSmrg if (format == XYBitmap) 53005b261ecSmrg (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC, 53105b261ecSmrg sx, sy, sw, sh, dx, dy, 1L); 53205b261ecSmrg else 53305b261ecSmrg (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC, 53405b261ecSmrg sx, sy, sw, sh, dx, dy); 53505b261ecSmrg FreeScratchPixmapHeader(pPixmap); 53605b261ecSmrg } 53705b261ecSmrg else 53805b261ecSmrg miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, 53905b261ecSmrg data); 54005b261ecSmrg} 54105b261ecSmrg 54205b261ecSmrg 54305b261ecSmrg#ifdef PANORAMIX 54405b261ecSmrgstatic int 54505b261ecSmrgProcPanoramiXShmPutImage(register ClientPtr client) 54605b261ecSmrg{ 54705b261ecSmrg int j, result = 0, orig_x, orig_y; 54805b261ecSmrg PanoramiXRes *draw, *gc; 54905b261ecSmrg Bool sendEvent, isRoot; 55005b261ecSmrg 55105b261ecSmrg REQUEST(xShmPutImageReq); 55205b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 55305b261ecSmrg 55405b261ecSmrg if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( 55505b261ecSmrg client, stuff->drawable, XRC_DRAWABLE, DixWriteAccess))) 55605b261ecSmrg return BadDrawable; 55705b261ecSmrg 55805b261ecSmrg if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( 55905b261ecSmrg client, stuff->gc, XRT_GC, DixReadAccess))) 56005b261ecSmrg return BadGC; 56105b261ecSmrg 56205b261ecSmrg isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 56305b261ecSmrg 56405b261ecSmrg orig_x = stuff->dstX; 56505b261ecSmrg orig_y = stuff->dstY; 56605b261ecSmrg sendEvent = stuff->sendEvent; 56705b261ecSmrg stuff->sendEvent = 0; 56805b261ecSmrg FOR_NSCREENS(j) { 56905b261ecSmrg if(!j) stuff->sendEvent = sendEvent; 57005b261ecSmrg stuff->drawable = draw->info[j].id; 57105b261ecSmrg stuff->gc = gc->info[j].id; 57205b261ecSmrg if (isRoot) { 57305b261ecSmrg stuff->dstX = orig_x - panoramiXdataPtr[j].x; 57405b261ecSmrg stuff->dstY = orig_y - panoramiXdataPtr[j].y; 57505b261ecSmrg } 57605b261ecSmrg result = ProcShmPutImage(client); 57705b261ecSmrg if(result != client->noClientException) break; 57805b261ecSmrg } 57905b261ecSmrg return(result); 58005b261ecSmrg} 58105b261ecSmrg 58205b261ecSmrgstatic int 58305b261ecSmrgProcPanoramiXShmGetImage(ClientPtr client) 58405b261ecSmrg{ 58505b261ecSmrg PanoramiXRes *draw; 58605b261ecSmrg DrawablePtr drawables[MAXSCREENS]; 58705b261ecSmrg DrawablePtr pDraw; 58805b261ecSmrg xShmGetImageReply xgi; 58905b261ecSmrg ShmDescPtr shmdesc; 59005b261ecSmrg int i, x, y, w, h, format, rc; 59105b261ecSmrg Mask plane = 0, planemask; 59205b261ecSmrg long lenPer = 0, length, widthBytesLine; 59305b261ecSmrg Bool isRoot; 59405b261ecSmrg 59505b261ecSmrg REQUEST(xShmGetImageReq); 59605b261ecSmrg 59705b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 59805b261ecSmrg 59905b261ecSmrg if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { 60005b261ecSmrg client->errorValue = stuff->format; 60105b261ecSmrg return(BadValue); 60205b261ecSmrg } 60305b261ecSmrg 60405b261ecSmrg if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( 60505b261ecSmrg client, stuff->drawable, XRC_DRAWABLE, DixWriteAccess))) 60605b261ecSmrg return BadDrawable; 60705b261ecSmrg 60805b261ecSmrg if (draw->type == XRT_PIXMAP) 60905b261ecSmrg return ProcShmGetImage(client); 61005b261ecSmrg 61105b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, 61205b261ecSmrg DixUnknownAccess); 61305b261ecSmrg if (rc != Success) 61405b261ecSmrg return rc; 61505b261ecSmrg 61605b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 61705b261ecSmrg 61805b261ecSmrg x = stuff->x; 61905b261ecSmrg y = stuff->y; 62005b261ecSmrg w = stuff->width; 62105b261ecSmrg h = stuff->height; 62205b261ecSmrg format = stuff->format; 62305b261ecSmrg planemask = stuff->planeMask; 62405b261ecSmrg 62505b261ecSmrg isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 62605b261ecSmrg 62705b261ecSmrg if(isRoot) { 62805b261ecSmrg if( /* check for being onscreen */ 62905b261ecSmrg x < 0 || x + w > PanoramiXPixWidth || 63005b261ecSmrg y < 0 || y + h > PanoramiXPixHeight ) 63105b261ecSmrg return(BadMatch); 63205b261ecSmrg } else { 63305b261ecSmrg if( /* check for being onscreen */ 63405b261ecSmrg panoramiXdataPtr[0].x + pDraw->x + x < 0 || 63505b261ecSmrg panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || 63605b261ecSmrg panoramiXdataPtr[0].y + pDraw->y + y < 0 || 63705b261ecSmrg panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || 63805b261ecSmrg /* check for being inside of border */ 63905b261ecSmrg x < - wBorderWidth((WindowPtr)pDraw) || 64005b261ecSmrg x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || 64105b261ecSmrg y < -wBorderWidth((WindowPtr)pDraw) || 64205b261ecSmrg y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) 64305b261ecSmrg return(BadMatch); 64405b261ecSmrg } 64505b261ecSmrg 64605b261ecSmrg drawables[0] = pDraw; 64705b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 64805b261ecSmrg rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0, 64905b261ecSmrg DixUnknownAccess); 65005b261ecSmrg if (rc != Success) 65105b261ecSmrg return rc; 65205b261ecSmrg } 65305b261ecSmrg 65405b261ecSmrg xgi.visual = wVisual(((WindowPtr)pDraw)); 65505b261ecSmrg xgi.type = X_Reply; 65605b261ecSmrg xgi.length = 0; 65705b261ecSmrg xgi.sequenceNumber = client->sequence; 65805b261ecSmrg xgi.depth = pDraw->depth; 65905b261ecSmrg 66005b261ecSmrg if(format == ZPixmap) { 66105b261ecSmrg widthBytesLine = PixmapBytePad(w, pDraw->depth); 66205b261ecSmrg length = widthBytesLine * h; 66305b261ecSmrg } else { 66405b261ecSmrg widthBytesLine = PixmapBytePad(w, 1); 66505b261ecSmrg lenPer = widthBytesLine * h; 66605b261ecSmrg plane = ((Mask)1) << (pDraw->depth - 1); 66705b261ecSmrg length = lenPer * Ones(planemask & (plane | (plane - 1))); 66805b261ecSmrg } 66905b261ecSmrg 67005b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 67105b261ecSmrg xgi.size = length; 67205b261ecSmrg 67305b261ecSmrg if (length == 0) {/* nothing to do */ } 67405b261ecSmrg else if (format == ZPixmap) { 67505b261ecSmrg XineramaGetImageData(drawables, x, y, w, h, format, planemask, 67605b261ecSmrg shmdesc->addr + stuff->offset, 67705b261ecSmrg widthBytesLine, isRoot); 67805b261ecSmrg } else { 67905b261ecSmrg 68005b261ecSmrg length = stuff->offset; 68105b261ecSmrg for (; plane; plane >>= 1) { 68205b261ecSmrg if (planemask & plane) { 68305b261ecSmrg XineramaGetImageData(drawables, x, y, w, h, 68405b261ecSmrg format, plane, shmdesc->addr + length, 68505b261ecSmrg widthBytesLine, isRoot); 68605b261ecSmrg length += lenPer; 68705b261ecSmrg } 68805b261ecSmrg } 68905b261ecSmrg } 69005b261ecSmrg 69105b261ecSmrg if (client->swapped) { 69205b261ecSmrg register int n; 69305b261ecSmrg swaps(&xgi.sequenceNumber, n); 69405b261ecSmrg swapl(&xgi.length, n); 69505b261ecSmrg swapl(&xgi.visual, n); 69605b261ecSmrg swapl(&xgi.size, n); 69705b261ecSmrg } 69805b261ecSmrg WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); 69905b261ecSmrg 70005b261ecSmrg return(client->noClientException); 70105b261ecSmrg} 70205b261ecSmrg 70305b261ecSmrgstatic int 70405b261ecSmrgProcPanoramiXShmCreatePixmap( 70505b261ecSmrg register ClientPtr client) 70605b261ecSmrg{ 70705b261ecSmrg ScreenPtr pScreen = NULL; 70805b261ecSmrg PixmapPtr pMap = NULL; 70905b261ecSmrg DrawablePtr pDraw; 71005b261ecSmrg DepthPtr pDepth; 71105b261ecSmrg int i, j, result, rc; 71205b261ecSmrg ShmDescPtr shmdesc; 71305b261ecSmrg REQUEST(xShmCreatePixmapReq); 71405b261ecSmrg unsigned int width, height, depth; 71505b261ecSmrg unsigned long size; 71605b261ecSmrg PanoramiXRes *newPix; 71705b261ecSmrg 71805b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 71905b261ecSmrg client->errorValue = stuff->pid; 72005b261ecSmrg if (!sharedPixmaps) 72105b261ecSmrg return BadImplementation; 72205b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 72305b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 72405b261ecSmrg DixUnknownAccess); 72505b261ecSmrg if (rc != Success) 72605b261ecSmrg return rc; 72705b261ecSmrg 72805b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 72905b261ecSmrg 73005b261ecSmrg width = stuff->width; 73105b261ecSmrg height = stuff->height; 73205b261ecSmrg depth = stuff->depth; 73305b261ecSmrg if (!width || !height || !depth) 73405b261ecSmrg { 73505b261ecSmrg client->errorValue = 0; 73605b261ecSmrg return BadValue; 73705b261ecSmrg } 73805b261ecSmrg if (width > 32767 || height > 32767) 73905b261ecSmrg return BadAlloc; 74005b261ecSmrg 74105b261ecSmrg if (stuff->depth != 1) 74205b261ecSmrg { 74305b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 74405b261ecSmrg for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++) 74505b261ecSmrg if (pDepth->depth == stuff->depth) 74605b261ecSmrg goto CreatePmap; 74705b261ecSmrg client->errorValue = stuff->depth; 74805b261ecSmrg return BadValue; 74905b261ecSmrg } 75005b261ecSmrg 75105b261ecSmrgCreatePmap: 75205b261ecSmrg size = PixmapBytePad(width, depth) * height; 75305b261ecSmrg if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 75405b261ecSmrg if (size < width * height) 75505b261ecSmrg return BadAlloc; 75605b261ecSmrg } 75705b261ecSmrg /* thankfully, offset is unsigned */ 75805b261ecSmrg if (stuff->offset + size < size) 75905b261ecSmrg return BadAlloc; 76005b261ecSmrg 76105b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 76205b261ecSmrg 76305b261ecSmrg if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) 76405b261ecSmrg return BadAlloc; 76505b261ecSmrg 76605b261ecSmrg newPix->type = XRT_PIXMAP; 76705b261ecSmrg newPix->u.pix.shared = TRUE; 76805b261ecSmrg newPix->info[0].id = stuff->pid; 76905b261ecSmrg for(j = 1; j < PanoramiXNumScreens; j++) 77005b261ecSmrg newPix->info[j].id = FakeClientID(client->index); 77105b261ecSmrg 77205b261ecSmrg result = (client->noClientException); 77305b261ecSmrg 77405b261ecSmrg FOR_NSCREENS(j) { 77505b261ecSmrg pScreen = screenInfo.screens[j]; 77605b261ecSmrg 77705b261ecSmrg pMap = (*shmFuncs[j]->CreatePixmap)(pScreen, 77805b261ecSmrg stuff->width, stuff->height, stuff->depth, 77905b261ecSmrg shmdesc->addr + stuff->offset); 78005b261ecSmrg 78105b261ecSmrg if (pMap) { 78205b261ecSmrg pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; 78305b261ecSmrg shmdesc->refcnt++; 78405b261ecSmrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 78505b261ecSmrg pMap->drawable.id = newPix->info[j].id; 78605b261ecSmrg if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { 78705b261ecSmrg (*pScreen->DestroyPixmap)(pMap); 78805b261ecSmrg result = BadAlloc; 78905b261ecSmrg break; 79005b261ecSmrg } 79105b261ecSmrg } else { 79205b261ecSmrg result = BadAlloc; 79305b261ecSmrg break; 79405b261ecSmrg } 79505b261ecSmrg } 79605b261ecSmrg 79705b261ecSmrg if(result == BadAlloc) { 79805b261ecSmrg while(j--) { 79905b261ecSmrg (*pScreen->DestroyPixmap)(pMap); 80005b261ecSmrg FreeResource(newPix->info[j].id, RT_NONE); 80105b261ecSmrg } 80205b261ecSmrg xfree(newPix); 80305b261ecSmrg } else 80405b261ecSmrg AddResource(stuff->pid, XRT_PIXMAP, newPix); 80505b261ecSmrg 80605b261ecSmrg return result; 80705b261ecSmrg} 80805b261ecSmrg 80905b261ecSmrg#endif 81005b261ecSmrg 81105b261ecSmrgstatic int 81205b261ecSmrgProcShmPutImage(client) 81305b261ecSmrg register ClientPtr client; 81405b261ecSmrg{ 81505b261ecSmrg GCPtr pGC; 81605b261ecSmrg DrawablePtr pDraw; 81705b261ecSmrg long length; 81805b261ecSmrg ShmDescPtr shmdesc; 81905b261ecSmrg REQUEST(xShmPutImageReq); 82005b261ecSmrg 82105b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 82205b261ecSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); 82305b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); 82405b261ecSmrg if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) 82505b261ecSmrg return BadValue; 82605b261ecSmrg if (stuff->format == XYBitmap) 82705b261ecSmrg { 82805b261ecSmrg if (stuff->depth != 1) 82905b261ecSmrg return BadMatch; 83005b261ecSmrg length = PixmapBytePad(stuff->totalWidth, 1); 83105b261ecSmrg } 83205b261ecSmrg else if (stuff->format == XYPixmap) 83305b261ecSmrg { 83405b261ecSmrg if (pDraw->depth != stuff->depth) 83505b261ecSmrg return BadMatch; 83605b261ecSmrg length = PixmapBytePad(stuff->totalWidth, 1); 83705b261ecSmrg length *= stuff->depth; 83805b261ecSmrg } 83905b261ecSmrg else if (stuff->format == ZPixmap) 84005b261ecSmrg { 84105b261ecSmrg if (pDraw->depth != stuff->depth) 84205b261ecSmrg return BadMatch; 84305b261ecSmrg length = PixmapBytePad(stuff->totalWidth, stuff->depth); 84405b261ecSmrg } 84505b261ecSmrg else 84605b261ecSmrg { 84705b261ecSmrg client->errorValue = stuff->format; 84805b261ecSmrg return BadValue; 84905b261ecSmrg } 85005b261ecSmrg 85105b261ecSmrg /* 85205b261ecSmrg * There's a potential integer overflow in this check: 85305b261ecSmrg * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, 85405b261ecSmrg * client); 85505b261ecSmrg * the version below ought to avoid it 85605b261ecSmrg */ 85705b261ecSmrg if (stuff->totalHeight != 0 && 85805b261ecSmrg length > (shmdesc->size - stuff->offset)/stuff->totalHeight) { 85905b261ecSmrg client->errorValue = stuff->totalWidth; 86005b261ecSmrg return BadValue; 86105b261ecSmrg } 86205b261ecSmrg if (stuff->srcX > stuff->totalWidth) 86305b261ecSmrg { 86405b261ecSmrg client->errorValue = stuff->srcX; 86505b261ecSmrg return BadValue; 86605b261ecSmrg } 86705b261ecSmrg if (stuff->srcY > stuff->totalHeight) 86805b261ecSmrg { 86905b261ecSmrg client->errorValue = stuff->srcY; 87005b261ecSmrg return BadValue; 87105b261ecSmrg } 87205b261ecSmrg if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) 87305b261ecSmrg { 87405b261ecSmrg client->errorValue = stuff->srcWidth; 87505b261ecSmrg return BadValue; 87605b261ecSmrg } 87705b261ecSmrg if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) 87805b261ecSmrg { 87905b261ecSmrg client->errorValue = stuff->srcHeight; 88005b261ecSmrg return BadValue; 88105b261ecSmrg } 88205b261ecSmrg 88305b261ecSmrg if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || 88405b261ecSmrg ((stuff->format != ZPixmap) && 88505b261ecSmrg (stuff->srcX < screenInfo.bitmapScanlinePad) && 88605b261ecSmrg ((stuff->format == XYBitmap) || 88705b261ecSmrg ((stuff->srcY == 0) && 88805b261ecSmrg (stuff->srcHeight == stuff->totalHeight))))) && 88905b261ecSmrg ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) 89005b261ecSmrg (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, 89105b261ecSmrg stuff->dstX, stuff->dstY, 89205b261ecSmrg stuff->totalWidth, stuff->srcHeight, 89305b261ecSmrg stuff->srcX, stuff->format, 89405b261ecSmrg shmdesc->addr + stuff->offset + 89505b261ecSmrg (stuff->srcY * length)); 89605b261ecSmrg else 89705b261ecSmrg (*shmFuncs[pDraw->pScreen->myNum]->PutImage)( 89805b261ecSmrg pDraw, pGC, stuff->depth, stuff->format, 89905b261ecSmrg stuff->totalWidth, stuff->totalHeight, 90005b261ecSmrg stuff->srcX, stuff->srcY, 90105b261ecSmrg stuff->srcWidth, stuff->srcHeight, 90205b261ecSmrg stuff->dstX, stuff->dstY, 90305b261ecSmrg shmdesc->addr + stuff->offset); 90405b261ecSmrg 90505b261ecSmrg if (stuff->sendEvent) 90605b261ecSmrg { 90705b261ecSmrg xShmCompletionEvent ev; 90805b261ecSmrg 90905b261ecSmrg ev.type = ShmCompletionCode; 91005b261ecSmrg ev.drawable = stuff->drawable; 91105b261ecSmrg ev.sequenceNumber = client->sequence; 91205b261ecSmrg ev.minorEvent = X_ShmPutImage; 91305b261ecSmrg ev.majorEvent = ShmReqCode; 91405b261ecSmrg ev.shmseg = stuff->shmseg; 91505b261ecSmrg ev.offset = stuff->offset; 91605b261ecSmrg WriteEventsToClient(client, 1, (xEvent *) &ev); 91705b261ecSmrg } 91805b261ecSmrg 91905b261ecSmrg return (client->noClientException); 92005b261ecSmrg} 92105b261ecSmrg 92205b261ecSmrg 92305b261ecSmrg 92405b261ecSmrgstatic int 92505b261ecSmrgProcShmGetImage(client) 92605b261ecSmrg register ClientPtr client; 92705b261ecSmrg{ 92805b261ecSmrg DrawablePtr pDraw; 92905b261ecSmrg long lenPer = 0, length; 93005b261ecSmrg Mask plane = 0; 93105b261ecSmrg xShmGetImageReply xgi; 93205b261ecSmrg ShmDescPtr shmdesc; 93305b261ecSmrg int n, rc; 93405b261ecSmrg 93505b261ecSmrg REQUEST(xShmGetImageReq); 93605b261ecSmrg 93705b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 93805b261ecSmrg if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) 93905b261ecSmrg { 94005b261ecSmrg client->errorValue = stuff->format; 94105b261ecSmrg return(BadValue); 94205b261ecSmrg } 94305b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, 94405b261ecSmrg DixUnknownAccess); 94505b261ecSmrg if (rc != Success) 94605b261ecSmrg return rc; 94705b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 94805b261ecSmrg if (pDraw->type == DRAWABLE_WINDOW) 94905b261ecSmrg { 95005b261ecSmrg if( /* check for being viewable */ 95105b261ecSmrg !((WindowPtr) pDraw)->realized || 95205b261ecSmrg /* check for being on screen */ 95305b261ecSmrg pDraw->x + stuff->x < 0 || 95405b261ecSmrg pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || 95505b261ecSmrg pDraw->y + stuff->y < 0 || 95605b261ecSmrg pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || 95705b261ecSmrg /* check for being inside of border */ 95805b261ecSmrg stuff->x < - wBorderWidth((WindowPtr)pDraw) || 95905b261ecSmrg stuff->x + (int)stuff->width > 96005b261ecSmrg wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || 96105b261ecSmrg stuff->y < -wBorderWidth((WindowPtr)pDraw) || 96205b261ecSmrg stuff->y + (int)stuff->height > 96305b261ecSmrg wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height 96405b261ecSmrg ) 96505b261ecSmrg return(BadMatch); 96605b261ecSmrg xgi.visual = wVisual(((WindowPtr)pDraw)); 96705b261ecSmrg } 96805b261ecSmrg else 96905b261ecSmrg { 97005b261ecSmrg if (stuff->x < 0 || 97105b261ecSmrg stuff->x+(int)stuff->width > pDraw->width || 97205b261ecSmrg stuff->y < 0 || 97305b261ecSmrg stuff->y+(int)stuff->height > pDraw->height 97405b261ecSmrg ) 97505b261ecSmrg return(BadMatch); 97605b261ecSmrg xgi.visual = None; 97705b261ecSmrg } 97805b261ecSmrg xgi.type = X_Reply; 97905b261ecSmrg xgi.length = 0; 98005b261ecSmrg xgi.sequenceNumber = client->sequence; 98105b261ecSmrg xgi.depth = pDraw->depth; 98205b261ecSmrg if(stuff->format == ZPixmap) 98305b261ecSmrg { 98405b261ecSmrg length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; 98505b261ecSmrg } 98605b261ecSmrg else 98705b261ecSmrg { 98805b261ecSmrg lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; 98905b261ecSmrg plane = ((Mask)1) << (pDraw->depth - 1); 99005b261ecSmrg /* only planes asked for */ 99105b261ecSmrg length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); 99205b261ecSmrg } 99305b261ecSmrg 99405b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 99505b261ecSmrg xgi.size = length; 99605b261ecSmrg 99705b261ecSmrg if (length == 0) 99805b261ecSmrg { 99905b261ecSmrg /* nothing to do */ 100005b261ecSmrg } 100105b261ecSmrg else if (stuff->format == ZPixmap) 100205b261ecSmrg { 100305b261ecSmrg (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, 100405b261ecSmrg stuff->width, stuff->height, 100505b261ecSmrg stuff->format, stuff->planeMask, 100605b261ecSmrg shmdesc->addr + stuff->offset); 100705b261ecSmrg } 100805b261ecSmrg else 100905b261ecSmrg { 101005b261ecSmrg 101105b261ecSmrg length = stuff->offset; 101205b261ecSmrg for (; plane; plane >>= 1) 101305b261ecSmrg { 101405b261ecSmrg if (stuff->planeMask & plane) 101505b261ecSmrg { 101605b261ecSmrg (*pDraw->pScreen->GetImage)(pDraw, 101705b261ecSmrg stuff->x, stuff->y, 101805b261ecSmrg stuff->width, stuff->height, 101905b261ecSmrg stuff->format, plane, 102005b261ecSmrg shmdesc->addr + length); 102105b261ecSmrg length += lenPer; 102205b261ecSmrg } 102305b261ecSmrg } 102405b261ecSmrg } 102505b261ecSmrg 102605b261ecSmrg if (client->swapped) { 102705b261ecSmrg swaps(&xgi.sequenceNumber, n); 102805b261ecSmrg swapl(&xgi.length, n); 102905b261ecSmrg swapl(&xgi.visual, n); 103005b261ecSmrg swapl(&xgi.size, n); 103105b261ecSmrg } 103205b261ecSmrg WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); 103305b261ecSmrg 103405b261ecSmrg return(client->noClientException); 103505b261ecSmrg} 103605b261ecSmrg 103705b261ecSmrgstatic PixmapPtr 103805b261ecSmrgfbShmCreatePixmap (pScreen, width, height, depth, addr) 103905b261ecSmrg ScreenPtr pScreen; 104005b261ecSmrg int width; 104105b261ecSmrg int height; 104205b261ecSmrg int depth; 104305b261ecSmrg char *addr; 104405b261ecSmrg{ 104505b261ecSmrg register PixmapPtr pPixmap; 104605b261ecSmrg 104705b261ecSmrg pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth); 104805b261ecSmrg if (!pPixmap) 104905b261ecSmrg return NullPixmap; 105005b261ecSmrg 105105b261ecSmrg if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, 105205b261ecSmrg BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) { 105305b261ecSmrg (*pScreen->DestroyPixmap)(pPixmap); 105405b261ecSmrg return NullPixmap; 105505b261ecSmrg } 105605b261ecSmrg return pPixmap; 105705b261ecSmrg} 105805b261ecSmrg 105905b261ecSmrgstatic int 106005b261ecSmrgProcShmCreatePixmap(client) 106105b261ecSmrg register ClientPtr client; 106205b261ecSmrg{ 106305b261ecSmrg PixmapPtr pMap; 106405b261ecSmrg DrawablePtr pDraw; 106505b261ecSmrg DepthPtr pDepth; 106605b261ecSmrg register int i, rc; 106705b261ecSmrg ShmDescPtr shmdesc; 106805b261ecSmrg REQUEST(xShmCreatePixmapReq); 106905b261ecSmrg unsigned int width, height, depth; 107005b261ecSmrg unsigned long size; 107105b261ecSmrg 107205b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 107305b261ecSmrg client->errorValue = stuff->pid; 107405b261ecSmrg if (!sharedPixmaps) 107505b261ecSmrg return BadImplementation; 107605b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 107705b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 107805b261ecSmrg DixUnknownAccess); 107905b261ecSmrg if (rc != Success) 108005b261ecSmrg return rc; 108105b261ecSmrg 108205b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 108305b261ecSmrg 108405b261ecSmrg width = stuff->width; 108505b261ecSmrg height = stuff->height; 108605b261ecSmrg depth = stuff->depth; 108705b261ecSmrg if (!width || !height || !depth) 108805b261ecSmrg { 108905b261ecSmrg client->errorValue = 0; 109005b261ecSmrg return BadValue; 109105b261ecSmrg } 109205b261ecSmrg if (width > 32767 || height > 32767) 109305b261ecSmrg return BadAlloc; 109405b261ecSmrg 109505b261ecSmrg if (stuff->depth != 1) 109605b261ecSmrg { 109705b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 109805b261ecSmrg for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++) 109905b261ecSmrg if (pDepth->depth == stuff->depth) 110005b261ecSmrg goto CreatePmap; 110105b261ecSmrg client->errorValue = stuff->depth; 110205b261ecSmrg return BadValue; 110305b261ecSmrg } 110405b261ecSmrg 110505b261ecSmrgCreatePmap: 110605b261ecSmrg size = PixmapBytePad(width, depth) * height; 110705b261ecSmrg if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 110805b261ecSmrg if (size < width * height) 110905b261ecSmrg return BadAlloc; 111005b261ecSmrg } 111105b261ecSmrg /* thankfully, offset is unsigned */ 111205b261ecSmrg if (stuff->offset + size < size) 111305b261ecSmrg return BadAlloc; 111405b261ecSmrg 111505b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 111605b261ecSmrg pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( 111705b261ecSmrg pDraw->pScreen, stuff->width, 111805b261ecSmrg stuff->height, stuff->depth, 111905b261ecSmrg shmdesc->addr + stuff->offset); 112005b261ecSmrg if (pMap) 112105b261ecSmrg { 112205b261ecSmrg pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc; 112305b261ecSmrg shmdesc->refcnt++; 112405b261ecSmrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 112505b261ecSmrg pMap->drawable.id = stuff->pid; 112605b261ecSmrg if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) 112705b261ecSmrg { 112805b261ecSmrg return(client->noClientException); 112905b261ecSmrg } 113005b261ecSmrg } 113105b261ecSmrg return (BadAlloc); 113205b261ecSmrg} 113305b261ecSmrg 113405b261ecSmrgstatic int 113505b261ecSmrgProcShmDispatch (client) 113605b261ecSmrg register ClientPtr client; 113705b261ecSmrg{ 113805b261ecSmrg REQUEST(xReq); 113905b261ecSmrg switch (stuff->data) 114005b261ecSmrg { 114105b261ecSmrg case X_ShmQueryVersion: 114205b261ecSmrg return ProcShmQueryVersion(client); 114305b261ecSmrg case X_ShmAttach: 114405b261ecSmrg return ProcShmAttach(client); 114505b261ecSmrg case X_ShmDetach: 114605b261ecSmrg return ProcShmDetach(client); 114705b261ecSmrg case X_ShmPutImage: 114805b261ecSmrg#ifdef PANORAMIX 114905b261ecSmrg if ( !noPanoramiXExtension ) 115005b261ecSmrg return ProcPanoramiXShmPutImage(client); 115105b261ecSmrg#endif 115205b261ecSmrg return ProcShmPutImage(client); 115305b261ecSmrg case X_ShmGetImage: 115405b261ecSmrg#ifdef PANORAMIX 115505b261ecSmrg if ( !noPanoramiXExtension ) 115605b261ecSmrg return ProcPanoramiXShmGetImage(client); 115705b261ecSmrg#endif 115805b261ecSmrg return ProcShmGetImage(client); 115905b261ecSmrg case X_ShmCreatePixmap: 116005b261ecSmrg#ifdef PANORAMIX 116105b261ecSmrg if ( !noPanoramiXExtension ) 116205b261ecSmrg return ProcPanoramiXShmCreatePixmap(client); 116305b261ecSmrg#endif 116405b261ecSmrg return ProcShmCreatePixmap(client); 116505b261ecSmrg default: 116605b261ecSmrg return BadRequest; 116705b261ecSmrg } 116805b261ecSmrg} 116905b261ecSmrg 117005b261ecSmrgstatic void 117105b261ecSmrgSShmCompletionEvent(from, to) 117205b261ecSmrg xShmCompletionEvent *from, *to; 117305b261ecSmrg{ 117405b261ecSmrg to->type = from->type; 117505b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 117605b261ecSmrg cpswapl(from->drawable, to->drawable); 117705b261ecSmrg cpswaps(from->minorEvent, to->minorEvent); 117805b261ecSmrg to->majorEvent = from->majorEvent; 117905b261ecSmrg cpswapl(from->shmseg, to->shmseg); 118005b261ecSmrg cpswapl(from->offset, to->offset); 118105b261ecSmrg} 118205b261ecSmrg 118305b261ecSmrgstatic int 118405b261ecSmrgSProcShmQueryVersion(client) 118505b261ecSmrg register ClientPtr client; 118605b261ecSmrg{ 118705b261ecSmrg register int n; 118805b261ecSmrg REQUEST(xShmQueryVersionReq); 118905b261ecSmrg 119005b261ecSmrg swaps(&stuff->length, n); 119105b261ecSmrg return ProcShmQueryVersion(client); 119205b261ecSmrg} 119305b261ecSmrg 119405b261ecSmrgstatic int 119505b261ecSmrgSProcShmAttach(client) 119605b261ecSmrg ClientPtr client; 119705b261ecSmrg{ 119805b261ecSmrg register int n; 119905b261ecSmrg REQUEST(xShmAttachReq); 120005b261ecSmrg swaps(&stuff->length, n); 120105b261ecSmrg REQUEST_SIZE_MATCH(xShmAttachReq); 120205b261ecSmrg swapl(&stuff->shmseg, n); 120305b261ecSmrg swapl(&stuff->shmid, n); 120405b261ecSmrg return ProcShmAttach(client); 120505b261ecSmrg} 120605b261ecSmrg 120705b261ecSmrgstatic int 120805b261ecSmrgSProcShmDetach(client) 120905b261ecSmrg ClientPtr client; 121005b261ecSmrg{ 121105b261ecSmrg register int n; 121205b261ecSmrg REQUEST(xShmDetachReq); 121305b261ecSmrg swaps(&stuff->length, n); 121405b261ecSmrg REQUEST_SIZE_MATCH(xShmDetachReq); 121505b261ecSmrg swapl(&stuff->shmseg, n); 121605b261ecSmrg return ProcShmDetach(client); 121705b261ecSmrg} 121805b261ecSmrg 121905b261ecSmrgstatic int 122005b261ecSmrgSProcShmPutImage(client) 122105b261ecSmrg ClientPtr client; 122205b261ecSmrg{ 122305b261ecSmrg register int n; 122405b261ecSmrg REQUEST(xShmPutImageReq); 122505b261ecSmrg swaps(&stuff->length, n); 122605b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 122705b261ecSmrg swapl(&stuff->drawable, n); 122805b261ecSmrg swapl(&stuff->gc, n); 122905b261ecSmrg swaps(&stuff->totalWidth, n); 123005b261ecSmrg swaps(&stuff->totalHeight, n); 123105b261ecSmrg swaps(&stuff->srcX, n); 123205b261ecSmrg swaps(&stuff->srcY, n); 123305b261ecSmrg swaps(&stuff->srcWidth, n); 123405b261ecSmrg swaps(&stuff->srcHeight, n); 123505b261ecSmrg swaps(&stuff->dstX, n); 123605b261ecSmrg swaps(&stuff->dstY, n); 123705b261ecSmrg swapl(&stuff->shmseg, n); 123805b261ecSmrg swapl(&stuff->offset, n); 123905b261ecSmrg return ProcShmPutImage(client); 124005b261ecSmrg} 124105b261ecSmrg 124205b261ecSmrgstatic int 124305b261ecSmrgSProcShmGetImage(client) 124405b261ecSmrg ClientPtr client; 124505b261ecSmrg{ 124605b261ecSmrg register int n; 124705b261ecSmrg REQUEST(xShmGetImageReq); 124805b261ecSmrg swaps(&stuff->length, n); 124905b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 125005b261ecSmrg swapl(&stuff->drawable, n); 125105b261ecSmrg swaps(&stuff->x, n); 125205b261ecSmrg swaps(&stuff->y, n); 125305b261ecSmrg swaps(&stuff->width, n); 125405b261ecSmrg swaps(&stuff->height, n); 125505b261ecSmrg swapl(&stuff->planeMask, n); 125605b261ecSmrg swapl(&stuff->shmseg, n); 125705b261ecSmrg swapl(&stuff->offset, n); 125805b261ecSmrg return ProcShmGetImage(client); 125905b261ecSmrg} 126005b261ecSmrg 126105b261ecSmrgstatic int 126205b261ecSmrgSProcShmCreatePixmap(client) 126305b261ecSmrg ClientPtr client; 126405b261ecSmrg{ 126505b261ecSmrg register int n; 126605b261ecSmrg REQUEST(xShmCreatePixmapReq); 126705b261ecSmrg swaps(&stuff->length, n); 126805b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 126905b261ecSmrg swapl(&stuff->pid, n); 127005b261ecSmrg swapl(&stuff->drawable, n); 127105b261ecSmrg swaps(&stuff->width, n); 127205b261ecSmrg swaps(&stuff->height, n); 127305b261ecSmrg swapl(&stuff->shmseg, n); 127405b261ecSmrg swapl(&stuff->offset, n); 127505b261ecSmrg return ProcShmCreatePixmap(client); 127605b261ecSmrg} 127705b261ecSmrg 127805b261ecSmrgstatic int 127905b261ecSmrgSProcShmDispatch (client) 128005b261ecSmrg register ClientPtr client; 128105b261ecSmrg{ 128205b261ecSmrg REQUEST(xReq); 128305b261ecSmrg switch (stuff->data) 128405b261ecSmrg { 128505b261ecSmrg case X_ShmQueryVersion: 128605b261ecSmrg return SProcShmQueryVersion(client); 128705b261ecSmrg case X_ShmAttach: 128805b261ecSmrg return SProcShmAttach(client); 128905b261ecSmrg case X_ShmDetach: 129005b261ecSmrg return SProcShmDetach(client); 129105b261ecSmrg case X_ShmPutImage: 129205b261ecSmrg return SProcShmPutImage(client); 129305b261ecSmrg case X_ShmGetImage: 129405b261ecSmrg return SProcShmGetImage(client); 129505b261ecSmrg case X_ShmCreatePixmap: 129605b261ecSmrg return SProcShmCreatePixmap(client); 129705b261ecSmrg default: 129805b261ecSmrg return BadRequest; 129905b261ecSmrg } 130005b261ecSmrg} 1301