diff options
Diffstat (limited to 'xorg-server/Xext')
-rw-r--r-- | xorg-server/Xext/Makefile | 37 | ||||
-rw-r--r-- | xorg-server/Xext/Makefile.am | 266 | ||||
-rw-r--r-- | xorg-server/Xext/dpms.c | 2 | ||||
-rw-r--r-- | xorg-server/Xext/panoramiX.c | 2598 | ||||
-rw-r--r-- | xorg-server/Xext/panoramiXsrv.h | 108 | ||||
-rw-r--r-- | xorg-server/Xext/saver.c | 6 | ||||
-rw-r--r-- | xorg-server/Xext/security.c | 2 | ||||
-rw-r--r-- | xorg-server/Xext/securitysrv.h | 5 | ||||
-rw-r--r-- | xorg-server/Xext/shape.c | 2 | ||||
-rw-r--r-- | xorg-server/Xext/shm.c | 19 | ||||
-rw-r--r-- | xorg-server/Xext/sync.c | 4 | ||||
-rw-r--r-- | xorg-server/Xext/xace.c | 2 | ||||
-rw-r--r-- | xorg-server/Xext/xselinux_hooks.c | 1870 | ||||
-rw-r--r-- | xorg-server/Xext/xvdix.h | 550 | ||||
-rw-r--r-- | xorg-server/Xext/xvmain.c | 2366 | ||||
-rw-r--r-- | xorg-server/Xext/xvmc.c | 1578 |
16 files changed, 4743 insertions, 4672 deletions
diff --git a/xorg-server/Xext/Makefile b/xorg-server/Xext/Makefile new file mode 100644 index 000000000..1fd048d52 --- /dev/null +++ b/xorg-server/Xext/Makefile @@ -0,0 +1,37 @@ +CSRCS=\ +bigreq.c \ +dpms.c \ +dpmsstubs.c \ +saver.c \ +security.c \ +shape.c \ +sleepuntil.c \ +sync.c \ +xace.c \ +xcmisc.c \ +xres.c \ +xtest.c \ +geext.c \ +panoramiX.c \ +panoramiXprocs.c \ +panoramiXSwap.c + +#shm.c \ +#appgroup.c \ +#fontcache.c \ +#mbufbf.c \ +#mbufpx.c \ +#xcalibrate.c \ +#xf86bigfont.c \ +#xprint.c \ +#xselinux.c \ +#xvdisp.c \ +#xvmain.c \ +#xvmc.c + +LIBRARY=libxext + +INCLUDES += ..\hw\xfree86\dixmods\extmod ..\composite ..\miext\sync + + + diff --git a/xorg-server/Xext/Makefile.am b/xorg-server/Xext/Makefile.am index cb432e00e..cb47d38cc 100644 --- a/xorg-server/Xext/Makefile.am +++ b/xorg-server/Xext/Makefile.am @@ -1,133 +1,133 @@ -# libXext.la: includes all extensions and should be linked into Xvfb, -# Xnest, Xdmx and Xprt -# libXextbuiltin.la: includes those extensions that are built directly into -# Xorg by default -# libXextmodule.la: includes those extensions that are built into a module -# that Xorg loads -if XORG -noinst_LTLIBRARIES = libXext.la libXextbuiltin.la libXextmodule.la -else -noinst_LTLIBRARIES = libXext.la -endif - -INCLUDES = -I$(top_srcdir)/hw/xfree86/dixmods/extmod - -AM_CFLAGS = $(DIX_CFLAGS) - -if XORG -sdk_HEADERS = xvdix.h xvmcext.h geext.h geint.h shmint.h syncsdk.h -endif - -# Sources always included in libXextbuiltin.la & libXext.la -BUILTIN_SRCS = \ - bigreq.c \ - geext.c \ - shape.c \ - sleepuntil.c \ - sleepuntil.h \ - sync.c \ - syncsdk.h \ - syncsrv.h \ - xcmisc.c \ - xtest.c - -# Sources always included in libXextmodule.la & libXext.la. That's right, zero. -MODULE_SRCS = -MODULE_LIBS = - -# Optional sources included if extension enabled by configure.ac rules - -# MIT Shared Memory extension -MITSHM_SRCS = shm.c shmint.h -if MITSHM -BUILTIN_SRCS += $(MITSHM_SRCS) -endif - -# XVideo extension -XV_SRCS = xvmain.c xvdisp.c xvmc.c xvdix.h xvmcext.h xvdisp.h -if XV -MODULE_SRCS += $(XV_SRCS) -endif - -# XResource extension: lets clients get data about per-client resource usage -RES_SRCS = xres.c -if RES -MODULE_SRCS += $(RES_SRCS) -endif - -# MIT ScreenSaver extension -SCREENSAVER_SRCS = saver.c -if SCREENSAVER -MODULE_SRCS += $(SCREENSAVER_SRCS) -endif - -# Xinerama extension: making multiple video devices act as one virtual screen -XINERAMA_SRCS = panoramiX.c panoramiX.h panoramiXh.h panoramiXsrv.h panoramiXprocs.c panoramiXSwap.c -if XINERAMA -BUILTIN_SRCS += $(XINERAMA_SRCS) -if XORG -sdk_HEADERS += panoramiXsrv.h panoramiX.h -endif -endif - -# X-ACE extension: provides hooks for building security policy extensions -# like XC-Security, X-SELinux & XTSol -XACE_SRCS = xace.c xace.h xacestr.h -if XACE -BUILTIN_SRCS += $(XACE_SRCS) -if XORG -sdk_HEADERS += xace.h xacestr.h -endif -endif - -# SELinux extension: provides SELinux policy support for X objects -# requires X-ACE extension -XSELINUX_SRCS = xselinux_ext.c xselinux_hooks.c xselinux_label.c xselinux.h xselinuxint.h -if XSELINUX -MODULE_SRCS += $(XSELINUX_SRCS) -MODULE_LIBS += $(SELINUX_LIBS) -endif - -# Security extension: multi-level security to protect clients from each other -XCSECURITY_SRCS = security.c securitysrv.h -if XCSECURITY -BUILTIN_SRCS += $(XCSECURITY_SRCS) -endif - -# XF86 Big Font extension -BIGFONT_SRCS = xf86bigfont.c xf86bigfontsrv.h -if XF86BIGFONT -BUILTIN_SRCS += $(BIGFONT_SRCS) -endif - -# DPMS extension -DPMS_SRCS = dpms.c dpmsproc.h -if DPMSExtension -MODULE_SRCS += $(DPMS_SRCS) -endif - -# Now take all of the above, mix well, bake for 10 minutes and get libXext*.la - -libXext_la_SOURCES = $(BUILTIN_SRCS) $(MODULE_SRCS) -libXext_la_LIBADD = $(MODULE_LIBS) - -if XORG -libXextbuiltin_la_SOURCES = $(BUILTIN_SRCS) - -libXextmodule_la_SOURCES = $(MODULE_SRCS) -libXextmodule_la_LIBADD = $(MODULE_LIBS) -endif - -EXTRA_DIST = \ - $(MITSHM_SRCS) \ - $(XV_SRCS) \ - $(RES_SRCS) \ - $(SCREENSAVER_SRCS) \ - $(XACE_SRCS) \ - $(XCSECURITY_SRCS) \ - $(XSELINUX_SRCS) \ - $(XINERAMA_SRCS) \ - $(BIGFONT_SRCS) \ - $(DPMS_SRCS) \ - $(GE_SRCS) - +# libXext.la: includes all extensions and should be linked into Xvfb,
+# Xnest, Xdmx and Xprt
+# libXextbuiltin.la: includes those extensions that are built directly into
+# Xorg by default
+# libXextmodule.la: includes those extensions that are built into a module
+# that Xorg loads
+if XORG
+noinst_LTLIBRARIES = libXext.la libXextbuiltin.la libXextmodule.la
+else
+noinst_LTLIBRARIES = libXext.la
+endif
+
+INCLUDES = -I$(top_srcdir)/hw/xfree86/dixmods/extmod
+
+AM_CFLAGS = $(DIX_CFLAGS)
+
+if XORG
+sdk_HEADERS = xvdix.h xvmcext.h geext.h geint.h shmint.h syncsdk.h
+endif
+
+# Sources always included in libXextbuiltin.la & libXext.la
+BUILTIN_SRCS = \
+ bigreq.c \
+ geext.c \
+ shape.c \
+ sleepuntil.c \
+ sleepuntil.h \
+ sync.c \
+ syncsdk.h \
+ syncsrv.h \
+ xcmisc.c \
+ xtest.c
+
+# Sources always included in libXextmodule.la & libXext.la. That's right, zero.
+MODULE_SRCS =
+MODULE_LIBS =
+
+# Optional sources included if extension enabled by configure.ac rules
+
+# MIT Shared Memory extension
+MITSHM_SRCS = shm.c shmint.h
+if MITSHM
+BUILTIN_SRCS += $(MITSHM_SRCS)
+endif
+
+# XVideo extension
+XV_SRCS = xvmain.c xvdisp.c xvmc.c xvdix.h xvmcext.h xvdisp.h
+if XV
+MODULE_SRCS += $(XV_SRCS)
+endif
+
+# XResource extension: lets clients get data about per-client resource usage
+RES_SRCS = xres.c
+if RES
+MODULE_SRCS += $(RES_SRCS)
+endif
+
+# MIT ScreenSaver extension
+SCREENSAVER_SRCS = saver.c
+if SCREENSAVER
+MODULE_SRCS += $(SCREENSAVER_SRCS)
+endif
+
+# Xinerama extension: making multiple video devices act as one virtual screen
+XINERAMA_SRCS = panoramiX.c panoramiX.h panoramiXh.h panoramiXsrv.h panoramiXprocs.c panoramiXSwap.c
+if XINERAMA
+BUILTIN_SRCS += $(XINERAMA_SRCS)
+if XORG
+sdk_HEADERS += panoramiXsrv.h panoramiX.h
+endif
+endif
+
+# X-ACE extension: provides hooks for building security policy extensions
+# like XC-Security, X-SELinux & XTSol
+XACE_SRCS = xace.c xace.h xacestr.h
+if XACE
+BUILTIN_SRCS += $(XACE_SRCS)
+if XORG
+sdk_HEADERS += xace.h xacestr.h
+endif
+endif
+
+# SELinux extension: provides SELinux policy support for X objects
+# requires X-ACE extension
+XSELINUX_SRCS = xselinux_ext.c xselinux_hooks.c xselinux_label.c xselinux.h xselinuxint.h
+if XSELINUX
+MODULE_SRCS += $(XSELINUX_SRCS)
+MODULE_LIBS += $(SELINUX_LIBS)
+endif
+
+# Security extension: multi-level security to protect clients from each other
+XCSECURITY_SRCS = security.c securitysrv.h
+if XCSECURITY
+BUILTIN_SRCS += $(XCSECURITY_SRCS)
+endif
+
+# XF86 Big Font extension
+BIGFONT_SRCS = xf86bigfont.c xf86bigfontsrv.h
+if XF86BIGFONT
+BUILTIN_SRCS += $(BIGFONT_SRCS)
+endif
+
+# DPMS extension
+DPMS_SRCS = dpms.c dpmsproc.h
+if DPMSExtension
+MODULE_SRCS += $(DPMS_SRCS)
+endif
+
+# Now take all of the above, mix well, bake for 10 minutes and get libXext*.la
+
+libXext_la_SOURCES = $(BUILTIN_SRCS) $(MODULE_SRCS)
+libXext_la_LIBADD = $(MODULE_LIBS)
+
+if XORG
+libXextbuiltin_la_SOURCES = $(BUILTIN_SRCS)
+
+libXextmodule_la_SOURCES = $(MODULE_SRCS)
+libXextmodule_la_LIBADD = $(MODULE_LIBS)
+endif
+
+EXTRA_DIST = \
+ $(MITSHM_SRCS) \
+ $(XV_SRCS) \
+ $(RES_SRCS) \
+ $(SCREENSAVER_SRCS) \
+ $(XACE_SRCS) \
+ $(XCSECURITY_SRCS) \
+ $(XSELINUX_SRCS) \
+ $(XINERAMA_SRCS) \
+ $(BIGFONT_SRCS) \
+ $(DPMS_SRCS) \
+ $(GE_SRCS)
+
diff --git a/xorg-server/Xext/dpms.c b/xorg-server/Xext/dpms.c index 13854f704..79b2e2944 100644 --- a/xorg-server/Xext/dpms.c +++ b/xorg-server/Xext/dpms.c @@ -28,6 +28,8 @@ Equipment Corporation. #ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
+#else
+#define DPMSExtension
#endif
#include <X11/X.h>
diff --git a/xorg-server/Xext/panoramiX.c b/xorg-server/Xext/panoramiX.c index 391346a6b..309c09cda 100644 --- a/xorg-server/Xext/panoramiX.c +++ b/xorg-server/Xext/panoramiX.c @@ -1,1299 +1,1299 @@ -/***************************************************************** -Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, -BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of Digital Equipment Corporation -shall not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization from Digital -Equipment Corporation. -******************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include <stdio.h> -#include <X11/X.h> -#include <X11/Xproto.h> -#include <X11/Xarch.h> -#include "misc.h" -#include "cursor.h" -#include "cursorstr.h" -#include "extnsionst.h" -#include "dixstruct.h" -#include "gc.h" -#include "gcstruct.h" -#include "scrnintstr.h" -#include "window.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "panoramiX.h" -#include <X11/extensions/panoramiXproto.h> -#include "panoramiXsrv.h" -#include "globals.h" -#include "servermd.h" -#include "resource.h" -#include "picturestr.h" -#ifdef XFIXES -#include "xfixesint.h" -#endif -#ifdef COMPOSITE -#include "compint.h" -#endif -#include "modinit.h" -#include "protocol-versions.h" - -#ifdef GLXPROXY -extern VisualPtr glxMatchVisual(ScreenPtr pScreen, - VisualPtr pVisual, - ScreenPtr pMatchScreen); -#endif - -/* - * PanoramiX data declarations - */ - -int PanoramiXPixWidth = 0; -int PanoramiXPixHeight = 0; -int PanoramiXNumScreens = 0; - -static RegionRec PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL}; - -static int PanoramiXNumDepths; -static DepthPtr PanoramiXDepths; -static int PanoramiXNumVisuals; -static VisualPtr PanoramiXVisuals; - -RESTYPE XRC_DRAWABLE; -RESTYPE XRT_WINDOW; -RESTYPE XRT_PIXMAP; -RESTYPE XRT_GC; -RESTYPE XRT_COLORMAP; - -static Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr); -XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr = &VisualsEqual; - -/* - * Function prototypes - */ - -static int panoramiXGeneration; -static int ProcPanoramiXDispatch(ClientPtr client); - -static void PanoramiXResetProc(ExtensionEntry*); - -/* - * External references for functions and data variables - */ - -#include "panoramiXh.h" - -int (* SavedProcVector[256]) (ClientPtr client) = { NULL, }; - -static DevPrivateKeyRec PanoramiXGCKeyRec; -#define PanoramiXGCKey (&PanoramiXGCKeyRec) -static DevPrivateKeyRec PanoramiXScreenKeyRec; -#define PanoramiXScreenKey (&PanoramiXScreenKeyRec) - -typedef struct { - DDXPointRec clipOrg; - DDXPointRec patOrg; - GCFuncs *wrapFuncs; -} PanoramiXGCRec, *PanoramiXGCPtr; - -typedef struct { - CreateGCProcPtr CreateGC; - CloseScreenProcPtr CloseScreen; -} PanoramiXScreenRec, *PanoramiXScreenPtr; - -static void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr); -static void XineramaChangeGC(GCPtr, unsigned long); -static void XineramaCopyGC(GCPtr, unsigned long, GCPtr); -static void XineramaDestroyGC(GCPtr); -static void XineramaChangeClip(GCPtr, int, pointer, int); -static void XineramaDestroyClip(GCPtr); -static void XineramaCopyClip(GCPtr, GCPtr); - -static GCFuncs XineramaGCFuncs = { - XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC, - XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip -}; - -#define Xinerama_GC_FUNC_PROLOGUE(pGC)\ - PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) \ - dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \ - (pGC)->funcs = pGCPriv->wrapFuncs; - -#define Xinerama_GC_FUNC_EPILOGUE(pGC)\ - pGCPriv->wrapFuncs = (pGC)->funcs;\ - (pGC)->funcs = &XineramaGCFuncs; - - -static Bool -XineramaCloseScreen (int i, ScreenPtr pScreen) -{ - PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr) - dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - pScreen->CreateGC = pScreenPriv->CreateGC; - - if (pScreen->myNum == 0) - RegionUninit(&PanoramiXScreenRegion); - - free((pointer) pScreenPriv); - - return (*pScreen->CloseScreen) (i, pScreen); -} - -static Bool -XineramaCreateGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr) - dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey); - Bool ret; - - pScreen->CreateGC = pScreenPriv->CreateGC; - if((ret = (*pScreen->CreateGC)(pGC))) { - PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) - dixLookupPrivate(&pGC->devPrivates, PanoramiXGCKey); - - pGCPriv->wrapFuncs = pGC->funcs; - pGC->funcs = &XineramaGCFuncs; - - pGCPriv->clipOrg.x = pGC->clipOrg.x; - pGCPriv->clipOrg.y = pGC->clipOrg.y; - pGCPriv->patOrg.x = pGC->patOrg.x; - pGCPriv->patOrg.y = pGC->patOrg.y; - } - pScreen->CreateGC = XineramaCreateGC; - - return ret; -} - -static void -XineramaValidateGC( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -){ - Xinerama_GC_FUNC_PROLOGUE (pGC); - - if((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr)pDraw)->parent)) { - /* the root window */ - int x_off = pGC->pScreen->x; - int y_off = pGC->pScreen->y; - int new_val; - - new_val = pGCPriv->clipOrg.x - x_off; - if(pGC->clipOrg.x != new_val) { - pGC->clipOrg.x = new_val; - changes |= GCClipXOrigin; - } - new_val = pGCPriv->clipOrg.y - y_off; - if(pGC->clipOrg.y != new_val) { - pGC->clipOrg.y = new_val; - changes |= GCClipYOrigin; - } - new_val = pGCPriv->patOrg.x - x_off; - if(pGC->patOrg.x != new_val) { - pGC->patOrg.x = new_val; - changes |= GCTileStipXOrigin; - } - new_val = pGCPriv->patOrg.y - y_off; - if(pGC->patOrg.y != new_val) { - pGC->patOrg.y = new_val; - changes |= GCTileStipYOrigin; - } - } else { - if(pGC->clipOrg.x != pGCPriv->clipOrg.x) { - pGC->clipOrg.x = pGCPriv->clipOrg.x; - changes |= GCClipXOrigin; - } - if(pGC->clipOrg.y != pGCPriv->clipOrg.y) { - pGC->clipOrg.y = pGCPriv->clipOrg.y; - changes |= GCClipYOrigin; - } - if(pGC->patOrg.x != pGCPriv->patOrg.x) { - pGC->patOrg.x = pGCPriv->patOrg.x; - changes |= GCTileStipXOrigin; - } - if(pGC->patOrg.y != pGCPriv->patOrg.y) { - pGC->patOrg.y = pGCPriv->patOrg.y; - changes |= GCTileStipYOrigin; - } - } - - (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaDestroyGC(GCPtr pGC) -{ - Xinerama_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->DestroyGC)(pGC); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaChangeGC ( - GCPtr pGC, - unsigned long mask -){ - Xinerama_GC_FUNC_PROLOGUE (pGC); - - if(mask & GCTileStipXOrigin) - pGCPriv->patOrg.x = pGC->patOrg.x; - if(mask & GCTileStipYOrigin) - pGCPriv->patOrg.y = pGC->patOrg.y; - if(mask & GCClipXOrigin) - pGCPriv->clipOrg.x = pGC->clipOrg.x; - if(mask & GCClipYOrigin) - pGCPriv->clipOrg.y = pGC->clipOrg.y; - - (*pGC->funcs->ChangeGC) (pGC, mask); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaCopyGC ( - GCPtr pGCSrc, - unsigned long mask, - GCPtr pGCDst -){ - PanoramiXGCPtr pSrcPriv = (PanoramiXGCPtr) - dixLookupPrivate(&pGCSrc->devPrivates, PanoramiXGCKey); - Xinerama_GC_FUNC_PROLOGUE (pGCDst); - - if(mask & GCTileStipXOrigin) - pGCPriv->patOrg.x = pSrcPriv->patOrg.x; - if(mask & GCTileStipYOrigin) - pGCPriv->patOrg.y = pSrcPriv->patOrg.y; - if(mask & GCClipXOrigin) - pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x; - if(mask & GCClipYOrigin) - pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y; - - (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); - Xinerama_GC_FUNC_EPILOGUE (pGCDst); -} - -static void -XineramaChangeClip ( - GCPtr pGC, - int type, - pointer pvalue, - int nrects -){ - Xinerama_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc) -{ - Xinerama_GC_FUNC_PROLOGUE (pgcDst); - (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); - Xinerama_GC_FUNC_EPILOGUE (pgcDst); -} - -static void -XineramaDestroyClip(GCPtr pGC) -{ - Xinerama_GC_FUNC_PROLOGUE (pGC); - (* pGC->funcs->DestroyClip)(pGC); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -int -XineramaDeleteResource(pointer data, XID id) -{ - free(data); - return 1; -} - -typedef struct { - int screen; - int id; -} PanoramiXSearchData; - -static Bool -XineramaFindIDByScrnum(pointer resource, XID id, pointer privdata) -{ - PanoramiXRes *res = (PanoramiXRes*)resource; - PanoramiXSearchData *data = (PanoramiXSearchData*)privdata; - - return res->info[data->screen].id == data->id; -} - -PanoramiXRes * -PanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen) -{ - PanoramiXSearchData data; - pointer val; - - if(!screen) { - dixLookupResourceByType(&val, id, type, serverClient, DixReadAccess); - return val; - } - - data.screen = screen; - data.id = id; - - return LookupClientResourceComplex(clients[CLIENT_ID(id)], type, - XineramaFindIDByScrnum, &data); -} - -typedef struct _connect_callback_list { - void (*func)(void); - struct _connect_callback_list *next; -} XineramaConnectionCallbackList; - -static XineramaConnectionCallbackList *ConnectionCallbackList = NULL; - -Bool -XineramaRegisterConnectionBlockCallback(void (*func)(void)) -{ - XineramaConnectionCallbackList *newlist; - - if(!(newlist = malloc(sizeof(XineramaConnectionCallbackList)))) - return FALSE; - - newlist->next = ConnectionCallbackList; - newlist->func = func; - ConnectionCallbackList = newlist; - - return TRUE; -} - -static void XineramaInitData(ScreenPtr pScreen) -{ - int i, w, h; - - RegionNull(&PanoramiXScreenRegion); - for (i = 0; i < PanoramiXNumScreens; i++) { - BoxRec TheBox; - RegionRec ScreenRegion; - - pScreen = screenInfo.screens[i]; - - TheBox.x1 = pScreen->x; - TheBox.x2 = TheBox.x1 + pScreen->width; - TheBox.y1 = pScreen->y; - TheBox.y2 = TheBox.y1 + pScreen->height; - - RegionInit(&ScreenRegion, &TheBox, 1); - RegionUnion(&PanoramiXScreenRegion, &PanoramiXScreenRegion, - &ScreenRegion); - RegionUninit(&ScreenRegion); - } - - PanoramiXPixWidth = screenInfo.screens[0]->x + screenInfo.screens[0]->width; - PanoramiXPixHeight = screenInfo.screens[0]->y + screenInfo.screens[0]->height; - - for (i = 1; i < PanoramiXNumScreens; i++) { - pScreen = screenInfo.screens[i]; - w = pScreen->x + pScreen->width; - h = pScreen->y + pScreen->height; - - if (PanoramiXPixWidth < w) - PanoramiXPixWidth = w; - if (PanoramiXPixHeight < h) - PanoramiXPixHeight = h; - } -} - -void XineramaReinitData(ScreenPtr pScreen) -{ - RegionUninit(&PanoramiXScreenRegion); - XineramaInitData(pScreen); -} - -/* - * PanoramiXExtensionInit(): - * Called from InitExtensions in main(). - * Register PanoramiXeen Extension - * Initialize global variables. - */ - -void PanoramiXExtensionInit(int argc, char *argv[]) -{ - int i; - Bool success = FALSE; - ExtensionEntry *extEntry; - ScreenPtr pScreen = screenInfo.screens[0]; - PanoramiXScreenPtr pScreenPriv; - - if (noPanoramiXExtension) - return; - - if (!dixRegisterPrivateKey(&PanoramiXScreenKeyRec, PRIVATE_SCREEN, 0)) { - noPanoramiXExtension = TRUE; - return; - } - - if (!dixRegisterPrivateKey(&PanoramiXGCKeyRec, PRIVATE_GC, sizeof(PanoramiXGCRec))) { - noPanoramiXExtension = TRUE; - return; - } - - PanoramiXNumScreens = screenInfo.numScreens; - if (PanoramiXNumScreens == 1) { /* Only 1 screen */ - noPanoramiXExtension = TRUE; - return; - } - - while (panoramiXGeneration != serverGeneration) { - extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, - ProcPanoramiXDispatch, - SProcPanoramiXDispatch, PanoramiXResetProc, - StandardMinorOpcode); - if (!extEntry) - break; - - /* - * First make sure all the basic allocations succeed. If not, - * run in non-PanoramiXeen mode. - */ - - for (i = 0; i < PanoramiXNumScreens; i++) { - pScreen = screenInfo.screens[i]; - pScreenPriv = malloc(sizeof(PanoramiXScreenRec)); - dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey, - pScreenPriv); - if(!pScreenPriv) { - noPanoramiXExtension = TRUE; - return; - } - - pScreenPriv->CreateGC = pScreen->CreateGC; - pScreenPriv->CloseScreen = pScreen->CloseScreen; - - pScreen->CreateGC = XineramaCreateGC; - pScreen->CloseScreen = XineramaCloseScreen; - } - - XRC_DRAWABLE = CreateNewResourceClass(); - XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource, - "XineramaWindow"); - if (XRT_WINDOW) - XRT_WINDOW |= XRC_DRAWABLE; - XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource, - "XineramaPixmap"); - if (XRT_PIXMAP) - XRT_PIXMAP |= XRC_DRAWABLE; - XRT_GC = CreateNewResourceType(XineramaDeleteResource, - "XineramaGC"); - XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource, - "XineramaColormap"); - - if (XRT_WINDOW && XRT_PIXMAP && XRT_GC && XRT_COLORMAP) { - panoramiXGeneration = serverGeneration; - success = TRUE; - } - SetResourceTypeErrorValue(XRT_WINDOW, BadWindow); - SetResourceTypeErrorValue(XRT_PIXMAP, BadPixmap); - SetResourceTypeErrorValue(XRT_GC, BadGC); - SetResourceTypeErrorValue(XRT_COLORMAP, BadColor); - } - - if (!success) { - noPanoramiXExtension = TRUE; - ErrorF(PANORAMIX_PROTOCOL_NAME " extension failed to initialize\n"); - return; - } - - XineramaInitData(pScreen); - - /* - * Put our processes into the ProcVector - */ - - for (i = 256; i--; ) - SavedProcVector[i] = ProcVector[i]; - - ProcVector[X_CreateWindow] = PanoramiXCreateWindow; - ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes; - ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow; - ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows; - ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet; - ProcVector[X_ReparentWindow] = PanoramiXReparentWindow; - ProcVector[X_MapWindow] = PanoramiXMapWindow; - ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows; - ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow; - ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows; - ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow; - ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow; - ProcVector[X_GetGeometry] = PanoramiXGetGeometry; - ProcVector[X_TranslateCoords] = PanoramiXTranslateCoords; - ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap; - ProcVector[X_FreePixmap] = PanoramiXFreePixmap; - ProcVector[X_CreateGC] = PanoramiXCreateGC; - ProcVector[X_ChangeGC] = PanoramiXChangeGC; - ProcVector[X_CopyGC] = PanoramiXCopyGC; - ProcVector[X_SetDashes] = PanoramiXSetDashes; - ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles; - ProcVector[X_FreeGC] = PanoramiXFreeGC; - ProcVector[X_ClearArea] = PanoramiXClearToBackground; - ProcVector[X_CopyArea] = PanoramiXCopyArea; - ProcVector[X_CopyPlane] = PanoramiXCopyPlane; - ProcVector[X_PolyPoint] = PanoramiXPolyPoint; - ProcVector[X_PolyLine] = PanoramiXPolyLine; - ProcVector[X_PolySegment] = PanoramiXPolySegment; - ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle; - ProcVector[X_PolyArc] = PanoramiXPolyArc; - ProcVector[X_FillPoly] = PanoramiXFillPoly; - ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle; - ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc; - ProcVector[X_PutImage] = PanoramiXPutImage; - ProcVector[X_GetImage] = PanoramiXGetImage; - ProcVector[X_PolyText8] = PanoramiXPolyText8; - ProcVector[X_PolyText16] = PanoramiXPolyText16; - ProcVector[X_ImageText8] = PanoramiXImageText8; - ProcVector[X_ImageText16] = PanoramiXImageText16; - ProcVector[X_CreateColormap] = PanoramiXCreateColormap; - ProcVector[X_FreeColormap] = PanoramiXFreeColormap; - ProcVector[X_CopyColormapAndFree] = PanoramiXCopyColormapAndFree; - ProcVector[X_InstallColormap] = PanoramiXInstallColormap; - ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap; - ProcVector[X_AllocColor] = PanoramiXAllocColor; - ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor; - ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells; - ProcVector[X_AllocColorPlanes] = PanoramiXAllocColorPlanes; - ProcVector[X_FreeColors] = PanoramiXFreeColors; - ProcVector[X_StoreColors] = PanoramiXStoreColors; - ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor; - - PanoramiXRenderInit (); -#ifdef XFIXES - PanoramiXFixesInit (); -#endif -#ifdef COMPOSITE - PanoramiXCompositeInit (); -#endif - -} - -extern Bool CreateConnectionBlock(void); - -Bool PanoramiXCreateConnectionBlock(void) -{ - int i, j, length; - Bool disableBackingStore = FALSE; - int old_width, old_height; - float width_mult, height_mult; - xWindowRoot *root; - xVisualType *visual; - xDepth *depth; - VisualPtr pVisual; - ScreenPtr pScreen; - - /* - * Do normal CreateConnectionBlock but faking it for only one screen - */ - - if(!PanoramiXNumDepths) { - ErrorF("Xinerama error: No common visuals\n"); - return FALSE; - } - - for(i = 1; i < screenInfo.numScreens; i++) { - pScreen = screenInfo.screens[i]; - if(pScreen->rootDepth != screenInfo.screens[0]->rootDepth) { - ErrorF("Xinerama error: Root window depths differ\n"); - return FALSE; - } - if(pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport) - disableBackingStore = TRUE; - } - - if (disableBackingStore) { - for (i = 0; i < screenInfo.numScreens; i++) { - pScreen = screenInfo.screens[i]; - pScreen->backingStoreSupport = NotUseful; - } - } - - i = screenInfo.numScreens; - screenInfo.numScreens = 1; - if (!CreateConnectionBlock()) { - screenInfo.numScreens = i; - return FALSE; - } - - screenInfo.numScreens = i; - - root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart); - length = connBlockScreenStart + sizeof(xWindowRoot); - - /* overwrite the connection block */ - root->nDepths = PanoramiXNumDepths; - - for (i = 0; i < PanoramiXNumDepths; i++) { - depth = (xDepth *) (ConnectionInfo + length); - depth->depth = PanoramiXDepths[i].depth; - depth->nVisuals = PanoramiXDepths[i].numVids; - length += sizeof(xDepth); - visual = (xVisualType *)(ConnectionInfo + length); - - for (j = 0; j < depth->nVisuals; j++, visual++) { - visual->visualID = PanoramiXDepths[i].vids[j]; - - for (pVisual = PanoramiXVisuals; - pVisual->vid != visual->visualID; - pVisual++) - ; - - visual->class = pVisual->class; - visual->bitsPerRGB = pVisual->bitsPerRGBValue; - visual->colormapEntries = pVisual->ColormapEntries; - visual->redMask = pVisual->redMask; - visual->greenMask = pVisual->greenMask; - visual->blueMask = pVisual->blueMask; - } - - length += (depth->nVisuals * sizeof(xVisualType)); - } - - connSetupPrefix.length = bytes_to_int32(length); - - for (i = 0; i < PanoramiXNumDepths; i++) - free(PanoramiXDepths[i].vids); - free(PanoramiXDepths); - PanoramiXDepths = NULL; - - /* - * OK, change some dimensions so it looks as if it were one big screen - */ - - old_width = root->pixWidth; - old_height = root->pixHeight; - - root->pixWidth = PanoramiXPixWidth; - root->pixHeight = PanoramiXPixHeight; - width_mult = (1.0 * root->pixWidth) / old_width; - height_mult = (1.0 * root->pixHeight) / old_height; - root->mmWidth *= width_mult; - root->mmHeight *= height_mult; - - while(ConnectionCallbackList) { - pointer tmp; - - tmp = (pointer)ConnectionCallbackList; - (*ConnectionCallbackList->func)(); - ConnectionCallbackList = ConnectionCallbackList->next; - free(tmp); - } - - return TRUE; -} - -/* - * This isn't just memcmp(), bitsPerRGBValue is skipped. markv made that - * change way back before xf86 4.0, but the comment for _why_ is a bit - * opaque, so I'm not going to question it for now. - * - * This is probably better done as a screen hook so DBE/EVI/GLX can add - * their own tests, and adding privates to VisualRec so they don't have to - * do their own back-mapping. - */ -static Bool -VisualsEqual(VisualPtr a, ScreenPtr pScreenB, VisualPtr b) -{ - return ((a->class == b->class) && - (a->ColormapEntries == b->ColormapEntries) && - (a->nplanes == b->nplanes) && - (a->redMask == b->redMask) && - (a->greenMask == b->greenMask) && - (a->blueMask == b->blueMask) && - (a->offsetRed == b->offsetRed) && - (a->offsetGreen == b->offsetGreen) && - (a->offsetBlue == b->offsetBlue)); -} - -static void -PanoramiXMaybeAddDepth(DepthPtr pDepth) -{ - ScreenPtr pScreen; - int j, k; - Bool found = FALSE; - - for (j = 1; j < PanoramiXNumScreens; j++) { - pScreen = screenInfo.screens[j]; - for (k = 0; k < pScreen->numDepths; k++) { - if (pScreen->allowedDepths[k].depth == pDepth->depth) { - found = TRUE; - break; - } - } - } - - if (!found) - return; - - j = PanoramiXNumDepths; - PanoramiXNumDepths++; - PanoramiXDepths = realloc(PanoramiXDepths, - PanoramiXNumDepths * sizeof(DepthRec)); - PanoramiXDepths[j].depth = pDepth->depth; - PanoramiXDepths[j].numVids = 0; - /* XXX suboptimal, should grow these dynamically */ - if(pDepth->numVids) - PanoramiXDepths[j].vids = malloc(sizeof(VisualID) * pDepth->numVids); - else - PanoramiXDepths[j].vids = NULL; -} - -static void -PanoramiXMaybeAddVisual(VisualPtr pVisual) -{ - ScreenPtr pScreen; - int j, k; - Bool found = FALSE; - - for (j = 1; j < PanoramiXNumScreens; j++) { - pScreen = screenInfo.screens[j]; - found = FALSE; - - for (k = 0; k < pScreen->numVisuals; k++) { - VisualPtr candidate = &pScreen->visuals[k]; - - if ((*XineramaVisualsEqualPtr)(pVisual, pScreen, candidate) -#ifdef GLXPROXY - && glxMatchVisual(screenInfo.screens[0], pVisual, pScreen) -#endif - ) { - found = TRUE; - break; - } - } - - if (!found) - return; - } - - /* found a matching visual on all screens, add it to the subset list */ - j = PanoramiXNumVisuals; - PanoramiXNumVisuals++; - PanoramiXVisuals = realloc(PanoramiXVisuals, - PanoramiXNumVisuals * sizeof(VisualRec)); - - memcpy(&PanoramiXVisuals[j], pVisual, sizeof(VisualRec)); - - for (k = 0; k < PanoramiXNumDepths; k++) { - if (PanoramiXDepths[k].depth == pVisual->nplanes) { - PanoramiXDepths[k].vids[PanoramiXDepths[k].numVids] = pVisual->vid; - PanoramiXDepths[k].numVids++; - break; - } - } -} - -extern void -PanoramiXConsolidate(void) -{ - int i; - PanoramiXRes *root, *defmap, *saver; - ScreenPtr pScreen = screenInfo.screens[0]; - DepthPtr pDepth = pScreen->allowedDepths; - VisualPtr pVisual = pScreen->visuals; - - PanoramiXNumDepths = 0; - PanoramiXNumVisuals = 0; - - for (i = 0; i < pScreen->numDepths; i++) - PanoramiXMaybeAddDepth(pDepth++); - - for (i = 0; i < pScreen->numVisuals; i++) - PanoramiXMaybeAddVisual(pVisual++); - - root = malloc(sizeof(PanoramiXRes)); - root->type = XRT_WINDOW; - defmap = malloc(sizeof(PanoramiXRes)); - defmap->type = XRT_COLORMAP; - saver = malloc(sizeof(PanoramiXRes)); - saver->type = XRT_WINDOW; - - for (i = 0; i < PanoramiXNumScreens; i++) { - ScreenPtr pScreen = screenInfo.screens[i]; - root->info[i].id = pScreen->root->drawable.id; - root->u.win.class = InputOutput; - root->u.win.root = TRUE; - saver->info[i].id = pScreen->screensaver.wid; - saver->u.win.class = InputOutput; - saver->u.win.root = TRUE; - defmap->info[i].id = pScreen->defColormap; - } - - AddResource(root->info[0].id, XRT_WINDOW, root); - AddResource(saver->info[0].id, XRT_WINDOW, saver); - AddResource(defmap->info[0].id, XRT_COLORMAP, defmap); -} - -VisualID -PanoramiXTranslateVisualID(int screen, VisualID orig) -{ - ScreenPtr pOtherScreen = screenInfo.screens[screen]; - VisualPtr pVisual = NULL; - int i; - - for (i = 0; i < PanoramiXNumVisuals; i++) { - if (orig == PanoramiXVisuals[i].vid) { - pVisual = &PanoramiXVisuals[i]; - break; - } - } - - if (!pVisual) - return 0; - - /* if screen is 0, orig is already the correct visual ID */ - if (screen == 0) - return orig; - - /* found the original, now translate it relative to the backend screen */ - for (i = 0; i < pOtherScreen->numVisuals; i++) { - VisualPtr pOtherVisual = &pOtherScreen->visuals[i]; - - if ((*XineramaVisualsEqualPtr)(pVisual, pOtherScreen, pOtherVisual)) - return pOtherVisual->vid; - } - - return 0; -} - - -/* - * PanoramiXResetProc() - * Exit, deallocating as needed. - */ - -static void PanoramiXResetProc(ExtensionEntry* extEntry) -{ - int i; - - PanoramiXRenderReset (); -#ifdef XFIXES - PanoramiXFixesReset (); -#endif - screenInfo.numScreens = PanoramiXNumScreens; - for (i = 256; i--; ) - ProcVector[i] = SavedProcVector[i]; -} - - -int -ProcPanoramiXQueryVersion (ClientPtr client) -{ - /* REQUEST(xPanoramiXQueryVersionReq); */ - xPanoramiXQueryVersionReply rep; - register int n; - - REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_PANORAMIX_MAJOR_VERSION; - rep.minorVersion = SERVER_PANORAMIX_MINOR_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep); - return Success; -} - -int -ProcPanoramiXGetState(ClientPtr client) -{ - REQUEST(xPanoramiXGetStateReq); - WindowPtr pWin; - xPanoramiXGetStateReply rep; - int n, rc; - - REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.state = !noPanoramiXExtension; - rep.window = stuff->window; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.window, n); - } - WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep); - return Success; - -} - -int -ProcPanoramiXGetScreenCount(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenCountReq); - WindowPtr pWin; - xPanoramiXGetScreenCountReply rep; - int n, rc; - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.ScreenCount = PanoramiXNumScreens; - rep.window = stuff->window; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.window, n); - } - WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep); - return Success; -} - -int -ProcPanoramiXGetScreenSize(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenSizeReq); - WindowPtr pWin; - xPanoramiXGetScreenSizeReply rep; - int n, rc; - - if (stuff->screen >= PanoramiXNumScreens) - return BadMatch; - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - /* screen dimensions */ - rep.width = screenInfo.screens[stuff->screen]->width; - rep.height = screenInfo.screens[stuff->screen]->height; - rep.window = stuff->window; - rep.screen = stuff->screen; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.width, n); - swapl (&rep.height, n); - swapl (&rep.window, n); - swapl (&rep.screen, n); - } - WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep); - return Success; -} - - -int -ProcXineramaIsActive(ClientPtr client) -{ - /* REQUEST(xXineramaIsActiveReq); */ - xXineramaIsActiveReply rep; - - REQUEST_SIZE_MATCH(xXineramaIsActiveReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; -#if 1 - { - /* The following hack fools clients into thinking that Xinerama - * is disabled even though it is not. */ - rep.state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack; - } -#else - rep.state = !noPanoramiXExtension; -#endif - if (client->swapped) { - int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.state, n); - } - WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep); - return Success; -} - - -int -ProcXineramaQueryScreens(ClientPtr client) -{ - /* REQUEST(xXineramaQueryScreensReq); */ - xXineramaQueryScreensReply rep; - - REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens; - rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo); - if (client->swapped) { - int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.number, n); - } - WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep); - - if(!noPanoramiXExtension) { - xXineramaScreenInfo scratch; - int i; - - for(i = 0; i < PanoramiXNumScreens; i++) { - scratch.x_org = screenInfo.screens[i]->x; - scratch.y_org = screenInfo.screens[i]->y; - scratch.width = screenInfo.screens[i]->width; - scratch.height = screenInfo.screens[i]->height; - - if(client->swapped) { - int n; - swaps (&scratch.x_org, n); - swaps (&scratch.y_org, n); - swaps (&scratch.width, n); - swaps (&scratch.height, n); - } - WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch); - } - } - - return Success; -} - - -static int -ProcPanoramiXDispatch (ClientPtr client) -{ REQUEST(xReq); - switch (stuff->data) - { - case X_PanoramiXQueryVersion: - return ProcPanoramiXQueryVersion(client); - case X_PanoramiXGetState: - return ProcPanoramiXGetState(client); - case X_PanoramiXGetScreenCount: - return ProcPanoramiXGetScreenCount(client); - case X_PanoramiXGetScreenSize: - return ProcPanoramiXGetScreenSize(client); - case X_XineramaIsActive: - return ProcXineramaIsActive(client); - case X_XineramaQueryScreens: - return ProcXineramaQueryScreens(client); - } - return BadRequest; -} - - -#if X_BYTE_ORDER == X_LITTLE_ENDIAN -#define SHIFT_L(v,s) (v) << (s) -#define SHIFT_R(v,s) (v) >> (s) -#else -#define SHIFT_L(v,s) (v) >> (s) -#define SHIFT_R(v,s) (v) << (s) -#endif - -static void -CopyBits(char *dst, int shiftL, char *src, int bytes) -{ - /* Just get it to work. Worry about speed later */ - int shiftR = 8 - shiftL; - - while(bytes--) { - *dst |= SHIFT_L(*src, shiftL); - *(dst + 1) |= SHIFT_R(*src, shiftR); - dst++; src++; - } -} - - -/* Caution. This doesn't support 2 and 4 bpp formats. We expect - 1 bpp and planar data to be already cleared when presented - to this function */ - -void -XineramaGetImageData( - DrawablePtr *pDrawables, - int left, - int top, - int width, - int height, - unsigned int format, - unsigned long planemask, - char *data, - int pitch, - Bool isRoot -){ - RegionRec SrcRegion, ScreenRegion, GrabRegion; - BoxRec SrcBox, *pbox; - int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth; - DrawablePtr pDraw = pDrawables[0]; - char *ScratchMem = NULL; - - size = 0; - - /* find box in logical screen space */ - SrcBox.x1 = left; - SrcBox.y1 = top; - if(!isRoot) { - SrcBox.x1 += pDraw->x + screenInfo.screens[0]->x; - SrcBox.y1 += pDraw->y + screenInfo.screens[0]->y; - } - SrcBox.x2 = SrcBox.x1 + width; - SrcBox.y2 = SrcBox.y1 + height; - - RegionInit(&SrcRegion, &SrcBox, 1); - RegionNull(&GrabRegion); - - depth = (format == XYPixmap) ? 1 : pDraw->depth; - - for(i = 0; i < PanoramiXNumScreens; i++) { - BoxRec TheBox; - ScreenPtr pScreen; - pDraw = pDrawables[i]; - pScreen = pDraw->pScreen; - - TheBox.x1 = pScreen->x; - TheBox.x2 = TheBox.x1 + pScreen->width; - TheBox.y1 = pScreen->y; - TheBox.y2 = TheBox.y1 + pScreen->height; - - RegionInit(&ScreenRegion, &TheBox, 1); - inOut = RegionContainsRect(&ScreenRegion, &SrcBox); - if(inOut == rgnPART) - RegionIntersect(&GrabRegion, &SrcRegion, &ScreenRegion); - RegionUninit(&ScreenRegion); - - if(inOut == rgnIN) { - (*pScreen->GetImage)(pDraw, - SrcBox.x1 - pDraw->x - screenInfo.screens[i]->x, - SrcBox.y1 - pDraw->y - screenInfo.screens[i]->y, - width, height, format, planemask, data); - break; - } else if (inOut == rgnOUT) - continue; - - nbox = RegionNumRects(&GrabRegion); - - if(nbox) { - pbox = RegionRects(&GrabRegion); - - while(nbox--) { - w = pbox->x2 - pbox->x1; - h = pbox->y2 - pbox->y1; - ScratchPitch = PixmapBytePad(w, depth); - sizeNeeded = ScratchPitch * h; - - if(sizeNeeded > size) { - char *tmpdata = ScratchMem; - ScratchMem = realloc(ScratchMem, sizeNeeded); - if(ScratchMem) - size = sizeNeeded; - else { - ScratchMem = tmpdata; - break; - } - } - - x = pbox->x1 - pDraw->x - screenInfo.screens[i]->x; - y = pbox->y1 - pDraw->y - screenInfo.screens[i]->y; - - (*pScreen->GetImage)(pDraw, x, y, w, h, - format, planemask, ScratchMem); - - /* copy the memory over */ - - if(depth == 1) { - int k, shift, leftover, index, index2; - - x = pbox->x1 - SrcBox.x1; - y = pbox->y1 - SrcBox.y1; - shift = x & 7; - x >>= 3; - leftover = w & 7; - w >>= 3; - - /* clean up the edge */ - if(leftover) { - int mask = (1 << leftover) - 1; - for(j = h, k = w; j--; k += ScratchPitch) - ScratchMem[k] &= mask; - } - - for(j = 0, index = (pitch * y) + x, index2 = 0; j < h; - j++, index += pitch, index2 += ScratchPitch) - { - if(w) { - if(!shift) - memcpy(data + index, ScratchMem + index2, w); - else - CopyBits(data + index, shift, - ScratchMem + index2, w); - } - - if(leftover) { - data[index + w] |= - SHIFT_L(ScratchMem[index2 + w], shift); - if((shift + leftover) > 8) - data[index + w + 1] |= - SHIFT_R(ScratchMem[index2 + w],(8 - shift)); - } - } - } else { - j = BitsPerPixel(depth) >> 3; - x = (pbox->x1 - SrcBox.x1) * j; - y = pbox->y1 - SrcBox.y1; - w *= j; - - for(j = 0; j < h; j++) { - memcpy(data + (pitch * (y + j)) + x, - ScratchMem + (ScratchPitch * j), w); - } - } - pbox++; - } - - RegionSubtract(&SrcRegion, &SrcRegion, &GrabRegion); - if(!RegionNotEmpty(&SrcRegion)) - break; - } - - } - - free(ScratchMem); - - RegionUninit(&SrcRegion); - RegionUninit(&GrabRegion); -} +/*****************************************************************
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include <stdio.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xarch.h>
+#include "misc.h"
+#include "cursor.h"
+#include "cursorstr.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "gc.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#include "window.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "panoramiX.h"
+#include <X11/extensions/panoramiXproto.h>
+#include "panoramiXsrv.h"
+#include "globals.h"
+#include "servermd.h"
+#include "resource.h"
+#include "picturestr.h"
+#ifdef XFIXES
+#include "xfixesint.h"
+#endif
+#ifdef COMPOSITE
+#include "compint.h"
+#endif
+#include "modinit.h"
+#include "protocol-versions.h"
+
+#ifdef GLXPROXY
+extern VisualPtr glxMatchVisual(ScreenPtr pScreen,
+ VisualPtr pVisual,
+ ScreenPtr pMatchScreen);
+#endif
+
+/*
+ * PanoramiX data declarations
+ */
+
+int PanoramiXPixWidth = 0;
+int PanoramiXPixHeight = 0;
+int PanoramiXNumScreens = 0;
+
+static RegionRec PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL};
+
+static int PanoramiXNumDepths;
+static DepthPtr PanoramiXDepths;
+static int PanoramiXNumVisuals;
+static VisualPtr PanoramiXVisuals;
+
+RESTYPE XRC_DRAWABLE;
+RESTYPE XRT_WINDOW;
+RESTYPE XRT_PIXMAP;
+RESTYPE XRT_GC;
+RESTYPE XRT_COLORMAP;
+
+static Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr);
+XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr = &VisualsEqual;
+
+/*
+ * Function prototypes
+ */
+
+static int panoramiXGeneration;
+static int ProcPanoramiXDispatch(ClientPtr client);
+
+static void PanoramiXResetProc(ExtensionEntry*);
+
+/*
+ * External references for functions and data variables
+ */
+
+#include "panoramiXh.h"
+
+int (* SavedProcVector[256]) (ClientPtr client) = { NULL, };
+
+static DevPrivateKeyRec PanoramiXGCKeyRec;
+#define PanoramiXGCKey (&PanoramiXGCKeyRec)
+static DevPrivateKeyRec PanoramiXScreenKeyRec;
+#define PanoramiXScreenKey (&PanoramiXScreenKeyRec)
+
+typedef struct {
+ DDXPointRec clipOrg;
+ DDXPointRec patOrg;
+ GCFuncs *wrapFuncs;
+} PanoramiXGCRec, *PanoramiXGCPtr;
+
+typedef struct {
+ CreateGCProcPtr CreateGC;
+ CloseScreenProcPtr CloseScreen;
+} PanoramiXScreenRec, *PanoramiXScreenPtr;
+
+static void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr);
+static void XineramaChangeGC(GCPtr, unsigned long);
+static void XineramaCopyGC(GCPtr, unsigned long, GCPtr);
+static void XineramaDestroyGC(GCPtr);
+static void XineramaChangeClip(GCPtr, int, pointer, int);
+static void XineramaDestroyClip(GCPtr);
+static void XineramaCopyClip(GCPtr, GCPtr);
+
+static GCFuncs XineramaGCFuncs = {
+ XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC,
+ XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip
+};
+
+#define Xinerama_GC_FUNC_PROLOGUE(pGC)\
+ PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) \
+ dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \
+ (pGC)->funcs = pGCPriv->wrapFuncs;
+
+#define Xinerama_GC_FUNC_EPILOGUE(pGC)\
+ pGCPriv->wrapFuncs = (pGC)->funcs;\
+ (pGC)->funcs = &XineramaGCFuncs;
+
+
+static Bool
+XineramaCloseScreen (int i, ScreenPtr pScreen)
+{
+ PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
+ dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ pScreen->CreateGC = pScreenPriv->CreateGC;
+
+ if (pScreen->myNum == 0)
+ RegionUninit(&PanoramiXScreenRegion);
+
+ free((pointer) pScreenPriv);
+
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+static Bool
+XineramaCreateGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
+ dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
+ Bool ret;
+
+ pScreen->CreateGC = pScreenPriv->CreateGC;
+ if((ret = (*pScreen->CreateGC)(pGC))) {
+ PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr)
+ dixLookupPrivate(&pGC->devPrivates, PanoramiXGCKey);
+
+ pGCPriv->wrapFuncs = pGC->funcs;
+ pGC->funcs = &XineramaGCFuncs;
+
+ pGCPriv->clipOrg.x = pGC->clipOrg.x;
+ pGCPriv->clipOrg.y = pGC->clipOrg.y;
+ pGCPriv->patOrg.x = pGC->patOrg.x;
+ pGCPriv->patOrg.y = pGC->patOrg.y;
+ }
+ pScreen->CreateGC = XineramaCreateGC;
+
+ return ret;
+}
+
+static void
+XineramaValidateGC(
+ GCPtr pGC,
+ unsigned long changes,
+ DrawablePtr pDraw
+){
+ Xinerama_GC_FUNC_PROLOGUE (pGC);
+
+ if((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr)pDraw)->parent)) {
+ /* the root window */
+ int x_off = pGC->pScreen->x;
+ int y_off = pGC->pScreen->y;
+ int new_val;
+
+ new_val = pGCPriv->clipOrg.x - x_off;
+ if(pGC->clipOrg.x != new_val) {
+ pGC->clipOrg.x = new_val;
+ changes |= GCClipXOrigin;
+ }
+ new_val = pGCPriv->clipOrg.y - y_off;
+ if(pGC->clipOrg.y != new_val) {
+ pGC->clipOrg.y = new_val;
+ changes |= GCClipYOrigin;
+ }
+ new_val = pGCPriv->patOrg.x - x_off;
+ if(pGC->patOrg.x != new_val) {
+ pGC->patOrg.x = new_val;
+ changes |= GCTileStipXOrigin;
+ }
+ new_val = pGCPriv->patOrg.y - y_off;
+ if(pGC->patOrg.y != new_val) {
+ pGC->patOrg.y = new_val;
+ changes |= GCTileStipYOrigin;
+ }
+ } else {
+ if(pGC->clipOrg.x != pGCPriv->clipOrg.x) {
+ pGC->clipOrg.x = pGCPriv->clipOrg.x;
+ changes |= GCClipXOrigin;
+ }
+ if(pGC->clipOrg.y != pGCPriv->clipOrg.y) {
+ pGC->clipOrg.y = pGCPriv->clipOrg.y;
+ changes |= GCClipYOrigin;
+ }
+ if(pGC->patOrg.x != pGCPriv->patOrg.x) {
+ pGC->patOrg.x = pGCPriv->patOrg.x;
+ changes |= GCTileStipXOrigin;
+ }
+ if(pGC->patOrg.y != pGCPriv->patOrg.y) {
+ pGC->patOrg.y = pGCPriv->patOrg.y;
+ changes |= GCTileStipYOrigin;
+ }
+ }
+
+ (*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
+ Xinerama_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+XineramaDestroyGC(GCPtr pGC)
+{
+ Xinerama_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->DestroyGC)(pGC);
+ Xinerama_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+XineramaChangeGC (
+ GCPtr pGC,
+ unsigned long mask
+){
+ Xinerama_GC_FUNC_PROLOGUE (pGC);
+
+ if(mask & GCTileStipXOrigin)
+ pGCPriv->patOrg.x = pGC->patOrg.x;
+ if(mask & GCTileStipYOrigin)
+ pGCPriv->patOrg.y = pGC->patOrg.y;
+ if(mask & GCClipXOrigin)
+ pGCPriv->clipOrg.x = pGC->clipOrg.x;
+ if(mask & GCClipYOrigin)
+ pGCPriv->clipOrg.y = pGC->clipOrg.y;
+
+ (*pGC->funcs->ChangeGC) (pGC, mask);
+ Xinerama_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+XineramaCopyGC (
+ GCPtr pGCSrc,
+ unsigned long mask,
+ GCPtr pGCDst
+){
+ PanoramiXGCPtr pSrcPriv = (PanoramiXGCPtr)
+ dixLookupPrivate(&pGCSrc->devPrivates, PanoramiXGCKey);
+ Xinerama_GC_FUNC_PROLOGUE (pGCDst);
+
+ if(mask & GCTileStipXOrigin)
+ pGCPriv->patOrg.x = pSrcPriv->patOrg.x;
+ if(mask & GCTileStipYOrigin)
+ pGCPriv->patOrg.y = pSrcPriv->patOrg.y;
+ if(mask & GCClipXOrigin)
+ pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x;
+ if(mask & GCClipYOrigin)
+ pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y;
+
+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
+ Xinerama_GC_FUNC_EPILOGUE (pGCDst);
+}
+
+static void
+XineramaChangeClip (
+ GCPtr pGC,
+ int type,
+ pointer pvalue,
+ int nrects
+){
+ Xinerama_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
+ Xinerama_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+XineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ Xinerama_GC_FUNC_PROLOGUE (pgcDst);
+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
+ Xinerama_GC_FUNC_EPILOGUE (pgcDst);
+}
+
+static void
+XineramaDestroyClip(GCPtr pGC)
+{
+ Xinerama_GC_FUNC_PROLOGUE (pGC);
+ (* pGC->funcs->DestroyClip)(pGC);
+ Xinerama_GC_FUNC_EPILOGUE (pGC);
+}
+
+int
+XineramaDeleteResource(pointer data, XID id)
+{
+ free(data);
+ return 1;
+}
+
+typedef struct {
+ int screen;
+ int id;
+} PanoramiXSearchData;
+
+static Bool
+XineramaFindIDByScrnum(pointer resource, XID id, pointer privdata)
+{
+ PanoramiXRes *res = (PanoramiXRes*)resource;
+ PanoramiXSearchData *data = (PanoramiXSearchData*)privdata;
+
+ return res->info[data->screen].id == data->id;
+}
+
+PanoramiXRes *
+PanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen)
+{
+ PanoramiXSearchData data;
+ pointer val;
+
+ if(!screen) {
+ dixLookupResourceByType(&val, id, type, serverClient, DixReadAccess);
+ return val;
+ }
+
+ data.screen = screen;
+ data.id = id;
+
+ return LookupClientResourceComplex(clients[CLIENT_ID(id)], type,
+ XineramaFindIDByScrnum, &data);
+}
+
+typedef struct _connect_callback_list {
+ void (*func)(void);
+ struct _connect_callback_list *next;
+} XineramaConnectionCallbackList;
+
+static XineramaConnectionCallbackList *ConnectionCallbackList = NULL;
+
+Bool
+XineramaRegisterConnectionBlockCallback(void (*func)(void))
+{
+ XineramaConnectionCallbackList *newlist;
+
+ if(!(newlist = malloc(sizeof(XineramaConnectionCallbackList))))
+ return FALSE;
+
+ newlist->next = ConnectionCallbackList;
+ newlist->func = func;
+ ConnectionCallbackList = newlist;
+
+ return TRUE;
+}
+
+static void XineramaInitData(ScreenPtr pScreen)
+{
+ int i, w, h;
+
+ RegionNull(&PanoramiXScreenRegion);
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ BoxRec TheBox;
+ RegionRec ScreenRegion;
+
+ pScreen = screenInfo.screens[i];
+
+ TheBox.x1 = pScreen->x;
+ TheBox.x2 = TheBox.x1 + pScreen->width;
+ TheBox.y1 = pScreen->y;
+ TheBox.y2 = TheBox.y1 + pScreen->height;
+
+ RegionInit(&ScreenRegion, &TheBox, 1);
+ RegionUnion(&PanoramiXScreenRegion, &PanoramiXScreenRegion,
+ &ScreenRegion);
+ RegionUninit(&ScreenRegion);
+ }
+
+ PanoramiXPixWidth = screenInfo.screens[0]->x + screenInfo.screens[0]->width;
+ PanoramiXPixHeight = screenInfo.screens[0]->y + screenInfo.screens[0]->height;
+
+ for (i = 1; i < PanoramiXNumScreens; i++) {
+ pScreen = screenInfo.screens[i];
+ w = pScreen->x + pScreen->width;
+ h = pScreen->y + pScreen->height;
+
+ if (PanoramiXPixWidth < w)
+ PanoramiXPixWidth = w;
+ if (PanoramiXPixHeight < h)
+ PanoramiXPixHeight = h;
+ }
+}
+
+void XineramaReinitData(ScreenPtr pScreen)
+{
+ RegionUninit(&PanoramiXScreenRegion);
+ XineramaInitData(pScreen);
+}
+
+/*
+ * PanoramiXExtensionInit():
+ * Called from InitExtensions in main().
+ * Register PanoramiXeen Extension
+ * Initialize global variables.
+ */
+
+void PanoramiXExtensionInit(int argc, char *argv[])
+{
+ int i;
+ Bool success = FALSE;
+ ExtensionEntry *extEntry;
+ ScreenPtr pScreen = screenInfo.screens[0];
+ PanoramiXScreenPtr pScreenPriv;
+
+ if (noPanoramiXExtension)
+ return;
+
+ if (!dixRegisterPrivateKey(&PanoramiXScreenKeyRec, PRIVATE_SCREEN, 0)) {
+ noPanoramiXExtension = TRUE;
+ return;
+ }
+
+ if (!dixRegisterPrivateKey(&PanoramiXGCKeyRec, PRIVATE_GC, sizeof(PanoramiXGCRec))) {
+ noPanoramiXExtension = TRUE;
+ return;
+ }
+
+ PanoramiXNumScreens = screenInfo.numScreens;
+ if (PanoramiXNumScreens == 1) { /* Only 1 screen */
+ noPanoramiXExtension = TRUE;
+ return;
+ }
+
+ while (panoramiXGeneration != serverGeneration) {
+ extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0,
+ ProcPanoramiXDispatch,
+ SProcPanoramiXDispatch, PanoramiXResetProc,
+ StandardMinorOpcode);
+ if (!extEntry)
+ break;
+
+ /*
+ * First make sure all the basic allocations succeed. If not,
+ * run in non-PanoramiXeen mode.
+ */
+
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ pScreen = screenInfo.screens[i];
+ pScreenPriv = malloc(sizeof(PanoramiXScreenRec));
+ dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey,
+ pScreenPriv);
+ if(!pScreenPriv) {
+ noPanoramiXExtension = TRUE;
+ return;
+ }
+
+ pScreenPriv->CreateGC = pScreen->CreateGC;
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+
+ pScreen->CreateGC = XineramaCreateGC;
+ pScreen->CloseScreen = XineramaCloseScreen;
+ }
+
+ XRC_DRAWABLE = CreateNewResourceClass();
+ XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource,
+ "XineramaWindow");
+ if (XRT_WINDOW)
+ XRT_WINDOW |= XRC_DRAWABLE;
+ XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource,
+ "XineramaPixmap");
+ if (XRT_PIXMAP)
+ XRT_PIXMAP |= XRC_DRAWABLE;
+ XRT_GC = CreateNewResourceType(XineramaDeleteResource,
+ "XineramaGC");
+ XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource,
+ "XineramaColormap");
+
+ if (XRT_WINDOW && XRT_PIXMAP && XRT_GC && XRT_COLORMAP) {
+ panoramiXGeneration = serverGeneration;
+ success = TRUE;
+ }
+ SetResourceTypeErrorValue(XRT_WINDOW, BadWindow);
+ SetResourceTypeErrorValue(XRT_PIXMAP, BadPixmap);
+ SetResourceTypeErrorValue(XRT_GC, BadGC);
+ SetResourceTypeErrorValue(XRT_COLORMAP, BadColor);
+ }
+
+ if (!success) {
+ noPanoramiXExtension = TRUE;
+ ErrorF(PANORAMIX_PROTOCOL_NAME " extension failed to initialize\n");
+ return;
+ }
+
+ XineramaInitData(pScreen);
+
+ /*
+ * Put our processes into the ProcVector
+ */
+
+ for (i = 256; i--; )
+ SavedProcVector[i] = ProcVector[i];
+
+ ProcVector[X_CreateWindow] = PanoramiXCreateWindow;
+ ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes;
+ ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow;
+ ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows;
+ ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet;
+ ProcVector[X_ReparentWindow] = PanoramiXReparentWindow;
+ ProcVector[X_MapWindow] = PanoramiXMapWindow;
+ ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows;
+ ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow;
+ ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows;
+ ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow;
+ ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow;
+ ProcVector[X_GetGeometry] = PanoramiXGetGeometry;
+ ProcVector[X_TranslateCoords] = PanoramiXTranslateCoords;
+ ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap;
+ ProcVector[X_FreePixmap] = PanoramiXFreePixmap;
+ ProcVector[X_CreateGC] = PanoramiXCreateGC;
+ ProcVector[X_ChangeGC] = PanoramiXChangeGC;
+ ProcVector[X_CopyGC] = PanoramiXCopyGC;
+ ProcVector[X_SetDashes] = PanoramiXSetDashes;
+ ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles;
+ ProcVector[X_FreeGC] = PanoramiXFreeGC;
+ ProcVector[X_ClearArea] = PanoramiXClearToBackground;
+ ProcVector[X_CopyArea] = PanoramiXCopyArea;
+ ProcVector[X_CopyPlane] = PanoramiXCopyPlane;
+ ProcVector[X_PolyPoint] = PanoramiXPolyPoint;
+ ProcVector[X_PolyLine] = PanoramiXPolyLine;
+ ProcVector[X_PolySegment] = PanoramiXPolySegment;
+ ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle;
+ ProcVector[X_PolyArc] = PanoramiXPolyArc;
+ ProcVector[X_FillPoly] = PanoramiXFillPoly;
+ ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle;
+ ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc;
+ ProcVector[X_PutImage] = PanoramiXPutImage;
+ ProcVector[X_GetImage] = PanoramiXGetImage;
+ ProcVector[X_PolyText8] = PanoramiXPolyText8;
+ ProcVector[X_PolyText16] = PanoramiXPolyText16;
+ ProcVector[X_ImageText8] = PanoramiXImageText8;
+ ProcVector[X_ImageText16] = PanoramiXImageText16;
+ ProcVector[X_CreateColormap] = PanoramiXCreateColormap;
+ ProcVector[X_FreeColormap] = PanoramiXFreeColormap;
+ ProcVector[X_CopyColormapAndFree] = PanoramiXCopyColormapAndFree;
+ ProcVector[X_InstallColormap] = PanoramiXInstallColormap;
+ ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap;
+ ProcVector[X_AllocColor] = PanoramiXAllocColor;
+ ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor;
+ ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells;
+ ProcVector[X_AllocColorPlanes] = PanoramiXAllocColorPlanes;
+ ProcVector[X_FreeColors] = PanoramiXFreeColors;
+ ProcVector[X_StoreColors] = PanoramiXStoreColors;
+ ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor;
+
+ PanoramiXRenderInit ();
+#ifdef XFIXES
+ PanoramiXFixesInit ();
+#endif
+#ifdef COMPOSITE
+ PanoramiXCompositeInit ();
+#endif
+
+}
+
+extern Bool CreateConnectionBlock(void);
+
+Bool PanoramiXCreateConnectionBlock(void)
+{
+ int i, j, length;
+ Bool disableBackingStore = FALSE;
+ int old_width, old_height;
+ float width_mult, height_mult;
+ xWindowRoot *root;
+ xVisualType *visual;
+ xDepth *depth;
+ VisualPtr pVisual;
+ ScreenPtr pScreen;
+
+ /*
+ * Do normal CreateConnectionBlock but faking it for only one screen
+ */
+
+ if(!PanoramiXNumDepths) {
+ ErrorF("Xinerama error: No common visuals\n");
+ return FALSE;
+ }
+
+ for(i = 1; i < screenInfo.numScreens; i++) {
+ pScreen = screenInfo.screens[i];
+ if(pScreen->rootDepth != screenInfo.screens[0]->rootDepth) {
+ ErrorF("Xinerama error: Root window depths differ\n");
+ return FALSE;
+ }
+ if(pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport)
+ disableBackingStore = TRUE;
+ }
+
+ if (disableBackingStore) {
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ pScreen = screenInfo.screens[i];
+ pScreen->backingStoreSupport = NotUseful;
+ }
+ }
+
+ i = screenInfo.numScreens;
+ screenInfo.numScreens = 1;
+ if (!CreateConnectionBlock()) {
+ screenInfo.numScreens = i;
+ return FALSE;
+ }
+
+ screenInfo.numScreens = i;
+
+ root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart);
+ length = connBlockScreenStart + sizeof(xWindowRoot);
+
+ /* overwrite the connection block */
+ root->nDepths = PanoramiXNumDepths;
+
+ for (i = 0; i < PanoramiXNumDepths; i++) {
+ depth = (xDepth *) (ConnectionInfo + length);
+ depth->depth = PanoramiXDepths[i].depth;
+ depth->nVisuals = PanoramiXDepths[i].numVids;
+ length += sizeof(xDepth);
+ visual = (xVisualType *)(ConnectionInfo + length);
+
+ for (j = 0; j < depth->nVisuals; j++, visual++) {
+ visual->visualID = PanoramiXDepths[i].vids[j];
+
+ for (pVisual = PanoramiXVisuals;
+ pVisual->vid != visual->visualID;
+ pVisual++)
+ ;
+
+ visual->class = pVisual->class;
+ visual->bitsPerRGB = pVisual->bitsPerRGBValue;
+ visual->colormapEntries = pVisual->ColormapEntries;
+ visual->redMask = pVisual->redMask;
+ visual->greenMask = pVisual->greenMask;
+ visual->blueMask = pVisual->blueMask;
+ }
+
+ length += (depth->nVisuals * sizeof(xVisualType));
+ }
+
+ connSetupPrefix.length = bytes_to_int32(length);
+
+ for (i = 0; i < PanoramiXNumDepths; i++)
+ free(PanoramiXDepths[i].vids);
+ free(PanoramiXDepths);
+ PanoramiXDepths = NULL;
+
+ /*
+ * OK, change some dimensions so it looks as if it were one big screen
+ */
+
+ old_width = root->pixWidth;
+ old_height = root->pixHeight;
+
+ root->pixWidth = PanoramiXPixWidth;
+ root->pixHeight = PanoramiXPixHeight;
+ width_mult = (1.0 * root->pixWidth) / old_width;
+ height_mult = (1.0 * root->pixHeight) / old_height;
+ root->mmWidth *= width_mult;
+ root->mmHeight *= height_mult;
+
+ while(ConnectionCallbackList) {
+ pointer tmp;
+
+ tmp = (pointer)ConnectionCallbackList;
+ (*ConnectionCallbackList->func)();
+ ConnectionCallbackList = ConnectionCallbackList->next;
+ free(tmp);
+ }
+
+ return TRUE;
+}
+
+/*
+ * This isn't just memcmp(), bitsPerRGBValue is skipped. markv made that
+ * change way back before xf86 4.0, but the comment for _why_ is a bit
+ * opaque, so I'm not going to question it for now.
+ *
+ * This is probably better done as a screen hook so DBE/EVI/GLX can add
+ * their own tests, and adding privates to VisualRec so they don't have to
+ * do their own back-mapping.
+ */
+static Bool
+VisualsEqual(VisualPtr a, ScreenPtr pScreenB, VisualPtr b)
+{
+ return ((a->class == b->class) &&
+ (a->ColormapEntries == b->ColormapEntries) &&
+ (a->nplanes == b->nplanes) &&
+ (a->redMask == b->redMask) &&
+ (a->greenMask == b->greenMask) &&
+ (a->blueMask == b->blueMask) &&
+ (a->offsetRed == b->offsetRed) &&
+ (a->offsetGreen == b->offsetGreen) &&
+ (a->offsetBlue == b->offsetBlue));
+}
+
+static void
+PanoramiXMaybeAddDepth(DepthPtr pDepth)
+{
+ ScreenPtr pScreen;
+ int j, k;
+ Bool found = FALSE;
+
+ for (j = 1; j < PanoramiXNumScreens; j++) {
+ pScreen = screenInfo.screens[j];
+ for (k = 0; k < pScreen->numDepths; k++) {
+ if (pScreen->allowedDepths[k].depth == pDepth->depth) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ return;
+
+ j = PanoramiXNumDepths;
+ PanoramiXNumDepths++;
+ PanoramiXDepths = realloc(PanoramiXDepths,
+ PanoramiXNumDepths * sizeof(DepthRec));
+ PanoramiXDepths[j].depth = pDepth->depth;
+ PanoramiXDepths[j].numVids = 0;
+ /* XXX suboptimal, should grow these dynamically */
+ if(pDepth->numVids)
+ PanoramiXDepths[j].vids = malloc(sizeof(VisualID) * pDepth->numVids);
+ else
+ PanoramiXDepths[j].vids = NULL;
+}
+
+static void
+PanoramiXMaybeAddVisual(VisualPtr pVisual)
+{
+ ScreenPtr pScreen;
+ int j, k;
+ Bool found = FALSE;
+
+ for (j = 1; j < PanoramiXNumScreens; j++) {
+ pScreen = screenInfo.screens[j];
+ found = FALSE;
+
+ for (k = 0; k < pScreen->numVisuals; k++) {
+ VisualPtr candidate = &pScreen->visuals[k];
+
+ if ((*XineramaVisualsEqualPtr)(pVisual, pScreen, candidate)
+#ifdef GLXPROXY
+ && glxMatchVisual(screenInfo.screens[0], pVisual, pScreen)
+#endif
+ ) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ return;
+ }
+
+ /* found a matching visual on all screens, add it to the subset list */
+ j = PanoramiXNumVisuals;
+ PanoramiXNumVisuals++;
+ PanoramiXVisuals = realloc(PanoramiXVisuals,
+ PanoramiXNumVisuals * sizeof(VisualRec));
+
+ memcpy(&PanoramiXVisuals[j], pVisual, sizeof(VisualRec));
+
+ for (k = 0; k < PanoramiXNumDepths; k++) {
+ if (PanoramiXDepths[k].depth == pVisual->nplanes) {
+ PanoramiXDepths[k].vids[PanoramiXDepths[k].numVids] = pVisual->vid;
+ PanoramiXDepths[k].numVids++;
+ break;
+ }
+ }
+}
+
+extern void
+PanoramiXConsolidate(void)
+{
+ int i;
+ PanoramiXRes *root, *defmap, *saver;
+ ScreenPtr pScreen = screenInfo.screens[0];
+ DepthPtr pDepth = pScreen->allowedDepths;
+ VisualPtr pVisual = pScreen->visuals;
+
+ PanoramiXNumDepths = 0;
+ PanoramiXNumVisuals = 0;
+
+ for (i = 0; i < pScreen->numDepths; i++)
+ PanoramiXMaybeAddDepth(pDepth++);
+
+ for (i = 0; i < pScreen->numVisuals; i++)
+ PanoramiXMaybeAddVisual(pVisual++);
+
+ root = malloc(sizeof(PanoramiXRes));
+ root->type = XRT_WINDOW;
+ defmap = malloc(sizeof(PanoramiXRes));
+ defmap->type = XRT_COLORMAP;
+ saver = malloc(sizeof(PanoramiXRes));
+ saver->type = XRT_WINDOW;
+
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ root->info[i].id = pScreen->root->drawable.id;
+ root->u.win.class = InputOutput;
+ root->u.win.root = TRUE;
+ saver->info[i].id = pScreen->screensaver.wid;
+ saver->u.win.class = InputOutput;
+ saver->u.win.root = TRUE;
+ defmap->info[i].id = pScreen->defColormap;
+ }
+
+ AddResource(root->info[0].id, XRT_WINDOW, root);
+ AddResource(saver->info[0].id, XRT_WINDOW, saver);
+ AddResource(defmap->info[0].id, XRT_COLORMAP, defmap);
+}
+
+VisualID
+PanoramiXTranslateVisualID(int screen, VisualID orig)
+{
+ ScreenPtr pOtherScreen = screenInfo.screens[screen];
+ VisualPtr pVisual = NULL;
+ int i;
+
+ for (i = 0; i < PanoramiXNumVisuals; i++) {
+ if (orig == PanoramiXVisuals[i].vid) {
+ pVisual = &PanoramiXVisuals[i];
+ break;
+ }
+ }
+
+ if (!pVisual)
+ return 0;
+
+ /* if screen is 0, orig is already the correct visual ID */
+ if (screen == 0)
+ return orig;
+
+ /* found the original, now translate it relative to the backend screen */
+ for (i = 0; i < pOtherScreen->numVisuals; i++) {
+ VisualPtr pOtherVisual = &pOtherScreen->visuals[i];
+
+ if ((*XineramaVisualsEqualPtr)(pVisual, pOtherScreen, pOtherVisual))
+ return pOtherVisual->vid;
+ }
+
+ return 0;
+}
+
+
+/*
+ * PanoramiXResetProc()
+ * Exit, deallocating as needed.
+ */
+
+static void PanoramiXResetProc(ExtensionEntry* extEntry)
+{
+ int i;
+
+ PanoramiXRenderReset ();
+#ifdef XFIXES
+ PanoramiXFixesReset ();
+#endif
+ screenInfo.numScreens = PanoramiXNumScreens;
+ for (i = 256; i--; )
+ ProcVector[i] = SavedProcVector[i];
+}
+
+
+int
+ProcPanoramiXQueryVersion (ClientPtr client)
+{
+ /* REQUEST(xPanoramiXQueryVersionReq); */
+ xPanoramiXQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = SERVER_PANORAMIX_MAJOR_VERSION;
+ rep.minorVersion = SERVER_PANORAMIX_MINOR_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep);
+ return Success;
+}
+
+int
+ProcPanoramiXGetState(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetStateReq);
+ WindowPtr pWin;
+ xPanoramiXGetStateReply rep;
+ int n, rc;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.state = !noPanoramiXExtension;
+ rep.window = stuff->window;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.window, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep);
+ return Success;
+
+}
+
+int
+ProcPanoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenCountReply rep;
+ int n, rc;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.ScreenCount = PanoramiXNumScreens;
+ rep.window = stuff->window;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.window, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep);
+ return Success;
+}
+
+int
+ProcPanoramiXGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenSizeReply rep;
+ int n, rc;
+
+ if (stuff->screen >= PanoramiXNumScreens)
+ return BadMatch;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ /* screen dimensions */
+ rep.width = screenInfo.screens[stuff->screen]->width;
+ rep.height = screenInfo.screens[stuff->screen]->height;
+ rep.window = stuff->window;
+ rep.screen = stuff->screen;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.width, n);
+ swapl (&rep.height, n);
+ swapl (&rep.window, n);
+ swapl (&rep.screen, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep);
+ return Success;
+}
+
+
+int
+ProcXineramaIsActive(ClientPtr client)
+{
+ /* REQUEST(xXineramaIsActiveReq); */
+ xXineramaIsActiveReply rep;
+
+ REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+#if 1
+ {
+ /* The following hack fools clients into thinking that Xinerama
+ * is disabled even though it is not. */
+ rep.state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack;
+ }
+#else
+ rep.state = !noPanoramiXExtension;
+#endif
+ if (client->swapped) {
+ int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.state, n);
+ }
+ WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep);
+ return Success;
+}
+
+
+int
+ProcXineramaQueryScreens(ClientPtr client)
+{
+ /* REQUEST(xXineramaQueryScreensReq); */
+ xXineramaQueryScreensReply rep;
+
+ REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens;
+ rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo);
+ if (client->swapped) {
+ int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.number, n);
+ }
+ WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep);
+
+ if(!noPanoramiXExtension) {
+ xXineramaScreenInfo scratch;
+ int i;
+
+ for(i = 0; i < PanoramiXNumScreens; i++) {
+ scratch.x_org = screenInfo.screens[i]->x;
+ scratch.y_org = screenInfo.screens[i]->y;
+ scratch.width = screenInfo.screens[i]->width;
+ scratch.height = screenInfo.screens[i]->height;
+
+ if(client->swapped) {
+ int n;
+ swaps (&scratch.x_org, n);
+ swaps (&scratch.y_org, n);
+ swaps (&scratch.width, n);
+ swaps (&scratch.height, n);
+ }
+ WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch);
+ }
+ }
+
+ return Success;
+}
+
+
+static int
+ProcPanoramiXDispatch (ClientPtr client)
+{ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_PanoramiXQueryVersion:
+ return ProcPanoramiXQueryVersion(client);
+ case X_PanoramiXGetState:
+ return ProcPanoramiXGetState(client);
+ case X_PanoramiXGetScreenCount:
+ return ProcPanoramiXGetScreenCount(client);
+ case X_PanoramiXGetScreenSize:
+ return ProcPanoramiXGetScreenSize(client);
+ case X_XineramaIsActive:
+ return ProcXineramaIsActive(client);
+ case X_XineramaQueryScreens:
+ return ProcXineramaQueryScreens(client);
+ }
+ return BadRequest;
+}
+
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+#define SHIFT_L(v,s) (v) << (s)
+#define SHIFT_R(v,s) (v) >> (s)
+#else
+#define SHIFT_L(v,s) (v) >> (s)
+#define SHIFT_R(v,s) (v) << (s)
+#endif
+
+static void
+CopyBits(char *dst, int shiftL, char *src, int bytes)
+{
+ /* Just get it to work. Worry about speed later */
+ int shiftR = 8 - shiftL;
+
+ while(bytes--) {
+ *dst |= SHIFT_L(*src, shiftL);
+ *(dst + 1) |= SHIFT_R(*src, shiftR);
+ dst++; src++;
+ }
+}
+
+
+/* Caution. This doesn't support 2 and 4 bpp formats. We expect
+ 1 bpp and planar data to be already cleared when presented
+ to this function */
+
+void
+XineramaGetImageData(
+ DrawablePtr *pDrawables,
+ int left,
+ int top,
+ int width,
+ int height,
+ unsigned int format,
+ unsigned long planemask,
+ char *data,
+ int pitch,
+ Bool isRoot
+){
+ RegionRec SrcRegion, ScreenRegion, GrabRegion;
+ BoxRec SrcBox, *pbox;
+ int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth;
+ DrawablePtr pDraw = pDrawables[0];
+ char *ScratchMem = NULL;
+
+ size = 0;
+
+ /* find box in logical screen space */
+ SrcBox.x1 = left;
+ SrcBox.y1 = top;
+ if(!isRoot) {
+ SrcBox.x1 += pDraw->x + screenInfo.screens[0]->x;
+ SrcBox.y1 += pDraw->y + screenInfo.screens[0]->y;
+ }
+ SrcBox.x2 = SrcBox.x1 + width;
+ SrcBox.y2 = SrcBox.y1 + height;
+
+ RegionInit(&SrcRegion, &SrcBox, 1);
+ RegionNull(&GrabRegion);
+
+ depth = (format == XYPixmap) ? 1 : pDraw->depth;
+
+ for(i = 0; i < PanoramiXNumScreens; i++) {
+ BoxRec TheBox;
+ ScreenPtr pScreen;
+ pDraw = pDrawables[i];
+ pScreen = pDraw->pScreen;
+
+ TheBox.x1 = pScreen->x;
+ TheBox.x2 = TheBox.x1 + pScreen->width;
+ TheBox.y1 = pScreen->y;
+ TheBox.y2 = TheBox.y1 + pScreen->height;
+
+ RegionInit(&ScreenRegion, &TheBox, 1);
+ inOut = RegionContainsRect(&ScreenRegion, &SrcBox);
+ if(inOut == rgnPART)
+ RegionIntersect(&GrabRegion, &SrcRegion, &ScreenRegion);
+ RegionUninit(&ScreenRegion);
+
+ if(inOut == rgnIN) {
+ (*pScreen->GetImage)(pDraw,
+ SrcBox.x1 - pDraw->x - screenInfo.screens[i]->x,
+ SrcBox.y1 - pDraw->y - screenInfo.screens[i]->y,
+ width, height, format, planemask, data);
+ break;
+ } else if (inOut == rgnOUT)
+ continue;
+
+ nbox = RegionNumRects(&GrabRegion);
+
+ if(nbox) {
+ pbox = RegionRects(&GrabRegion);
+
+ while(nbox--) {
+ w = pbox->x2 - pbox->x1;
+ h = pbox->y2 - pbox->y1;
+ ScratchPitch = PixmapBytePad(w, depth);
+ sizeNeeded = ScratchPitch * h;
+
+ if(sizeNeeded > size) {
+ char *tmpdata = ScratchMem;
+ ScratchMem = realloc(ScratchMem, sizeNeeded);
+ if(ScratchMem)
+ size = sizeNeeded;
+ else {
+ ScratchMem = tmpdata;
+ break;
+ }
+ }
+
+ x = pbox->x1 - pDraw->x - screenInfo.screens[i]->x;
+ y = pbox->y1 - pDraw->y - screenInfo.screens[i]->y;
+
+ (*pScreen->GetImage)(pDraw, x, y, w, h,
+ format, planemask, ScratchMem);
+
+ /* copy the memory over */
+
+ if(depth == 1) {
+ int k, shift, leftover, index, index2;
+
+ x = pbox->x1 - SrcBox.x1;
+ y = pbox->y1 - SrcBox.y1;
+ shift = x & 7;
+ x >>= 3;
+ leftover = w & 7;
+ w >>= 3;
+
+ /* clean up the edge */
+ if(leftover) {
+ int mask = (1 << leftover) - 1;
+ for(j = h, k = w; j--; k += ScratchPitch)
+ ScratchMem[k] &= mask;
+ }
+
+ for(j = 0, index = (pitch * y) + x, index2 = 0; j < h;
+ j++, index += pitch, index2 += ScratchPitch)
+ {
+ if(w) {
+ if(!shift)
+ memcpy(data + index, ScratchMem + index2, w);
+ else
+ CopyBits(data + index, shift,
+ ScratchMem + index2, w);
+ }
+
+ if(leftover) {
+ data[index + w] |=
+ SHIFT_L(ScratchMem[index2 + w], shift);
+ if((shift + leftover) > 8)
+ data[index + w + 1] |=
+ SHIFT_R(ScratchMem[index2 + w],(8 - shift));
+ }
+ }
+ } else {
+ j = BitsPerPixel(depth) >> 3;
+ x = (pbox->x1 - SrcBox.x1) * j;
+ y = pbox->y1 - SrcBox.y1;
+ w *= j;
+
+ for(j = 0; j < h; j++) {
+ memcpy(data + (pitch * (y + j)) + x,
+ ScratchMem + (ScratchPitch * j), w);
+ }
+ }
+ pbox++;
+ }
+
+ RegionSubtract(&SrcRegion, &SrcRegion, &GrabRegion);
+ if(!RegionNotEmpty(&SrcRegion))
+ break;
+ }
+
+ }
+
+ free(ScratchMem);
+
+ RegionUninit(&SrcRegion);
+ RegionUninit(&GrabRegion);
+}
diff --git a/xorg-server/Xext/panoramiXsrv.h b/xorg-server/Xext/panoramiXsrv.h index 9751feb54..21f1b4cb8 100644 --- a/xorg-server/Xext/panoramiXsrv.h +++ b/xorg-server/Xext/panoramiXsrv.h @@ -1,54 +1,54 @@ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#ifndef _PANORAMIXSRV_H_ -#define _PANORAMIXSRV_H_ - -#include "panoramiX.h" - -extern _X_EXPORT int PanoramiXNumScreens; -extern _X_EXPORT int PanoramiXPixWidth; -extern _X_EXPORT int PanoramiXPixHeight; - -extern _X_EXPORT VisualID PanoramiXTranslateVisualID(int screen, VisualID orig); -extern _X_EXPORT void PanoramiXConsolidate(void); -extern _X_EXPORT Bool PanoramiXCreateConnectionBlock(void); -extern _X_EXPORT PanoramiXRes * PanoramiXFindIDByScrnum(RESTYPE, XID, int); -extern _X_EXPORT Bool XineramaRegisterConnectionBlockCallback(void (*func)(void)); -extern _X_EXPORT int XineramaDeleteResource(pointer, XID); - -extern _X_EXPORT void XineramaReinitData(ScreenPtr); - -extern _X_EXPORT RESTYPE XRC_DRAWABLE; -extern _X_EXPORT RESTYPE XRT_WINDOW; -extern _X_EXPORT RESTYPE XRT_PIXMAP; -extern _X_EXPORT RESTYPE XRT_GC; -extern _X_EXPORT RESTYPE XRT_COLORMAP; -extern _X_EXPORT RESTYPE XRT_PICTURE; - -/* - * Drivers are allowed to wrap this function. Each wrapper can decide that the - * two visuals are unequal, but if they are deemed equal, the wrapper must call - * down and return FALSE if the wrapped function does. This ensures that all - * layers agree that the visuals are equal. The first visual is always from - * screen 0. - */ -typedef Bool (*XineramaVisualsEqualProcPtr)(VisualPtr, ScreenPtr, VisualPtr); -extern _X_EXPORT XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr; - -extern _X_EXPORT void XineramaGetImageData( - DrawablePtr *pDrawables, - int left, - int top, - int width, - int height, - unsigned int format, - unsigned long planemask, - char *data, - int pitch, - Bool isRoot -); - -#endif /* _PANORAMIXSRV_H_ */ +
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _PANORAMIXSRV_H_
+#define _PANORAMIXSRV_H_
+
+#include "panoramiX.h"
+
+extern _X_EXPORT int PanoramiXNumScreens;
+extern _X_EXPORT int PanoramiXPixWidth;
+extern _X_EXPORT int PanoramiXPixHeight;
+
+extern _X_EXPORT VisualID PanoramiXTranslateVisualID(int screen, VisualID orig);
+extern _X_EXPORT void PanoramiXConsolidate(void);
+extern _X_EXPORT Bool PanoramiXCreateConnectionBlock(void);
+extern _X_EXPORT PanoramiXRes * PanoramiXFindIDByScrnum(RESTYPE, XID, int);
+extern _X_EXPORT Bool XineramaRegisterConnectionBlockCallback(void (*func)(void));
+extern _X_EXPORT int XineramaDeleteResource(pointer, XID);
+
+extern _X_EXPORT void XineramaReinitData(ScreenPtr);
+
+extern _X_EXPORT RESTYPE XRC_DRAWABLE;
+extern _X_EXPORT RESTYPE XRT_WINDOW;
+extern _X_EXPORT RESTYPE XRT_PIXMAP;
+extern _X_EXPORT RESTYPE XRT_GC;
+extern _X_EXPORT RESTYPE XRT_COLORMAP;
+extern _X_EXPORT RESTYPE XRT_PICTURE;
+
+/*
+ * Drivers are allowed to wrap this function. Each wrapper can decide that the
+ * two visuals are unequal, but if they are deemed equal, the wrapper must call
+ * down and return FALSE if the wrapped function does. This ensures that all
+ * layers agree that the visuals are equal. The first visual is always from
+ * screen 0.
+ */
+typedef Bool (*XineramaVisualsEqualProcPtr)(VisualPtr, ScreenPtr, VisualPtr);
+extern _X_EXPORT XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr;
+
+extern _X_EXPORT void XineramaGetImageData(
+ DrawablePtr *pDrawables,
+ int left,
+ int top,
+ int width,
+ int height,
+ unsigned int format,
+ unsigned long planemask,
+ char *data,
+ int pitch,
+ Bool isRoot
+);
+
+#endif /* _PANORAMIXSRV_H_ */
diff --git a/xorg-server/Xext/saver.c b/xorg-server/Xext/saver.c index 3b8b6de59..5fd6c895d 100644 --- a/xorg-server/Xext/saver.c +++ b/xorg-server/Xext/saver.c @@ -29,6 +29,12 @@ in this Software without prior written authorization from the X Consortium. #ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
+#else
+#define SCREENSAVER
+#endif
+
+#ifdef CreateWindow
+#undef CreateWindow
#endif
#include <X11/X.h>
diff --git a/xorg-server/Xext/security.c b/xorg-server/Xext/security.c index d687926c6..ad6f9a3ef 100644 --- a/xorg-server/Xext/security.c +++ b/xorg-server/Xext/security.c @@ -26,6 +26,8 @@ in this Software without prior written authorization from The Open Group. #ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
+#else
+#define XACE
#endif
#include "scrnintstr.h"
diff --git a/xorg-server/Xext/securitysrv.h b/xorg-server/Xext/securitysrv.h index 3d3894a18..68f51d2f5 100644 --- a/xorg-server/Xext/securitysrv.h +++ b/xorg-server/Xext/securitysrv.h @@ -31,10 +31,7 @@ from The Open Group. #define _SECURITY_SRV_H /* Allow client side portions of <X11/extensions/security.h> to compile */ -#ifndef Status -# define Status int -# define NEED_UNDEF_Status -#endif +typedef int Status; #ifndef Display # define Display void # define NEED_UNDEF_Display diff --git a/xorg-server/Xext/shape.c b/xorg-server/Xext/shape.c index 79dc77635..6a35a0451 100644 --- a/xorg-server/Xext/shape.c +++ b/xorg-server/Xext/shape.c @@ -26,6 +26,8 @@ in this Software without prior written authorization from The Open Group. #ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
+#else
+#define SHAPE
#endif
#include <stdlib.h>
diff --git a/xorg-server/Xext/shm.c b/xorg-server/Xext/shm.c index 8a048deb0..7099e8f36 100644 --- a/xorg-server/Xext/shm.c +++ b/xorg-server/Xext/shm.c @@ -34,8 +34,10 @@ in this Software without prior written authorization from The Open Group. #endif
#include <sys/types.h>
+#if !defined(_MSC_VER)
#include <sys/ipc.h>
#include <sys/shm.h>
+#endif
#include <unistd.h>
#include <sys/stat.h>
#include <X11/X.h>
@@ -300,8 +302,10 @@ ProcShmQueryVersion(ClientPtr client) rep.pixmapFormat = sharedPixmaps ? ZPixmap : 0;
rep.majorVersion = SERVER_SHM_MAJOR_VERSION;
rep.minorVersion = SERVER_SHM_MINOR_VERSION;
+#ifndef _MSC_VER
rep.uid = geteuid();
rep.gid = getegid();
+#endif
if (client->swapped) {
swaps(&rep.sequenceNumber, n);
swapl(&rep.length, n);
@@ -351,6 +355,9 @@ shm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly) if (uid == 0) {
return 0;
}
+ #ifdef _MSC_VER
+ __asm int 3;
+ #else
/* Check the owner */
if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) {
mask = S_IRUSR;
@@ -359,10 +366,14 @@ shm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly) }
return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
}
+ #endif
}
if (gidset) {
/* Check the group */
+ #ifdef _MSC_VER
+ __asm int 3;
+ #else
if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) {
mask = S_IRGRP;
if (!readonly) {
@@ -370,14 +381,20 @@ shm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly) }
return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
}
+ #endif
}
}
+ #ifdef _MSC_VER
+ __asm int 3;
+ return -1;
+ #else
/* Otherwise, check everyone else */
mask = S_IROTH;
if (!readonly) {
mask |= S_IWOTH;
}
return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
+ #endif
}
static int
@@ -450,7 +467,9 @@ ShmDetachSegment(pointer value, /* must conform to DeleteType */ if (--shmdesc->refcnt)
return TRUE;
+#ifndef _MSC_VER
shmdt(shmdesc->addr);
+#endif
for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next)
;
*prev = shmdesc->next;
diff --git a/xorg-server/Xext/sync.c b/xorg-server/Xext/sync.c index 4f80c7f30..60bcfe8d8 100644 --- a/xorg-server/Xext/sync.c +++ b/xorg-server/Xext/sync.c @@ -1235,6 +1235,10 @@ FreeAwait(void *addr, XID id) return Success;
}
+#ifdef _MSC_VER
+#pragma warning(disable:4715) /* Not all control paths return a value */
+#endif
+
/* loosely based on dix/events.c/OtherClientGone */
static int
FreeAlarmClient(void *value, XID id)
diff --git a/xorg-server/Xext/xace.c b/xorg-server/Xext/xace.c index 28c51687c..77b713ffb 100644 --- a/xorg-server/Xext/xace.c +++ b/xorg-server/Xext/xace.c @@ -19,6 +19,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
+#else
+#define XACE
#endif
#include <stdarg.h>
diff --git a/xorg-server/Xext/xselinux_hooks.c b/xorg-server/Xext/xselinux_hooks.c index f1d8e5d2f..1c048bd68 100644 --- a/xorg-server/Xext/xselinux_hooks.c +++ b/xorg-server/Xext/xselinux_hooks.c @@ -1,935 +1,935 @@ -/************************************************************ - -Author: Eamon Walsh <ewalsh@tycho.nsa.gov> - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -this permission notice appear in supporting documentation. This permission -notice shall be included in all copies or substantial portions of the -Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -********************************************************/ - -/* - * Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc. - * All rights reserved. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <sys/socket.h> -#include <stdio.h> -#include <stdarg.h> - -#include <libaudit.h> - -#include <X11/Xatom.h> -#include "selection.h" -#include "inputstr.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "propertyst.h" -#include "extnsionst.h" -#include "xacestr.h" -#include "client.h" -#include "../os/osdep.h" -#define _XSELINUX_NEED_FLASK_MAP -#include "xselinuxint.h" - - -/* structure passed to auditing callback */ -typedef struct { - ClientPtr client; /* client */ - DeviceIntPtr dev; /* device */ - char *command; /* client's executable path */ - unsigned id; /* resource id, if any */ - int restype; /* resource type, if any */ - int event; /* event type, if any */ - Atom property; /* property name, if any */ - Atom selection; /* selection name, if any */ - char *extension; /* extension name, if any */ -} SELinuxAuditRec; - -/* private state keys */ -DevPrivateKeyRec subjectKeyRec; -DevPrivateKeyRec objectKeyRec; -DevPrivateKeyRec dataKeyRec; - -/* audit file descriptor */ -static int audit_fd; - -/* atoms for window label properties */ -static Atom atom_ctx; -static Atom atom_client_ctx; - -/* The unlabeled SID */ -static security_id_t unlabeled_sid; - -/* forward declarations */ -static void SELinuxScreen(CallbackListPtr *, pointer, pointer); - -/* "true" pointer value for use as callback data */ -static pointer truep = (pointer)1; - - -/* - * Performs an SELinux permission check. - */ -static int -SELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj, - security_class_t class, Mask mode, SELinuxAuditRec *auditdata) -{ - /* serverClient requests OK */ - if (subj->privileged) - return Success; - - auditdata->command = subj->command; - errno = 0; - - if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref, - auditdata) < 0) { - if (mode == DixUnknownAccess) - return Success; /* DixUnknownAccess requests OK ... for now */ - if (errno == EACCES) - return BadAccess; - ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno); - return BadValue; - } - - return Success; -} - -/* - * Labels a newly connected client. - */ -static void -SELinuxLabelClient(ClientPtr client) -{ - int fd = XaceGetConnectionNumber(client); - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - security_context_t ctx; - - subj = dixLookupPrivate(&client->devPrivates, subjectKey); - obj = dixLookupPrivate(&client->devPrivates, objectKey); - - /* Try to get a context from the socket */ - if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) { - /* Otherwise, fall back to a default context */ - ctx = SELinuxDefaultClientLabel(); - } - - /* For local clients, try and determine the executable name */ - if (XaceIsLocal(client)) { - /* Get cached command name if CLIENTIDS is enabled. */ - const char *cmdname = GetClientCmdName(client); - Bool cached = (cmdname != NULL); - /* If CLIENTIDS is disabled, figure out the command name from - * scratch. */ - if (!cmdname) - { - pid_t pid = DetermineClientPid(client); - if (pid != -1) - DetermineClientCmd(pid, &cmdname, NULL); - } - - if (!cmdname) - goto finish; - - strncpy(subj->command, cmdname, COMMAND_LEN - 1); - - if (!cached) - free((void *) cmdname); /* const char * */ - } - -finish: - /* Get a SID from the context */ - if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) - FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n", - client->index, ctx); - - obj->sid = subj->sid; - freecon(ctx); -} - -/* - * Labels initial server objects. - */ -static void -SELinuxLabelInitial(void) -{ - int i; - XaceScreenAccessRec srec; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - security_context_t ctx; - pointer unused; - - /* Do the serverClient */ - subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey); - obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); - subj->privileged = 1; - - /* Use the context of the X server process for the serverClient */ - if (getcon_raw(&ctx) < 0) - FatalError("SELinux: couldn't get context of X server process\n"); - - /* Get a SID from the context */ - if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) - FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); - - obj->sid = subj->sid; - freecon(ctx); - - srec.client = serverClient; - srec.access_mode = DixCreateAccess; - srec.status = Success; - - for (i = 0; i < screenInfo.numScreens; i++) { - /* Do the screen object */ - srec.screen = screenInfo.screens[i]; - SELinuxScreen(NULL, NULL, &srec); - - /* Do the default colormap */ - dixLookupResourceByType(&unused, screenInfo.screens[i]->defColormap, - RT_COLORMAP, serverClient, DixCreateAccess); - } -} - -/* - * Labels new resource objects. - */ -static int -SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj, - SELinuxObjectRec *obj, security_class_t class) -{ - int offset; - security_id_t tsid; - - /* Check for a create context */ - if (rec->rtype & RC_DRAWABLE && subj->win_create_sid) { - obj->sid = subj->win_create_sid; - return Success; - } - - if (rec->parent) - offset = dixLookupPrivateOffset(rec->ptype); - - if (rec->parent && offset >= 0) { - /* Use the SID of the parent object in the labeling operation */ - PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset); - SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey); - tsid = pobj->sid; - } else { - /* Use the SID of the subject */ - tsid = subj->sid; - } - - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) { - ErrorF("SELinux: a compute_create call failed!\n"); - return BadValue; - } - - return Success; -} - - -/* - * Libselinux Callbacks - */ - -static int -SELinuxAudit(void *auditdata, - security_class_t class, - char *msgbuf, - size_t msgbufsize) -{ - SELinuxAuditRec *audit = auditdata; - ClientPtr client = audit->client; - char idNum[16]; - const char *propertyName, *selectionName; - int major = -1, minor = -1; - - if (client) { - REQUEST(xReq); - if (stuff) { - major = stuff->reqType; - minor = MinorOpcodeOfRequest(client); - } - } - if (audit->id) - snprintf(idNum, 16, "%x", audit->id); - - propertyName = audit->property ? NameForAtom(audit->property) : NULL; - selectionName = audit->selection ? NameForAtom(audit->selection) : NULL; - - return snprintf(msgbuf, msgbufsize, - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", - (major >= 0) ? "request=" : "", - (major >= 0) ? LookupRequestName(major, minor) : "", - audit->command ? " comm=" : "", - audit->command ? audit->command : "", - audit->dev ? " xdevice=\"" : "", - audit->dev ? audit->dev->name : "", - audit->dev ? "\"" : "", - audit->id ? " resid=" : "", - audit->id ? idNum : "", - audit->restype ? " restype=" : "", - audit->restype ? LookupResourceName(audit->restype) : "", - audit->event ? " event=" : "", - audit->event ? LookupEventName(audit->event & 127) : "", - audit->property ? " property=" : "", - audit->property ? propertyName : "", - audit->selection ? " selection=" : "", - audit->selection ? selectionName : "", - audit->extension ? " extension=" : "", - audit->extension ? audit->extension : ""); -} - -static int -SELinuxLog(int type, const char *fmt, ...) -{ - va_list ap; - char buf[MAX_AUDIT_MESSAGE_LENGTH]; - int rc, aut; - - switch (type) { - case SELINUX_INFO: - aut = AUDIT_USER_MAC_POLICY_LOAD; - break; - case SELINUX_AVC: - aut = AUDIT_USER_AVC; - break; - default: - aut = AUDIT_USER_SELINUX_ERR; - break; - } - - va_start(ap, fmt); - vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap); - rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0); - va_end(ap); - LogMessageVerb(X_WARNING, 0, "%s", buf); - return 0; -} - -/* - * XACE Callbacks - */ - -static void -SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceDeviceAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; - security_class_t cls; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (rec->access_mode & DixCreateAccess) { - SELinuxSubjectRec *dsubj; - dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); - - if (subj->dev_create_sid) { - /* Label the device with the create context */ - obj->sid = subj->dev_create_sid; - dsubj->sid = subj->dev_create_sid; - } else { - /* Label the device directly with the process SID */ - obj->sid = subj->sid; - dsubj->sid = subj->sid; - } - } - - cls = IsPointerDevice(rec->dev) ? SECCLASS_X_POINTER : SECCLASS_X_KEYBOARD; - rc = SELinuxDoCheck(subj, obj, cls, rec->access_mode, &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceSendAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, ev_sid; - SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; - security_class_t class; - int rc, i, type; - - if (rec->dev) - subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); - else - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - - obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); - - /* Check send permission on window */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess, - &auditdata); - if (rc != Success) - goto err; - - /* Check send permission on specific event types */ - for (i = 0; i < rec->count; i++) { - type = rec->events[i].u.u.type; - class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; - - rc = SELinuxEventToSID(type, obj->sid, &ev_sid); - if (rc != Success) - goto err; - - auditdata.event = type; - rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata); - if (rc != Success) - goto err; - } - return; -err: - rec->status = rc; -} - -static void -SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceReceiveAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, ev_sid; - SELinuxAuditRec auditdata = { .client = NULL }; - security_class_t class; - int rc, i, type; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); - - /* Check receive permission on window */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess, - &auditdata); - if (rc != Success) - goto err; - - /* Check receive permission on specific event types */ - for (i = 0; i < rec->count; i++) { - type = rec->events[i].u.u.type; - class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; - - rc = SELinuxEventToSID(type, obj->sid, &ev_sid); - if (rc != Success) - goto err; - - auditdata.event = type; - rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata); - if (rc != Success) - goto err; - } - return; -err: - rec->status = rc; -} - -static void -SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceExtAccessRec *rec = calldata; - SELinuxSubjectRec *subj, *serv; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - /* XXX there should be a separate callback for this */ - if (obj->sid == NULL) { - security_id_t sid; - - serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey); - rc = SELinuxExtensionToSID(rec->ext->name, &sid); - if (rc != Success) { - rec->status = rc; - return; - } - - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION, - &obj->sid) < 0) { - ErrorF("SELinux: a SID transition call failed!\n"); - rec->status = BadValue; - return; - } - } - - /* Perform the security check */ - auditdata.extension = rec->ext->name; - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceSelectionAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, *data; - Selection *pSel = *rec->ppSel; - Atom name = pSel->selection; - Mask access_mode = rec->access_mode; - SELinuxAuditRec auditdata = { .client = rec->client, .selection = name }; - security_id_t tsid; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&pSel->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (access_mode & DixCreateAccess) { - rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly); - if (rc != Success) - obj->sid = unlabeled_sid; - access_mode = DixSetAttrAccess; - } - /* If this is a polyinstantiated object, find the right instance */ - else if (obj->poly) { - rc = SELinuxSelectionToSID(name, subj, &tsid, NULL); - if (rc != Success) { - rec->status = rc; - return; - } - while (pSel->selection != name || obj->sid != tsid) { - if ((pSel = pSel->next) == NULL) - break; - obj = dixLookupPrivate(&pSel->devPrivates, objectKey); - } - - if (pSel) - *rec->ppSel = pSel; - else { - rec->status = BadMatch; - return; - } - } - - /* Perform the security check */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; - - /* Label the content (advisory only) */ - if (access_mode & DixSetAttrAccess) { - data = dixLookupPrivate(&pSel->devPrivates, dataKey); - if (subj->sel_create_sid) - data->sid = subj->sel_create_sid; - else - data->sid = obj->sid; - } -} - -static void -SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XacePropertyAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, *data; - PropertyPtr pProp = *rec->ppProp; - Atom name = pProp->propertyName; - SELinuxAuditRec auditdata = { .client = rec->client, .property = name }; - security_id_t tsid; - int rc; - - /* Don't care about the new content check */ - if (rec->access_mode & DixPostAccess) - return; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&pProp->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (rec->access_mode & DixCreateAccess) { - rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly); - if (rc != Success) { - rec->status = rc; - return; - } - } - /* If this is a polyinstantiated object, find the right instance */ - else if (obj->poly) { - rc = SELinuxPropertyToSID(name, subj, &tsid, NULL); - if (rc != Success) { - rec->status = rc; - return; - } - while (pProp->propertyName != name || obj->sid != tsid) { - if ((pProp = pProp->next) == NULL) - break; - obj = dixLookupPrivate(&pProp->devPrivates, objectKey); - } - - if (pProp) - *rec->ppProp = pProp; - else { - rec->status = BadMatch; - return; - } - } - - /* Perform the security check */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; - - /* Label the content (advisory only) */ - if (rec->access_mode & DixWriteAccess) { - data = dixLookupPrivate(&pProp->devPrivates, dataKey); - if (subj->prp_create_sid) - data->sid = subj->prp_create_sid; - else - data->sid = obj->sid; - } -} - -static void -SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceResourceAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - Mask access_mode = rec->access_mode; - PrivateRec **privatePtr; - security_class_t class; - int rc, offset; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - - /* Determine if the resource object has a devPrivates field */ - offset = dixLookupPrivateOffset(rec->rtype); - if (offset < 0) { - /* No: use the SID of the owning client */ - class = SECCLASS_X_RESOURCE; - privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates; - obj = dixLookupPrivate(privatePtr, objectKey); - } else { - /* Yes: use the SID from the resource object itself */ - class = SELinuxTypeToClass(rec->rtype); - privatePtr = DEVPRIV_AT(rec->res, offset); - obj = dixLookupPrivate(privatePtr, objectKey); - } - - /* If this is a new object that needs labeling, do it now */ - if (access_mode & DixCreateAccess && offset >= 0) { - rc = SELinuxLabelResource(rec, subj, obj, class); - if (rc != Success) { - rec->status = rc; - return; - } - } - - /* Collapse generic resource permissions down to read/write */ - if (class == SECCLASS_X_RESOURCE) { - access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */ - access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */ - } - - /* Perform the security check */ - auditdata.restype = rec->rtype; - auditdata.id = rec->id; - rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata); - if (rc != Success) - rec->status = rc; - - /* Perform the background none check on windows */ - if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) { - rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata); - if (rc != Success) - ((WindowPtr)rec->res)->forcedBG = TRUE; - } -} - -static void -SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata) -{ - XaceScreenAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - Mask access_mode = rec->access_mode; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (access_mode & DixCreateAccess) { - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN, - &obj->sid) < 0) { - ErrorF("SELinux: a compute_create call failed!\n"); - rec->status = BadValue; - return; - } - } - - if (is_saver) - access_mode <<= 2; - - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceClientAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->target->devPrivates, objectKey); - - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceServerAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); - - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; -} - - -/* - * DIX Callbacks - */ - -static void -SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - NewClientInfoRec *pci = calldata; - - switch (pci->client->clientState) { - case ClientStateInitial: - SELinuxLabelClient(pci->client); - break; - - default: - break; - } -} - -static void -SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - ResourceStateInfoRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - WindowPtr pWin; - - if (rec->type != RT_WINDOW) - return; - if (rec->state != ResourceStateAdding) - return; - - pWin = (WindowPtr)rec->value; - subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey); - - if (subj->sid) { - security_context_t ctx; - int rc = avc_sid_to_context_raw(subj->sid, &ctx); - if (rc < 0) - FatalError("SELinux: Failed to get security context!\n"); - rc = dixChangeWindowProperty(serverClient, - pWin, atom_client_ctx, XA_STRING, 8, - PropModeReplace, strlen(ctx), ctx, FALSE); - if (rc != Success) - FatalError("SELinux: Failed to set label property on window!\n"); - freecon(ctx); - } else - FatalError("SELinux: Unexpected unlabeled client found\n"); - - obj = dixLookupPrivate(&pWin->devPrivates, objectKey); - - if (obj->sid) { - security_context_t ctx; - int rc = avc_sid_to_context_raw(obj->sid, &ctx); - if (rc < 0) - FatalError("SELinux: Failed to get security context!\n"); - rc = dixChangeWindowProperty(serverClient, - pWin, atom_ctx, XA_STRING, 8, - PropModeReplace, strlen(ctx), ctx, FALSE); - if (rc != Success) - FatalError("SELinux: Failed to set label property on window!\n"); - freecon(ctx); - } else - FatalError("SELinux: Unexpected unlabeled window found\n"); -} - - -static int netlink_fd; - -static void -SELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask) -{ -} - -static void -SELinuxWakeupHandler(void *data, int err, void *read_mask) -{ - if (FD_ISSET(netlink_fd, (fd_set *)read_mask)) - avc_netlink_check_nb(); -} - -void -SELinuxFlaskReset(void) -{ - /* Unregister callbacks */ - DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL); - DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL); - - XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); - XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); - XaceDeleteCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); - XaceDeleteCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); - XaceDeleteCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); - XaceDeleteCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); - XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); - XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); - XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); - XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); - XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); - XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); - - /* Tear down SELinux stuff */ - audit_close(audit_fd); - avc_netlink_release_fd(); - RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, - NULL); - RemoveGeneralSocket(netlink_fd); - - avc_destroy(); -} - -void -SELinuxFlaskInit(void) -{ - struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 }; - security_context_t ctx; - int ret = TRUE; - - switch(selinuxEnforcingState) { - case SELINUX_MODE_ENFORCING: - LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n"); - avc_option.value = (char *)1; - break; - case SELINUX_MODE_PERMISSIVE: - LogMessage(X_INFO, "SELinux: Configured in permissive mode\n"); - avc_option.value = (char *)0; - break; - default: - avc_option.type = AVC_OPT_UNUSED; - break; - } - - /* Set up SELinux stuff */ - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog); - selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit); - - if (selinux_set_mapping(map) < 0) { - if (errno == EINVAL) { - ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n"); - return; - } - FatalError("SELinux: Failed to set up security class mapping\n"); - } - - if (avc_open(&avc_option, 1) < 0) - FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n"); - - if (security_get_initial_context_raw("unlabeled", &ctx) < 0) - FatalError("SELinux: Failed to look up unlabeled context\n"); - if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0) - FatalError("SELinux: a context_to_SID call failed!\n"); - freecon(ctx); - - /* Prepare for auditing */ - audit_fd = audit_open(); - if (audit_fd < 0) - FatalError("SELinux: Failed to open the system audit log\n"); - - /* Allocate private storage */ - if (!dixRegisterPrivateKey(subjectKey, PRIVATE_XSELINUX, sizeof(SELinuxSubjectRec)) || - !dixRegisterPrivateKey(objectKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec)) || - !dixRegisterPrivateKey(dataKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec))) - FatalError("SELinux: Failed to allocate private storage.\n"); - - /* Create atoms for doing window labeling */ - atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE); - if (atom_ctx == BAD_RESOURCE) - FatalError("SELinux: Failed to create atom\n"); - atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE); - if (atom_client_ctx == BAD_RESOURCE) - FatalError("SELinux: Failed to create atom\n"); - - netlink_fd = avc_netlink_acquire_fd(); - AddGeneralSocket(netlink_fd); - RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, - NULL); - - /* Register callbacks */ - ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); - ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); - - ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); - ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); - ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); - ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); - ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); - ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); - ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); - ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); - ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); - ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); - ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); - ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); - if (!ret) - FatalError("SELinux: Failed to register one or more callbacks\n"); - - /* Label objects that were created before we could register ourself */ - SELinuxLabelInitial(); -} +/************************************************************
+
+Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+this permission notice appear in supporting documentation. This permission
+notice shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+********************************************************/
+
+/*
+ * Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc.
+ * All rights reserved.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <libaudit.h>
+
+#include <X11/Xatom.h>
+#include "selection.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "propertyst.h"
+#include "extnsionst.h"
+#include "xacestr.h"
+#include "client.h"
+#include "../os/osdep.h"
+#define _XSELINUX_NEED_FLASK_MAP
+#include "xselinuxint.h"
+
+
+/* structure passed to auditing callback */
+typedef struct {
+ ClientPtr client; /* client */
+ DeviceIntPtr dev; /* device */
+ char *command; /* client's executable path */
+ unsigned id; /* resource id, if any */
+ int restype; /* resource type, if any */
+ int event; /* event type, if any */
+ Atom property; /* property name, if any */
+ Atom selection; /* selection name, if any */
+ char *extension; /* extension name, if any */
+} SELinuxAuditRec;
+
+/* private state keys */
+DevPrivateKeyRec subjectKeyRec;
+DevPrivateKeyRec objectKeyRec;
+DevPrivateKeyRec dataKeyRec;
+
+/* audit file descriptor */
+static int audit_fd;
+
+/* atoms for window label properties */
+static Atom atom_ctx;
+static Atom atom_client_ctx;
+
+/* The unlabeled SID */
+static security_id_t unlabeled_sid;
+
+/* forward declarations */
+static void SELinuxScreen(CallbackListPtr *, pointer, pointer);
+
+/* "true" pointer value for use as callback data */
+static pointer truep = (pointer)1;
+
+
+/*
+ * Performs an SELinux permission check.
+ */
+static int
+SELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj,
+ security_class_t class, Mask mode, SELinuxAuditRec *auditdata)
+{
+ /* serverClient requests OK */
+ if (subj->privileged)
+ return Success;
+
+ auditdata->command = subj->command;
+ errno = 0;
+
+ if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref,
+ auditdata) < 0) {
+ if (mode == DixUnknownAccess)
+ return Success; /* DixUnknownAccess requests OK ... for now */
+ if (errno == EACCES)
+ return BadAccess;
+ ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno);
+ return BadValue;
+ }
+
+ return Success;
+}
+
+/*
+ * Labels a newly connected client.
+ */
+static void
+SELinuxLabelClient(ClientPtr client)
+{
+ int fd = XaceGetConnectionNumber(client);
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ security_context_t ctx;
+
+ subj = dixLookupPrivate(&client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&client->devPrivates, objectKey);
+
+ /* Try to get a context from the socket */
+ if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) {
+ /* Otherwise, fall back to a default context */
+ ctx = SELinuxDefaultClientLabel();
+ }
+
+ /* For local clients, try and determine the executable name */
+ if (XaceIsLocal(client)) {
+ /* Get cached command name if CLIENTIDS is enabled. */
+ const char *cmdname = GetClientCmdName(client);
+ Bool cached = (cmdname != NULL);
+ /* If CLIENTIDS is disabled, figure out the command name from
+ * scratch. */
+ if (!cmdname)
+ {
+ pid_t pid = DetermineClientPid(client);
+ if (pid != -1)
+ DetermineClientCmd(pid, &cmdname, NULL);
+ }
+
+ if (!cmdname)
+ goto finish;
+
+ strncpy(subj->command, cmdname, COMMAND_LEN - 1);
+
+ if (!cached)
+ free((void *) cmdname); /* const char * */
+ }
+
+finish:
+ /* Get a SID from the context */
+ if (avc_context_to_sid_raw(ctx, &subj->sid) < 0)
+ FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n",
+ client->index, ctx);
+
+ obj->sid = subj->sid;
+ freecon(ctx);
+}
+
+/*
+ * Labels initial server objects.
+ */
+static void
+SELinuxLabelInitial(void)
+{
+ int i;
+ XaceScreenAccessRec srec;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ security_context_t ctx;
+ pointer unused;
+
+ /* Do the serverClient */
+ subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&serverClient->devPrivates, objectKey);
+ subj->privileged = 1;
+
+ /* Use the context of the X server process for the serverClient */
+ if (getcon_raw(&ctx) < 0)
+ FatalError("SELinux: couldn't get context of X server process\n");
+
+ /* Get a SID from the context */
+ if (avc_context_to_sid_raw(ctx, &subj->sid) < 0)
+ FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx);
+
+ obj->sid = subj->sid;
+ freecon(ctx);
+
+ srec.client = serverClient;
+ srec.access_mode = DixCreateAccess;
+ srec.status = Success;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ /* Do the screen object */
+ srec.screen = screenInfo.screens[i];
+ SELinuxScreen(NULL, NULL, &srec);
+
+ /* Do the default colormap */
+ dixLookupResourceByType(&unused, screenInfo.screens[i]->defColormap,
+ RT_COLORMAP, serverClient, DixCreateAccess);
+ }
+}
+
+/*
+ * Labels new resource objects.
+ */
+static int
+SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj,
+ SELinuxObjectRec *obj, security_class_t class)
+{
+ int offset;
+ security_id_t tsid;
+
+ /* Check for a create context */
+ if (rec->rtype & RC_DRAWABLE && subj->win_create_sid) {
+ obj->sid = subj->win_create_sid;
+ return Success;
+ }
+
+ if (rec->parent)
+ offset = dixLookupPrivateOffset(rec->ptype);
+
+ if (rec->parent && offset >= 0) {
+ /* Use the SID of the parent object in the labeling operation */
+ PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset);
+ SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey);
+ tsid = pobj->sid;
+ } else {
+ /* Use the SID of the subject */
+ tsid = subj->sid;
+ }
+
+ /* Perform a transition to obtain the final SID */
+ if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) {
+ ErrorF("SELinux: a compute_create call failed!\n");
+ return BadValue;
+ }
+
+ return Success;
+}
+
+
+/*
+ * Libselinux Callbacks
+ */
+
+static int
+SELinuxAudit(void *auditdata,
+ security_class_t class,
+ char *msgbuf,
+ size_t msgbufsize)
+{
+ SELinuxAuditRec *audit = auditdata;
+ ClientPtr client = audit->client;
+ char idNum[16];
+ const char *propertyName, *selectionName;
+ int major = -1, minor = -1;
+
+ if (client) {
+ REQUEST(xReq);
+ if (stuff) {
+ major = stuff->reqType;
+ minor = MinorOpcodeOfRequest(client);
+ }
+ }
+ if (audit->id)
+ snprintf(idNum, 16, "%x", audit->id);
+
+ propertyName = audit->property ? NameForAtom(audit->property) : NULL;
+ selectionName = audit->selection ? NameForAtom(audit->selection) : NULL;
+
+ return snprintf(msgbuf, msgbufsize,
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ (major >= 0) ? "request=" : "",
+ (major >= 0) ? LookupRequestName(major, minor) : "",
+ audit->command ? " comm=" : "",
+ audit->command ? audit->command : "",
+ audit->dev ? " xdevice=\"" : "",
+ audit->dev ? audit->dev->name : "",
+ audit->dev ? "\"" : "",
+ audit->id ? " resid=" : "",
+ audit->id ? idNum : "",
+ audit->restype ? " restype=" : "",
+ audit->restype ? LookupResourceName(audit->restype) : "",
+ audit->event ? " event=" : "",
+ audit->event ? LookupEventName(audit->event & 127) : "",
+ audit->property ? " property=" : "",
+ audit->property ? propertyName : "",
+ audit->selection ? " selection=" : "",
+ audit->selection ? selectionName : "",
+ audit->extension ? " extension=" : "",
+ audit->extension ? audit->extension : "");
+}
+
+static int
+SELinuxLog(int type, const char *fmt, ...)
+{
+ va_list ap;
+ char buf[MAX_AUDIT_MESSAGE_LENGTH];
+ int rc, aut;
+
+ switch (type) {
+ case SELINUX_INFO:
+ aut = AUDIT_USER_MAC_POLICY_LOAD;
+ break;
+ case SELINUX_AVC:
+ aut = AUDIT_USER_AVC;
+ break;
+ default:
+ aut = AUDIT_USER_SELINUX_ERR;
+ break;
+ }
+
+ va_start(ap, fmt);
+ vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap);
+ rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0);
+ va_end(ap);
+ LogMessageVerb(X_WARNING, 0, "%s", buf);
+ return 0;
+}
+
+/*
+ * XACE Callbacks
+ */
+
+static void
+SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceDeviceAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev };
+ security_class_t cls;
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey);
+
+ /* If this is a new object that needs labeling, do it now */
+ if (rec->access_mode & DixCreateAccess) {
+ SELinuxSubjectRec *dsubj;
+ dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey);
+
+ if (subj->dev_create_sid) {
+ /* Label the device with the create context */
+ obj->sid = subj->dev_create_sid;
+ dsubj->sid = subj->dev_create_sid;
+ } else {
+ /* Label the device directly with the process SID */
+ obj->sid = subj->sid;
+ dsubj->sid = subj->sid;
+ }
+ }
+
+ cls = IsPointerDevice(rec->dev) ? SECCLASS_X_POINTER : SECCLASS_X_KEYBOARD;
+ rc = SELinuxDoCheck(subj, obj, cls, rec->access_mode, &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+}
+
+static void
+SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceSendAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj, ev_sid;
+ SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev };
+ security_class_t class;
+ int rc, i, type;
+
+ if (rec->dev)
+ subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey);
+ else
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+
+ obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey);
+
+ /* Check send permission on window */
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess,
+ &auditdata);
+ if (rc != Success)
+ goto err;
+
+ /* Check send permission on specific event types */
+ for (i = 0; i < rec->count; i++) {
+ type = rec->events[i].u.u.type;
+ class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT;
+
+ rc = SELinuxEventToSID(type, obj->sid, &ev_sid);
+ if (rc != Success)
+ goto err;
+
+ auditdata.event = type;
+ rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata);
+ if (rc != Success)
+ goto err;
+ }
+ return;
+err:
+ rec->status = rc;
+}
+
+static void
+SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceReceiveAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj, ev_sid;
+ SELinuxAuditRec auditdata = { .client = NULL };
+ security_class_t class;
+ int rc, i, type;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey);
+
+ /* Check receive permission on window */
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess,
+ &auditdata);
+ if (rc != Success)
+ goto err;
+
+ /* Check receive permission on specific event types */
+ for (i = 0; i < rec->count; i++) {
+ type = rec->events[i].u.u.type;
+ class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT;
+
+ rc = SELinuxEventToSID(type, obj->sid, &ev_sid);
+ if (rc != Success)
+ goto err;
+
+ auditdata.event = type;
+ rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata);
+ if (rc != Success)
+ goto err;
+ }
+ return;
+err:
+ rec->status = rc;
+}
+
+static void
+SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceExtAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj, *serv;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client };
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey);
+
+ /* If this is a new object that needs labeling, do it now */
+ /* XXX there should be a separate callback for this */
+ if (obj->sid == NULL) {
+ security_id_t sid;
+
+ serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey);
+ rc = SELinuxExtensionToSID(rec->ext->name, &sid);
+ if (rc != Success) {
+ rec->status = rc;
+ return;
+ }
+
+ /* Perform a transition to obtain the final SID */
+ if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION,
+ &obj->sid) < 0) {
+ ErrorF("SELinux: a SID transition call failed!\n");
+ rec->status = BadValue;
+ return;
+ }
+ }
+
+ /* Perform the security check */
+ auditdata.extension = rec->ext->name;
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode,
+ &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+}
+
+static void
+SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceSelectionAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj, *data;
+ Selection *pSel = *rec->ppSel;
+ Atom name = pSel->selection;
+ Mask access_mode = rec->access_mode;
+ SELinuxAuditRec auditdata = { .client = rec->client, .selection = name };
+ security_id_t tsid;
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&pSel->devPrivates, objectKey);
+
+ /* If this is a new object that needs labeling, do it now */
+ if (access_mode & DixCreateAccess) {
+ rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly);
+ if (rc != Success)
+ obj->sid = unlabeled_sid;
+ access_mode = DixSetAttrAccess;
+ }
+ /* If this is a polyinstantiated object, find the right instance */
+ else if (obj->poly) {
+ rc = SELinuxSelectionToSID(name, subj, &tsid, NULL);
+ if (rc != Success) {
+ rec->status = rc;
+ return;
+ }
+ while (pSel->selection != name || obj->sid != tsid) {
+ if ((pSel = pSel->next) == NULL)
+ break;
+ obj = dixLookupPrivate(&pSel->devPrivates, objectKey);
+ }
+
+ if (pSel)
+ *rec->ppSel = pSel;
+ else {
+ rec->status = BadMatch;
+ return;
+ }
+ }
+
+ /* Perform the security check */
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode,
+ &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+
+ /* Label the content (advisory only) */
+ if (access_mode & DixSetAttrAccess) {
+ data = dixLookupPrivate(&pSel->devPrivates, dataKey);
+ if (subj->sel_create_sid)
+ data->sid = subj->sel_create_sid;
+ else
+ data->sid = obj->sid;
+ }
+}
+
+static void
+SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XacePropertyAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj, *data;
+ PropertyPtr pProp = *rec->ppProp;
+ Atom name = pProp->propertyName;
+ SELinuxAuditRec auditdata = { .client = rec->client, .property = name };
+ security_id_t tsid;
+ int rc;
+
+ /* Don't care about the new content check */
+ if (rec->access_mode & DixPostAccess)
+ return;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&pProp->devPrivates, objectKey);
+
+ /* If this is a new object that needs labeling, do it now */
+ if (rec->access_mode & DixCreateAccess) {
+ rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly);
+ if (rc != Success) {
+ rec->status = rc;
+ return;
+ }
+ }
+ /* If this is a polyinstantiated object, find the right instance */
+ else if (obj->poly) {
+ rc = SELinuxPropertyToSID(name, subj, &tsid, NULL);
+ if (rc != Success) {
+ rec->status = rc;
+ return;
+ }
+ while (pProp->propertyName != name || obj->sid != tsid) {
+ if ((pProp = pProp->next) == NULL)
+ break;
+ obj = dixLookupPrivate(&pProp->devPrivates, objectKey);
+ }
+
+ if (pProp)
+ *rec->ppProp = pProp;
+ else {
+ rec->status = BadMatch;
+ return;
+ }
+ }
+
+ /* Perform the security check */
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode,
+ &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+
+ /* Label the content (advisory only) */
+ if (rec->access_mode & DixWriteAccess) {
+ data = dixLookupPrivate(&pProp->devPrivates, dataKey);
+ if (subj->prp_create_sid)
+ data->sid = subj->prp_create_sid;
+ else
+ data->sid = obj->sid;
+ }
+}
+
+static void
+SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceResourceAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client };
+ Mask access_mode = rec->access_mode;
+ PrivateRec **privatePtr;
+ security_class_t class;
+ int rc, offset;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+
+ /* Determine if the resource object has a devPrivates field */
+ offset = dixLookupPrivateOffset(rec->rtype);
+ if (offset < 0) {
+ /* No: use the SID of the owning client */
+ class = SECCLASS_X_RESOURCE;
+ privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates;
+ obj = dixLookupPrivate(privatePtr, objectKey);
+ } else {
+ /* Yes: use the SID from the resource object itself */
+ class = SELinuxTypeToClass(rec->rtype);
+ privatePtr = DEVPRIV_AT(rec->res, offset);
+ obj = dixLookupPrivate(privatePtr, objectKey);
+ }
+
+ /* If this is a new object that needs labeling, do it now */
+ if (access_mode & DixCreateAccess && offset >= 0) {
+ rc = SELinuxLabelResource(rec, subj, obj, class);
+ if (rc != Success) {
+ rec->status = rc;
+ return;
+ }
+ }
+
+ /* Collapse generic resource permissions down to read/write */
+ if (class == SECCLASS_X_RESOURCE) {
+ access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */
+ access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */
+ }
+
+ /* Perform the security check */
+ auditdata.restype = rec->rtype;
+ auditdata.id = rec->id;
+ rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+
+ /* Perform the background none check on windows */
+ if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) {
+ rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata);
+ if (rc != Success)
+ ((WindowPtr)rec->res)->forcedBG = TRUE;
+ }
+}
+
+static void
+SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata)
+{
+ XaceScreenAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client };
+ Mask access_mode = rec->access_mode;
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey);
+
+ /* If this is a new object that needs labeling, do it now */
+ if (access_mode & DixCreateAccess) {
+ /* Perform a transition to obtain the final SID */
+ if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN,
+ &obj->sid) < 0) {
+ ErrorF("SELinux: a compute_create call failed!\n");
+ rec->status = BadValue;
+ return;
+ }
+ }
+
+ if (is_saver)
+ access_mode <<= 2;
+
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+}
+
+static void
+SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceClientAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client };
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&rec->target->devPrivates, objectKey);
+
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode,
+ &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+}
+
+static void
+SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ XaceServerAccessRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ SELinuxAuditRec auditdata = { .client = rec->client };
+ int rc;
+
+ subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey);
+ obj = dixLookupPrivate(&serverClient->devPrivates, objectKey);
+
+ rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode,
+ &auditdata);
+ if (rc != Success)
+ rec->status = rc;
+}
+
+
+/*
+ * DIX Callbacks
+ */
+
+static void
+SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ NewClientInfoRec *pci = calldata;
+
+ switch (pci->client->clientState) {
+ case ClientStateInitial:
+ SELinuxLabelClient(pci->client);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+{
+ ResourceStateInfoRec *rec = calldata;
+ SELinuxSubjectRec *subj;
+ SELinuxObjectRec *obj;
+ WindowPtr pWin;
+
+ if (rec->type != RT_WINDOW)
+ return;
+ if (rec->state != ResourceStateAdding)
+ return;
+
+ pWin = (WindowPtr)rec->value;
+ subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey);
+
+ if (subj->sid) {
+ security_context_t ctx;
+ int rc = avc_sid_to_context_raw(subj->sid, &ctx);
+ if (rc < 0)
+ FatalError("SELinux: Failed to get security context!\n");
+ rc = dixChangeWindowProperty(serverClient,
+ pWin, atom_client_ctx, XA_STRING, 8,
+ PropModeReplace, strlen(ctx), ctx, FALSE);
+ if (rc != Success)
+ FatalError("SELinux: Failed to set label property on window!\n");
+ freecon(ctx);
+ } else
+ FatalError("SELinux: Unexpected unlabeled client found\n");
+
+ obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
+
+ if (obj->sid) {
+ security_context_t ctx;
+ int rc = avc_sid_to_context_raw(obj->sid, &ctx);
+ if (rc < 0)
+ FatalError("SELinux: Failed to get security context!\n");
+ rc = dixChangeWindowProperty(serverClient,
+ pWin, atom_ctx, XA_STRING, 8,
+ PropModeReplace, strlen(ctx), ctx, FALSE);
+ if (rc != Success)
+ FatalError("SELinux: Failed to set label property on window!\n");
+ freecon(ctx);
+ } else
+ FatalError("SELinux: Unexpected unlabeled window found\n");
+}
+
+
+static int netlink_fd;
+
+static void
+SELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask)
+{
+}
+
+static void
+SELinuxWakeupHandler(void *data, int err, void *read_mask)
+{
+ if (FD_ISSET(netlink_fd, (fd_set *)read_mask))
+ avc_netlink_check_nb();
+}
+
+void
+SELinuxFlaskReset(void)
+{
+ /* Unregister callbacks */
+ DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL);
+ DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
+
+ XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
+ XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
+ XaceDeleteCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL);
+ XaceDeleteCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL);
+ XaceDeleteCallback(XACE_SEND_ACCESS, SELinuxSend, NULL);
+ XaceDeleteCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL);
+ XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
+ XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
+ XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
+ XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
+ XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
+ XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
+
+ /* Tear down SELinux stuff */
+ audit_close(audit_fd);
+ avc_netlink_release_fd();
+ RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler,
+ NULL);
+ RemoveGeneralSocket(netlink_fd);
+
+ avc_destroy();
+}
+
+void
+SELinuxFlaskInit(void)
+{
+ struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 };
+ security_context_t ctx;
+ int ret = TRUE;
+
+ switch(selinuxEnforcingState) {
+ case SELINUX_MODE_ENFORCING:
+ LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n");
+ avc_option.value = (char *)1;
+ break;
+ case SELINUX_MODE_PERMISSIVE:
+ LogMessage(X_INFO, "SELinux: Configured in permissive mode\n");
+ avc_option.value = (char *)0;
+ break;
+ default:
+ avc_option.type = AVC_OPT_UNUSED;
+ break;
+ }
+
+ /* Set up SELinux stuff */
+ selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog);
+ selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit);
+
+ if (selinux_set_mapping(map) < 0) {
+ if (errno == EINVAL) {
+ ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n");
+ return;
+ }
+ FatalError("SELinux: Failed to set up security class mapping\n");
+ }
+
+ if (avc_open(&avc_option, 1) < 0)
+ FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n");
+
+ if (security_get_initial_context_raw("unlabeled", &ctx) < 0)
+ FatalError("SELinux: Failed to look up unlabeled context\n");
+ if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0)
+ FatalError("SELinux: a context_to_SID call failed!\n");
+ freecon(ctx);
+
+ /* Prepare for auditing */
+ audit_fd = audit_open();
+ if (audit_fd < 0)
+ FatalError("SELinux: Failed to open the system audit log\n");
+
+ /* Allocate private storage */
+ if (!dixRegisterPrivateKey(subjectKey, PRIVATE_XSELINUX, sizeof(SELinuxSubjectRec)) ||
+ !dixRegisterPrivateKey(objectKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec)) ||
+ !dixRegisterPrivateKey(dataKey, PRIVATE_XSELINUX, sizeof(SELinuxObjectRec)))
+ FatalError("SELinux: Failed to allocate private storage.\n");
+
+ /* Create atoms for doing window labeling */
+ atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE);
+ if (atom_ctx == BAD_RESOURCE)
+ FatalError("SELinux: Failed to create atom\n");
+ atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE);
+ if (atom_client_ctx == BAD_RESOURCE)
+ FatalError("SELinux: Failed to create atom\n");
+
+ netlink_fd = avc_netlink_acquire_fd();
+ AddGeneralSocket(netlink_fd);
+ RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler,
+ NULL);
+
+ /* Register callbacks */
+ ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL);
+ ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL);
+
+ ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL);
+ ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL);
+ ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL);
+ ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL);
+ ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL);
+ ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL);
+ ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL);
+ ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL);
+ ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL);
+ ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL);
+ ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL);
+ ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep);
+ if (!ret)
+ FatalError("SELinux: Failed to register one or more callbacks\n");
+
+ /* Label objects that were created before we could register ourself */
+ SELinuxLabelInitial();
+}
diff --git a/xorg-server/Xext/xvdix.h b/xorg-server/Xext/xvdix.h index e9c22bf65..58069f040 100644 --- a/xorg-server/Xext/xvdix.h +++ b/xorg-server/Xext/xvdix.h @@ -1,275 +1,275 @@ -/*********************************************************** -Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, -and the Massachusetts Institute of Technology, Cambridge, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Digital or MIT not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - -#ifndef XVDIX_H -#define XVDIX_H -/* -** File: -** -** xvdix.h --- Xv device independent header file -** -** Author: -** -** David Carver (Digital Workstation Engineering/Project Athena) -** -** Revisions: -** -** 29.08.91 Carver -** - removed UnrealizeWindow wrapper unrealizing windows no longer -** preempts video -** -** 11.06.91 Carver -** - changed SetPortControl to SetPortAttribute -** - changed GetPortControl to GetPortAttribute -** - changed QueryBestSize -** -** 15.05.91 Carver -** - version 2.0 upgrade -** -** 24.01.91 Carver -** - version 1.4 upgrade -** -*/ - -#include "scrnintstr.h" -#include <X11/extensions/Xvproto.h> - -#ifndef XorgLoader -extern _X_EXPORT unsigned long XvExtensionGeneration; -extern _X_EXPORT unsigned long XvScreenGeneration; -extern _X_EXPORT unsigned long XvResourceGeneration; - -extern _X_EXPORT int XvReqCode; -extern _X_EXPORT int XvEventBase; -extern _X_EXPORT int XvErrorBase; - -extern _X_EXPORT RESTYPE XvRTPort; -extern _X_EXPORT RESTYPE XvRTEncoding; -extern _X_EXPORT RESTYPE XvRTGrab; -extern _X_EXPORT RESTYPE XvRTVideoNotify; -extern _X_EXPORT RESTYPE XvRTVideoNotifyList; -extern _X_EXPORT RESTYPE XvRTPortNotify; -#endif - -typedef struct { - int numerator; - int denominator; -} XvRationalRec, *XvRationalPtr; - -typedef struct { - char depth; - unsigned long visual; -} XvFormatRec, *XvFormatPtr; - -typedef struct { - unsigned long id; - ClientPtr client; -} XvGrabRec, *XvGrabPtr; - -typedef struct _XvVideoNotifyRec { - struct _XvVideoNotifyRec *next; - ClientPtr client; - unsigned long id; - unsigned long mask; -} XvVideoNotifyRec, *XvVideoNotifyPtr; - -typedef struct _XvPortNotifyRec { - struct _XvPortNotifyRec *next; - ClientPtr client; - unsigned long id; -} XvPortNotifyRec, *XvPortNotifyPtr; - -typedef struct { - int id; - ScreenPtr pScreen; - char *name; - unsigned short width, height; - XvRationalRec rate; -} XvEncodingRec, *XvEncodingPtr; - -typedef struct _XvAttributeRec { - int flags; - int min_value; - int max_value; - char *name; -} XvAttributeRec, *XvAttributePtr; - -typedef struct { - int id; - int type; - int byte_order; - char guid[16]; - int bits_per_pixel; - int format; - int num_planes; - - /* for RGB formats only */ - int depth; - unsigned int red_mask; - unsigned int green_mask; - unsigned int blue_mask; - - /* for YUV formats only */ - unsigned int y_sample_bits; - unsigned int u_sample_bits; - unsigned int v_sample_bits; - unsigned int horz_y_period; - unsigned int horz_u_period; - unsigned int horz_v_period; - unsigned int vert_y_period; - unsigned int vert_u_period; - unsigned int vert_v_period; - char component_order[32]; - int scanline_order; -} XvImageRec, *XvImagePtr; - -typedef struct { - unsigned long base_id; - unsigned char type; - char *name; - int nEncodings; - XvEncodingPtr pEncodings; - int nFormats; - XvFormatPtr pFormats; - int nAttributes; - XvAttributePtr pAttributes; - int nImages; - XvImagePtr pImages; - int nPorts; - struct _XvPortRec *pPorts; - ScreenPtr pScreen; - int (* ddAllocatePort)(unsigned long, struct _XvPortRec*, - struct _XvPortRec**); - int (* ddFreePort)(struct _XvPortRec*); - int (* ddPutVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); - int (* ddPutStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); - int (* ddGetVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); - int (* ddGetStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); - int (* ddStopVideo)(ClientPtr, struct _XvPortRec*, DrawablePtr); - int (* ddSetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32); - int (* ddGetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32*); - int (* ddQueryBestSize)(ClientPtr, struct _XvPortRec*, CARD8, - CARD16, CARD16,CARD16, CARD16, - unsigned int*, unsigned int*); - int (* ddPutImage)(ClientPtr, DrawablePtr, struct _XvPortRec*, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16, - XvImagePtr, unsigned char*, Bool, - CARD16, CARD16); - int (* ddQueryImageAttributes)(ClientPtr, struct _XvPortRec*, XvImagePtr, - CARD16*, CARD16*, int*, int*); - DevUnion devPriv; -} XvAdaptorRec, *XvAdaptorPtr; - -typedef struct _XvPortRec { - unsigned long id; - XvAdaptorPtr pAdaptor; - XvPortNotifyPtr pNotify; - DrawablePtr pDraw; - ClientPtr client; - XvGrabRec grab; - TimeStamp time; - DevUnion devPriv; -} XvPortRec, *XvPortPtr; - -#define VALIDATE_XV_PORT(portID, pPort, mode)\ - {\ - int rc = dixLookupResourceByType((pointer *)&(pPort), portID,\ - XvRTPort, client, mode);\ - if (rc != Success)\ - return rc;\ - } - -typedef struct { - int version, revision; - int nAdaptors; - XvAdaptorPtr pAdaptors; - DestroyWindowProcPtr DestroyWindow; - DestroyPixmapProcPtr DestroyPixmap; - CloseScreenProcPtr CloseScreen; - Bool (* ddCloseScreen)(int, ScreenPtr); - int (* ddQueryAdaptors)(ScreenPtr, XvAdaptorPtr*, int*); - DevUnion devPriv; -} XvScreenRec, *XvScreenPtr; - -#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = ((XvScreenPtr) \ - dixLookupPrivate(&(pScreen)->devPrivates, XvScreenKey))->field) - -#define SCREEN_EPILOGUE(pScreen, field, wrapper)\ - ((pScreen)->field = wrapper) - -/* Errors */ - -#define _XvBadPort (XvBadPort+XvErrorBase) -#define _XvBadEncoding (XvBadEncoding+XvErrorBase) - -#ifndef XorgLoader -extern _X_EXPORT int ProcXvDispatch(ClientPtr); -extern _X_EXPORT int SProcXvDispatch(ClientPtr); - -extern _X_EXPORT void XvExtensionInit(void); -extern _X_EXPORT int XvScreenInit(ScreenPtr); -extern _X_EXPORT DevPrivateKey XvGetScreenKey(void); -extern _X_EXPORT unsigned long XvGetRTPort(void); -extern _X_EXPORT int XvdiSendPortNotify(XvPortPtr, Atom, INT32); -extern _X_EXPORT int XvdiVideoStopped(XvPortPtr, int); - -extern _X_EXPORT int XvdiPutVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -extern _X_EXPORT int XvdiPutStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -extern _X_EXPORT int XvdiGetVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -extern _X_EXPORT int XvdiGetStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16); -extern _X_EXPORT int XvdiPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr, - INT16, INT16, CARD16, CARD16, - INT16, INT16, CARD16, CARD16, - XvImagePtr, unsigned char*, Bool, - CARD16, CARD16); -extern _X_EXPORT int XvdiSelectVideoNotify(ClientPtr, DrawablePtr, BOOL); -extern _X_EXPORT int XvdiSelectPortNotify(ClientPtr, XvPortPtr, BOOL); -extern _X_EXPORT int XvdiSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32); -extern _X_EXPORT int XvdiGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*); -extern _X_EXPORT int XvdiStopVideo(ClientPtr, XvPortPtr, DrawablePtr); -extern _X_EXPORT int XvdiPreemptVideo(ClientPtr, XvPortPtr, DrawablePtr); -extern _X_EXPORT int XvdiMatchPort(XvPortPtr, DrawablePtr); -extern _X_EXPORT int XvdiGrabPort(ClientPtr, XvPortPtr, Time, int *); -extern _X_EXPORT int XvdiUngrabPort( ClientPtr, XvPortPtr, Time); -#endif /* XorgLoader */ - -#endif /* XVDIX_H */ - +/***********************************************************
+Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
+and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Digital or MIT not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+#ifndef XVDIX_H
+#define XVDIX_H
+/*
+** File:
+**
+** xvdix.h --- Xv device independent header file
+**
+** Author:
+**
+** David Carver (Digital Workstation Engineering/Project Athena)
+**
+** Revisions:
+**
+** 29.08.91 Carver
+** - removed UnrealizeWindow wrapper unrealizing windows no longer
+** preempts video
+**
+** 11.06.91 Carver
+** - changed SetPortControl to SetPortAttribute
+** - changed GetPortControl to GetPortAttribute
+** - changed QueryBestSize
+**
+** 15.05.91 Carver
+** - version 2.0 upgrade
+**
+** 24.01.91 Carver
+** - version 1.4 upgrade
+**
+*/
+
+#include "scrnintstr.h"
+#include <X11/extensions/Xvproto.h>
+
+#ifndef XorgLoader
+extern _X_EXPORT unsigned long XvExtensionGeneration;
+extern _X_EXPORT unsigned long XvScreenGeneration;
+extern _X_EXPORT unsigned long XvResourceGeneration;
+
+extern _X_EXPORT int XvReqCode;
+extern _X_EXPORT int XvEventBase;
+extern _X_EXPORT int XvErrorBase;
+
+extern _X_EXPORT RESTYPE XvRTPort;
+extern _X_EXPORT RESTYPE XvRTEncoding;
+extern _X_EXPORT RESTYPE XvRTGrab;
+extern _X_EXPORT RESTYPE XvRTVideoNotify;
+extern _X_EXPORT RESTYPE XvRTVideoNotifyList;
+extern _X_EXPORT RESTYPE XvRTPortNotify;
+#endif
+
+typedef struct {
+ int numerator;
+ int denominator;
+} XvRationalRec, *XvRationalPtr;
+
+typedef struct {
+ char depth;
+ unsigned long visual;
+} XvFormatRec, *XvFormatPtr;
+
+typedef struct {
+ unsigned long id;
+ ClientPtr client;
+} XvGrabRec, *XvGrabPtr;
+
+typedef struct _XvVideoNotifyRec {
+ struct _XvVideoNotifyRec *next;
+ ClientPtr client;
+ unsigned long id;
+ unsigned long mask;
+} XvVideoNotifyRec, *XvVideoNotifyPtr;
+
+typedef struct _XvPortNotifyRec {
+ struct _XvPortNotifyRec *next;
+ ClientPtr client;
+ unsigned long id;
+} XvPortNotifyRec, *XvPortNotifyPtr;
+
+typedef struct {
+ int id;
+ ScreenPtr pScreen;
+ char *name;
+ unsigned short width, height;
+ XvRationalRec rate;
+} XvEncodingRec, *XvEncodingPtr;
+
+typedef struct _XvAttributeRec {
+ int flags;
+ int min_value;
+ int max_value;
+ char *name;
+} XvAttributeRec, *XvAttributePtr;
+
+typedef struct {
+ int id;
+ int type;
+ int byte_order;
+ char guid[16];
+ int bits_per_pixel;
+ int format;
+ int num_planes;
+
+ /* for RGB formats only */
+ int depth;
+ unsigned int red_mask;
+ unsigned int green_mask;
+ unsigned int blue_mask;
+
+ /* for YUV formats only */
+ unsigned int y_sample_bits;
+ unsigned int u_sample_bits;
+ unsigned int v_sample_bits;
+ unsigned int horz_y_period;
+ unsigned int horz_u_period;
+ unsigned int horz_v_period;
+ unsigned int vert_y_period;
+ unsigned int vert_u_period;
+ unsigned int vert_v_period;
+ char component_order[32];
+ int scanline_order;
+} XvImageRec, *XvImagePtr;
+
+typedef struct {
+ unsigned long base_id;
+ unsigned char type;
+ char *name;
+ int nEncodings;
+ XvEncodingPtr pEncodings;
+ int nFormats;
+ XvFormatPtr pFormats;
+ int nAttributes;
+ XvAttributePtr pAttributes;
+ int nImages;
+ XvImagePtr pImages;
+ int nPorts;
+ struct _XvPortRec *pPorts;
+ ScreenPtr pScreen;
+ int (* ddAllocatePort)(unsigned long, struct _XvPortRec*,
+ struct _XvPortRec**);
+ int (* ddFreePort)(struct _XvPortRec*);
+ int (* ddPutVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+ int (* ddPutStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+ int (* ddGetVideo)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+ int (* ddGetStill)(ClientPtr, DrawablePtr,struct _XvPortRec*, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+ int (* ddStopVideo)(ClientPtr, struct _XvPortRec*, DrawablePtr);
+ int (* ddSetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32);
+ int (* ddGetPortAttribute)(ClientPtr, struct _XvPortRec*, Atom, INT32*);
+ int (* ddQueryBestSize)(ClientPtr, struct _XvPortRec*, CARD8,
+ CARD16, CARD16,CARD16, CARD16,
+ unsigned int*, unsigned int*);
+ int (* ddPutImage)(ClientPtr, DrawablePtr, struct _XvPortRec*, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16,
+ XvImagePtr, unsigned char*, Bool,
+ CARD16, CARD16);
+ int (* ddQueryImageAttributes)(ClientPtr, struct _XvPortRec*, XvImagePtr,
+ CARD16*, CARD16*, int*, int*);
+ DevUnion devPriv;
+} XvAdaptorRec, *XvAdaptorPtr;
+
+typedef struct _XvPortRec {
+ unsigned long id;
+ XvAdaptorPtr pAdaptor;
+ XvPortNotifyPtr pNotify;
+ DrawablePtr pDraw;
+ ClientPtr client;
+ XvGrabRec grab;
+ TimeStamp time;
+ DevUnion devPriv;
+} XvPortRec, *XvPortPtr;
+
+#define VALIDATE_XV_PORT(portID, pPort, mode)\
+ {\
+ int rc = dixLookupResourceByType((pointer *)&(pPort), portID,\
+ XvRTPort, client, mode);\
+ if (rc != Success)\
+ return rc;\
+ }
+
+typedef struct {
+ int version, revision;
+ int nAdaptors;
+ XvAdaptorPtr pAdaptors;
+ DestroyWindowProcPtr DestroyWindow;
+ DestroyPixmapProcPtr DestroyPixmap;
+ CloseScreenProcPtr CloseScreen;
+ Bool (* ddCloseScreen)(int, ScreenPtr);
+ int (* ddQueryAdaptors)(ScreenPtr, XvAdaptorPtr*, int*);
+ DevUnion devPriv;
+} XvScreenRec, *XvScreenPtr;
+
+#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = ((XvScreenPtr) \
+ dixLookupPrivate(&(pScreen)->devPrivates, XvScreenKey))->field)
+
+#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
+ ((pScreen)->field = wrapper)
+
+/* Errors */
+
+#define _XvBadPort (XvBadPort+XvErrorBase)
+#define _XvBadEncoding (XvBadEncoding+XvErrorBase)
+
+#ifndef XorgLoader
+extern _X_EXPORT int ProcXvDispatch(ClientPtr);
+extern _X_EXPORT int SProcXvDispatch(ClientPtr);
+
+extern _X_EXPORT void XvExtensionInit(void);
+extern _X_EXPORT int XvScreenInit(ScreenPtr);
+extern _X_EXPORT DevPrivateKey XvGetScreenKey(void);
+extern _X_EXPORT unsigned long XvGetRTPort(void);
+extern _X_EXPORT int XvdiSendPortNotify(XvPortPtr, Atom, INT32);
+extern _X_EXPORT int XvdiVideoStopped(XvPortPtr, int);
+
+extern _X_EXPORT int XvdiPutVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+extern _X_EXPORT int XvdiPutStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+extern _X_EXPORT int XvdiGetVideo(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+extern _X_EXPORT int XvdiGetStill(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16);
+extern _X_EXPORT int XvdiPutImage(ClientPtr, DrawablePtr, XvPortPtr, GCPtr,
+ INT16, INT16, CARD16, CARD16,
+ INT16, INT16, CARD16, CARD16,
+ XvImagePtr, unsigned char*, Bool,
+ CARD16, CARD16);
+extern _X_EXPORT int XvdiSelectVideoNotify(ClientPtr, DrawablePtr, BOOL);
+extern _X_EXPORT int XvdiSelectPortNotify(ClientPtr, XvPortPtr, BOOL);
+extern _X_EXPORT int XvdiSetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32);
+extern _X_EXPORT int XvdiGetPortAttribute(ClientPtr, XvPortPtr, Atom, INT32*);
+extern _X_EXPORT int XvdiStopVideo(ClientPtr, XvPortPtr, DrawablePtr);
+extern _X_EXPORT int XvdiPreemptVideo(ClientPtr, XvPortPtr, DrawablePtr);
+extern _X_EXPORT int XvdiMatchPort(XvPortPtr, DrawablePtr);
+extern _X_EXPORT int XvdiGrabPort(ClientPtr, XvPortPtr, Time, int *);
+extern _X_EXPORT int XvdiUngrabPort( ClientPtr, XvPortPtr, Time);
+#endif /* XorgLoader */
+
+#endif /* XVDIX_H */
+
diff --git a/xorg-server/Xext/xvmain.c b/xorg-server/Xext/xvmain.c index cd6f0979c..bbd2b3c6c 100644 --- a/xorg-server/Xext/xvmain.c +++ b/xorg-server/Xext/xvmain.c @@ -1,1183 +1,1183 @@ -/*********************************************************** -Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, -and the Massachusetts Institute of Technology, Cambridge, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the names of Digital or MIT not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - -/* -** File: -** -** xvmain.c --- Xv server extension main device independent module. -** -** Author: -** -** David Carver (Digital Workstation Engineering/Project Athena) -** -** Revisions: -** -** 04.09.91 Carver -** - change: stop video always generates an event even when video -** wasn't active -** -** 29.08.91 Carver -** - change: unrealizing windows no longer preempts video -** -** 11.06.91 Carver -** - changed SetPortControl to SetPortAttribute -** - changed GetPortControl to GetPortAttribute -** - changed QueryBestSize -** -** 28.05.91 Carver -** - fixed Put and Get requests to not preempt operations to same drawable -** -** 15.05.91 Carver -** - version 2.0 upgrade -** -** 19.03.91 Carver -** - fixed Put and Get requests to honor grabbed ports. -** - fixed Video requests to update di structure with new drawable, and -** client after calling ddx. -** -** 24.01.91 Carver -** - version 1.4 upgrade -** -** Notes: -** -** Port structures reference client structures in a two different -** ways: when grabs, or video is active. Each reference is encoded -** as fake client resources and thus when the client is goes away so -** does the reference (it is zeroed). No other action is taken, so -** video doesn't necessarily stop. It probably will as a result of -** other resources going away, but if a client starts video using -** none of its own resources, then the video will continue to play -** after the client disappears. -** -** -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <string.h> - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "misc.h" -#include "os.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "gc.h" -#include "extnsionst.h" -#include "dixstruct.h" -#include "resource.h" -#include "opaque.h" -#include "input.h" - -#define GLOBAL - -#include <X11/extensions/Xv.h> -#include <X11/extensions/Xvproto.h> -#include "xvdix.h" - -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" -#endif -#include "xvdisp.h" - -static DevPrivateKeyRec XvScreenKeyRec; -#define XvScreenKey (&XvScreenKeyRec) -unsigned long XvExtensionGeneration = 0; -unsigned long XvScreenGeneration = 0; -unsigned long XvResourceGeneration = 0; - -int XvReqCode; -int XvEventBase; -int XvErrorBase; - -RESTYPE XvRTPort; -RESTYPE XvRTEncoding; -RESTYPE XvRTGrab; -RESTYPE XvRTVideoNotify; -RESTYPE XvRTVideoNotifyList; -RESTYPE XvRTPortNotify; - -/* EXTERNAL */ - -static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *); -static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *); -static Bool CreateResourceTypes(void); - -static Bool XvCloseScreen(int, ScreenPtr); -static Bool XvDestroyPixmap(PixmapPtr); -static Bool XvDestroyWindow(WindowPtr); -static void XvResetProc(ExtensionEntry*); -static int XvdiDestroyGrab(pointer, XID); -static int XvdiDestroyEncoding(pointer, XID); -static int XvdiDestroyVideoNotify(pointer, XID); -static int XvdiDestroyPortNotify(pointer, XID); -static int XvdiDestroyVideoNotifyList(pointer, XID); -static int XvdiDestroyPort(pointer, XID); -static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int); - - - - -/* -** XvExtensionInit -** -** -*/ - -void -XvExtensionInit(void) -{ - ExtensionEntry *extEntry; - - if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0)) - return; - - /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN - INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */ - if (XvScreenGeneration != serverGeneration) - { - if (!CreateResourceTypes()) - { - ErrorF("XvExtensionInit: Unable to allocate resource types\n"); - return; - } -#ifdef PANORAMIX - XineramaRegisterConnectionBlockCallback(XineramifyXv); -#endif - XvScreenGeneration = serverGeneration; - } - - if (XvExtensionGeneration != serverGeneration) - { - XvExtensionGeneration = serverGeneration; - - extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors, - ProcXvDispatch, SProcXvDispatch, - XvResetProc, StandardMinorOpcode); - if (!extEntry) - { - FatalError("XvExtensionInit: AddExtensions failed\n"); - } - - XvReqCode = extEntry->base; - XvEventBase = extEntry->eventBase; - XvErrorBase = extEntry->errorBase; - - EventSwapVector[XvEventBase+XvVideoNotify] = - (EventSwapPtr)WriteSwappedVideoNotifyEvent; - EventSwapVector[XvEventBase+XvPortNotify] = - (EventSwapPtr)WriteSwappedPortNotifyEvent; - - SetResourceTypeErrorValue(XvRTPort, _XvBadPort); - (void)MakeAtom(XvName, strlen(XvName), xTrue); - - } -} - -static Bool -CreateResourceTypes(void) - -{ - - if (XvResourceGeneration == serverGeneration) return TRUE; - - XvResourceGeneration = serverGeneration; - - if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort"))) - { - ErrorF("CreateResourceTypes: failed to allocate port resource.\n"); - return FALSE; - } - - if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab"))) - { - ErrorF("CreateResourceTypes: failed to allocate grab resource.\n"); - return FALSE; - } - - if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding, - "XvRTEncoding"))) - { - ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n"); - return FALSE; - } - - if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify, - "XvRTVideoNotify"))) - { - ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n"); - return FALSE; - } - - if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList, - "XvRTVideoNotifyList"))) - { - ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n"); - return FALSE; - } - - if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify, - "XvRTPortNotify"))) - { - ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n"); - return FALSE; - } - - return TRUE; - -} - -int -XvScreenInit(ScreenPtr pScreen) -{ - XvScreenPtr pxvs; - - if (XvScreenGeneration != serverGeneration) - { - if (!CreateResourceTypes()) - { - ErrorF("XvScreenInit: Unable to allocate resource types\n"); - return BadAlloc; - } -#ifdef PANORAMIX - XineramaRegisterConnectionBlockCallback(XineramifyXv); -#endif - XvScreenGeneration = serverGeneration; - } - - if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0)) - return BadAlloc; - - if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey)) - { - ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n"); - } - - /* ALLOCATE SCREEN PRIVATE RECORD */ - - pxvs = malloc(sizeof (XvScreenRec)); - if (!pxvs) - { - ErrorF("XvScreenInit: Unable to allocate screen private structure\n"); - return BadAlloc; - } - - dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs); - - pxvs->DestroyPixmap = pScreen->DestroyPixmap; - pxvs->DestroyWindow = pScreen->DestroyWindow; - pxvs->CloseScreen = pScreen->CloseScreen; - - pScreen->DestroyPixmap = XvDestroyPixmap; - pScreen->DestroyWindow = XvDestroyWindow; - pScreen->CloseScreen = XvCloseScreen; - - return Success; -} - -static Bool -XvCloseScreen( - int ii, - ScreenPtr pScreen -){ - - XvScreenPtr pxvs; - - pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); - - pScreen->DestroyPixmap = pxvs->DestroyPixmap; - pScreen->DestroyWindow = pxvs->DestroyWindow; - pScreen->CloseScreen = pxvs->CloseScreen; - - (* pxvs->ddCloseScreen)(ii, pScreen); - - free(pxvs); - - dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL); - - return (*pScreen->CloseScreen)(ii, pScreen); -} - -static void -XvResetProc(ExtensionEntry* extEntry) -{ - XvResetProcVector(); -} - -DevPrivateKey -XvGetScreenKey(void) -{ - return XvScreenKey; -} - -unsigned long -XvGetRTPort(void) -{ - return XvRTPort; -} - -static Bool -XvDestroyPixmap(PixmapPtr pPix) -{ - Bool status; - ScreenPtr pScreen; - XvScreenPtr pxvs; - XvAdaptorPtr pa; - int na; - XvPortPtr pp; - int np; - - pScreen = pPix->drawable.pScreen; - - SCREEN_PROLOGUE(pScreen, DestroyPixmap); - - pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); - - /* CHECK TO SEE IF THIS PORT IS IN USE */ - - pa = pxvs->pAdaptors; - na = pxvs->nAdaptors; - while (na--) - { - np = pa->nPorts; - pp = pa->pPorts; - - while (np--) - { - if (pp->pDraw == (DrawablePtr)pPix) - { - XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); - - (void)(* pp->pAdaptor->ddStopVideo)(NULL, pp, pp->pDraw); - - pp->pDraw = NULL; - pp->client = NULL; - pp->time = currentTime; - } - pp++; - } - pa++; - } - - status = (* pScreen->DestroyPixmap)(pPix); - - SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap); - - return status; - -} - -static Bool -XvDestroyWindow(WindowPtr pWin) -{ - Bool status; - ScreenPtr pScreen; - XvScreenPtr pxvs; - XvAdaptorPtr pa; - int na; - XvPortPtr pp; - int np; - - pScreen = pWin->drawable.pScreen; - - SCREEN_PROLOGUE(pScreen, DestroyWindow); - - pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); - - /* CHECK TO SEE IF THIS PORT IS IN USE */ - - pa = pxvs->pAdaptors; - na = pxvs->nAdaptors; - while (na--) - { - np = pa->nPorts; - pp = pa->pPorts; - - while (np--) - { - if (pp->pDraw == (DrawablePtr)pWin) - { - XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); - - (void)(* pp->pAdaptor->ddStopVideo)(NULL, pp, pp->pDraw); - - pp->pDraw = NULL; - pp->client = NULL; - pp->time = currentTime; - } - pp++; - } - pa++; - } - - - status = (* pScreen->DestroyWindow)(pWin); - - SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow); - - return status; - -} - -/* The XvdiVideoStopped procedure is a hook for the device dependent layer. - It provides a way for the dd layer to inform the di layer that video has - stopped in a port for reasons that the di layer had no control over; note - that it doesn't call back into the dd layer */ - -int -XvdiVideoStopped(XvPortPtr pPort, int reason) -{ - - /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ - - if (!pPort->pDraw) return Success; - - XvdiSendVideoNotify(pPort, pPort->pDraw, reason); - - pPort->pDraw = NULL; - pPort->client = NULL; - pPort->time = currentTime; - - return Success; - -} - -static int -XvdiDestroyPort(pointer pPort, XID id) -{ - return (* ((XvPortPtr)pPort)->pAdaptor->ddFreePort)(pPort); -} - -static int -XvdiDestroyGrab(pointer pGrab, XID id) -{ - ((XvGrabPtr)pGrab)->client = NULL; - return Success; -} - -static int -XvdiDestroyVideoNotify(pointer pn, XID id) -{ - /* JUST CLEAR OUT THE client POINTER FIELD */ - - ((XvVideoNotifyPtr)pn)->client = NULL; - return Success; -} - -static int -XvdiDestroyPortNotify(pointer pn, XID id) -{ - /* JUST CLEAR OUT THE client POINTER FIELD */ - - ((XvPortNotifyPtr)pn)->client = NULL; - return Success; -} - -static int -XvdiDestroyVideoNotifyList(pointer pn, XID id) -{ - XvVideoNotifyPtr npn,cpn; - - /* ACTUALLY DESTROY THE NOTITY LIST */ - - cpn = (XvVideoNotifyPtr)pn; - - while (cpn) - { - npn = cpn->next; - if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify); - free(cpn); - cpn = npn; - } - return Success; -} - -static int -XvdiDestroyEncoding(pointer value, XID id) -{ - return Success; -} - -static int -XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason) -{ - xvEvent event; - XvVideoNotifyPtr pn; - - dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList, - serverClient, DixReadAccess); - - while (pn) - { - event.u.u.type = XvEventBase + XvVideoNotify; - event.u.videoNotify.time = currentTime.milliseconds; - event.u.videoNotify.drawable = pDraw->id; - event.u.videoNotify.port = pPort->id; - event.u.videoNotify.reason = reason; - WriteEventsToClient(pn->client, 1, (xEventPtr)&event); - pn = pn->next; - } - - return Success; - -} - - -int -XvdiSendPortNotify( - XvPortPtr pPort, - Atom attribute, - INT32 value -){ - xvEvent event; - XvPortNotifyPtr pn; - - pn = pPort->pNotify; - - while (pn) - { - event.u.u.type = XvEventBase + XvPortNotify; - event.u.portNotify.time = currentTime.milliseconds; - event.u.portNotify.port = pPort->id; - event.u.portNotify.attribute = attribute; - event.u.portNotify.value = value; - WriteEventsToClient(pn->client, 1, (xEventPtr)&event); - pn = pn->next; - } - - return Success; - -} - - -#define CHECK_SIZE(dw, dh, sw, sh) { \ - if(!dw || !dh || !sw || !sh) return Success; \ - /* The region code will break these if they are too large */ \ - if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767)) \ - return BadValue; \ -} - - -int -XvdiPutVideo( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - DrawablePtr pOldDraw; - - CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); - - /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ - - UpdateCurrentTime(); - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if (pPort->grab.client && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED - EVENTS TO ANY CLIENTS WHO WANT THEM */ - - pOldDraw = pPort->pDraw; - if ((pOldDraw) && (pOldDraw != pDraw)) - { - XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); - } - - (void) (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC, - vid_x, vid_y, vid_w, vid_h, - drw_x, drw_y, drw_w, drw_h); - - if ((pPort->pDraw) && (pOldDraw != pDraw)) - { - pPort->client = client; - XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); - } - - pPort->time = currentTime; - - return Success; - -} - -int -XvdiPutStill( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - int status; - - CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); - - /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ - - UpdateCurrentTime(); - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if (pPort->grab.client && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - pPort->time = currentTime; - - status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC, - vid_x, vid_y, vid_w, vid_h, - drw_x, drw_y, drw_w, drw_h); - - return status; - -} - -int -XvdiPutImage( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 src_x, INT16 src_y, - CARD16 src_w, CARD16 src_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h, - XvImagePtr image, - unsigned char* data, - Bool sync, - CARD16 width, CARD16 height -){ - CHECK_SIZE(drw_w, drw_h, src_w, src_h); - - /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ - - UpdateCurrentTime(); - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if (pPort->grab.client && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - pPort->time = currentTime; - - return (* pPort->pAdaptor->ddPutImage)(client, pDraw, pPort, pGC, - src_x, src_y, src_w, src_h, - drw_x, drw_y, drw_w, drw_h, - image, data, sync, width, height); -} - - -int -XvdiGetVideo( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - DrawablePtr pOldDraw; - - CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); - - /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ - - UpdateCurrentTime(); - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if (pPort->grab.client && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED - EVENTS TO ANY CLIENTS WHO WANT THEM */ - - pOldDraw = pPort->pDraw; - if ((pOldDraw) && (pOldDraw != pDraw)) - { - XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); - } - - (void) (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC, - vid_x, vid_y, vid_w, vid_h, - drw_x, drw_y, drw_w, drw_h); - - if ((pPort->pDraw) && (pOldDraw != pDraw)) - { - pPort->client = client; - XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); - } - - pPort->time = currentTime; - - return Success; - -} - -int -XvdiGetStill( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - int status; - - CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); - - /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ - - UpdateCurrentTime(); - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if (pPort->grab.client && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC, - vid_x, vid_y, vid_w, vid_h, - drw_x, drw_y, drw_w, drw_h); - - pPort->time = currentTime; - - return status; - -} - -int -XvdiGrabPort( - ClientPtr client, - XvPortPtr pPort, - Time ctime, - int *p_result -){ - unsigned long id; - TimeStamp time; - - UpdateCurrentTime(); - time = ClientTimeToServerTime(ctime); - - if (pPort->grab.client && (client != pPort->grab.client)) - { - *p_result = XvAlreadyGrabbed; - return Success; - } - - if ((CompareTimeStamps(time, currentTime) == LATER) || - (CompareTimeStamps(time, pPort->time) == EARLIER)) - { - *p_result = XvInvalidTime; - return Success; - } - - if (client == pPort->grab.client) - { - *p_result = Success; - return Success; - } - - id = FakeClientID(client->index); - - if (!AddResource(id, XvRTGrab, &pPort->grab)) - { - return BadAlloc; - } - - /* IF THERE IS ACTIVE VIDEO THEN STOP IT */ - - if ((pPort->pDraw) && (client != pPort->client)) - { - XvdiStopVideo(NULL, pPort, pPort->pDraw); - } - - pPort->grab.client = client; - pPort->grab.id = id; - - pPort->time = currentTime; - - *p_result = Success; - - return Success; - -} - -int -XvdiUngrabPort( - ClientPtr client, - XvPortPtr pPort, - Time ctime -){ - TimeStamp time; - - UpdateCurrentTime(); - time = ClientTimeToServerTime(ctime); - - if ((!pPort->grab.client) || (client != pPort->grab.client)) - { - return Success; - } - - if ((CompareTimeStamps(time, currentTime) == LATER) || - (CompareTimeStamps(time, pPort->time) == EARLIER)) - { - return Success; - } - - /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */ - - FreeResource(pPort->grab.id, XvRTGrab); - pPort->grab.client = NULL; - - pPort->time = currentTime; - - return Success; - -} - - -int -XvdiSelectVideoNotify( - ClientPtr client, - DrawablePtr pDraw, - BOOL onoff -){ - XvVideoNotifyPtr pn,tpn,fpn; - int rc; - - /* FIND VideoNotify LIST */ - - rc = dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList, - client, DixWriteAccess); - if (rc != Success && rc != BadValue) - return rc; - - /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */ - - if (!onoff && !pn) return Success; - - /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST - WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */ - - if (!pn) - { - if (!(tpn = malloc(sizeof(XvVideoNotifyRec)))) - return BadAlloc; - tpn->next = NULL; - if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn)) - { - free(tpn); - return BadAlloc; - } - } - else - { - /* LOOK TO SEE IF ENTRY ALREADY EXISTS */ - - fpn = NULL; - tpn = pn; - while (tpn) - { - if (tpn->client == client) - { - if (!onoff) tpn->client = NULL; - return Success; - } - if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */ - tpn = tpn->next; - } - - /* IF TUNNING OFF, THEN JUST RETURN */ - - if (!onoff) return Success; - - /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */ - - if (fpn) - { - tpn = fpn; - } - else - { - if (!(tpn = malloc(sizeof(XvVideoNotifyRec)))) - return BadAlloc; - tpn->next = pn->next; - pn->next = tpn; - } - } - - /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */ - /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */ - - tpn->client = NULL; - tpn->id = FakeClientID(client->index); - AddResource(tpn->id, XvRTVideoNotify, tpn); - - tpn->client = client; - return Success; - -} - -int -XvdiSelectPortNotify( - ClientPtr client, - XvPortPtr pPort, - BOOL onoff -){ - XvPortNotifyPtr pn,tpn; - - /* SEE IF CLIENT IS ALREADY IN LIST */ - - tpn = NULL; - pn = pPort->pNotify; - while (pn) - { - if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */ - if (pn->client == client) break; - pn = pn->next; - } - - /* IS THE CLIENT ALREADY ON THE LIST? */ - - if (pn) - { - /* REMOVE IT? */ - - if (!onoff) - { - pn->client = NULL; - FreeResource(pn->id, XvRTPortNotify); - } - - return Success; - } - - /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE - CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */ - - if (!tpn) - { - if (!(tpn = malloc(sizeof(XvPortNotifyRec)))) - return BadAlloc; - tpn->next = pPort->pNotify; - pPort->pNotify = tpn; - } - - tpn->client = client; - tpn->id = FakeClientID(client->index); - AddResource(tpn->id, XvRTPortNotify, tpn); - - return Success; - -} - -int -XvdiStopVideo( - ClientPtr client, - XvPortPtr pPort, - DrawablePtr pDraw -){ - int status; - - /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ - - if (!pPort->pDraw || (pPort->pDraw != pDraw)) - { - XvdiSendVideoNotify(pPort, pDraw, XvStopped); - return Success; - } - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - XvdiSendVideoNotify(pPort, pDraw, XvStopped); - - status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw); - - pPort->pDraw = NULL; - pPort->client = (ClientPtr)client; - pPort->time = currentTime; - - return status; - -} - -int -XvdiPreemptVideo( - ClientPtr client, - XvPortPtr pPort, - DrawablePtr pDraw -){ - int status; - - /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ - - if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success; - - XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); - - status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw); - - pPort->pDraw = NULL; - pPort->client = (ClientPtr)client; - pPort->time = currentTime; - - return status; - -} - -int -XvdiMatchPort( - XvPortPtr pPort, - DrawablePtr pDraw -){ - - XvAdaptorPtr pa; - XvFormatPtr pf; - int nf; - - pa = pPort->pAdaptor; - - if (pa->pScreen != pDraw->pScreen) return BadMatch; - - nf = pa->nFormats; - pf = pa->pFormats; - - while (nf--) - { - if ((pf->depth == pDraw->depth) -#if 0 - && ((pDraw->type == DRAWABLE_PIXMAP) || - (wVisual(((WindowPtr)pDraw)) == pf->visual)) -#endif - ) - return Success; - pf++; - } - - return BadMatch; - -} - -int -XvdiSetPortAttribute( - ClientPtr client, - XvPortPtr pPort, - Atom attribute, - INT32 value -){ - int status; - - status = (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value); - if (status == Success) - XvdiSendPortNotify(pPort, attribute, value); - - return status; -} - -int -XvdiGetPortAttribute( - ClientPtr client, - XvPortPtr pPort, - Atom attribute, - INT32 *p_value -){ - - return - (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value); - -} - -static void -WriteSwappedVideoNotifyEvent(xvEvent *from, xvEvent *to) - -{ - - to->u.u.type = from->u.u.type; - to->u.u.detail = from->u.u.detail; - cpswaps(from->u.videoNotify.sequenceNumber, - to->u.videoNotify.sequenceNumber); - cpswapl(from->u.videoNotify.time, to->u.videoNotify.time); - cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable); - cpswapl(from->u.videoNotify.port, to->u.videoNotify.port); - -} - -static void -WriteSwappedPortNotifyEvent(xvEvent *from, xvEvent *to) - -{ - - to->u.u.type = from->u.u.type; - to->u.u.detail = from->u.u.detail; - cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber); - cpswapl(from->u.portNotify.time, to->u.portNotify.time); - cpswapl(from->u.portNotify.port, to->u.portNotify.port); - cpswapl(from->u.portNotify.value, to->u.portNotify.value); - -} +/***********************************************************
+Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
+and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Digital or MIT not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+** File:
+**
+** xvmain.c --- Xv server extension main device independent module.
+**
+** Author:
+**
+** David Carver (Digital Workstation Engineering/Project Athena)
+**
+** Revisions:
+**
+** 04.09.91 Carver
+** - change: stop video always generates an event even when video
+** wasn't active
+**
+** 29.08.91 Carver
+** - change: unrealizing windows no longer preempts video
+**
+** 11.06.91 Carver
+** - changed SetPortControl to SetPortAttribute
+** - changed GetPortControl to GetPortAttribute
+** - changed QueryBestSize
+**
+** 28.05.91 Carver
+** - fixed Put and Get requests to not preempt operations to same drawable
+**
+** 15.05.91 Carver
+** - version 2.0 upgrade
+**
+** 19.03.91 Carver
+** - fixed Put and Get requests to honor grabbed ports.
+** - fixed Video requests to update di structure with new drawable, and
+** client after calling ddx.
+**
+** 24.01.91 Carver
+** - version 1.4 upgrade
+**
+** Notes:
+**
+** Port structures reference client structures in a two different
+** ways: when grabs, or video is active. Each reference is encoded
+** as fake client resources and thus when the client is goes away so
+** does the reference (it is zeroed). No other action is taken, so
+** video doesn't necessarily stop. It probably will as a result of
+** other resources going away, but if a client starts video using
+** none of its own resources, then the video will continue to play
+** after the client disappears.
+**
+**
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "gc.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "opaque.h"
+#include "input.h"
+
+#define GLOBAL
+
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/Xvproto.h>
+#include "xvdix.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+#include "xvdisp.h"
+
+static DevPrivateKeyRec XvScreenKeyRec;
+#define XvScreenKey (&XvScreenKeyRec)
+unsigned long XvExtensionGeneration = 0;
+unsigned long XvScreenGeneration = 0;
+unsigned long XvResourceGeneration = 0;
+
+int XvReqCode;
+int XvEventBase;
+int XvErrorBase;
+
+RESTYPE XvRTPort;
+RESTYPE XvRTEncoding;
+RESTYPE XvRTGrab;
+RESTYPE XvRTVideoNotify;
+RESTYPE XvRTVideoNotifyList;
+RESTYPE XvRTPortNotify;
+
+/* EXTERNAL */
+
+static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *);
+static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *);
+static Bool CreateResourceTypes(void);
+
+static Bool XvCloseScreen(int, ScreenPtr);
+static Bool XvDestroyPixmap(PixmapPtr);
+static Bool XvDestroyWindow(WindowPtr);
+static void XvResetProc(ExtensionEntry*);
+static int XvdiDestroyGrab(pointer, XID);
+static int XvdiDestroyEncoding(pointer, XID);
+static int XvdiDestroyVideoNotify(pointer, XID);
+static int XvdiDestroyPortNotify(pointer, XID);
+static int XvdiDestroyVideoNotifyList(pointer, XID);
+static int XvdiDestroyPort(pointer, XID);
+static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int);
+
+
+
+
+/*
+** XvExtensionInit
+**
+**
+*/
+
+void
+XvExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+
+ if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
+ return;
+
+ /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN
+ INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */
+ if (XvScreenGeneration != serverGeneration)
+ {
+ if (!CreateResourceTypes())
+ {
+ ErrorF("XvExtensionInit: Unable to allocate resource types\n");
+ return;
+ }
+#ifdef PANORAMIX
+ XineramaRegisterConnectionBlockCallback(XineramifyXv);
+#endif
+ XvScreenGeneration = serverGeneration;
+ }
+
+ if (XvExtensionGeneration != serverGeneration)
+ {
+ XvExtensionGeneration = serverGeneration;
+
+ extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors,
+ ProcXvDispatch, SProcXvDispatch,
+ XvResetProc, StandardMinorOpcode);
+ if (!extEntry)
+ {
+ FatalError("XvExtensionInit: AddExtensions failed\n");
+ }
+
+ XvReqCode = extEntry->base;
+ XvEventBase = extEntry->eventBase;
+ XvErrorBase = extEntry->errorBase;
+
+ EventSwapVector[XvEventBase+XvVideoNotify] =
+ (EventSwapPtr)WriteSwappedVideoNotifyEvent;
+ EventSwapVector[XvEventBase+XvPortNotify] =
+ (EventSwapPtr)WriteSwappedPortNotifyEvent;
+
+ SetResourceTypeErrorValue(XvRTPort, _XvBadPort);
+ (void)MakeAtom(XvName, strlen(XvName), xTrue);
+
+ }
+}
+
+static Bool
+CreateResourceTypes(void)
+
+{
+
+ if (XvResourceGeneration == serverGeneration) return TRUE;
+
+ XvResourceGeneration = serverGeneration;
+
+ if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
+ return FALSE;
+ }
+
+ if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
+ return FALSE;
+ }
+
+ if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding,
+ "XvRTEncoding")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
+ return FALSE;
+ }
+
+ if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify,
+ "XvRTVideoNotify")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n");
+ return FALSE;
+ }
+
+ if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList,
+ "XvRTVideoNotifyList")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n");
+ return FALSE;
+ }
+
+ if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify,
+ "XvRTPortNotify")))
+ {
+ ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
+
+int
+XvScreenInit(ScreenPtr pScreen)
+{
+ XvScreenPtr pxvs;
+
+ if (XvScreenGeneration != serverGeneration)
+ {
+ if (!CreateResourceTypes())
+ {
+ ErrorF("XvScreenInit: Unable to allocate resource types\n");
+ return BadAlloc;
+ }
+#ifdef PANORAMIX
+ XineramaRegisterConnectionBlockCallback(XineramifyXv);
+#endif
+ XvScreenGeneration = serverGeneration;
+ }
+
+ if (!dixRegisterPrivateKey(&XvScreenKeyRec, PRIVATE_SCREEN, 0))
+ return BadAlloc;
+
+ if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey))
+ {
+ ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
+ }
+
+ /* ALLOCATE SCREEN PRIVATE RECORD */
+
+ pxvs = calloc (1,sizeof (XvScreenRec));
+ if (!pxvs)
+ {
+ ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
+ return BadAlloc;
+ }
+
+ dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs);
+
+ pxvs->DestroyPixmap = pScreen->DestroyPixmap;
+ pxvs->DestroyWindow = pScreen->DestroyWindow;
+ pxvs->CloseScreen = pScreen->CloseScreen;
+
+ pScreen->DestroyPixmap = XvDestroyPixmap;
+ pScreen->DestroyWindow = XvDestroyWindow;
+ pScreen->CloseScreen = XvCloseScreen;
+
+ return Success;
+}
+
+static Bool
+XvCloseScreen(
+ int ii,
+ ScreenPtr pScreen
+){
+
+ XvScreenPtr pxvs;
+
+ pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
+
+ pScreen->DestroyPixmap = pxvs->DestroyPixmap;
+ pScreen->DestroyWindow = pxvs->DestroyWindow;
+ pScreen->CloseScreen = pxvs->CloseScreen;
+
+ if (pxvs->ddCloseScreen) (* pxvs->ddCloseScreen)(ii, pScreen);
+
+ free(pxvs);
+
+ dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL);
+
+ return (*pScreen->CloseScreen)(ii, pScreen);
+}
+
+static void
+XvResetProc(ExtensionEntry* extEntry)
+{
+ XvResetProcVector();
+}
+
+DevPrivateKey
+XvGetScreenKey(void)
+{
+ return XvScreenKey;
+}
+
+unsigned long
+XvGetRTPort(void)
+{
+ return XvRTPort;
+}
+
+static Bool
+XvDestroyPixmap(PixmapPtr pPix)
+{
+ Bool status;
+ ScreenPtr pScreen;
+ XvScreenPtr pxvs;
+ XvAdaptorPtr pa;
+ int na;
+ XvPortPtr pp;
+ int np;
+
+ pScreen = pPix->drawable.pScreen;
+
+ SCREEN_PROLOGUE(pScreen, DestroyPixmap);
+
+ pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
+
+ /* CHECK TO SEE IF THIS PORT IS IN USE */
+
+ pa = pxvs->pAdaptors;
+ na = pxvs->nAdaptors;
+ while (na--)
+ {
+ np = pa->nPorts;
+ pp = pa->pPorts;
+
+ while (np--)
+ {
+ if (pp->pDraw == (DrawablePtr)pPix)
+ {
+ XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
+
+ (void)(* pp->pAdaptor->ddStopVideo)(NULL, pp, pp->pDraw);
+
+ pp->pDraw = NULL;
+ pp->client = NULL;
+ pp->time = currentTime;
+ }
+ pp++;
+ }
+ pa++;
+ }
+
+ status = (* pScreen->DestroyPixmap)(pPix);
+
+ SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap);
+
+ return status;
+
+}
+
+static Bool
+XvDestroyWindow(WindowPtr pWin)
+{
+ Bool status;
+ ScreenPtr pScreen;
+ XvScreenPtr pxvs;
+ XvAdaptorPtr pa;
+ int na;
+ XvPortPtr pp;
+ int np;
+
+ pScreen = pWin->drawable.pScreen;
+
+ SCREEN_PROLOGUE(pScreen, DestroyWindow);
+
+ pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey);
+
+ /* CHECK TO SEE IF THIS PORT IS IN USE */
+
+ pa = pxvs->pAdaptors;
+ na = pxvs->nAdaptors;
+ while (na--)
+ {
+ np = pa->nPorts;
+ pp = pa->pPorts;
+
+ while (np--)
+ {
+ if (pp->pDraw == (DrawablePtr)pWin)
+ {
+ XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
+
+ (void)(* pp->pAdaptor->ddStopVideo)(NULL, pp, pp->pDraw);
+
+ pp->pDraw = NULL;
+ pp->client = NULL;
+ pp->time = currentTime;
+ }
+ pp++;
+ }
+ pa++;
+ }
+
+
+ status = (* pScreen->DestroyWindow)(pWin);
+
+ SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
+
+ return status;
+
+}
+
+/* The XvdiVideoStopped procedure is a hook for the device dependent layer.
+ It provides a way for the dd layer to inform the di layer that video has
+ stopped in a port for reasons that the di layer had no control over; note
+ that it doesn't call back into the dd layer */
+
+int
+XvdiVideoStopped(XvPortPtr pPort, int reason)
+{
+
+ /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
+
+ if (!pPort->pDraw) return Success;
+
+ XvdiSendVideoNotify(pPort, pPort->pDraw, reason);
+
+ pPort->pDraw = NULL;
+ pPort->client = NULL;
+ pPort->time = currentTime;
+
+ return Success;
+
+}
+
+static int
+XvdiDestroyPort(pointer pPort, XID id)
+{
+ return (* ((XvPortPtr)pPort)->pAdaptor->ddFreePort)(pPort);
+}
+
+static int
+XvdiDestroyGrab(pointer pGrab, XID id)
+{
+ ((XvGrabPtr)pGrab)->client = NULL;
+ return Success;
+}
+
+static int
+XvdiDestroyVideoNotify(pointer pn, XID id)
+{
+ /* JUST CLEAR OUT THE client POINTER FIELD */
+
+ ((XvVideoNotifyPtr)pn)->client = NULL;
+ return Success;
+}
+
+static int
+XvdiDestroyPortNotify(pointer pn, XID id)
+{
+ /* JUST CLEAR OUT THE client POINTER FIELD */
+
+ ((XvPortNotifyPtr)pn)->client = NULL;
+ return Success;
+}
+
+static int
+XvdiDestroyVideoNotifyList(pointer pn, XID id)
+{
+ XvVideoNotifyPtr npn,cpn;
+
+ /* ACTUALLY DESTROY THE NOTITY LIST */
+
+ cpn = (XvVideoNotifyPtr)pn;
+
+ while (cpn)
+ {
+ npn = cpn->next;
+ if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify);
+ free(cpn);
+ cpn = npn;
+ }
+ return Success;
+}
+
+static int
+XvdiDestroyEncoding(pointer value, XID id)
+{
+ return Success;
+}
+
+static int
+XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason)
+{
+ xvEvent event;
+ XvVideoNotifyPtr pn;
+
+ dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList,
+ serverClient, DixReadAccess);
+
+ while (pn)
+ {
+ event.u.u.type = XvEventBase + XvVideoNotify;
+ event.u.videoNotify.time = currentTime.milliseconds;
+ event.u.videoNotify.drawable = pDraw->id;
+ event.u.videoNotify.port = pPort->id;
+ event.u.videoNotify.reason = reason;
+ WriteEventsToClient(pn->client, 1, (xEventPtr)&event);
+ pn = pn->next;
+ }
+
+ return Success;
+
+}
+
+
+int
+XvdiSendPortNotify(
+ XvPortPtr pPort,
+ Atom attribute,
+ INT32 value
+){
+ xvEvent event;
+ XvPortNotifyPtr pn;
+
+ pn = pPort->pNotify;
+
+ while (pn)
+ {
+ event.u.u.type = XvEventBase + XvPortNotify;
+ event.u.portNotify.time = currentTime.milliseconds;
+ event.u.portNotify.port = pPort->id;
+ event.u.portNotify.attribute = attribute;
+ event.u.portNotify.value = value;
+ WriteEventsToClient(pn->client, 1, (xEventPtr)&event);
+ pn = pn->next;
+ }
+
+ return Success;
+
+}
+
+
+#define CHECK_SIZE(dw, dh, sw, sh) { \
+ if(!dw || !dh || !sw || !sh) return Success; \
+ /* The region code will break these if they are too large */ \
+ if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767)) \
+ return BadValue; \
+}
+
+
+int
+XvdiPutVideo(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ DrawablePtr pOldDraw;
+
+ CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
+
+ /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
+
+ UpdateCurrentTime();
+
+ /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
+ INFORM CLIENT OF ITS FAILURE */
+
+ if (pPort->grab.client && (pPort->grab.client != client))
+ {
+ XvdiSendVideoNotify(pPort, pDraw, XvBusy);
+ return Success;
+ }
+
+ /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
+ EVENTS TO ANY CLIENTS WHO WANT THEM */
+
+ pOldDraw = pPort->pDraw;
+ if ((pOldDraw) && (pOldDraw != pDraw))
+ {
+ XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
+ }
+
+ (void) (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC,
+ vid_x, vid_y, vid_w, vid_h,
+ drw_x, drw_y, drw_w, drw_h);
+
+ if ((pPort->pDraw) && (pOldDraw != pDraw))
+ {
+ pPort->client = client;
+ XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
+ }
+
+ pPort->time = currentTime;
+
+ return Success;
+
+}
+
+int
+XvdiPutStill(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ int status;
+
+ CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
+
+ /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
+
+ UpdateCurrentTime();
+
+ /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
+ INFORM CLIENT OF ITS FAILURE */
+
+ if (pPort->grab.client && (pPort->grab.client != client))
+ {
+ XvdiSendVideoNotify(pPort, pDraw, XvBusy);
+ return Success;
+ }
+
+ pPort->time = currentTime;
+
+ status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC,
+ vid_x, vid_y, vid_w, vid_h,
+ drw_x, drw_y, drw_w, drw_h);
+
+ return status;
+
+}
+
+int
+XvdiPutImage(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 src_x, INT16 src_y,
+ CARD16 src_w, CARD16 src_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h,
+ XvImagePtr image,
+ unsigned char* data,
+ Bool sync,
+ CARD16 width, CARD16 height
+){
+ CHECK_SIZE(drw_w, drw_h, src_w, src_h);
+
+ /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
+
+ UpdateCurrentTime();
+
+ /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
+ INFORM CLIENT OF ITS FAILURE */
+
+ if (pPort->grab.client && (pPort->grab.client != client))
+ {
+ XvdiSendVideoNotify(pPort, pDraw, XvBusy);
+ return Success;
+ }
+
+ pPort->time = currentTime;
+
+ return (* pPort->pAdaptor->ddPutImage)(client, pDraw, pPort, pGC,
+ src_x, src_y, src_w, src_h,
+ drw_x, drw_y, drw_w, drw_h,
+ image, data, sync, width, height);
+}
+
+
+int
+XvdiGetVideo(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ DrawablePtr pOldDraw;
+
+ CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
+
+ /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
+
+ UpdateCurrentTime();
+
+ /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
+ INFORM CLIENT OF ITS FAILURE */
+
+ if (pPort->grab.client && (pPort->grab.client != client))
+ {
+ XvdiSendVideoNotify(pPort, pDraw, XvBusy);
+ return Success;
+ }
+
+ /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
+ EVENTS TO ANY CLIENTS WHO WANT THEM */
+
+ pOldDraw = pPort->pDraw;
+ if ((pOldDraw) && (pOldDraw != pDraw))
+ {
+ XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
+ }
+
+ (void) (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC,
+ vid_x, vid_y, vid_w, vid_h,
+ drw_x, drw_y, drw_w, drw_h);
+
+ if ((pPort->pDraw) && (pOldDraw != pDraw))
+ {
+ pPort->client = client;
+ XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
+ }
+
+ pPort->time = currentTime;
+
+ return Success;
+
+}
+
+int
+XvdiGetStill(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ XvPortPtr pPort,
+ GCPtr pGC,
+ INT16 vid_x, INT16 vid_y,
+ CARD16 vid_w, CARD16 vid_h,
+ INT16 drw_x, INT16 drw_y,
+ CARD16 drw_w, CARD16 drw_h
+){
+ int status;
+
+ CHECK_SIZE(drw_w, drw_h, vid_w, vid_h);
+
+ /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
+
+ UpdateCurrentTime();
+
+ /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
+ INFORM CLIENT OF ITS FAILURE */
+
+ if (pPort->grab.client && (pPort->grab.client != client))
+ {
+ XvdiSendVideoNotify(pPort, pDraw, XvBusy);
+ return Success;
+ }
+
+ status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC,
+ vid_x, vid_y, vid_w, vid_h,
+ drw_x, drw_y, drw_w, drw_h);
+
+ pPort->time = currentTime;
+
+ return status;
+
+}
+
+int
+XvdiGrabPort(
+ ClientPtr client,
+ XvPortPtr pPort,
+ Time ctime,
+ int *p_result
+){
+ unsigned long id;
+ TimeStamp time;
+
+ UpdateCurrentTime();
+ time = ClientTimeToServerTime(ctime);
+
+ if (pPort->grab.client && (client != pPort->grab.client))
+ {
+ *p_result = XvAlreadyGrabbed;
+ return Success;
+ }
+
+ if ((CompareTimeStamps(time, currentTime) == LATER) ||
+ (CompareTimeStamps(time, pPort->time) == EARLIER))
+ {
+ *p_result = XvInvalidTime;
+ return Success;
+ }
+
+ if (client == pPort->grab.client)
+ {
+ *p_result = Success;
+ return Success;
+ }
+
+ id = FakeClientID(client->index);
+
+ if (!AddResource(id, XvRTGrab, &pPort->grab))
+ {
+ return BadAlloc;
+ }
+
+ /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
+
+ if ((pPort->pDraw) && (client != pPort->client))
+ {
+ XvdiStopVideo(NULL, pPort, pPort->pDraw);
+ }
+
+ pPort->grab.client = client;
+ pPort->grab.id = id;
+
+ pPort->time = currentTime;
+
+ *p_result = Success;
+
+ return Success;
+
+}
+
+int
+XvdiUngrabPort(
+ ClientPtr client,
+ XvPortPtr pPort,
+ Time ctime
+){
+ TimeStamp time;
+
+ UpdateCurrentTime();
+ time = ClientTimeToServerTime(ctime);
+
+ if ((!pPort->grab.client) || (client != pPort->grab.client))
+ {
+ return Success;
+ }
+
+ if ((CompareTimeStamps(time, currentTime) == LATER) ||
+ (CompareTimeStamps(time, pPort->time) == EARLIER))
+ {
+ return Success;
+ }
+
+ /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
+
+ FreeResource(pPort->grab.id, XvRTGrab);
+ pPort->grab.client = NULL;
+
+ pPort->time = currentTime;
+
+ return Success;
+
+}
+
+
+int
+XvdiSelectVideoNotify(
+ ClientPtr client,
+ DrawablePtr pDraw,
+ BOOL onoff
+){
+ XvVideoNotifyPtr pn,tpn,fpn;
+ int rc;
+
+ /* FIND VideoNotify LIST */
+
+ rc = dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList,
+ client, DixWriteAccess);
+ if (rc != Success && rc != BadValue)
+ return rc;
+
+ /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
+
+ if (!onoff && !pn) return Success;
+
+ /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
+ WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
+
+ if (!pn)
+ {
+ if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
+ return BadAlloc;
+ tpn->next = NULL;
+ if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
+ {
+ free(tpn);
+ return BadAlloc;
+ }
+ }
+ else
+ {
+ /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
+
+ fpn = NULL;
+ tpn = pn;
+ while (tpn)
+ {
+ if (tpn->client == client)
+ {
+ if (!onoff) tpn->client = NULL;
+ return Success;
+ }
+ if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */
+ tpn = tpn->next;
+ }
+
+ /* IF TUNNING OFF, THEN JUST RETURN */
+
+ if (!onoff) return Success;
+
+ /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
+
+ if (fpn)
+ {
+ tpn = fpn;
+ }
+ else
+ {
+ if (!(tpn = malloc(sizeof(XvVideoNotifyRec))))
+ return BadAlloc;
+ tpn->next = pn->next;
+ pn->next = tpn;
+ }
+ }
+
+ /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
+ /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
+
+ tpn->client = NULL;
+ tpn->id = FakeClientID(client->index);
+ AddResource(tpn->id, XvRTVideoNotify, tpn);
+
+ tpn->client = client;
+ return Success;
+
+}
+
+int
+XvdiSelectPortNotify(
+ ClientPtr client,
+ XvPortPtr pPort,
+ BOOL onoff
+){
+ XvPortNotifyPtr pn,tpn;
+
+ /* SEE IF CLIENT IS ALREADY IN LIST */
+
+ tpn = NULL;
+ pn = pPort->pNotify;
+ while (pn)
+ {
+ if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */
+ if (pn->client == client) break;
+ pn = pn->next;
+ }
+
+ /* IS THE CLIENT ALREADY ON THE LIST? */
+
+ if (pn)
+ {
+ /* REMOVE IT? */
+
+ if (!onoff)
+ {
+ pn->client = NULL;
+ FreeResource(pn->id, XvRTPortNotify);
+ }
+
+ return Success;
+ }
+
+ /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE
+ CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
+
+ if (!tpn)
+ {
+ if (!(tpn = malloc(sizeof(XvPortNotifyRec))))
+ return BadAlloc;
+ tpn->next = pPort->pNotify;
+ pPort->pNotify = tpn;
+ }
+
+ tpn->client = client;
+ tpn->id = FakeClientID(client->index);
+ AddResource(tpn->id, XvRTPortNotify, tpn);
+
+ return Success;
+
+}
+
+int
+XvdiStopVideo(
+ ClientPtr client,
+ XvPortPtr pPort,
+ DrawablePtr pDraw
+){
+ int status;
+
+ /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
+
+ if (!pPort->pDraw || (pPort->pDraw != pDraw))
+ {
+ XvdiSendVideoNotify(pPort, pDraw, XvStopped);
+ return Success;
+ }
+
+ /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
+ INFORM CLIENT OF ITS FAILURE */
+
+ if ((client) && (pPort->grab.client) && (pPort->grab.client != client))
+ {
+ XvdiSendVideoNotify(pPort, pDraw, XvBusy);
+ return Success;
+ }
+
+ XvdiSendVideoNotify(pPort, pDraw, XvStopped);
+
+ status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw);
+
+ pPort->pDraw = NULL;
+ pPort->client = (ClientPtr)client;
+ pPort->time = currentTime;
+
+ return status;
+
+}
+
+int
+XvdiPreemptVideo(
+ ClientPtr client,
+ XvPortPtr pPort,
+ DrawablePtr pDraw
+){
+ int status;
+
+ /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
+
+ if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success;
+
+ XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
+
+ status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw);
+
+ pPort->pDraw = NULL;
+ pPort->client = (ClientPtr)client;
+ pPort->time = currentTime;
+
+ return status;
+
+}
+
+int
+XvdiMatchPort(
+ XvPortPtr pPort,
+ DrawablePtr pDraw
+){
+
+ XvAdaptorPtr pa;
+ XvFormatPtr pf;
+ int nf;
+
+ pa = pPort->pAdaptor;
+
+ if (pa->pScreen != pDraw->pScreen) return BadMatch;
+
+ nf = pa->nFormats;
+ pf = pa->pFormats;
+
+ while (nf--)
+ {
+ if ((pf->depth == pDraw->depth)
+#if 0
+ && ((pDraw->type == DRAWABLE_PIXMAP) ||
+ (wVisual(((WindowPtr)pDraw)) == pf->visual))
+#endif
+ )
+ return Success;
+ pf++;
+ }
+
+ return BadMatch;
+
+}
+
+int
+XvdiSetPortAttribute(
+ ClientPtr client,
+ XvPortPtr pPort,
+ Atom attribute,
+ INT32 value
+){
+ int status;
+
+ status = (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value);
+ if (status == Success)
+ XvdiSendPortNotify(pPort, attribute, value);
+
+ return status;
+}
+
+int
+XvdiGetPortAttribute(
+ ClientPtr client,
+ XvPortPtr pPort,
+ Atom attribute,
+ INT32 *p_value
+){
+
+ return
+ (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value);
+
+}
+
+static void
+WriteSwappedVideoNotifyEvent(xvEvent *from, xvEvent *to)
+
+{
+
+ to->u.u.type = from->u.u.type;
+ to->u.u.detail = from->u.u.detail;
+ cpswaps(from->u.videoNotify.sequenceNumber,
+ to->u.videoNotify.sequenceNumber);
+ cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
+ cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
+ cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
+
+}
+
+static void
+WriteSwappedPortNotifyEvent(xvEvent *from, xvEvent *to)
+
+{
+
+ to->u.u.type = from->u.u.type;
+ to->u.u.detail = from->u.u.detail;
+ cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
+ cpswapl(from->u.portNotify.time, to->u.portNotify.time);
+ cpswapl(from->u.portNotify.port, to->u.portNotify.port);
+ cpswapl(from->u.portNotify.value, to->u.portNotify.value);
+
+}
diff --git a/xorg-server/Xext/xvmc.c b/xorg-server/Xext/xvmc.c index 4d29941ee..0a0e9415e 100644 --- a/xorg-server/Xext/xvmc.c +++ b/xorg-server/Xext/xvmc.c @@ -1,789 +1,789 @@ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#include <string.h> - -#include <X11/X.h> -#include <X11/Xproto.h> -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "resource.h" -#include "scrnintstr.h" -#include "extnsionst.h" -#include "servermd.h" -#include <X11/Xfuncproto.h> -#include "xvdix.h" -#include <X11/extensions/XvMC.h> -#include <X11/extensions/Xvproto.h> -#include <X11/extensions/XvMCproto.h> -#include "xvmcext.h" -#include "protocol-versions.h" - -#ifdef HAS_XVMCSHM -#include <sys/ipc.h> -#include <sys/types.h> -#include <sys/shm.h> -#endif /* HAS_XVMCSHM */ - - - -#define DR_CLIENT_DRIVER_NAME_SIZE 48 -#define DR_BUSID_SIZE 48 - -static DevPrivateKeyRec XvMCScreenKeyRec; -#define XvMCScreenKey (&XvMCScreenKeyRec) -static Bool XvMCInUse; - -unsigned long XvMCGeneration = 0; - -int XvMCReqCode; -int XvMCEventBase; - -static RESTYPE XvMCRTContext; -static RESTYPE XvMCRTSurface; -static RESTYPE XvMCRTSubpicture; - -typedef struct { - int num_adaptors; - XvMCAdaptorPtr adaptors; - CloseScreenProcPtr CloseScreen; - char clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE]; - char busID[DR_BUSID_SIZE]; - int major; - int minor; - int patchLevel; -} XvMCScreenRec, *XvMCScreenPtr; - -#define XVMC_GET_PRIVATE(pScreen) \ - (XvMCScreenPtr)(dixLookupPrivate(&(pScreen)->devPrivates, XvMCScreenKey)) - - -static int -XvMCDestroyContextRes(pointer data, XID id) -{ - XvMCContextPtr pContext = (XvMCContextPtr)data; - - pContext->refcnt--; - - if(!pContext->refcnt) { - XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); - (*pScreenPriv->adaptors[pContext->adapt_num].DestroyContext)(pContext); - free(pContext); - } - - return Success; -} - -static int -XvMCDestroySurfaceRes(pointer data, XID id) -{ - XvMCSurfacePtr pSurface = (XvMCSurfacePtr)data; - XvMCContextPtr pContext = pSurface->context; - XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); - - (*pScreenPriv->adaptors[pContext->adapt_num].DestroySurface)(pSurface); - free(pSurface); - - XvMCDestroyContextRes((pointer)pContext, pContext->context_id); - - return Success; -} - - -static int -XvMCDestroySubpictureRes(pointer data, XID id) -{ - XvMCSubpicturePtr pSubpict = (XvMCSubpicturePtr)data; - XvMCContextPtr pContext = pSubpict->context; - XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); - - (*pScreenPriv->adaptors[pContext->adapt_num].DestroySubpicture)(pSubpict); - free(pSubpict); - - XvMCDestroyContextRes((pointer)pContext, pContext->context_id); - - return Success; -} - -static int -ProcXvMCQueryVersion(ClientPtr client) -{ - xvmcQueryVersionReply rep; - /* REQUEST(xvmcQueryVersionReq); */ - REQUEST_SIZE_MATCH(xvmcQueryVersionReq); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.major = SERVER_XVMC_MAJOR_VERSION; - rep.minor = SERVER_XVMC_MINOR_VERSION; - WriteToClient(client, sizeof(xvmcQueryVersionReply), (char*)&rep); - return Success; -} - - -static int -ProcXvMCListSurfaceTypes(ClientPtr client) -{ - XvPortPtr pPort; - int i; - XvMCScreenPtr pScreenPriv; - xvmcListSurfaceTypesReply rep; - xvmcSurfaceInfo info; - XvMCAdaptorPtr adaptor = NULL; - XvMCSurfaceInfoPtr surface; - REQUEST(xvmcListSurfaceTypesReq); - REQUEST_SIZE_MATCH(xvmcListSurfaceTypesReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if(XvMCInUse) { /* any adaptors at all */ - ScreenPtr pScreen = pPort->pAdaptor->pScreen; - if((pScreenPriv = XVMC_GET_PRIVATE(pScreen))) { /* any this screen */ - for(i = 0; i < pScreenPriv->num_adaptors; i++) { - if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { - adaptor = &(pScreenPriv->adaptors[i]); - break; - } - } - } - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.num = (adaptor) ? adaptor->num_surfaces : 0; - rep.length = bytes_to_int32(rep.num * sizeof(xvmcSurfaceInfo)); - - WriteToClient(client, sizeof(xvmcListSurfaceTypesReply), (char*)&rep); - - for(i = 0; i < rep.num; i++) { - surface = adaptor->surfaces[i]; - info.surface_type_id = surface->surface_type_id; - info.chroma_format = surface->chroma_format; - info.max_width = surface->max_width; - info.max_height = surface->max_height; - info.subpicture_max_width = surface->subpicture_max_width; - info.subpicture_max_height = surface->subpicture_max_height; - info.mc_type = surface->mc_type; - info.flags = surface->flags; - WriteToClient(client, sizeof(xvmcSurfaceInfo), (char*)&info); - } - - return Success; -} - -static int -ProcXvMCCreateContext(ClientPtr client) -{ - XvPortPtr pPort; - CARD32 *data = NULL; - int dwords = 0; - int i, result, adapt_num = -1; - ScreenPtr pScreen; - XvMCContextPtr pContext; - XvMCScreenPtr pScreenPriv; - XvMCAdaptorPtr adaptor = NULL; - XvMCSurfaceInfoPtr surface = NULL; - xvmcCreateContextReply rep; - REQUEST(xvmcCreateContextReq); - REQUEST_SIZE_MATCH(xvmcCreateContextReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - pScreen = pPort->pAdaptor->pScreen; - - if(!XvMCInUse) /* no XvMC adaptors */ - return BadMatch; - - if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) /* none this screen */ - return BadMatch; - - for(i = 0; i < pScreenPriv->num_adaptors; i++) { - if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { - adaptor = &(pScreenPriv->adaptors[i]); - adapt_num = i; - break; - } - } - - if(adapt_num < 0) /* none this port */ - return BadMatch; - - for(i = 0; i < adaptor->num_surfaces; i++) { - if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) { - surface = adaptor->surfaces[i]; - break; - } - } - - /* adaptor doesn't support this suface_type_id */ - if(!surface) return BadMatch; - - - if((stuff->width > surface->max_width) || - (stuff->height > surface->max_height)) - return BadValue; - - if(!(pContext = malloc(sizeof(XvMCContextRec)))) { - return BadAlloc; - } - - - pContext->pScreen = pScreen; - pContext->adapt_num = adapt_num; - pContext->context_id = stuff->context_id; - pContext->surface_type_id = stuff->surface_type_id; - pContext->width = stuff->width; - pContext->height = stuff->height; - pContext->flags = stuff->flags; - pContext->refcnt = 1; - - result = (*adaptor->CreateContext)(pPort, pContext, &dwords, &data); - - if(result != Success) { - free(pContext); - return result; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.width_actual = pContext->width; - rep.height_actual = pContext->height; - rep.flags_return = pContext->flags; - rep.length = dwords; - - WriteToClient(client, sizeof(xvmcCreateContextReply), (char*)&rep); - if(dwords) - WriteToClient(client, dwords << 2, (char*)data); - AddResource(pContext->context_id, XvMCRTContext, pContext); - - free(data); - - return Success; -} - -static int -ProcXvMCDestroyContext(ClientPtr client) -{ - pointer val; - int rc; - REQUEST(xvmcDestroyContextReq); - REQUEST_SIZE_MATCH(xvmcDestroyContextReq); - - rc = dixLookupResourceByType(&val, stuff->context_id, XvMCRTContext, - client, DixDestroyAccess); - if (rc != Success) - return rc; - - FreeResource(stuff->context_id, RT_NONE); - - return Success; -} - -static int -ProcXvMCCreateSurface(ClientPtr client) -{ - CARD32 *data = NULL; - int dwords = 0; - int result; - XvMCContextPtr pContext; - XvMCSurfacePtr pSurface; - XvMCScreenPtr pScreenPriv; - xvmcCreateSurfaceReply rep; - REQUEST(xvmcCreateSurfaceReq); - REQUEST_SIZE_MATCH(xvmcCreateSurfaceReq); - - result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id, - XvMCRTContext, client, DixUseAccess); - if (result != Success) - return result; - - pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); - - if(!(pSurface = malloc(sizeof(XvMCSurfaceRec)))) - return BadAlloc; - - pSurface->surface_id = stuff->surface_id; - pSurface->surface_type_id = pContext->surface_type_id; - pSurface->context = pContext; - - result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSurface)( - pSurface, &dwords, &data); - - if(result != Success) { - free(pSurface); - return result; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = dwords; - - WriteToClient(client, sizeof(xvmcCreateSurfaceReply), (char*)&rep); - if(dwords) - WriteToClient(client, dwords << 2, (char*)data); - AddResource(pSurface->surface_id, XvMCRTSurface, pSurface); - - free(data); - - pContext->refcnt++; - - return Success; -} - -static int -ProcXvMCDestroySurface(ClientPtr client) -{ - pointer val; - int rc; - REQUEST(xvmcDestroySurfaceReq); - REQUEST_SIZE_MATCH(xvmcDestroySurfaceReq); - - rc = dixLookupResourceByType(&val, stuff->surface_id, XvMCRTSurface, - client, DixDestroyAccess); - if (rc != Success) - return rc; - - FreeResource(stuff->surface_id, RT_NONE); - - return Success; -} - -static int -ProcXvMCCreateSubpicture(ClientPtr client) -{ - Bool image_supported = FALSE; - CARD32 *data = NULL; - int i, result, dwords = 0; - XvMCContextPtr pContext; - XvMCSubpicturePtr pSubpicture; - XvMCScreenPtr pScreenPriv; - xvmcCreateSubpictureReply rep; - XvMCAdaptorPtr adaptor; - XvMCSurfaceInfoPtr surface = NULL; - REQUEST(xvmcCreateSubpictureReq); - REQUEST_SIZE_MATCH(xvmcCreateSubpictureReq); - - result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id, - XvMCRTContext, client, DixUseAccess); - if (result != Success) - return result; - - pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); - - adaptor = &(pScreenPriv->adaptors[pContext->adapt_num]); - - /* find which surface this context supports */ - for(i = 0; i < adaptor->num_surfaces; i++) { - if(adaptor->surfaces[i]->surface_type_id == pContext->surface_type_id){ - surface = adaptor->surfaces[i]; - break; - } - } - - if(!surface) return BadMatch; - - /* make sure this surface supports that xvimage format */ - if(!surface->compatible_subpictures) return BadMatch; - - for(i = 0; i < surface->compatible_subpictures->num_xvimages; i++) { - if(surface->compatible_subpictures->xvimage_ids[i] == stuff->xvimage_id) { - image_supported = TRUE; - break; - } - } - - if(!image_supported) return BadMatch; - - /* make sure the size is OK */ - if((stuff->width > surface->subpicture_max_width) || - (stuff->height > surface->subpicture_max_height)) - return BadValue; - - if(!(pSubpicture = malloc(sizeof(XvMCSubpictureRec)))) - return BadAlloc; - - pSubpicture->subpicture_id = stuff->subpicture_id; - pSubpicture->xvimage_id = stuff->xvimage_id; - pSubpicture->width = stuff->width; - pSubpicture->height = stuff->height; - pSubpicture->num_palette_entries = 0; /* overwritten by DDX */ - pSubpicture->entry_bytes = 0; /* overwritten by DDX */ - pSubpicture->component_order[0] = 0; /* overwritten by DDX */ - pSubpicture->component_order[1] = 0; - pSubpicture->component_order[2] = 0; - pSubpicture->component_order[3] = 0; - pSubpicture->context = pContext; - - result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSubpicture)( - pSubpicture, &dwords, &data); - - if(result != Success) { - free(pSubpicture); - return result; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.width_actual = pSubpicture->width; - rep.height_actual = pSubpicture->height; - rep.num_palette_entries = pSubpicture->num_palette_entries; - rep.entry_bytes = pSubpicture->entry_bytes; - rep.component_order[0] = pSubpicture->component_order[0]; - rep.component_order[1] = pSubpicture->component_order[1]; - rep.component_order[2] = pSubpicture->component_order[2]; - rep.component_order[3] = pSubpicture->component_order[3]; - rep.length = dwords; - - WriteToClient(client, sizeof(xvmcCreateSubpictureReply), (char*)&rep); - if(dwords) - WriteToClient(client, dwords << 2, (char*)data); - AddResource(pSubpicture->subpicture_id, XvMCRTSubpicture, pSubpicture); - - free(data); - - pContext->refcnt++; - - return Success; -} - -static int -ProcXvMCDestroySubpicture(ClientPtr client) -{ - pointer val; - int rc; - REQUEST(xvmcDestroySubpictureReq); - REQUEST_SIZE_MATCH(xvmcDestroySubpictureReq); - - rc = dixLookupResourceByType(&val, stuff->subpicture_id, XvMCRTSubpicture, - client, DixDestroyAccess); - if (rc != Success) - return rc; - - FreeResource(stuff->subpicture_id, RT_NONE); - - return Success; -} - - -static int -ProcXvMCListSubpictureTypes(ClientPtr client) -{ - XvPortPtr pPort; - xvmcListSubpictureTypesReply rep; - XvMCScreenPtr pScreenPriv; - ScreenPtr pScreen; - XvMCAdaptorPtr adaptor = NULL; - XvMCSurfaceInfoPtr surface = NULL; - xvImageFormatInfo info; - XvImagePtr pImage; - int i, j; - REQUEST(xvmcListSubpictureTypesReq); - REQUEST_SIZE_MATCH(xvmcListSubpictureTypesReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - pScreen = pPort->pAdaptor->pScreen; - - if(XvMCScreenKey == NULL) /* No XvMC adaptors */ - return BadMatch; - - if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) - return BadMatch; /* None this screen */ - - for(i = 0; i < pScreenPriv->num_adaptors; i++) { - if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { - adaptor = &(pScreenPriv->adaptors[i]); - break; - } - } - - if(!adaptor) return BadMatch; - - for(i = 0; i < adaptor->num_surfaces; i++) { - if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) { - surface = adaptor->surfaces[i]; - break; - } - } - - if(!surface) return BadMatch; - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.num = 0; - if(surface->compatible_subpictures) - rep.num = surface->compatible_subpictures->num_xvimages; - - rep.length = bytes_to_int32(rep.num * sizeof(xvImageFormatInfo)); - - WriteToClient(client, sizeof(xvmcListSubpictureTypesReply), (char*)&rep); - - for(i = 0; i < rep.num; i++) { - pImage = NULL; - for(j = 0; j < adaptor->num_subpictures; j++) { - if(surface->compatible_subpictures->xvimage_ids[i] == - adaptor->subpictures[j]->id) - { - pImage = adaptor->subpictures[j]; - break; - } - } - if(!pImage) return BadImplementation; - - info.id = pImage->id; - info.type = pImage->type; - info.byte_order = pImage->byte_order; - memcpy(&info.guid, pImage->guid, 16); - info.bpp = pImage->bits_per_pixel; - info.num_planes = pImage->num_planes; - info.depth = pImage->depth; - info.red_mask = pImage->red_mask; - info.green_mask = pImage->green_mask; - info.blue_mask = pImage->blue_mask; - info.format = pImage->format; - info.y_sample_bits = pImage->y_sample_bits; - info.u_sample_bits = pImage->u_sample_bits; - info.v_sample_bits = pImage->v_sample_bits; - info.horz_y_period = pImage->horz_y_period; - info.horz_u_period = pImage->horz_u_period; - info.horz_v_period = pImage->horz_v_period; - info.vert_y_period = pImage->vert_y_period; - info.vert_u_period = pImage->vert_u_period; - info.vert_v_period = pImage->vert_v_period; - memcpy(&info.comp_order, pImage->component_order, 32); - info.scanline_order = pImage->scanline_order; - WriteToClient(client, sizeof(xvImageFormatInfo), (char*)&info); - } - - return Success; -} - -static int -ProcXvMCGetDRInfo(ClientPtr client) -{ - xvmcGetDRInfoReply rep; - XvPortPtr pPort; - ScreenPtr pScreen; - XvMCScreenPtr pScreenPriv; - -#ifdef HAS_XVMCSHM - volatile CARD32 *patternP; -#endif - - REQUEST(xvmcGetDRInfoReq); - REQUEST_SIZE_MATCH(xvmcGetDRInfoReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - pScreen = pPort->pAdaptor->pScreen; - pScreenPriv = XVMC_GET_PRIVATE(pScreen); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.major = pScreenPriv->major; - rep.minor = pScreenPriv->minor; - rep.patchLevel = pScreenPriv->patchLevel; - rep.nameLen = bytes_to_int32(strlen(pScreenPriv->clientDriverName) + 1); - rep.busIDLen = bytes_to_int32(strlen(pScreenPriv->busID) + 1); - - rep.length = rep.nameLen + rep.busIDLen; - rep.nameLen <<=2; - rep.busIDLen <<=2; - - /* - * Read back to the client what she has put in the shared memory - * segment she prepared for us. - */ - - rep.isLocal = 1; -#ifdef HAS_XVMCSHM - patternP = (CARD32 *)shmat( stuff->shmKey, NULL, SHM_RDONLY ); - if ( -1 != (long) patternP) { - volatile CARD32 *patternC = patternP; - int i; - CARD32 magic = stuff->magic; - - rep.isLocal = 1; - i = 1024 / sizeof(CARD32); - - while ( i-- ) { - if (*patternC++ != magic) { - rep.isLocal = 0; - break; - } - magic = ~magic; - } - shmdt( (char *)patternP ); - } -#endif /* HAS_XVMCSHM */ - - WriteToClient(client, sizeof(xvmcGetDRInfoReply), - (char*)&rep); - if (rep.length) { - WriteToClient(client, rep.nameLen, - pScreenPriv->clientDriverName); - WriteToClient(client, rep.busIDLen, - pScreenPriv->busID); - } - return Success; -} - - -int (*ProcXvMCVector[xvmcNumRequest])(ClientPtr) = { - ProcXvMCQueryVersion, - ProcXvMCListSurfaceTypes, - ProcXvMCCreateContext, - ProcXvMCDestroyContext, - ProcXvMCCreateSurface, - ProcXvMCDestroySurface, - ProcXvMCCreateSubpicture, - ProcXvMCDestroySubpicture, - ProcXvMCListSubpictureTypes, - ProcXvMCGetDRInfo -}; - -static int -ProcXvMCDispatch (ClientPtr client) -{ - REQUEST(xReq); - - if(stuff->data < xvmcNumRequest) - return (*ProcXvMCVector[stuff->data])(client); - else - return BadRequest; -} - -static int -SProcXvMCDispatch (ClientPtr client) -{ - /* We only support local */ - return BadImplementation; -} - -void -XvMCExtensionInit(void) -{ - ExtensionEntry *extEntry; - - if(XvMCScreenKey == NULL) /* nobody supports it */ - return; - - if(!(XvMCRTContext = CreateNewResourceType(XvMCDestroyContextRes, - "XvMCRTContext"))) - return; - - if(!(XvMCRTSurface = CreateNewResourceType(XvMCDestroySurfaceRes, - "XvMCRTSurface"))) - return; - - if(!(XvMCRTSubpicture = CreateNewResourceType(XvMCDestroySubpictureRes, - "XvMCRTSubpicture"))) - return; - - extEntry = AddExtension(XvMCName, XvMCNumEvents, XvMCNumErrors, - ProcXvMCDispatch, SProcXvMCDispatch, - NULL, StandardMinorOpcode); - - if(!extEntry) return; - - XvMCReqCode = extEntry->base; - XvMCEventBase = extEntry->eventBase; - SetResourceTypeErrorValue(XvMCRTContext, extEntry->errorBase + XvMCBadContext); - SetResourceTypeErrorValue(XvMCRTSurface, extEntry->errorBase + XvMCBadSurface); - SetResourceTypeErrorValue(XvMCRTSubpicture, extEntry->errorBase + XvMCBadSubpicture); -} - -static Bool -XvMCCloseScreen (int i, ScreenPtr pScreen) -{ - XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - - free(pScreenPriv); - - return (*pScreen->CloseScreen)(i, pScreen); -} - - -int -XvMCScreenInit(ScreenPtr pScreen, int num, XvMCAdaptorPtr pAdapt) -{ - XvMCScreenPtr pScreenPriv; - - if (!dixRegisterPrivateKey(&XvMCScreenKeyRec, PRIVATE_SCREEN, 0)) - return BadAlloc; - - if(!(pScreenPriv = malloc(sizeof(XvMCScreenRec)))) - return BadAlloc; - - dixSetPrivate(&pScreen->devPrivates, XvMCScreenKey, pScreenPriv); - - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = XvMCCloseScreen; - - pScreenPriv->num_adaptors = num; - pScreenPriv->adaptors = pAdapt; - pScreenPriv->clientDriverName[0] = 0; - pScreenPriv->busID[0] = 0; - pScreenPriv->major = 0; - pScreenPriv->minor = 0; - pScreenPriv->patchLevel = 0; - - XvMCInUse = TRUE; - - return Success; -} - -XvImagePtr XvMCFindXvImage(XvPortPtr pPort, CARD32 id) -{ - XvImagePtr pImage = NULL; - ScreenPtr pScreen = pPort->pAdaptor->pScreen; - XvMCScreenPtr pScreenPriv; - XvMCAdaptorPtr adaptor = NULL; - int i; - - if(XvMCScreenKey == NULL) return NULL; - - if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) - return NULL; - - for(i = 0; i < pScreenPriv->num_adaptors; i++) { - if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { - adaptor = &(pScreenPriv->adaptors[i]); - break; - } - } - - if(!adaptor) return NULL; - - for(i = 0; i < adaptor->num_subpictures; i++) { - if(adaptor->subpictures[i]->id == id) { - pImage = adaptor->subpictures[i]; - break; - } - } - - return pImage; -} - -int -xf86XvMCRegisterDRInfo(ScreenPtr pScreen, char *name, - char *busID, int major, int minor, - int patchLevel) -{ - XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen); - strncpy(pScreenPriv->clientDriverName, name, - DR_CLIENT_DRIVER_NAME_SIZE); - strncpy(pScreenPriv->busID, busID, DR_BUSID_SIZE); - pScreenPriv->major = major; - pScreenPriv->minor = minor; - pScreenPriv->patchLevel = patchLevel; - pScreenPriv->clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE-1] = 0; - pScreenPriv->busID[DR_BUSID_SIZE-1] = 0; - return Success; -} - +
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "scrnintstr.h"
+#include "extnsionst.h"
+#include "servermd.h"
+#include <X11/Xfuncproto.h>
+#include "xvdix.h"
+#include <X11/extensions/XvMC.h>
+#include <X11/extensions/Xvproto.h>
+#include <X11/extensions/XvMCproto.h>
+#include "xvmcext.h"
+#include "protocol-versions.h"
+
+#ifdef HAS_XVMCSHM
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#endif /* HAS_XVMCSHM */
+
+
+
+#define DR_CLIENT_DRIVER_NAME_SIZE 48
+#define DR_BUSID_SIZE 48
+
+static DevPrivateKeyRec XvMCScreenKeyRec;
+#define XvMCScreenKey (&XvMCScreenKeyRec)
+static Bool XvMCInUse;
+
+unsigned long XvMCGeneration = 0;
+
+int XvMCReqCode;
+int XvMCEventBase;
+
+static RESTYPE XvMCRTContext;
+static RESTYPE XvMCRTSurface;
+static RESTYPE XvMCRTSubpicture;
+
+typedef struct {
+ int num_adaptors;
+ XvMCAdaptorPtr adaptors;
+ CloseScreenProcPtr CloseScreen;
+ char clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE];
+ char busID[DR_BUSID_SIZE];
+ int major;
+ int minor;
+ int patchLevel;
+} XvMCScreenRec, *XvMCScreenPtr;
+
+#define XVMC_GET_PRIVATE(pScreen) \
+ (XvMCScreenPtr)(dixLookupPrivate(&(pScreen)->devPrivates, XvMCScreenKey))
+
+
+static int
+XvMCDestroyContextRes(pointer data, XID id)
+{
+ XvMCContextPtr pContext = (XvMCContextPtr)data;
+
+ pContext->refcnt--;
+
+ if(!pContext->refcnt) {
+ XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
+ (*pScreenPriv->adaptors[pContext->adapt_num].DestroyContext)(pContext);
+ free(pContext);
+ }
+
+ return Success;
+}
+
+static int
+XvMCDestroySurfaceRes(pointer data, XID id)
+{
+ XvMCSurfacePtr pSurface = (XvMCSurfacePtr)data;
+ XvMCContextPtr pContext = pSurface->context;
+ XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
+
+ (*pScreenPriv->adaptors[pContext->adapt_num].DestroySurface)(pSurface);
+ free(pSurface);
+
+ XvMCDestroyContextRes((pointer)pContext, pContext->context_id);
+
+ return Success;
+}
+
+
+static int
+XvMCDestroySubpictureRes(pointer data, XID id)
+{
+ XvMCSubpicturePtr pSubpict = (XvMCSubpicturePtr)data;
+ XvMCContextPtr pContext = pSubpict->context;
+ XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
+
+ (*pScreenPriv->adaptors[pContext->adapt_num].DestroySubpicture)(pSubpict);
+ free(pSubpict);
+
+ XvMCDestroyContextRes((pointer)pContext, pContext->context_id);
+
+ return Success;
+}
+
+static int
+ProcXvMCQueryVersion(ClientPtr client)
+{
+ xvmcQueryVersionReply rep;
+ /* REQUEST(xvmcQueryVersionReq); */
+ REQUEST_SIZE_MATCH(xvmcQueryVersionReq);
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.major = SERVER_XVMC_MAJOR_VERSION;
+ rep.minor = SERVER_XVMC_MINOR_VERSION;
+ WriteToClient(client, sizeof(xvmcQueryVersionReply), (char*)&rep);
+ return Success;
+}
+
+
+static int
+ProcXvMCListSurfaceTypes(ClientPtr client)
+{
+ XvPortPtr pPort;
+ int i;
+ XvMCScreenPtr pScreenPriv;
+ xvmcListSurfaceTypesReply rep;
+ xvmcSurfaceInfo info;
+ XvMCAdaptorPtr adaptor = NULL;
+ XvMCSurfaceInfoPtr surface;
+ REQUEST(xvmcListSurfaceTypesReq);
+ REQUEST_SIZE_MATCH(xvmcListSurfaceTypesReq);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ if(XvMCInUse) { /* any adaptors at all */
+ ScreenPtr pScreen = pPort->pAdaptor->pScreen;
+ if((pScreenPriv = XVMC_GET_PRIVATE(pScreen))) { /* any this screen */
+ for(i = 0; i < pScreenPriv->num_adaptors; i++) {
+ if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
+ adaptor = &(pScreenPriv->adaptors[i]);
+ break;
+ }
+ }
+ }
+ }
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.num = (adaptor) ? adaptor->num_surfaces : 0;
+ rep.length = bytes_to_int32(rep.num * sizeof(xvmcSurfaceInfo));
+
+ WriteToClient(client, sizeof(xvmcListSurfaceTypesReply), (char*)&rep);
+
+ for(i = 0; i < rep.num; i++) {
+ surface = adaptor->surfaces[i];
+ info.surface_type_id = surface->surface_type_id;
+ info.chroma_format = surface->chroma_format;
+ info.max_width = surface->max_width;
+ info.max_height = surface->max_height;
+ info.subpicture_max_width = surface->subpicture_max_width;
+ info.subpicture_max_height = surface->subpicture_max_height;
+ info.mc_type = surface->mc_type;
+ info.flags = surface->flags;
+ WriteToClient(client, sizeof(xvmcSurfaceInfo), (char*)&info);
+ }
+
+ return Success;
+}
+
+static int
+ProcXvMCCreateContext(ClientPtr client)
+{
+ XvPortPtr pPort;
+ CARD32 *data = NULL;
+ int dwords = 0;
+ int i, result, adapt_num = -1;
+ ScreenPtr pScreen;
+ XvMCContextPtr pContext;
+ XvMCScreenPtr pScreenPriv;
+ XvMCAdaptorPtr adaptor = NULL;
+ XvMCSurfaceInfoPtr surface = NULL;
+ xvmcCreateContextReply rep;
+ REQUEST(xvmcCreateContextReq);
+ REQUEST_SIZE_MATCH(xvmcCreateContextReq);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ pScreen = pPort->pAdaptor->pScreen;
+
+ if(!XvMCInUse) /* no XvMC adaptors */
+ return BadMatch;
+
+ if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) /* none this screen */
+ return BadMatch;
+
+ for(i = 0; i < pScreenPriv->num_adaptors; i++) {
+ if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
+ adaptor = &(pScreenPriv->adaptors[i]);
+ adapt_num = i;
+ break;
+ }
+ }
+
+ if(adapt_num < 0) /* none this port */
+ return BadMatch;
+
+ for(i = 0; i < adaptor->num_surfaces; i++) {
+ if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) {
+ surface = adaptor->surfaces[i];
+ break;
+ }
+ }
+
+ /* adaptor doesn't support this suface_type_id */
+ if(!surface) return BadMatch;
+
+
+ if((stuff->width > surface->max_width) ||
+ (stuff->height > surface->max_height))
+ return BadValue;
+
+ if(!(pContext = malloc(sizeof(XvMCContextRec)))) {
+ return BadAlloc;
+ }
+
+
+ pContext->pScreen = pScreen;
+ pContext->adapt_num = adapt_num;
+ pContext->context_id = stuff->context_id;
+ pContext->surface_type_id = stuff->surface_type_id;
+ pContext->width = stuff->width;
+ pContext->height = stuff->height;
+ pContext->flags = stuff->flags;
+ pContext->refcnt = 1;
+
+ result = (*adaptor->CreateContext)(pPort, pContext, &dwords, &data);
+
+ if(result != Success) {
+ free(pContext);
+ return result;
+ }
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.width_actual = pContext->width;
+ rep.height_actual = pContext->height;
+ rep.flags_return = pContext->flags;
+ rep.length = dwords;
+
+ WriteToClient(client, sizeof(xvmcCreateContextReply), (char*)&rep);
+ if(dwords)
+ WriteToClient(client, dwords << 2, (char*)data);
+ AddResource(pContext->context_id, XvMCRTContext, pContext);
+
+ free(data);
+
+ return Success;
+}
+
+static int
+ProcXvMCDestroyContext(ClientPtr client)
+{
+ pointer val;
+ int rc;
+ REQUEST(xvmcDestroyContextReq);
+ REQUEST_SIZE_MATCH(xvmcDestroyContextReq);
+
+ rc = dixLookupResourceByType(&val, stuff->context_id, XvMCRTContext,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ FreeResource(stuff->context_id, RT_NONE);
+
+ return Success;
+}
+
+static int
+ProcXvMCCreateSurface(ClientPtr client)
+{
+ CARD32 *data = NULL;
+ int dwords = 0;
+ int result;
+ XvMCContextPtr pContext;
+ XvMCSurfacePtr pSurface;
+ XvMCScreenPtr pScreenPriv;
+ xvmcCreateSurfaceReply rep;
+ REQUEST(xvmcCreateSurfaceReq);
+ REQUEST_SIZE_MATCH(xvmcCreateSurfaceReq);
+
+ result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id,
+ XvMCRTContext, client, DixUseAccess);
+ if (result != Success)
+ return result;
+
+ pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
+
+ if(!(pSurface = malloc(sizeof(XvMCSurfaceRec))))
+ return BadAlloc;
+
+ pSurface->surface_id = stuff->surface_id;
+ pSurface->surface_type_id = pContext->surface_type_id;
+ pSurface->context = pContext;
+
+ result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSurface)(
+ pSurface, &dwords, &data);
+
+ if(result != Success) {
+ free(pSurface);
+ return result;
+ }
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = dwords;
+
+ WriteToClient(client, sizeof(xvmcCreateSurfaceReply), (char*)&rep);
+ if(dwords)
+ WriteToClient(client, dwords << 2, (char*)data);
+ AddResource(pSurface->surface_id, XvMCRTSurface, pSurface);
+
+ free(data);
+
+ pContext->refcnt++;
+
+ return Success;
+}
+
+static int
+ProcXvMCDestroySurface(ClientPtr client)
+{
+ pointer val;
+ int rc;
+ REQUEST(xvmcDestroySurfaceReq);
+ REQUEST_SIZE_MATCH(xvmcDestroySurfaceReq);
+
+ rc = dixLookupResourceByType(&val, stuff->surface_id, XvMCRTSurface,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ FreeResource(stuff->surface_id, RT_NONE);
+
+ return Success;
+}
+
+static int
+ProcXvMCCreateSubpicture(ClientPtr client)
+{
+ Bool image_supported = FALSE;
+ CARD32 *data = NULL;
+ int i, result, dwords = 0;
+ XvMCContextPtr pContext;
+ XvMCSubpicturePtr pSubpicture;
+ XvMCScreenPtr pScreenPriv;
+ xvmcCreateSubpictureReply rep;
+ XvMCAdaptorPtr adaptor;
+ XvMCSurfaceInfoPtr surface = NULL;
+ REQUEST(xvmcCreateSubpictureReq);
+ REQUEST_SIZE_MATCH(xvmcCreateSubpictureReq);
+
+ result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id,
+ XvMCRTContext, client, DixUseAccess);
+ if (result != Success)
+ return result;
+
+ pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
+
+ adaptor = &(pScreenPriv->adaptors[pContext->adapt_num]);
+
+ /* find which surface this context supports */
+ for(i = 0; i < adaptor->num_surfaces; i++) {
+ if(adaptor->surfaces[i]->surface_type_id == pContext->surface_type_id){
+ surface = adaptor->surfaces[i];
+ break;
+ }
+ }
+
+ if(!surface) return BadMatch;
+
+ /* make sure this surface supports that xvimage format */
+ if(!surface->compatible_subpictures) return BadMatch;
+
+ for(i = 0; i < surface->compatible_subpictures->num_xvimages; i++) {
+ if(surface->compatible_subpictures->xvimage_ids[i] == stuff->xvimage_id) {
+ image_supported = TRUE;
+ break;
+ }
+ }
+
+ if(!image_supported) return BadMatch;
+
+ /* make sure the size is OK */
+ if((stuff->width > surface->subpicture_max_width) ||
+ (stuff->height > surface->subpicture_max_height))
+ return BadValue;
+
+ if(!(pSubpicture = malloc(sizeof(XvMCSubpictureRec))))
+ return BadAlloc;
+
+ pSubpicture->subpicture_id = stuff->subpicture_id;
+ pSubpicture->xvimage_id = stuff->xvimage_id;
+ pSubpicture->width = stuff->width;
+ pSubpicture->height = stuff->height;
+ pSubpicture->num_palette_entries = 0; /* overwritten by DDX */
+ pSubpicture->entry_bytes = 0; /* overwritten by DDX */
+ pSubpicture->component_order[0] = 0; /* overwritten by DDX */
+ pSubpicture->component_order[1] = 0;
+ pSubpicture->component_order[2] = 0;
+ pSubpicture->component_order[3] = 0;
+ pSubpicture->context = pContext;
+
+ result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSubpicture)(
+ pSubpicture, &dwords, &data);
+
+ if(result != Success) {
+ free(pSubpicture);
+ return result;
+ }
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.width_actual = pSubpicture->width;
+ rep.height_actual = pSubpicture->height;
+ rep.num_palette_entries = pSubpicture->num_palette_entries;
+ rep.entry_bytes = pSubpicture->entry_bytes;
+ rep.component_order[0] = pSubpicture->component_order[0];
+ rep.component_order[1] = pSubpicture->component_order[1];
+ rep.component_order[2] = pSubpicture->component_order[2];
+ rep.component_order[3] = pSubpicture->component_order[3];
+ rep.length = dwords;
+
+ WriteToClient(client, sizeof(xvmcCreateSubpictureReply), (char*)&rep);
+ if(dwords)
+ WriteToClient(client, dwords << 2, (char*)data);
+ AddResource(pSubpicture->subpicture_id, XvMCRTSubpicture, pSubpicture);
+
+ free(data);
+
+ pContext->refcnt++;
+
+ return Success;
+}
+
+static int
+ProcXvMCDestroySubpicture(ClientPtr client)
+{
+ pointer val;
+ int rc;
+ REQUEST(xvmcDestroySubpictureReq);
+ REQUEST_SIZE_MATCH(xvmcDestroySubpictureReq);
+
+ rc = dixLookupResourceByType(&val, stuff->subpicture_id, XvMCRTSubpicture,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ FreeResource(stuff->subpicture_id, RT_NONE);
+
+ return Success;
+}
+
+
+static int
+ProcXvMCListSubpictureTypes(ClientPtr client)
+{
+ XvPortPtr pPort;
+ xvmcListSubpictureTypesReply rep;
+ XvMCScreenPtr pScreenPriv;
+ ScreenPtr pScreen;
+ XvMCAdaptorPtr adaptor = NULL;
+ XvMCSurfaceInfoPtr surface = NULL;
+ xvImageFormatInfo info;
+ XvImagePtr pImage;
+ int i, j;
+ REQUEST(xvmcListSubpictureTypesReq);
+ REQUEST_SIZE_MATCH(xvmcListSubpictureTypesReq);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ pScreen = pPort->pAdaptor->pScreen;
+
+ if(XvMCScreenKey == NULL) /* No XvMC adaptors */
+ return BadMatch;
+
+ if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen)))
+ return BadMatch; /* None this screen */
+
+ for(i = 0; i < pScreenPriv->num_adaptors; i++) {
+ if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
+ adaptor = &(pScreenPriv->adaptors[i]);
+ break;
+ }
+ }
+
+ if(!adaptor) return BadMatch;
+
+ for(i = 0; i < adaptor->num_surfaces; i++) {
+ if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) {
+ surface = adaptor->surfaces[i];
+ break;
+ }
+ }
+
+ if(!surface) return BadMatch;
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.num = 0;
+ if(surface->compatible_subpictures)
+ rep.num = surface->compatible_subpictures->num_xvimages;
+
+ rep.length = bytes_to_int32(rep.num * sizeof(xvImageFormatInfo));
+
+ WriteToClient(client, sizeof(xvmcListSubpictureTypesReply), (char*)&rep);
+
+ for(i = 0; i < rep.num; i++) {
+ pImage = NULL;
+ for(j = 0; j < adaptor->num_subpictures; j++) {
+ if(surface->compatible_subpictures->xvimage_ids[i] ==
+ adaptor->subpictures[j]->id)
+ {
+ pImage = adaptor->subpictures[j];
+ break;
+ }
+ }
+ if(!pImage) return BadImplementation;
+
+ info.id = pImage->id;
+ info.type = pImage->type;
+ info.byte_order = pImage->byte_order;
+ memcpy(&info.guid, pImage->guid, 16);
+ info.bpp = pImage->bits_per_pixel;
+ info.num_planes = pImage->num_planes;
+ info.depth = pImage->depth;
+ info.red_mask = pImage->red_mask;
+ info.green_mask = pImage->green_mask;
+ info.blue_mask = pImage->blue_mask;
+ info.format = pImage->format;
+ info.y_sample_bits = pImage->y_sample_bits;
+ info.u_sample_bits = pImage->u_sample_bits;
+ info.v_sample_bits = pImage->v_sample_bits;
+ info.horz_y_period = pImage->horz_y_period;
+ info.horz_u_period = pImage->horz_u_period;
+ info.horz_v_period = pImage->horz_v_period;
+ info.vert_y_period = pImage->vert_y_period;
+ info.vert_u_period = pImage->vert_u_period;
+ info.vert_v_period = pImage->vert_v_period;
+ memcpy(&info.comp_order, pImage->component_order, 32);
+ info.scanline_order = pImage->scanline_order;
+ WriteToClient(client, sizeof(xvImageFormatInfo), (char*)&info);
+ }
+
+ return Success;
+}
+
+static int
+ProcXvMCGetDRInfo(ClientPtr client)
+{
+ xvmcGetDRInfoReply rep;
+ XvPortPtr pPort;
+ ScreenPtr pScreen;
+ XvMCScreenPtr pScreenPriv;
+
+#ifdef HAS_XVMCSHM
+ volatile CARD32 *patternP;
+#endif
+
+ REQUEST(xvmcGetDRInfoReq);
+ REQUEST_SIZE_MATCH(xvmcGetDRInfoReq);
+
+ VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess);
+
+ pScreen = pPort->pAdaptor->pScreen;
+ pScreenPriv = XVMC_GET_PRIVATE(pScreen);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.major = pScreenPriv->major;
+ rep.minor = pScreenPriv->minor;
+ rep.patchLevel = pScreenPriv->patchLevel;
+ rep.nameLen = bytes_to_int32(strlen(pScreenPriv->clientDriverName) + 1);
+ rep.busIDLen = bytes_to_int32(strlen(pScreenPriv->busID) + 1);
+
+ rep.length = rep.nameLen + rep.busIDLen;
+ rep.nameLen <<=2;
+ rep.busIDLen <<=2;
+
+ /*
+ * Read back to the client what she has put in the shared memory
+ * segment she prepared for us.
+ */
+
+ rep.isLocal = 1;
+#ifdef HAS_XVMCSHM
+ patternP = (CARD32 *)shmat( stuff->shmKey, NULL, SHM_RDONLY );
+ if ( -1 != (long) patternP) {
+ volatile CARD32 *patternC = patternP;
+ int i;
+ CARD32 magic = stuff->magic;
+
+ rep.isLocal = 1;
+ i = 1024 / sizeof(CARD32);
+
+ while ( i-- ) {
+ if (*patternC++ != magic) {
+ rep.isLocal = 0;
+ break;
+ }
+ magic = ~magic;
+ }
+ shmdt( (char *)patternP );
+ }
+#endif /* HAS_XVMCSHM */
+
+ WriteToClient(client, sizeof(xvmcGetDRInfoReply),
+ (char*)&rep);
+ if (rep.length) {
+ WriteToClient(client, rep.nameLen,
+ pScreenPriv->clientDriverName);
+ WriteToClient(client, rep.busIDLen,
+ pScreenPriv->busID);
+ }
+ return Success;
+}
+
+
+int (*ProcXvMCVector[xvmcNumRequest])(ClientPtr) = {
+ ProcXvMCQueryVersion,
+ ProcXvMCListSurfaceTypes,
+ ProcXvMCCreateContext,
+ ProcXvMCDestroyContext,
+ ProcXvMCCreateSurface,
+ ProcXvMCDestroySurface,
+ ProcXvMCCreateSubpicture,
+ ProcXvMCDestroySubpicture,
+ ProcXvMCListSubpictureTypes,
+ ProcXvMCGetDRInfo
+};
+
+static int
+ProcXvMCDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ if(stuff->data < xvmcNumRequest)
+ return (*ProcXvMCVector[stuff->data])(client);
+ else
+ return BadRequest;
+}
+
+static int
+SProcXvMCDispatch (ClientPtr client)
+{
+ /* We only support local */
+ return BadImplementation;
+}
+
+void
+XvMCExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+
+ if(XvMCScreenKey == NULL) /* nobody supports it */
+ return;
+
+ if(!(XvMCRTContext = CreateNewResourceType(XvMCDestroyContextRes,
+ "XvMCRTContext")))
+ return;
+
+ if(!(XvMCRTSurface = CreateNewResourceType(XvMCDestroySurfaceRes,
+ "XvMCRTSurface")))
+ return;
+
+ if(!(XvMCRTSubpicture = CreateNewResourceType(XvMCDestroySubpictureRes,
+ "XvMCRTSubpicture")))
+ return;
+
+ extEntry = AddExtension(XvMCName, XvMCNumEvents, XvMCNumErrors,
+ ProcXvMCDispatch, SProcXvMCDispatch,
+ NULL, StandardMinorOpcode);
+
+ if(!extEntry) return;
+
+ XvMCReqCode = extEntry->base;
+ XvMCEventBase = extEntry->eventBase;
+ SetResourceTypeErrorValue(XvMCRTContext, extEntry->errorBase + XvMCBadContext);
+ SetResourceTypeErrorValue(XvMCRTSurface, extEntry->errorBase + XvMCBadSurface);
+ SetResourceTypeErrorValue(XvMCRTSubpicture, extEntry->errorBase + XvMCBadSubpicture);
+}
+
+static Bool
+XvMCCloseScreen (int i, ScreenPtr pScreen)
+{
+ XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen);
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+
+ free(pScreenPriv);
+
+ return (*pScreen->CloseScreen)(i, pScreen);
+}
+
+
+int
+XvMCScreenInit(ScreenPtr pScreen, int num, XvMCAdaptorPtr pAdapt)
+{
+ XvMCScreenPtr pScreenPriv;
+
+ if (!dixRegisterPrivateKey(&XvMCScreenKeyRec, PRIVATE_SCREEN, 0))
+ return BadAlloc;
+
+ if(!(pScreenPriv = malloc(sizeof(XvMCScreenRec))))
+ return BadAlloc;
+
+ dixSetPrivate(&pScreen->devPrivates, XvMCScreenKey, pScreenPriv);
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = XvMCCloseScreen;
+
+ pScreenPriv->num_adaptors = num;
+ pScreenPriv->adaptors = pAdapt;
+ pScreenPriv->clientDriverName[0] = 0;
+ pScreenPriv->busID[0] = 0;
+ pScreenPriv->major = 0;
+ pScreenPriv->minor = 0;
+ pScreenPriv->patchLevel = 0;
+
+ XvMCInUse = TRUE;
+
+ return Success;
+}
+
+XvImagePtr XvMCFindXvImage(XvPortPtr pPort, CARD32 id)
+{
+ XvImagePtr pImage = NULL;
+ ScreenPtr pScreen = pPort->pAdaptor->pScreen;
+ XvMCScreenPtr pScreenPriv;
+ XvMCAdaptorPtr adaptor = NULL;
+ int i;
+
+ if(XvMCScreenKey == NULL) return NULL;
+
+ if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen)))
+ return NULL;
+
+ for(i = 0; i < pScreenPriv->num_adaptors; i++) {
+ if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
+ adaptor = &(pScreenPriv->adaptors[i]);
+ break;
+ }
+ }
+
+ if(!adaptor) return NULL;
+
+ for(i = 0; i < adaptor->num_subpictures; i++) {
+ if(adaptor->subpictures[i]->id == id) {
+ pImage = adaptor->subpictures[i];
+ break;
+ }
+ }
+
+ return pImage;
+}
+
+int
+xf86XvMCRegisterDRInfo(ScreenPtr pScreen, char *name,
+ char *busID, int major, int minor,
+ int patchLevel)
+{
+ XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen);
+ strncpy(pScreenPriv->clientDriverName, name,
+ DR_CLIENT_DRIVER_NAME_SIZE);
+ strncpy(pScreenPriv->busID, busID, DR_BUSID_SIZE);
+ pScreenPriv->major = major;
+ pScreenPriv->minor = minor;
+ pScreenPriv->patchLevel = patchLevel;
+ pScreenPriv->clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE-1] = 0;
+ pScreenPriv->busID[DR_BUSID_SIZE-1] = 0;
+ return Success;
+}
+
|