summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKensuke Matsuzaki <zakki@peppermint.jp>2004-08-03 03:56:41 +0000
committerKensuke Matsuzaki <zakki@peppermint.jp>2004-08-03 03:56:41 +0000
commita6098447e985a4e4ef2eb4ca0708cf6e43455439 (patch)
tree40defd1b9a5c4ab2185a6e5e5ea4339cdc146d6d
parent9d1e08f4c3cde4b1c55af8fb3cfcebff6a637692 (diff)
Fix the bug that we can't copy & paste multi-byte string to Unicode-base
Windows application. Rename fUnicodeSupport to fUseUnicode, because it don't mean wheather Windows support Unicode or not.
-rw-r--r--GL/mesa/X/xf86glx.c939
-rw-r--r--Xext/xevie.c371
-rw-r--r--composite/compext.c408
-rwxr-xr-xdamageext/damageext.c480
-rw-r--r--damageext/damageext.h31
-rw-r--r--damageext/damageextint.h84
-rw-r--r--fb/fbmmx.c1514
-rw-r--r--fb/fbmmx.h160
-rw-r--r--fb/fbpseudocolor.c2330
-rw-r--r--fb/fbpseudocolor.h20
-rw-r--r--hw/darwin/darwinXinput.c310
-rw-r--r--hw/dmx/dmx.h374
-rw-r--r--hw/dmx/dmxextension.c1493
-rw-r--r--hw/dmx/dmxinit.c1058
-rw-r--r--hw/dmx/dmxwindow.c1081
-rw-r--r--hw/dmx/input/dmxconsole.c1019
-rw-r--r--hw/xfree86/os-support/drm/xf86drm.c2335
-rw-r--r--hw/xfree86/os-support/xf86drm.h636
-rw-r--r--hw/xfree86/parser/Extensions.c107
-rw-r--r--hw/xfree86/xaa/xaaWrapper.c924
-rw-r--r--hw/xfree86/xaa/xaaWrapper.h9
-rw-r--r--hw/xwin/winclipboardthread.c17
-rw-r--r--hw/xwin/winclipboardwndproc.c10
-rw-r--r--hw/xwin/winclipboardxevents.c31
-rwxr-xr-xhw/xwin/winwin32rootlesswndproc.c2
-rwxr-xr-xmiext/damage/damage.h80
-rw-r--r--miext/rootless/README.txt403
-rwxr-xr-xxfixes/cursor.c752
-rwxr-xr-xxfixes/region.c850
-rwxr-xr-xxfixes/saveset.c78
-rwxr-xr-xxfixes/select.c278
-rwxr-xr-xxfixes/xfixes.c230
-rwxr-xr-xxfixes/xfixes.h50
-rwxr-xr-xxfixes/xfixesint.h239
34 files changed, 18677 insertions, 26 deletions
diff --git a/GL/mesa/X/xf86glx.c b/GL/mesa/X/xf86glx.c
new file mode 100644
index 000000000..bd8ff7fe0
--- /dev/null
+++ b/GL/mesa/X/xf86glx.c
@@ -0,0 +1,939 @@
+/* $XFree86: xc/programs/Xserver/GL/mesa/src/X/xf86glx.c,v 1.19 2003/07/16 01:38:27 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+
+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, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) 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 NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ * Kevin E. Martin <kevin@precisioninsight.com>
+ * Brian E. Paul <brian@precisioninsight.com>
+ *
+ */
+
+#include <regionstr.h>
+#include <resource.h>
+#include <GL/gl.h>
+#include <GL/glxint.h>
+#include <GL/glxtokens.h>
+#include <scrnintstr.h>
+#include <config.h>
+#include <glxserver.h>
+#include <glxscreens.h>
+#include <glxdrawable.h>
+#include <glxcontext.h>
+#include <glxext.h>
+#include <glxutil.h>
+#include "xf86glxint.h"
+#include "context.h"
+#include "xmesaP.h"
+#include <GL/xf86glx.h>
+#include "context.h"
+
+/*
+ * This define is for the glcore.h header file.
+ * If you add it here, then make sure you also add it in
+ * ../../../glx/Imakefile.
+ */
+#if 0
+#define DEBUG
+#include <GL/internal/glcore.h>
+#undef DEBUG
+#else
+#include <GL/internal/glcore.h>
+#endif
+
+#include "glcontextmodes.h"
+
+/*
+ * This structure is statically allocated in the __glXScreens[]
+ * structure. This struct is not used anywhere other than in
+ * __glXScreenInit to initialize each of the active screens
+ * (__glXActiveScreens[]). Several of the fields must be initialized by
+ * the screenProbe routine before they are copied to the active screens
+ * struct. In particular, the contextCreate, pGlxVisual, numVisuals,
+ * and numUsableVisuals fields must be initialized.
+ */
+static __GLXscreenInfo __glDDXScreenInfo = {
+ __MESA_screenProbe, /* Must be generic and handle all screens */
+ __MESA_createContext, /* Substitute screen's createContext routine */
+ __MESA_createBuffer, /* Substitute screen's createBuffer routine */
+ NULL, /* Set up modes in probe */
+ NULL, /* Set up pVisualPriv in probe */
+ 0, /* Set up numVisuals in probe */
+ 0, /* Set up numUsableVisuals in probe */
+ "Vendor String", /* GLXvendor is overwritten by __glXScreenInit */
+ "Version String", /* GLXversion is overwritten by __glXScreenInit */
+ "Extensions String", /* GLXextensions is overwritten by __glXScreenInit */
+ NULL /* WrappedPositionWindow is overwritten */
+};
+
+void *__glXglDDXScreenInfo(void) {
+ return &__glDDXScreenInfo;
+}
+
+static __GLXextensionInfo __glDDXExtensionInfo = {
+ GL_CORE_MESA,
+ __MESA_resetExtension,
+ __MESA_initVisuals,
+ __MESA_setVisualConfigs
+};
+
+void *__glXglDDXExtensionInfo(void) {
+ return &__glDDXExtensionInfo;
+}
+
+static __MESA_screen MESAScreens[MAXSCREENS];
+static __GLcontext *MESA_CC = NULL;
+
+static int numConfigs = 0;
+static __GLXvisualConfig *visualConfigs = NULL;
+static void **visualPrivates = NULL;
+
+
+static int count_bits(unsigned int n)
+{
+ int bits = 0;
+
+ while (n > 0) {
+ if (n & 1) bits++;
+ n >>= 1;
+ }
+ return bits;
+}
+
+
+static XMesaVisual find_mesa_visual(int screen, VisualID vid)
+{
+ __MESA_screen * const pMScr = &MESAScreens[screen];
+ const __GLcontextModes *modes;
+ unsigned i = 0;
+
+ for ( modes = pMScr->modes ; modes != NULL ; modes = modes->next ) {
+ if ( modes->visualID == vid ) {
+ break;
+ }
+
+ i++;
+ }
+
+ return (modes != NULL) ? pMScr->xm_vis[i] : NULL;
+}
+
+
+/*
+ * In the case the driver defines no GLX visuals we'll use these.
+ * Note that for TrueColor and DirectColor visuals, bufferSize is the
+ * sum of redSize, greenSize, blueSize and alphaSize, which may be larger
+ * than the nplanes/rootDepth of the server's X11 visuals
+ */
+#define NUM_FALLBACK_CONFIGS 5
+static __GLXvisualConfig FallbackConfigs[NUM_FALLBACK_CONFIGS] = {
+ /* [0] = RGB, double buffered, Z */
+ {
+ -1, /* vid */
+ -1, /* class */
+ True, /* rgba */
+ -1, -1, -1, 0, /* rgba sizes */
+ -1, -1, -1, 0, /* rgba masks */
+ 0, 0, 0, 0, /* rgba accum sizes */
+ True, /* doubleBuffer */
+ False, /* stereo */
+ -1, /* bufferSize */
+ 16, /* depthSize */
+ 0, /* stencilSize */
+ 0, /* auxBuffers */
+ 0, /* level */
+ GLX_NONE, /* visualRating */
+ GLX_NONE, /* transparentPixel */
+ 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */
+ 0 /* transparentIndex */
+ },
+ /* [1] = RGB, double buffered, Z, stencil, accum */
+ {
+ -1, /* vid */
+ -1, /* class */
+ True, /* rgba */
+ -1, -1, -1, 0, /* rgba sizes */
+ -1, -1, -1, 0, /* rgba masks */
+ 16, 16, 16, 0, /* rgba accum sizes */
+ True, /* doubleBuffer */
+ False, /* stereo */
+ -1, /* bufferSize */
+ 16, /* depthSize */
+ 8, /* stencilSize */
+ 0, /* auxBuffers */
+ 0, /* level */
+ GLX_NONE, /* visualRating */
+ GLX_NONE, /* transparentPixel */
+ 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */
+ 0 /* transparentIndex */
+ },
+ /* [2] = RGB+Alpha, double buffered, Z, stencil, accum */
+ {
+ -1, /* vid */
+ -1, /* class */
+ True, /* rgba */
+ -1, -1, -1, 8, /* rgba sizes */
+ -1, -1, -1, -1, /* rgba masks */
+ 16, 16, 16, 16, /* rgba accum sizes */
+ True, /* doubleBuffer */
+ False, /* stereo */
+ -1, /* bufferSize */
+ 16, /* depthSize */
+ 8, /* stencilSize */
+ 0, /* auxBuffers */
+ 0, /* level */
+ GLX_NONE, /* visualRating */
+ GLX_NONE, /* transparentPixel */
+ 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */
+ 0 /* transparentIndex */
+ },
+ /* [3] = RGB+Alpha, single buffered, Z, stencil, accum */
+ {
+ -1, /* vid */
+ -1, /* class */
+ True, /* rgba */
+ -1, -1, -1, 8, /* rgba sizes */
+ -1, -1, -1, -1, /* rgba masks */
+ 16, 16, 16, 16, /* rgba accum sizes */
+ False, /* doubleBuffer */
+ False, /* stereo */
+ -1, /* bufferSize */
+ 16, /* depthSize */
+ 8, /* stencilSize */
+ 0, /* auxBuffers */
+ 0, /* level */
+ GLX_NONE, /* visualRating */
+ GLX_NONE, /* transparentPixel */
+ 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */
+ 0 /* transparentIndex */
+ },
+ /* [4] = CI, double buffered, Z */
+ {
+ -1, /* vid */
+ -1, /* class */
+ False, /* rgba? (false = color index) */
+ -1, -1, -1, 0, /* rgba sizes */
+ -1, -1, -1, 0, /* rgba masks */
+ 0, 0, 0, 0, /* rgba accum sizes */
+ True, /* doubleBuffer */
+ False, /* stereo */
+ -1, /* bufferSize */
+ 16, /* depthSize */
+ 0, /* stencilSize */
+ 0, /* auxBuffers */
+ 0, /* level */
+ GLX_NONE, /* visualRating */
+ GLX_NONE, /* transparentPixel */
+ 0, 0, 0, 0, /* transparent rgba color (floats scaled to ints) */
+ 0 /* transparentIndex */
+ },
+};
+
+
+static Bool init_visuals(int *nvisualp, VisualPtr *visualp,
+ VisualID *defaultVisp,
+ int ndepth, DepthPtr pdepth,
+ int rootDepth)
+{
+ int numRGBconfigs;
+ int numCIconfigs;
+ int numVisuals = *nvisualp;
+ int numNewVisuals;
+ int numNewConfigs;
+ VisualPtr pVisual = *visualp;
+ VisualPtr pVisualNew = NULL;
+ VisualID *orig_vid = NULL;
+ __GLcontextModes *modes;
+ __GLXvisualConfig *pNewVisualConfigs = NULL;
+ void **glXVisualPriv;
+ void **pNewVisualPriv;
+ int found_default;
+ int i, j, k;
+
+ if (numConfigs > 0)
+ numNewConfigs = numConfigs;
+ else
+ numNewConfigs = NUM_FALLBACK_CONFIGS;
+
+ /* Alloc space for the list of new GLX visuals */
+ pNewVisualConfigs = (__GLXvisualConfig *)
+ __glXMalloc(numNewConfigs * sizeof(__GLXvisualConfig));
+ if (!pNewVisualConfigs) {
+ return FALSE;
+ }
+
+ /* Alloc space for the list of new GLX visual privates */
+ pNewVisualPriv = (void **) __glXMalloc(numNewConfigs * sizeof(void *));
+ if (!pNewVisualPriv) {
+ __glXFree(pNewVisualConfigs);
+ return FALSE;
+ }
+
+ /*
+ ** If SetVisualConfigs was not called, then use default GLX
+ ** visual configs.
+ */
+ if (numConfigs == 0) {
+ memcpy(pNewVisualConfigs, FallbackConfigs,
+ NUM_FALLBACK_CONFIGS * sizeof(__GLXvisualConfig));
+ memset(pNewVisualPriv, 0, NUM_FALLBACK_CONFIGS * sizeof(void *));
+ }
+ else {
+ /* copy driver's visual config info */
+ for (i = 0; i < numConfigs; i++) {
+ pNewVisualConfigs[i] = visualConfigs[i];
+ pNewVisualPriv[i] = visualPrivates[i];
+ }
+ }
+
+ /* Count the number of RGB and CI visual configs */
+ numRGBconfigs = 0;
+ numCIconfigs = 0;
+ for (i = 0; i < numNewConfigs; i++) {
+ if (pNewVisualConfigs[i].rgba)
+ numRGBconfigs++;
+ else
+ numCIconfigs++;
+ }
+
+ /* Count the total number of visuals to compute */
+ numNewVisuals = 0;
+ for (i = 0; i < numVisuals; i++) {
+ numNewVisuals +=
+ (pVisual[i].class == TrueColor || pVisual[i].class == DirectColor)
+ ? numRGBconfigs : numCIconfigs;
+ }
+
+ /* Reset variables for use with the next screen/driver's visual configs */
+ visualConfigs = NULL;
+ numConfigs = 0;
+
+ /* Alloc temp space for the list of orig VisualIDs for each new visual */
+ orig_vid = (VisualID *)__glXMalloc(numNewVisuals * sizeof(VisualID));
+ if (!orig_vid) {
+ __glXFree(pNewVisualPriv);
+ __glXFree(pNewVisualConfigs);
+ return FALSE;
+ }
+
+ /* Alloc space for the list of glXVisuals */
+ modes = _gl_context_modes_create(numNewVisuals, sizeof(__GLcontextModes));
+ if (modes == NULL) {
+ __glXFree(orig_vid);
+ __glXFree(pNewVisualPriv);
+ __glXFree(pNewVisualConfigs);
+ return FALSE;
+ }
+
+ /* Alloc space for the list of glXVisualPrivates */
+ glXVisualPriv = (void **)__glXMalloc(numNewVisuals * sizeof(void *));
+ if (!glXVisualPriv) {
+ _gl_context_modes_destroy( modes );
+ __glXFree(orig_vid);
+ __glXFree(pNewVisualPriv);
+ __glXFree(pNewVisualConfigs);
+ return FALSE;
+ }
+
+ /* Alloc space for the new list of the X server's visuals */
+ pVisualNew = (VisualPtr)__glXMalloc(numNewVisuals * sizeof(VisualRec));
+ if (!pVisualNew) {
+ __glXFree(glXVisualPriv);
+ _gl_context_modes_destroy( modes );
+ __glXFree(orig_vid);
+ __glXFree(pNewVisualPriv);
+ __glXFree(pNewVisualConfigs);
+ return FALSE;
+ }
+
+ /* Initialize the new visuals */
+ found_default = FALSE;
+ MESAScreens[screenInfo.numScreens-1].modes = modes;
+ for (i = j = 0; i < numVisuals; i++) {
+ int is_rgb = (pVisual[i].class == TrueColor ||
+ pVisual[i].class == DirectColor);
+
+ for (k = 0; k < numNewConfigs; k++) {
+ if (pNewVisualConfigs[k].rgba != is_rgb)
+ continue;
+
+ assert( modes != NULL );
+
+ /* Initialize the new visual */
+ pVisualNew[j] = pVisual[i];
+ pVisualNew[j].vid = FakeClientID(0);
+
+ /* Check for the default visual */
+ if (!found_default && pVisual[i].vid == *defaultVisp) {
+ *defaultVisp = pVisualNew[j].vid;
+ found_default = TRUE;
+ }
+
+ /* Save the old VisualID */
+ orig_vid[j] = pVisual[i].vid;
+
+ /* Initialize the glXVisual */
+ _gl_copy_visual_to_context_mode( modes, & pNewVisualConfigs[k] );
+ modes->visualID = pVisualNew[j].vid;
+
+ /*
+ * If the class is -1, then assume the X visual information
+ * is identical to what GLX needs, and take them from the X
+ * visual. NOTE: if class != -1, then all other fields MUST
+ * be initialized.
+ */
+ if (modes->visualType == GLX_NONE) {
+ modes->visualType = _gl_convert_from_x_visual_type( pVisual[i].class );
+ modes->redBits = count_bits(pVisual[i].redMask);
+ modes->greenBits = count_bits(pVisual[i].greenMask);
+ modes->blueBits = count_bits(pVisual[i].blueMask);
+ modes->alphaBits = modes->alphaBits;
+ modes->redMask = pVisual[i].redMask;
+ modes->greenMask = pVisual[i].greenMask;
+ modes->blueMask = pVisual[i].blueMask;
+ modes->alphaMask = modes->alphaMask;
+ modes->rgbBits = (is_rgb)
+ ? (modes->redBits + modes->greenBits +
+ modes->blueBits + modes->alphaBits)
+ : rootDepth;
+ }
+
+ /* Save the device-dependent private for this visual */
+ glXVisualPriv[j] = pNewVisualPriv[k];
+
+ j++;
+ modes = modes->next;
+ }
+ }
+
+ assert(j <= numNewVisuals);
+
+ /* Save the GLX visuals in the screen structure */
+ MESAScreens[screenInfo.numScreens-1].num_vis = numNewVisuals;
+ MESAScreens[screenInfo.numScreens-1].private = glXVisualPriv;
+
+ /* Set up depth's VisualIDs */
+ for (i = 0; i < ndepth; i++) {
+ int numVids = 0;
+ VisualID *pVids = NULL;
+ int k, n = 0;
+
+ /* Count the new number of VisualIDs at this depth */
+ for (j = 0; j < pdepth[i].numVids; j++)
+ for (k = 0; k < numNewVisuals; k++)
+ if (pdepth[i].vids[j] == orig_vid[k])
+ numVids++;
+
+ /* Allocate a new list of VisualIDs for this depth */
+ pVids = (VisualID *)__glXMalloc(numVids * sizeof(VisualID));
+
+ /* Initialize the new list of VisualIDs for this depth */
+ for (j = 0; j < pdepth[i].numVids; j++)
+ for (k = 0; k < numNewVisuals; k++)
+ if (pdepth[i].vids[j] == orig_vid[k])
+ pVids[n++] = pVisualNew[k].vid;
+
+ /* Update this depth's list of VisualIDs */
+ __glXFree(pdepth[i].vids);
+ pdepth[i].vids = pVids;
+ pdepth[i].numVids = numVids;
+ }
+
+ /* Update the X server's visuals */
+ *nvisualp = numNewVisuals;
+ *visualp = pVisualNew;
+
+ /* Free the old list of the X server's visuals */
+ __glXFree(pVisual);
+
+ /* Clean up temporary allocations */
+ __glXFree(orig_vid);
+ __glXFree(pNewVisualPriv);
+ __glXFree(pNewVisualConfigs);
+
+ /* Free the private list created by DDX HW driver */
+ if (visualPrivates)
+ xfree(visualPrivates);
+ visualPrivates = NULL;
+
+ return TRUE;
+}
+
+void __MESA_setVisualConfigs(int nconfigs, __GLXvisualConfig *configs,
+ void **privates)
+{
+ numConfigs = nconfigs;
+ visualConfigs = configs;
+ visualPrivates = privates;
+}
+
+Bool __MESA_initVisuals(VisualPtr *visualp, DepthPtr *depthp,
+ int *nvisualp, int *ndepthp, int *rootDepthp,
+ VisualID *defaultVisp, unsigned long sizes,
+ int bitsPerRGB)
+{
+ /*
+ * Setup the visuals supported by this particular screen.
+ */
+ return init_visuals(nvisualp, visualp, defaultVisp,
+ *ndepthp, *depthp, *rootDepthp);
+}
+
+static void fixup_visuals(int screen)
+{
+ ScreenPtr pScreen = screenInfo.screens[screen];
+ __MESA_screen *pMScr = &MESAScreens[screen];
+ int j;
+ __GLcontextModes *modes;
+
+ for ( modes = pMScr->modes ; modes != NULL ; modes = modes->next ) {
+ const int vis_class = _gl_convert_to_x_visual_type( modes->visualType );
+ const int nplanes = (modes->rgbBits - modes->alphaBits);
+ const VisualPtr pVis = pScreen->visuals;
+
+ /* Find a visual that matches the GLX visual's class and size */
+ for (j = 0; j < pScreen->numVisuals; j++) {
+ if (pVis[j].class == vis_class &&
+ pVis[j].nplanes == nplanes) {
+
+ /* Fixup the masks */
+ modes->redMask = pVis[j].redMask;
+ modes->greenMask = pVis[j].greenMask;
+ modes->blueMask = pVis[j].blueMask;
+
+ /* Recalc the sizes */
+ modes->redBits = count_bits(modes->redMask);
+ modes->greenBits = count_bits(modes->greenMask);
+ modes->blueBits = count_bits(modes->blueMask);
+ }
+ }
+ }
+}
+
+static void init_screen_visuals(int screen)
+{
+ ScreenPtr pScreen = screenInfo.screens[screen];
+ __GLcontextModes *modes;
+ XMesaVisual *pXMesaVisual;
+ int *used;
+ int i, j;
+
+ /* Alloc space for the list of XMesa visuals */
+ pXMesaVisual = (XMesaVisual *)__glXMalloc(MESAScreens[screen].num_vis *
+ sizeof(XMesaVisual));
+ __glXMemset(pXMesaVisual, 0,
+ MESAScreens[screen].num_vis * sizeof(XMesaVisual));
+
+ /* FIXME: Change 'used' to be a array of bits (rather than of ints),
+ * FIXME: create a stack array of 8 or 16 bytes. If 'numVisuals' is less
+ * FIXME: than 64 or 128 the stack array can be used instead of calling
+ * FIXME: __glXMalloc / __glXFree. If nothing else, convert 'used' to
+ * FIXME: array of bytes instead of ints!
+ */
+ used = (int *)__glXMalloc(pScreen->numVisuals * sizeof(int));
+ __glXMemset(used, 0, pScreen->numVisuals * sizeof(int));
+
+ i = 0;
+ for ( modes = MESAScreens[screen].modes
+ ; modes != NULL
+ ; modes = modes->next ) {
+ const int vis_class = _gl_convert_to_x_visual_type( modes->visualType );
+ const int nplanes = (modes->rgbBits - modes->alphaBits);
+ const VisualPtr pVis = pScreen->visuals;
+
+ for (j = 0; j < pScreen->numVisuals; j++) {
+ if (pVis[j].class == vis_class &&
+ pVis[j].nplanes == nplanes &&
+ pVis[j].redMask == modes->redMask &&
+ pVis[j].greenMask == modes->greenMask &&
+ pVis[j].blueMask == modes->blueMask &&
+ !used[j]) {
+
+ /* Create the XMesa visual */
+ pXMesaVisual[i] =
+ XMesaCreateVisual(pScreen,
+ pVis,
+ modes->rgbMode,
+ (modes->alphaBits > 0),
+ modes->doubleBufferMode,
+ modes->stereoMode,
+ GL_TRUE, /* ximage_flag */
+ modes->depthBits,
+ modes->stencilBits,
+ modes->accumRedBits,
+ modes->accumGreenBits,
+ modes->accumBlueBits,
+ modes->accumAlphaBits,
+ modes->samples,
+ modes->level,
+ modes->visualRating);
+ /* Set the VisualID */
+ modes->visualID = pVis[j].vid;
+
+ /* Mark this visual used */
+ used[j] = 1;
+ break;
+ }
+ }
+
+ if ( j == pScreen->numVisuals ) {
+ ErrorF("No matching visual for __GLcontextMode with "
+ "visual class = %d (%d), nplanes = %u\n",
+ vis_class,
+ modes->visualType,
+ (modes->rgbBits - modes->alphaBits) );
+ }
+ else if ( modes->visualID == -1 ) {
+ FatalError( "Matching visual found, but visualID still -1!\n" );
+ }
+
+ i++;
+ }
+
+ __glXFree(used);
+
+ MESAScreens[screen].xm_vis = pXMesaVisual;
+}
+
+Bool __MESA_screenProbe(int screen)
+{
+ /*
+ * Set up the current screen's visuals.
+ */
+ __glDDXScreenInfo.modes = MESAScreens[screen].modes;
+ __glDDXScreenInfo.pVisualPriv = MESAScreens[screen].private;
+ __glDDXScreenInfo.numVisuals =
+ __glDDXScreenInfo.numUsableVisuals = MESAScreens[screen].num_vis;
+
+ /*
+ * Set the current screen's createContext routine. This could be
+ * wrapped by a DDX GLX context creation routine.
+ */
+ __glDDXScreenInfo.createContext = __MESA_createContext;
+
+ /*
+ * The ordering of the rgb compenents might have been changed by the
+ * driver after mi initialized them.
+ */
+ fixup_visuals(screen);
+
+ /*
+ * Find the GLX visuals that are supported by this screen and create
+ * XMesa's visuals.
+ */
+ init_screen_visuals(screen);
+
+ return TRUE;
+}
+
+extern void __MESA_resetExtension(void)
+{
+ int i, j;
+
+ XMesaReset();
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ for (j = 0; j < MESAScreens[i].num_vis; j++) {
+ if (MESAScreens[i].xm_vis[j]) {
+ XMesaDestroyVisual(MESAScreens[i].xm_vis[j]);
+ MESAScreens[i].xm_vis[j] = NULL;
+ }
+ }
+ _gl_context_modes_destroy( MESAScreens[i].modes );
+ MESAScreens[i].modes = NULL;
+ __glXFree(MESAScreens[i].private);
+ MESAScreens[i].private = NULL;
+ __glXFree(MESAScreens[i].xm_vis);
+ MESAScreens[i].xm_vis = NULL;
+ MESAScreens[i].num_vis = 0;
+ }
+ __glDDXScreenInfo.modes = NULL;
+ MESA_CC = NULL;
+}
+
+void __MESA_createBuffer(__GLXdrawablePrivate *glxPriv)
+{
+ DrawablePtr pDraw = glxPriv->pDraw;
+ XMesaVisual xm_vis = find_mesa_visual(pDraw->pScreen->myNum,
+ glxPriv->modes->visualID);
+ __GLdrawablePrivate *glPriv = &glxPriv->glPriv;
+ __MESA_buffer buf;
+
+ if (xm_vis == NULL) {
+ ErrorF("find_mesa_visual returned NULL for visualID = 0x%04x\n",
+ glxPriv->modes->visualID);
+ }
+ buf = (__MESA_buffer)__glXMalloc(sizeof(struct __MESA_bufferRec));
+
+ /* Create Mesa's buffers */
+ if (glxPriv->type == DRAWABLE_WINDOW) {
+ buf->xm_buf = (void *)XMesaCreateWindowBuffer(xm_vis,
+ (WindowPtr)pDraw);
+ } else {
+ buf->xm_buf = (void *)XMesaCreatePixmapBuffer(xm_vis,
+ (PixmapPtr)pDraw, 0);
+ }
+
+ /* Wrap the front buffer's resize routine */
+ buf->fbresize = glPriv->frontBuffer.resize;
+ glPriv->frontBuffer.resize = __MESA_resizeBuffers;
+
+ /* Wrap the swap buffers routine */
+ buf->fbswap = glxPriv->swapBuffers;
+ glxPriv->swapBuffers = __MESA_swapBuffers;
+
+ /* Save Mesa's private buffer structure */
+ glPriv->private = (void *)buf;
+ glPriv->freePrivate = __MESA_destroyBuffer;
+}
+
+GLboolean __MESA_resizeBuffers(__GLdrawableBuffer *buffer,
+ GLint x, GLint y,
+ GLuint width, GLuint height,
+ __GLdrawablePrivate *glPriv,
+ GLuint bufferMask)
+{
+ __MESA_buffer buf = (__MESA_buffer)glPriv->private;
+
+ if (buf->xm_buf)
+ XMesaResizeBuffers(buf->xm_buf);
+
+ return (*buf->fbresize)(buffer, x, y, width, height, glPriv, bufferMask);
+}
+
+GLboolean __MESA_swapBuffers(__GLXdrawablePrivate *glxPriv)
+{
+ __MESA_buffer buf = (__MESA_buffer)glxPriv->glPriv.private;
+
+ /*
+ ** Do not call the wrapped swap buffers routine since Mesa has
+ ** already done the swap.
+ */
+ XMesaSwapBuffers(buf->xm_buf);
+
+ return GL_TRUE;
+}
+
+void __MESA_destroyBuffer(__GLdrawablePrivate *glPriv)
+{
+ __MESA_buffer buf = (__MESA_buffer)glPriv->private;
+ __GLXdrawablePrivate *glxPriv = (__GLXdrawablePrivate *)glPriv->other;
+
+ /* Destroy Mesa's buffers */
+ if (buf->xm_buf)
+ XMesaDestroyBuffer(buf->xm_buf);
+
+ /* Unwrap these routines */
+ glxPriv->swapBuffers = buf->fbswap;
+ glPriv->frontBuffer.resize = buf->fbresize;
+
+ __glXFree(glPriv->private);
+ glPriv->private = NULL;
+}
+
+__GLinterface *__MESA_createContext(__GLimports *imports,
+ __GLcontextModes *modes,
+ __GLinterface *shareGC)
+{
+ __GLcontext *gl_ctx = NULL;
+ __GLcontext *m_share = NULL;
+ __GLXcontext *glxc = (__GLXcontext *)imports->other;
+ XMesaVisual xm_vis;
+
+ if (shareGC)
+ m_share = (__GLcontext *)shareGC;
+
+ xm_vis = find_mesa_visual(glxc->pScreen->myNum, glxc->modes->visualID);
+ if (xm_vis) {
+ XMesaContext xmshare = m_share ? m_share->DriverCtx : 0;
+ XMesaContext xmctx = XMesaCreateContext(xm_vis, xmshare);
+ gl_ctx = xmctx ? &xmctx->mesa : 0;
+ }
+ else {
+ ErrorF("find_mesa_visual returned NULL for visualID = 0x%04x\n",
+ glxc->modes->visualID);
+ }
+
+
+ if (!gl_ctx)
+ return NULL;
+
+ gl_ctx->imports = *imports;
+ gl_ctx->exports.destroyContext = __MESA_destroyContext;
+ gl_ctx->exports.loseCurrent = __MESA_loseCurrent;
+ gl_ctx->exports.makeCurrent = __MESA_makeCurrent;
+ gl_ctx->exports.shareContext = __MESA_shareContext;
+ gl_ctx->exports.copyContext = __MESA_copyContext;
+ gl_ctx->exports.forceCurrent = __MESA_forceCurrent;
+ gl_ctx->exports.notifyResize = __MESA_notifyResize;
+ gl_ctx->exports.notifyDestroy = __MESA_notifyDestroy;
+ gl_ctx->exports.notifySwapBuffers = __MESA_notifySwapBuffers;
+ gl_ctx->exports.dispatchExec = __MESA_dispatchExec;
+ gl_ctx->exports.beginDispatchOverride = __MESA_beginDispatchOverride;
+ gl_ctx->exports.endDispatchOverride = __MESA_endDispatchOverride;
+
+ return (__GLinterface *)gl_ctx;
+}
+
+GLboolean __MESA_destroyContext(__GLcontext *gc)
+{
+ XMesaContext xmesa = (XMesaContext) gc->DriverCtx;
+ XMesaDestroyContext( xmesa );
+ return GL_TRUE;
+}
+
+GLboolean __MESA_loseCurrent(__GLcontext *gc)
+{
+ XMesaContext xmesa = (XMesaContext) gc->DriverCtx;
+ MESA_CC = NULL;
+ __glXLastContext = NULL;
+ return XMesaLoseCurrent(xmesa);
+}
+
+GLboolean __MESA_makeCurrent(__GLcontext *gc)
+{
+ __GLdrawablePrivate *drawPriv = gc->imports.getDrawablePrivate( gc );
+ __MESA_buffer drawBuf = (__MESA_buffer)drawPriv->private;
+ __GLdrawablePrivate *readPriv = gc->imports.getReadablePrivate( gc );
+ __MESA_buffer readBuf = (__MESA_buffer)readPriv->private;
+ XMesaContext xmesa = (XMesaContext) gc->DriverCtx;
+
+ MESA_CC = gc;
+ return XMesaMakeCurrent2(xmesa, drawBuf->xm_buf, readBuf->xm_buf);
+}
+
+GLboolean __MESA_shareContext(__GLcontext *gc, __GLcontext *gcShare)
+{
+ /* NOT_DONE */
+ /* XXX I don't see where/how this could ever be called */
+ ErrorF("__MESA_shareContext\n");
+ return GL_FALSE;
+}
+
+GLboolean __MESA_copyContext(__GLcontext *dst, const __GLcontext *src,
+ GLuint mask)
+{
+ XMesaContext xm_dst = (XMesaContext) dst->DriverCtx;
+ const XMesaContext xm_src = (const XMesaContext) src->DriverCtx;
+ _mesa_copy_context(&xm_src->mesa, &xm_dst->mesa, mask);
+ return GL_TRUE;
+}
+
+GLboolean __MESA_forceCurrent(__GLcontext *gc)
+{
+ XMesaContext xmesa = (XMesaContext) gc->DriverCtx;
+ MESA_CC = gc;
+ return XMesaForceCurrent(xmesa);
+}
+
+GLboolean __MESA_notifyResize(__GLcontext *gc)
+{
+ /* NOT_DONE */
+ ErrorF("__MESA_notifyResize\n");
+ return GL_FALSE;
+}
+
+void __MESA_notifyDestroy(__GLcontext *gc)
+{
+ /* NOT_DONE */
+ ErrorF("__MESA_notifyDestroy\n");
+ return;
+}
+
+void __MESA_notifySwapBuffers(__GLcontext *gc)
+{
+ _mesa_notifySwapBuffers(gc);
+}
+
+struct __GLdispatchStateRec *__MESA_dispatchExec(__GLcontext *gc)
+{
+ /* NOT_DONE */
+ ErrorF("__MESA_dispatchExec\n");
+ return NULL;
+}
+
+void __MESA_beginDispatchOverride(__GLcontext *gc)
+{
+ /* NOT_DONE */
+ ErrorF("__MESA_beginDispatchOverride\n");
+ return;
+}
+
+void __MESA_endDispatchOverride(__GLcontext *gc)
+{
+ /* NOT_DONE */
+ ErrorF("__MESA_endDispatchOverride\n");
+ return;
+}
+
+
+/*
+ * Server-side GLX uses these functions which are normally defined
+ * in the OpenGL SI.
+ */
+
+GLint __glEvalComputeK(GLenum target)
+{
+ switch (target) {
+ case GL_MAP1_VERTEX_4:
+ case GL_MAP1_COLOR_4:
+ case GL_MAP1_TEXTURE_COORD_4:
+ case GL_MAP2_VERTEX_4:
+ case GL_MAP2_COLOR_4:
+ case GL_MAP2_TEXTURE_COORD_4:
+ return 4;
+ case GL_MAP1_VERTEX_3:
+ case GL_MAP1_TEXTURE_COORD_3:
+ case GL_MAP1_NORMAL:
+ case GL_MAP2_VERTEX_3:
+ case GL_MAP2_TEXTURE_COORD_3:
+ case GL_MAP2_NORMAL:
+ return 3;
+ case GL_MAP1_TEXTURE_COORD_2:
+ case GL_MAP2_TEXTURE_COORD_2:
+ return 2;
+ case GL_MAP1_TEXTURE_COORD_1:
+ case GL_MAP2_TEXTURE_COORD_1:
+ case GL_MAP1_INDEX:
+ case GL_MAP2_INDEX:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+GLuint __glFloorLog2(GLuint val)
+{
+ int c = 0;
+
+ while (val > 1) {
+ c++;
+ val >>= 1;
+ }
+ return c;
+}
+
diff --git a/Xext/xevie.c b/Xext/xevie.c
new file mode 100644
index 000000000..b024a622a
--- /dev/null
+++ b/Xext/xevie.c
@@ -0,0 +1,371 @@
+/************************************************************
+
+Copyright 2003 Sun Microsystems, Inc.
+
+All rights reserved.
+
+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, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+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
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+************************************************************/
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "colormapst.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#define _XEVIE_SERVER_
+#include "Xeviestr.h"
+#include "Xfuncproto.h"
+#include "input.h"
+
+#include "../os/osdep.h"
+
+#define NoSuchEvent 0x80000000
+
+extern Bool noXkbExtension;
+extern int xeviegrabState;
+
+static int ProcDispatch (), SProcDispatch ();
+static void ResetProc ();
+
+static unsigned char ReqCode = 0;
+static int ErrorBase;
+
+int xevieFlag = 0;
+int xevieClientIndex = 0;
+DeviceIntPtr xeviekb = NULL;
+DeviceIntPtr xeviemouse = NULL;
+Mask xevieMask = 0;
+int xevieEventSent = 0;
+int xevieKBEventSent = 0;
+Mask xevieFilters[128] =
+{
+ NoSuchEvent, /* 0 */
+ NoSuchEvent, /* 1 */
+ KeyPressMask, /* KeyPress */
+ KeyReleaseMask, /* KeyRelease */
+ ButtonPressMask, /* ButtonPress */
+ ButtonReleaseMask, /* ButtonRelease */
+ PointerMotionMask /* MotionNotify (initial state) */
+};
+
+static void XevieEnd(int clientIndex);
+static void XevieClientStateCallback(CallbackListPtr *pcbl, pointer nulldata,
+ pointer calldata);
+static void XevieServerGrabStateCallback(CallbackListPtr *pcbl,
+ pointer nulldata,
+ pointer calldata);
+
+void
+XevieExtensionInit ()
+{
+ ExtensionEntry* extEntry;
+
+ if (!AddCallback(&ServerGrabCallback,XevieServerGrabStateCallback,NULL))
+ return;
+
+ if (extEntry = AddExtension (XEVIENAME,
+ 0,
+ XevieNumberErrors,
+ ProcDispatch,
+ SProcDispatch,
+ ResetProc,
+ StandardMinorOpcode)) {
+ ReqCode = (unsigned char)extEntry->base;
+ ErrorBase = extEntry->errorBase;
+ }
+
+ /* PC servers initialize the desktop colors (citems) here! */
+}
+
+/*ARGSUSED*/
+static
+void ResetProc (extEntry)
+ ExtensionEntry* extEntry;
+{
+}
+
+static
+int ProcQueryVersion (client)
+ register ClientPtr client;
+{
+ REQUEST (xXevieQueryVersionReq);
+ xXevieQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xXevieQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequence_number = client->sequence;
+ rep.server_major_version = XEVIE_MAJOR_VERSION;
+ rep.server_minor_version = XEVIE_MINOR_VERSION;
+ WriteToClient (client, sizeof (xXevieQueryVersionReply), (char *)&rep);
+ return client->noClientException;
+}
+
+static
+int ProcStart (client)
+ register ClientPtr client;
+{
+ REQUEST (xXevieStartReq);
+ xXevieStartReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xXevieStartReq);
+ rep.pad1 = 0;
+
+ if(!xevieFlag){
+ if (AddCallback(&ClientStateCallback,XevieClientStateCallback,NULL)) {
+ xevieFlag = 1;
+ rep.pad1 = 1;
+ xevieClientIndex = client->index;
+ } else
+ return BadAlloc;
+ } else
+ return BadAccess;
+
+ rep.type = X_Reply;
+ rep.sequence_number = client->sequence;
+ WriteToClient (client, sizeof (xXevieStartReply), (char *)&rep);
+ return client->noClientException;
+}
+
+static
+int ProcEnd (client)
+ register ClientPtr client;
+{
+ xXevieEndReply rep;
+
+ XevieEnd(xevieClientIndex);
+
+ rep.type = X_Reply;
+ rep.sequence_number = client->sequence;
+ WriteToClient (client, sizeof (xXevieEndReply), (char *)&rep);
+ return client->noClientException;
+}
+
+static
+int ProcSend (client)
+ register ClientPtr client;
+{
+ REQUEST (xXevieSendReq);
+ xXevieSendReply rep;
+ xEvent *xE;
+ OsCommPtr oc;
+ static unsigned char lastDetail = 0, lastType = 0;
+
+ xE = (xEvent *)&stuff->event;
+ rep.type = X_Reply;
+ rep.sequence_number = client->sequence;
+ WriteToClient (client, sizeof (xXevieSendReply), (char *)&rep);
+
+ switch(xE->u.u.type) {
+ case KeyPress:
+ case KeyRelease:
+ xevieKBEventSent = 1;
+#ifdef XKB
+ if(noXkbExtension)
+#endif
+ CoreProcessKeyboardEvent (xE, xeviekb, 1);
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ xevieEventSent = 1;
+ CoreProcessPointerEvent(xE, xeviemouse, 1);
+ break;
+ default:
+ break;
+ }
+ lastType = xE->u.u.type;
+ lastDetail = xE->u.u.detail;
+ return client->noClientException;
+}
+
+static
+int ProcSelectInput (client)
+ register ClientPtr client;
+{
+ REQUEST (xXevieSelectInputReq);
+ xXevieSelectInputReply rep;
+
+ xevieMask = (long)stuff->event_mask;
+ rep.type = X_Reply;
+ rep.sequence_number = client->sequence;
+ WriteToClient (client, sizeof (xXevieSelectInputReply), (char *)&rep);
+ return client->noClientException;
+}
+
+static
+int ProcDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST (xReq);
+ switch (stuff->data)
+ {
+ case X_XevieQueryVersion:
+ return ProcQueryVersion (client);
+ case X_XevieStart:
+ return ProcStart (client);
+ case X_XevieEnd:
+ return ProcEnd (client);
+ case X_XevieSend:
+ return ProcSend (client);
+ case X_XevieSelectInput:
+ return ProcSelectInput(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static
+int SProcQueryVersion (client)
+ register ClientPtr client;
+{
+ register int n;
+
+ REQUEST(xXevieQueryVersionReq);
+ swaps(&stuff->length, n);
+ return ProcQueryVersion(client);
+}
+
+static
+int SProcStart (client)
+ ClientPtr client;
+{
+ register int n;
+
+ REQUEST (xXevieStartReq);
+ swaps (&stuff->length, n);
+ swapl (&stuff->screen, n);
+ REQUEST_AT_LEAST_SIZE (xXevieStartReq);
+ return ProcStart (client);
+}
+
+static
+int SProcEnd (client)
+ ClientPtr client;
+{
+ register int n;
+ int count;
+ xColorItem* pItem;
+
+ REQUEST (xXevieEndReq);
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE (xXevieEndReq);
+ swapl(&stuff->cmap, n);
+ return ProcEnd (client);
+}
+
+static
+int SProcSend (client)
+ ClientPtr client;
+{
+ register int n;
+ int count;
+
+ REQUEST (xXevieSendReq);
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE (xXevieSendReq);
+ swapl(&stuff->event, n);
+ return ProcSend (client);
+}
+
+static
+int SProcSelectInput (client)
+ ClientPtr client;
+{
+ register int n;
+ int count;
+
+ REQUEST (xXevieSelectInputReq);
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE (xXevieSendReq);
+ swapl(&stuff->event_mask, n);
+ return ProcSelectInput (client);
+}
+
+
+static
+int SProcDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_XevieQueryVersion:
+ return SProcQueryVersion (client);
+ case X_XevieStart:
+ return SProcStart (client);
+ case X_XevieEnd:
+ return SProcEnd (client);
+ case X_XevieSend:
+ return SProcSend (client);
+ case X_XevieSelectInput:
+ return SProcSelectInput(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static void
+XevieEnd(int clientIndex)
+{
+ if (!clientIndex || clientIndex == xevieClientIndex) {
+ xevieFlag = 0;
+ xevieClientIndex = 0;
+ DeleteCallback (&ClientStateCallback, XevieClientStateCallback, NULL);
+ }
+}
+
+static void
+XevieClientStateCallback(CallbackListPtr *pcbl, pointer nulldata,
+ pointer calldata)
+{
+ NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
+ ClientPtr client = pci->client;
+ if (client->clientState == ClientStateGone
+ || client->clientState == ClientStateRetained)
+ XevieEnd(client->index);
+}
+
+static void
+XevieServerGrabStateCallback(CallbackListPtr *pcbl, pointer nulldata,
+ pointer calldata)
+{
+ ServerGrabInfoRec *grbinfo = (ServerGrabInfoRec *)calldata;
+ if (grbinfo->grabstate == SERVER_GRABBED)
+ xeviegrabState = TRUE;
+ else
+ xeviegrabState = FALSE;
+}
+
+
diff --git a/composite/compext.c b/composite/compext.c
new file mode 100644
index 000000000..477066024
--- /dev/null
+++ b/composite/compext.c
@@ -0,0 +1,408 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2003 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "compint.h"
+
+static CARD8 CompositeReqCode;
+int CompositeClientPrivateIndex;
+RESTYPE CompositeClientWindowType;
+RESTYPE CompositeClientSubwindowsType;
+
+typedef struct _CompositeClient {
+ int major_version;
+ int minor_version;
+} CompositeClientRec, *CompositeClientPtr;
+
+#define GetCompositeClient(pClient) ((CompositeClientPtr) (pClient)->devPrivates[CompositeClientPrivateIndex].ptr)
+
+static void
+CompositeClientCallback (CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
+ ClientPtr pClient = clientinfo->client;
+ CompositeClientPtr pCompositeClient = GetCompositeClient (pClient);
+
+ pCompositeClient->major_version = 0;
+ pCompositeClient->minor_version = 0;
+}
+
+static void
+CompositeResetProc (ExtensionEntry *extEntry)
+{
+}
+
+static int
+FreeCompositeClientWindow (pointer value, XID ccwid)
+{
+ WindowPtr pWin = value;
+
+ compFreeClientWindow (pWin, ccwid);
+ return Success;
+}
+
+static int
+FreeCompositeClientSubwindows (pointer value, XID ccwid)
+{
+ WindowPtr pWin = value;
+
+ compFreeClientSubwindows (pWin, ccwid);
+ return Success;
+}
+
+static int
+ProcCompositeQueryVersion (ClientPtr client)
+{
+ CompositeClientPtr pCompositeClient = GetCompositeClient (client);
+ xCompositeQueryVersionReply rep;
+ register int n;
+ REQUEST(xCompositeQueryVersionReq);
+
+ REQUEST_SIZE_MATCH(xCompositeQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ if (stuff->majorVersion < COMPOSITE_MAJOR) {
+ rep.majorVersion = stuff->majorVersion;
+ rep.minorVersion = stuff->minorVersion;
+ } else {
+ rep.majorVersion = COMPOSITE_MAJOR;
+ if (stuff->majorVersion == COMPOSITE_MAJOR &&
+ stuff->minorVersion < COMPOSITE_MINOR)
+ rep.minorVersion = stuff->minorVersion;
+ else
+ rep.minorVersion = COMPOSITE_MINOR;
+ }
+ pCompositeClient->major_version = rep.majorVersion;
+ pCompositeClient->minor_version = rep.minorVersion;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.majorVersion, n);
+ swapl(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof(xCompositeQueryVersionReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcCompositeRedirectWindow (ClientPtr client)
+{
+ WindowPtr pWin;
+ REQUEST(xCompositeRedirectWindowReq);
+
+ REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+ return compRedirectWindow (client, pWin, stuff->update);
+}
+
+static int
+ProcCompositeRedirectSubwindows (ClientPtr client)
+{
+ WindowPtr pWin;
+ REQUEST(xCompositeRedirectSubwindowsReq);
+
+ REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+ return compRedirectSubwindows (client, pWin, stuff->update);
+}
+
+static int
+ProcCompositeUnredirectWindow (ClientPtr client)
+{
+ WindowPtr pWin;
+ REQUEST(xCompositeUnredirectWindowReq);
+
+ REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+ return compUnredirectWindow (client, pWin, stuff->update);
+}
+
+static int
+ProcCompositeUnredirectSubwindows (ClientPtr client)
+{
+ WindowPtr pWin;
+ REQUEST(xCompositeUnredirectSubwindowsReq);
+
+ REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+ return compUnredirectSubwindows (client, pWin, stuff->update);
+}
+
+static int
+ProcCompositeCreateRegionFromBorderClip (ClientPtr client)
+{
+ WindowPtr pWin;
+ CompWindowPtr cw;
+ RegionPtr pBorderClip, pRegion;
+ REQUEST(xCompositeCreateRegionFromBorderClipReq);
+
+ REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+
+ cw = GetCompWindow (pWin);
+ if (cw)
+ pBorderClip = &cw->borderClip;
+ else
+ pBorderClip = &pWin->borderClip;
+ pRegion = XFixesRegionCopy (pBorderClip);
+ if (!pRegion)
+ return BadAlloc;
+ REGION_TRANSLATE (pScreen, pRegion, -pWin->drawable.x, -pWin->drawable.y);
+
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+static int
+ProcCompositeNameWindowPixmap (ClientPtr client)
+{
+ WindowPtr pWin;
+ CompWindowPtr cw;
+ PixmapPtr pPixmap;
+ REQUEST(xCompositeNameWindowPixmapReq);
+
+ REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+
+ LEGAL_NEW_RESOURCE (stuff->pixmap, client);
+
+ cw = GetCompWindow (pWin);
+ if (!cw)
+ return BadMatch;
+
+ pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
+ if (!pPixmap)
+ return BadMatch;
+
+ ++pPixmap->refcnt;
+
+ if (!AddResource (stuff->pixmap, RT_PIXMAP, (pointer) pPixmap))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
+ ProcCompositeQueryVersion,
+ ProcCompositeRedirectWindow,
+ ProcCompositeRedirectSubwindows,
+ ProcCompositeUnredirectWindow,
+ ProcCompositeUnredirectSubwindows,
+ ProcCompositeCreateRegionFromBorderClip,
+ ProcCompositeNameWindowPixmap,
+};
+
+static int
+ProcCompositeDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ if (stuff->data < CompositeNumberRequests)
+ return (*ProcCompositeVector[stuff->data]) (client);
+ else
+ return BadRequest;
+}
+
+static int
+SProcCompositeQueryVersion (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeQueryVersionReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeQueryVersionReq);
+ swapl(&stuff->majorVersion, n);
+ swapl(&stuff->minorVersion, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeRedirectWindow (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeRedirectWindowReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
+ swapl (&stuff->window, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeRedirectSubwindows (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeRedirectSubwindowsReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
+ swapl (&stuff->window, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeUnredirectWindow (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeUnredirectWindowReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
+ swapl (&stuff->window, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeUnredirectSubwindows (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeUnredirectSubwindowsReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
+ swapl (&stuff->window, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeCreateRegionFromBorderClip (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeCreateRegionFromBorderClipReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
+ swapl (&stuff->region, n);
+ swapl (&stuff->window, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeNameWindowPixmap (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeNameWindowPixmapReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
+ swapl (&stuff->window, n);
+ swapl (&stuff->pixmap, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
+ SProcCompositeQueryVersion,
+ SProcCompositeRedirectWindow,
+ SProcCompositeRedirectSubwindows,
+ SProcCompositeUnredirectWindow,
+ SProcCompositeUnredirectSubwindows,
+ SProcCompositeCreateRegionFromBorderClip,
+ SProcCompositeNameWindowPixmap,
+};
+
+static int
+SProcCompositeDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ if (stuff->data < CompositeNumberRequests)
+ return (*SProcCompositeVector[stuff->data]) (client);
+ else
+ return BadRequest;
+}
+
+void
+CompositeExtensionInit (void)
+{
+ ExtensionEntry *extEntry;
+ int s;
+
+ CompositeClientWindowType = CreateNewResourceType (FreeCompositeClientWindow);
+ if (!CompositeClientWindowType)
+ return;
+
+ CompositeClientSubwindowsType = CreateNewResourceType (FreeCompositeClientSubwindows);
+ if (!CompositeClientSubwindowsType)
+ return;
+
+ CompositeClientPrivateIndex = AllocateClientPrivateIndex ();
+ if (!AllocateClientPrivate (CompositeClientPrivateIndex,
+ sizeof (CompositeClientRec)))
+ return;
+ if (!AddCallback (&ClientStateCallback, CompositeClientCallback, 0))
+ return;
+
+ extEntry = AddExtension (COMPOSITE_NAME, 0, 0,
+ ProcCompositeDispatch, SProcCompositeDispatch,
+ CompositeResetProc, StandardMinorOpcode);
+ if (!extEntry)
+ return;
+ CompositeReqCode = (CARD8) extEntry->base;
+
+
+ for (s = 0; s < screenInfo.numScreens; s++)
+ if (!compScreenInit (screenInfo.screens[s]))
+ return;
+ miRegisterRedirectBorderClipProc (compSetRedirectBorderClip,
+ compGetRedirectBorderClip);
+}
diff --git a/damageext/damageext.c b/damageext/damageext.c
new file mode 100755
index 000000000..e565517d6
--- /dev/null
+++ b/damageext/damageext.c
@@ -0,0 +1,480 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "damageextint.h"
+
+unsigned char DamageReqCode;
+int DamageEventBase;
+int DamageErrorBase;
+int DamageClientPrivateIndex;
+RESTYPE DamageExtType;
+RESTYPE DamageExtWinType;
+
+#define prScreen screenInfo.screens[0]
+
+static void
+DamageExtNotify (DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
+{
+ ClientPtr pClient = pDamageExt->pClient;
+ DamageClientPtr pDamageClient = GetDamageClient (pClient);
+ DrawablePtr pDrawable = pDamageExt->pDrawable;
+ xDamageNotifyEvent ev;
+ int i;
+
+ UpdateCurrentTimeIf ();
+ ev.type = DamageEventBase + XDamageNotify;
+ ev.level = pDamageExt->level;
+ ev.sequenceNumber = pClient->sequence;
+ ev.drawable = pDrawable->id;
+ ev.damage = pDamageExt->id;
+ ev.timestamp = currentTime.milliseconds;
+ ev.geometry.x = pDrawable->x;
+ ev.geometry.y = pDrawable->y;
+ ev.geometry.width = pDrawable->width;
+ ev.geometry.height = pDrawable->height;
+ if (pBoxes)
+ {
+ for (i = 0; i < nBoxes; i++)
+ {
+ ev.level = pDamageExt->level;
+ if (i < nBoxes - 1)
+ ev.level |= DamageNotifyMore;
+ ev.area.x = pBoxes[i].x1;
+ ev.area.y = pBoxes[i].y1;
+ ev.area.width = pBoxes[i].x2 - pBoxes[i].x1;
+ ev.area.height = pBoxes[i].y2 - pBoxes[i].y1;
+ if (!pClient->clientGone)
+ WriteEventsToClient (pClient, 1, (xEvent *) &ev);
+ }
+ }
+ else
+ {
+ ev.area.x = 0;
+ ev.area.y = 0;
+ ev.area.width = pDrawable->width;
+ ev.area.height = pDrawable->height;
+ if (!pClient->clientGone)
+ WriteEventsToClient (pClient, 1, (xEvent *) &ev);
+ }
+ /* Composite extension marks clients with manual Subwindows as critical */
+ if (pDamageClient->critical > 0)
+ {
+ SetCriticalOutputPending ();
+#ifdef SMART_SCHEDULE
+ pClient->smart_priority = SMART_MAX_PRIORITY;
+#endif
+ }
+}
+
+static void
+DamageExtReport (DamagePtr pDamage, RegionPtr pRegion, void *closure)
+{
+ DamageExtPtr pDamageExt = closure;
+
+ switch (pDamageExt->level) {
+ case DamageReportRawRegion:
+ case DamageReportDeltaRegion:
+ DamageExtNotify (pDamageExt, REGION_RECTS(pRegion), REGION_NUM_RECTS(pRegion));
+ break;
+ case DamageReportBoundingBox:
+ DamageExtNotify (pDamageExt, REGION_EXTENTS(prScreen, pRegion), 1);
+ break;
+ case DamageReportNonEmpty:
+ DamageExtNotify (pDamageExt, NullBox, 0);
+ break;
+ case DamageReportNone:
+ break;
+ }
+}
+
+static void
+DamageExtDestroy (DamagePtr pDamage, void *closure)
+{
+ DamageExtPtr pDamageExt = closure;
+
+ pDamageExt->pDamage = 0;
+ if (pDamageExt->id)
+ FreeResource (pDamageExt->id, RT_NONE);
+}
+
+void
+DamageExtSetCritical (ClientPtr pClient, Bool critical)
+{
+ DamageClientPtr pDamageClient = GetDamageClient (pClient);
+
+ if (pDamageClient)
+ pDamageClient->critical += critical ? 1 : -1;
+}
+
+static int
+ProcDamageQueryVersion(ClientPtr client)
+{
+ DamageClientPtr pDamageClient = GetDamageClient (client);
+ xDamageQueryVersionReply rep;
+ register int n;
+ REQUEST(xDamageQueryVersionReq);
+
+ REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ if (stuff->majorVersion < DAMAGE_MAJOR) {
+ rep.majorVersion = stuff->majorVersion;
+ rep.minorVersion = stuff->minorVersion;
+ } else {
+ rep.majorVersion = DAMAGE_MAJOR;
+ if (stuff->majorVersion == DAMAGE_MAJOR &&
+ stuff->minorVersion < DAMAGE_MINOR)
+ rep.minorVersion = stuff->minorVersion;
+ else
+ rep.minorVersion = DAMAGE_MINOR;
+ }
+ pDamageClient->major_version = rep.majorVersion;
+ pDamageClient->minor_version = rep.minorVersion;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.majorVersion, n);
+ swapl(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof(xDamageQueryVersionReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcDamageCreate (ClientPtr client)
+{
+ DrawablePtr pDrawable;
+ DamageExtPtr pDamageExt;
+ DamageReportLevel level;
+ RegionPtr pRegion;
+
+ REQUEST(xDamageCreateReq);
+
+ REQUEST_SIZE_MATCH(xDamageCreateReq);
+ LEGAL_NEW_RESOURCE(stuff->damage, client);
+ SECURITY_VERIFY_DRAWABLE (pDrawable, stuff->drawable, client,
+ SecurityReadAccess);
+ switch (stuff->level) {
+ case XDamageReportRawRectangles:
+ level = DamageReportRawRegion;
+ break;
+ case XDamageReportDeltaRectangles:
+ level = DamageReportDeltaRegion;
+ break;
+ case XDamageReportBoundingBox:
+ level = DamageReportBoundingBox;
+ break;
+ case XDamageReportNonEmpty:
+ level = DamageReportNonEmpty;
+ break;
+ default:
+ client->errorValue = stuff->level;
+ return BadValue;
+ }
+
+ pDamageExt = xalloc (sizeof (DamageExtRec));
+ if (!pDamageExt)
+ return BadAlloc;
+ pDamageExt->id = stuff->damage;
+ pDamageExt->pDrawable = pDrawable;
+ pDamageExt->level = level;
+ pDamageExt->pClient = client;
+ pDamageExt->pDamage = DamageCreate (DamageExtReport,
+ DamageExtDestroy,
+ level,
+ FALSE,
+ pDrawable->pScreen,
+ pDamageExt);
+ if (!pDamageExt->pDamage)
+ {
+ xfree (pDamageExt);
+ return BadAlloc;
+ }
+ if (!AddResource (stuff->damage, DamageExtType, (pointer) pDamageExt))
+ return BadAlloc;
+
+ DamageRegister (pDamageExt->pDrawable, pDamageExt->pDamage);
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ pRegion = &((WindowPtr) pDrawable)->borderClip;
+ DamageDamageRegion (pDrawable, pRegion);
+ }
+
+ return (client->noClientException);
+}
+
+static int
+ProcDamageDestroy (ClientPtr client)
+{
+ REQUEST(xDamageDestroyReq);
+ DamageExtPtr pDamageExt;
+
+ REQUEST_SIZE_MATCH(xDamageDestroyReq);
+ VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, SecurityWriteAccess);
+ FreeResource (stuff->damage, RT_NONE);
+ return (client->noClientException);
+}
+
+static int
+ProcDamageSubtract (ClientPtr client)
+{
+ REQUEST(xDamageSubtractReq);
+ DamageExtPtr pDamageExt;
+ RegionPtr pRepair;
+ RegionPtr pParts;
+
+ REQUEST_SIZE_MATCH(xDamageSubtractReq);
+ VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, SecurityWriteAccess);
+ VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, SecurityWriteAccess);
+ VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, SecurityWriteAccess);
+
+ if (pDamageExt->level != DamageReportRawRegion)
+ {
+ DamagePtr pDamage = pDamageExt->pDamage;
+ if (pRepair)
+ {
+ if (pParts)
+ REGION_INTERSECT (prScreen, pParts, DamageRegion (pDamage), pRepair);
+ if (DamageSubtract (pDamage, pRepair))
+ DamageExtReport (pDamage, DamageRegion (pDamage), (void *) pDamageExt);
+ }
+ else
+ {
+ if (pParts)
+ REGION_COPY (prScreen, pParts, DamageRegion (pDamage));
+ DamageEmpty (pDamage);
+ }
+ }
+ return (client->noClientException);
+}
+
+/* Major version controls available requests */
+static const int version_requests[] = {
+ X_DamageQueryVersion, /* before client sends QueryVersion */
+ X_DamageSubtract, /* Version 1 */
+};
+
+#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
+
+int (*ProcDamageVector[XDamageNumberRequests])(ClientPtr) = {
+/*************** Version 1 ******************/
+ ProcDamageQueryVersion,
+ ProcDamageCreate,
+ ProcDamageDestroy,
+ ProcDamageSubtract,
+};
+
+
+static int
+ProcDamageDispatch (ClientPtr client)
+{
+ REQUEST(xDamageReq);
+ DamageClientPtr pDamageClient = GetDamageClient (client);
+
+ if (pDamageClient->major_version > NUM_VERSION_REQUESTS)
+ return BadRequest;
+ if (stuff->damageReqType > version_requests[pDamageClient->major_version])
+ return BadRequest;
+ return (*ProcDamageVector[stuff->damageReqType]) (client);
+}
+
+static int
+SProcDamageQueryVersion(ClientPtr client)
+{
+ register int n;
+ REQUEST(xDamageQueryVersionReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
+ swapl(&stuff->majorVersion, n);
+ swapl(&stuff->minorVersion, n);
+ return (*ProcDamageVector[stuff->damageReqType]) (client);
+}
+
+static int
+SProcDamageCreate (ClientPtr client)
+{
+ register int n;
+ REQUEST(xDamageCreateReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDamageCreateReq);
+ swapl (&stuff->damage, n);
+ swapl (&stuff->drawable, n);
+ return (*ProcDamageVector[stuff->damageReqType]) (client);
+}
+
+static int
+SProcDamageDestroy (ClientPtr client)
+{
+ register int n;
+ REQUEST(xDamageDestroyReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDamageDestroyReq);
+ swapl (&stuff->damage, n);
+ return (*ProcDamageVector[stuff->damageReqType]) (client);
+}
+
+static int
+SProcDamageSubtract (ClientPtr client)
+{
+ register int n;
+ REQUEST(xDamageSubtractReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDamageSubtractReq);
+ swapl (&stuff->damage, n);
+ swapl (&stuff->repair, n);
+ swapl (&stuff->parts, n);
+ return (*ProcDamageVector[stuff->damageReqType]) (client);
+}
+
+int (*SProcDamageVector[XDamageNumberRequests])(ClientPtr) = {
+/*************** Version 1 ******************/
+ SProcDamageQueryVersion,
+ SProcDamageCreate,
+ SProcDamageDestroy,
+ SProcDamageSubtract,
+};
+
+static int
+SProcDamageDispatch (ClientPtr client)
+{
+ REQUEST(xDamageReq);
+ if (stuff->damageReqType >= XDamageNumberRequests)
+ return BadRequest;
+ return (*SProcDamageVector[stuff->damageReqType]) (client);
+}
+
+static void
+DamageClientCallback (CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
+ ClientPtr pClient = clientinfo->client;
+ DamageClientPtr pDamageClient = GetDamageClient (pClient);
+
+ pDamageClient->critical = 0;
+ pDamageClient->major_version = 0;
+ pDamageClient->minor_version = 0;
+}
+
+/*ARGSUSED*/
+static void
+DamageResetProc (ExtensionEntry *extEntry)
+{
+ DeleteCallback (&ClientStateCallback, DamageClientCallback, 0);
+}
+
+static int
+FreeDamageExt (pointer value, XID did)
+{
+ DamageExtPtr pDamageExt = (DamageExtPtr) value;
+
+ /*
+ * Get rid of the resource table entry hanging from the window id
+ */
+ pDamageExt->id = 0;
+ if (WindowDrawable(pDamageExt->pDrawable->type))
+ FreeResourceByType (pDamageExt->pDrawable->id, DamageExtWinType, TRUE);
+ if (pDamageExt->pDamage)
+ {
+ DamageUnregister (pDamageExt->pDrawable, pDamageExt->pDamage);
+ DamageDestroy (pDamageExt->pDamage);
+ }
+ xfree (pDamageExt);
+ return Success;
+}
+
+static int
+FreeDamageExtWin (pointer value, XID wid)
+{
+ DamageExtPtr pDamageExt = (DamageExtPtr) value;
+
+ if (pDamageExt->id)
+ FreeResource (pDamageExt->id, RT_NONE);
+ return Success;
+}
+
+void
+SDamageNotifyEvent (xDamageNotifyEvent *from,
+ xDamageNotifyEvent *to)
+{
+ to->type = from->type;
+ cpswaps (from->sequenceNumber, to->sequenceNumber);
+ cpswapl (from->drawable, to->drawable);
+ cpswapl (from->damage, to->damage);
+ cpswaps (from->area.x, to->area.x);
+ cpswaps (from->area.y, to->area.y);
+ cpswaps (from->area.width, to->area.width);
+ cpswaps (from->area.height, to->area.height);
+ cpswaps (from->geometry.x, to->geometry.x);
+ cpswaps (from->geometry.y, to->geometry.y);
+ cpswaps (from->geometry.width, to->geometry.width);
+ cpswaps (from->geometry.height, to->geometry.height);
+}
+
+void
+DamageExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+ int s;
+
+ for (s = 0; s < screenInfo.numScreens; s++)
+ DamageSetup (screenInfo.screens[s]);
+
+ DamageExtType = CreateNewResourceType (FreeDamageExt);
+ if (!DamageExtType)
+ return;
+
+ DamageExtWinType = CreateNewResourceType (FreeDamageExtWin);
+ if (!DamageExtWinType)
+ return;
+
+ DamageClientPrivateIndex = AllocateClientPrivateIndex ();
+ if (!AllocateClientPrivate (DamageClientPrivateIndex,
+ sizeof (DamageClientRec)))
+ return;
+ if (!AddCallback (&ClientStateCallback, DamageClientCallback, 0))
+ return;
+
+ if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents,
+ XDamageNumberErrors,
+ ProcDamageDispatch, SProcDamageDispatch,
+ DamageResetProc, StandardMinorOpcode)) != 0)
+ {
+ DamageReqCode = (unsigned char)extEntry->base;
+ DamageEventBase = extEntry->eventBase;
+ DamageErrorBase = extEntry->errorBase;
+ EventSwapVector[DamageEventBase + XDamageNotify] =
+ (EventSwapPtr) SDamageNotifyEvent;
+ }
+}
diff --git a/damageext/damageext.h b/damageext/damageext.h
new file mode 100644
index 000000000..b96de8854
--- /dev/null
+++ b/damageext/damageext.h
@@ -0,0 +1,31 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 _DAMAGEEXT_H_
+#define _DAMAGEEXT_H_
+
+void
+DamageExtensionInit(void);
+
+#endif /* _DAMAGEEXT_H_ */
diff --git a/damageext/damageextint.h b/damageext/damageextint.h
new file mode 100644
index 000000000..6486c985f
--- /dev/null
+++ b/damageext/damageextint.h
@@ -0,0 +1,84 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 _DAMAGEEXTINT_H_
+#define _DAMAGEEXTINT_H_
+
+#define NEED_EVENTS
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include <X11/extensions/damageproto.h>
+#include "windowstr.h"
+#include "selection.h"
+#include "scrnintstr.h"
+#include "damageext.h"
+#include "damage.h"
+#include "xfixes.h"
+
+extern unsigned char DamageReqCode;
+extern int DamageEventBase;
+extern int DamageErrorBase;
+extern int DamageClientPrivateIndex;
+extern RESTYPE DamageExtType;
+extern RESTYPE DamageExtWinType;
+
+typedef struct _DamageClient {
+ CARD32 major_version;
+ CARD32 minor_version;
+ int critical;
+} DamageClientRec, *DamageClientPtr;
+
+#define GetDamageClient(pClient) ((DamageClientPtr) (pClient)->devPrivates[DamageClientPrivateIndex].ptr)
+
+typedef struct _DamageExt {
+ DamagePtr pDamage;
+ DrawablePtr pDrawable;
+ DamageReportLevel level;
+ ClientPtr pClient;
+ XID id;
+} DamageExtRec, *DamageExtPtr;
+
+extern int (*ProcDamageVector[/*XDamageNumberRequests*/])(ClientPtr);
+extern int (*SProcDamageVector[/*XDamageNumberRequests*/])(ClientPtr);
+
+#define VERIFY_DAMAGEEXT(pDamageExt, rid, client, mode) { \
+ pDamageExt = SecurityLookupIDByType (client, rid, DamageExtType, mode); \
+ if (!pDamageExt) { \
+ client->errorValue = rid; \
+ return DamageErrorBase + BadDamage; \
+ } \
+}
+
+void
+SDamageNotifyEvent (xDamageNotifyEvent *from,
+ xDamageNotifyEvent *to);
+
+void
+DamageExtSetCritical (ClientPtr pClient, Bool critical);
+
+#endif /* _DAMAGEEXTINT_H_ */
diff --git a/fb/fbmmx.c b/fb/fbmmx.c
new file mode 100644
index 000000000..9adda92de
--- /dev/null
+++ b/fb/fbmmx.c
@@ -0,0 +1,1514 @@
+/*
+ * Copyright © 2004 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * 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.
+ *
+ * Author: Søren Sandmann (sandmann@redhat.com)
+ *
+ * Based on work by Owen Taylor
+ */
+
+#include "fb.h"
+
+#ifdef USE_GCC34_MMX
+
+#ifdef RENDER
+
+#include "picturestr.h"
+#include "mipict.h"
+#include "fbpict.h"
+
+typedef int Vector1x64 __attribute__ ((mode(DI)));
+typedef int Vector2x32 __attribute__ ((mode(V2SI)));
+typedef int Vector4x16 __attribute__ ((mode(V4HI)));
+typedef int Vector8x8 __attribute__ ((mode(V8QI)));
+
+typedef unsigned long long ullong;
+
+#define noVERBOSE
+
+#ifdef VERBOSE
+#define CHECKPOINT() ErrorF ("at %s %d\n", __FUNCTION__, __LINE__)
+#else
+#define CHECKPOINT()
+#endif
+
+typedef struct
+{
+ ullong mmx_zero;
+ ullong mmx_4x00ff;
+ ullong mmx_4x0080;
+ ullong mmx_565_rgb;
+ ullong mmx_565_unpack_multiplier;
+ ullong mmx_565_r;
+ ullong mmx_565_g;
+ ullong mmx_565_b;
+ ullong mmx_mask_0;
+ ullong mmx_mask_1;
+ ullong mmx_mask_2;
+ ullong mmx_mask_3;
+ ullong mmx_full_alpha;
+ ullong mmx_ffff0000ffff0000;
+ ullong mmx_0000ffff00000000;
+ ullong mmx_000000000000ffff;
+} MMXData;
+
+static const MMXData c =
+{
+ .mmx_zero = 0x0000000000000000ULL,
+ .mmx_4x00ff = 0x00ff00ff00ff00ffULL,
+ .mmx_4x0080 = 0x0080008000800080ULL,
+ .mmx_565_rgb = 0x000001f0003f001fULL,
+ .mmx_565_r = 0x000000f800000000ULL,
+ .mmx_565_g = 0x0000000000fc0000ULL,
+ .mmx_565_b = 0x00000000000000f8ULL,
+ .mmx_mask_0 = 0xffffffffffff0000ULL,
+ .mmx_mask_1 = 0xffffffff0000ffffULL,
+ .mmx_mask_2 = 0xffff0000ffffffffULL,
+ .mmx_mask_3 = 0x0000ffffffffffffULL,
+ .mmx_full_alpha = 0x00ff000000000000ULL,
+ .mmx_565_unpack_multiplier = 0x0000008404100840ULL,
+ .mmx_ffff0000ffff0000 = 0xffff0000ffff0000ULL,
+ .mmx_0000ffff00000000 = 0x0000ffff00000000ULL,
+ .mmx_000000000000ffff = 0x000000000000ffffULL,
+};
+
+static __inline__ Vector1x64
+shift (Vector1x64 v, int s)
+{
+ if (s > 0)
+ return __builtin_ia32_psllq (v, s);
+ else if (s < 0)
+ return __builtin_ia32_psrlq (v, -s);
+ else
+ return v;
+}
+
+static __inline__ Vector4x16
+negate (Vector4x16 mask)
+{
+ return (Vector4x16)__builtin_ia32_pxor (
+ (Vector1x64)mask,
+ (Vector1x64)c.mmx_4x00ff);
+}
+
+static __inline__ Vector4x16
+pix_multiply (Vector4x16 a, Vector4x16 b)
+{
+ Vector4x16 res;
+
+ res = __builtin_ia32_pmullw (a, b);
+ res = __builtin_ia32_paddw (res, (Vector4x16)c.mmx_4x0080);
+ res = __builtin_ia32_psrlw (res, 8);
+
+ return res;
+}
+
+#if 0
+#define HAVE_PSHUFW
+#endif
+
+#ifdef HAVE_PSHUFW
+
+static __inline__ Vector4x16
+expand_alpha (Vector4x16 pixel)
+{
+ Vector4x16 result;
+ __asm__ ("pshufw $0xFF, %1, %0\n\t" : "=y" (result) : "y" (pixel));
+ return result;
+}
+
+static __inline__ Vector4x16
+expand_alpha_rev (Vector4x16 pixel)
+{
+ Vector4x16 result;
+ __asm__ ("pshufw $0x00, %1, %0\n\t" : "=y" (result) : "y" (pixel));
+ return result;
+}
+
+static __inline__ Vector4x16
+invert_colors (Vector4x16 pixel)
+{
+ Vector4x16 result;
+
+ /* 0xC6 = 11000110 */
+ /* 3 0 1 2 */
+
+ __asm__ ("pshufw $0xC6, %1, %0\n\t" : "=y" (result) : "y" (pixel));
+
+ return result;
+}
+
+#else
+
+static __inline__ Vector4x16
+expand_alpha (Vector4x16 pixel)
+{
+ Vector1x64 t1, t2;
+
+ t1 = shift ((Vector1x64)pixel, -48);
+ t2 = shift (t1, 16);
+ t1 = __builtin_ia32_por (t1, t2);
+ t2 = shift (t1, 32);
+ t1 = __builtin_ia32_por (t1, t2);
+
+ return (Vector4x16)t1;
+}
+
+static __inline__ Vector4x16
+expand_alpha_rev (Vector4x16 pixel)
+{
+ Vector1x64 t1, t2;
+
+ t1 = shift ((Vector1x64)pixel, 48);
+ t1 = shift (t1, -48);
+ t2 = shift (t1, 16);
+ t1 = __builtin_ia32_por (t1, t2);
+ t2 = shift (t1, 32);
+ t1 = __builtin_ia32_por (t1, t2);
+
+ return (Vector4x16)t1;
+}
+
+static __inline__ Vector4x16
+invert_colors (Vector4x16 pixel)
+{
+ Vector1x64 x, y, z;
+
+ x = y = z = (Vector1x64)pixel;
+
+ x = __builtin_ia32_pand (x, (Vector1x64)c.mmx_ffff0000ffff0000);
+ y = __builtin_ia32_pand (y, (Vector1x64)c.mmx_000000000000ffff);
+ z = __builtin_ia32_pand (z, (Vector1x64)c.mmx_0000ffff00000000);
+
+ y = shift (y, 32);
+ z = shift (z, -32);
+
+ x = __builtin_ia32_por (x, y);
+ x = __builtin_ia32_por (x, z);
+
+ return (Vector4x16)x;
+}
+
+#endif
+
+/* Notes about writing mmx code
+ *
+ * give memory operands as the second operand. If you give it as the
+ * first, gcc will first load it into a register, then use that register
+ *
+ * ie. use
+ *
+ * __builtin_pmullw (x, mmx_constant[8]);
+ *
+ * not
+ *
+ * __builtin_pmullw (mmx_constant[8], x);
+ *
+ * Also try to minimize dependencies. Ie. when you need a value, try to calculate
+ * it from a value that was calculated as early as possible.
+ */
+
+static __inline__ Vector4x16
+over (Vector4x16 src, Vector4x16 srca, Vector4x16 dest)
+{
+ return (Vector4x16)__builtin_ia32_paddusb ((Vector8x8)src, (Vector8x8)pix_multiply(dest, negate(srca)));
+}
+
+static __inline__ Vector4x16
+over_rev_non_pre (Vector4x16 src, Vector4x16 dest)
+{
+ Vector4x16 srca = expand_alpha (src);
+ Vector4x16 srcfaaa = (Vector4x16)__builtin_ia32_por((Vector1x64)srca, (Vector1x64)c.mmx_full_alpha);
+
+ return over(pix_multiply(invert_colors(src), srcfaaa), srca, dest);
+}
+
+static __inline__ Vector4x16
+in (Vector4x16 src,
+ Vector4x16 mask)
+{
+ return pix_multiply (src, mask);
+}
+
+static __inline__ Vector4x16
+in_over (Vector4x16 src,
+ Vector4x16 srca,
+ Vector4x16 mask,
+ Vector4x16 dest)
+{
+ return over(in(src, mask), pix_multiply(srca, mask), dest);
+}
+
+static __inline__ Vector8x8
+cvt32to64 (CARD32 v)
+{
+ ullong r = v;
+ return (Vector8x8)r;
+}
+
+static __inline__ Vector4x16
+load8888 (CARD32 v)
+{
+ return (Vector4x16)__builtin_ia32_punpcklbw (cvt32to64 (v),
+ (Vector8x8)c.mmx_zero);
+}
+
+static __inline__ Vector8x8
+pack8888 (Vector4x16 lo, Vector4x16 hi)
+{
+ Vector8x8 r;
+ r = __builtin_ia32_packuswb ((Vector4x16)lo, (Vector4x16)hi);
+ return r;
+}
+
+/* Expand 16 bits positioned at @pos (0-3) of a mmx register into 00RR00GG00BB
+
+--- Expanding 565 in the low word ---
+
+m = (m << (32 - 3)) | (m << (16 - 5)) | m;
+m = m & (01f0003f001f);
+m = m * (008404100840);
+m = m >> 8;
+
+Note the trick here - the top word is shifted by another nibble to avoid
+it bumping into the middle word
+*/
+static __inline__ Vector4x16
+expand565 (Vector4x16 pixel, int pos)
+{
+ Vector1x64 p = (Vector1x64)pixel;
+
+ /* move pixel to low 16 bit and zero the rest */
+ p = shift (shift (p, (3 - pos) * 16), -48);
+
+ Vector1x64 t1 = shift (p, 36 - 11);
+ Vector1x64 t2 = shift (p, 16 - 5);
+
+ p = __builtin_ia32_por (t1, p);
+ p = __builtin_ia32_por (t2, p);
+ p = __builtin_ia32_pand (p, (Vector1x64)c.mmx_565_rgb);
+
+ pixel = __builtin_ia32_pmullw ((Vector4x16)p, (Vector4x16)c.mmx_565_unpack_multiplier);
+ return __builtin_ia32_psrlw (pixel, 8);
+}
+
+static __inline__ Vector4x16
+expand8888 (Vector4x16 in, int pos)
+{
+ if (pos == 0)
+ return (Vector4x16)__builtin_ia32_punpcklbw ((Vector8x8)in, (Vector8x8)c.mmx_zero);
+ else
+ return (Vector4x16)__builtin_ia32_punpckhbw ((Vector8x8)in, (Vector8x8)c.mmx_zero);
+}
+
+static __inline__ Vector4x16
+pack565 (Vector4x16 pixel, Vector4x16 target, int pos)
+{
+ Vector1x64 p = (Vector1x64)pixel;
+ Vector1x64 t = (Vector1x64)target;
+ Vector1x64 r, g, b;
+
+ r = __builtin_ia32_pand (p, (Vector1x64)c.mmx_565_r);
+ g = __builtin_ia32_pand (p, (Vector1x64)c.mmx_565_g);
+ b = __builtin_ia32_pand (p, (Vector1x64)c.mmx_565_b);
+
+ r = shift (r, - (32 - 8) + pos * 16);
+ g = shift (g, - (16 - 3) + pos * 16);
+ b = shift (b, - (0 + 3) + pos * 16);
+
+ if (pos == 0)
+ t = __builtin_ia32_pand (t, (Vector1x64)c.mmx_mask_0);
+ else if (pos == 1)
+ t = __builtin_ia32_pand (t, (Vector1x64)c.mmx_mask_1);
+ else if (pos == 2)
+ t = __builtin_ia32_pand (t, (Vector1x64)c.mmx_mask_2);
+ else if (pos == 3)
+ t = __builtin_ia32_pand (t, (Vector1x64)c.mmx_mask_3);
+
+ p = __builtin_ia32_por (r, t);
+ p = __builtin_ia32_por (g, p);
+
+ return (Vector4x16)__builtin_ia32_por (b, p);
+}
+
+static __inline__ void
+emms (void)
+{
+ __asm__ __volatile__ ("emms");
+}
+
+void
+fbCompositeSolid_nx8888mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ CARD32 src;
+ CARD32 *dstLine, *dst;
+ CARD16 w;
+ FbStride dstStride;
+ Vector4x16 vsrc, vsrca;
+
+ CHECKPOINT();
+
+ fbComposeGetSolid(pSrc, src);
+
+ if (src >> 24 == 0)
+ return;
+
+ fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
+
+ vsrc = load8888 (src);
+ vsrca = expand_alpha (vsrc);
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ w = width;
+
+ CHECKPOINT();
+
+ while (w && (unsigned long)dst & 7)
+ {
+ *dst = (ullong) pack8888(over(vsrc, vsrca, load8888(*dst)), (Vector4x16)c.mmx_zero);
+
+ w--;
+ dst++;
+ }
+
+ while (w >= 2)
+ {
+ Vector4x16 vdest;
+ Vector4x16 dest0, dest1;
+
+ vdest = *(Vector4x16 *)dst;
+
+ dest0 = over(vsrc, vsrca, expand8888(vdest, 0));
+ dest1 = over(vsrc, vsrca, expand8888(vdest, 1));
+
+ *(Vector8x8 *)dst = (Vector8x8)pack8888(dest0, dest1);
+
+ dst += 2;
+ w -= 2;
+ }
+
+ CHECKPOINT();
+
+ while (w)
+ {
+ *dst = (ullong) pack8888(over(vsrc, vsrca, load8888(*dst)), (Vector4x16)c.mmx_zero);
+
+ w--;
+ dst++;
+ }
+ }
+
+ emms();
+}
+
+void
+fbCompositeSolid_nx0565mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ CARD32 src;
+ CARD16 *dstLine, *dst;
+ CARD16 w;
+ FbStride dstStride;
+ Vector4x16 vsrc, vsrca;
+
+ CHECKPOINT();
+
+ fbComposeGetSolid(pSrc, src);
+
+ if (src >> 24 == 0)
+ return;
+
+ fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1);
+
+ vsrc = load8888 (src);
+ vsrca = expand_alpha (vsrc);
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ w = width;
+
+ CHECKPOINT();
+
+ while (w && (unsigned long)dst & 7)
+ {
+ ullong d = *dst;
+ Vector4x16 vdest = expand565 ((Vector4x16)d, 0);
+ vdest = pack565(over(vsrc, vsrca, vdest), vdest, 0);
+ *dst = (ullong)vdest;
+
+ w--;
+ dst++;
+ }
+
+ while (w >= 4)
+ {
+ Vector4x16 vdest;
+
+ vdest = *(Vector4x16 *)dst;
+
+ vdest = pack565 (over(vsrc, vsrca, expand565(vdest, 0)), vdest, 0);
+ vdest = pack565 (over(vsrc, vsrca, expand565(vdest, 1)), vdest, 1);
+ vdest = pack565 (over(vsrc, vsrca, expand565(vdest, 2)), vdest, 2);
+ vdest = pack565 (over(vsrc, vsrca, expand565(vdest, 3)), vdest, 3);
+
+ *(Vector8x8 *)dst = (Vector8x8)vdest;
+
+ dst += 4;
+ w -= 4;
+ }
+
+ CHECKPOINT();
+
+ while (w)
+ {
+ ullong d = *dst;
+ Vector4x16 vdest = expand565 ((Vector4x16)d, 0);
+ vdest = pack565(over(vsrc, vsrca, vdest), vdest, 0);
+ *dst = (ullong)vdest;
+
+ w--;
+ dst++;
+ }
+ }
+
+ emms();
+}
+
+void
+fbCompositeSolidMask_nx8888x8888Cmmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ CARD32 src, srca;
+ CARD32 *dstLine;
+ CARD32 *maskLine;
+ FbStride dstStride, maskStride;
+ Vector4x16 vsrc, vsrca;
+
+ CHECKPOINT();
+
+ fbComposeGetSolid(pSrc, src);
+
+ srca = src >> 24;
+ if (srca == 0)
+ return;
+
+ fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
+ fbComposeGetStart (pMask, xMask, yMask, CARD32, maskStride, maskLine, 1);
+
+ vsrc = load8888(src);
+ vsrca = expand_alpha(vsrc);
+
+ while (height--)
+ {
+ int twidth = width;
+ CARD32 *p = (CARD32 *)maskLine;
+ CARD32 *q = (CARD32 *)dstLine;
+
+ while (twidth && (unsigned long)q & 7)
+ {
+ CARD32 m = *(CARD32 *)p;
+
+ if (m)
+ {
+ Vector4x16 vdest = load8888(*q);
+ vdest = in_over(vsrc, vsrca, load8888(m), vdest);
+ *q = (ullong)pack8888(vdest, (Vector4x16)c.mmx_zero);
+ }
+
+ twidth--;
+ p++;
+ q++;
+ }
+
+ while (twidth >= 2)
+ {
+ CARD32 m0, m1;
+ m0 = *p;
+ m1 = *(p + 1);
+
+ if (m0 | m1)
+ {
+ Vector4x16 dest0, dest1;
+ Vector4x16 vdest = *(Vector4x16 *)q;
+
+ dest0 = in_over(vsrc, vsrca, load8888(m0),
+ expand8888 (vdest, 0));
+ dest1 = in_over(vsrc, vsrca, load8888(m1),
+ expand8888 (vdest, 1));
+
+ *(Vector8x8 *)q = (Vector8x8)pack8888(dest0, dest1);
+ }
+
+ p += 2;
+ q += 2;
+ twidth -= 2;
+ }
+
+ while (twidth)
+ {
+ CARD32 m = *(CARD32 *)p;
+
+ if (m)
+ {
+ Vector4x16 vdest = load8888(*q);
+ vdest = in_over(vsrc, vsrca, load8888(m), vdest);
+ *q = (ullong)pack8888(vdest, (Vector4x16)c.mmx_zero);
+ }
+
+ twidth--;
+ p++;
+ q++;
+ }
+
+ dstLine += dstStride;
+ maskLine += maskStride;
+ }
+
+ emms();
+}
+
+void
+fbCompositeSolidMask_nx8x8888mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ CARD32 src, srca;
+ CARD32 *dstLine, *dst;
+ CARD8 *maskLine, *mask;
+ FbStride dstStride, maskStride;
+ CARD16 w;
+ Vector4x16 vsrc, vsrca;
+ ullong srcsrc;
+
+ CHECKPOINT();
+
+ fbComposeGetSolid(pSrc, src);
+
+ srca = src >> 24;
+ if (srca == 0)
+ return;
+
+ srcsrc = (unsigned long long)src << 32 | src;
+
+ fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
+ fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
+
+ vsrc = load8888 (src);
+ vsrca = expand_alpha (vsrc);
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ mask = maskLine;
+ maskLine += maskStride;
+ w = width;
+
+ CHECKPOINT();
+
+ while (w && (unsigned long)dst & 7)
+ {
+ ullong m = *mask;
+
+ if (m)
+ {
+ Vector4x16 vdest = in_over(vsrc, vsrca, expand_alpha_rev ((Vector4x16)m), load8888(*dst));
+ *dst = (ullong)pack8888(vdest, (Vector4x16)c.mmx_zero);
+ }
+
+ w--;
+ mask++;
+ dst++;
+ }
+
+ CHECKPOINT();
+
+ while (w >= 2)
+ {
+ ullong m0, m1;
+ m0 = *mask;
+ m1 = *(mask + 1);
+
+ if (srca == 0xff && (m0 & m1) == 0xff)
+ {
+ *(unsigned long long *)dst = srcsrc;
+ }
+ else if (m0 | m1)
+ {
+ Vector4x16 vdest;
+ Vector4x16 dest0, dest1;
+
+ vdest = *(Vector4x16 *)dst;
+
+ dest0 = in_over(vsrc, vsrca, expand_alpha_rev ((Vector4x16)m0), expand8888(vdest, 0));
+ dest1 = in_over(vsrc, vsrca, expand_alpha_rev ((Vector4x16)m1), expand8888(vdest, 1));
+
+ *(Vector8x8 *)dst = (Vector8x8)pack8888(dest0, dest1);
+ }
+
+ mask += 2;
+ dst += 2;
+ w -= 2;
+ }
+
+ CHECKPOINT();
+
+ while (w)
+ {
+ ullong m = *mask;
+
+ if (m)
+ {
+ Vector4x16 vdest = load8888(*dst);
+ vdest = in_over(vsrc, vsrca, expand_alpha_rev ((Vector4x16)m), vdest);
+ *dst = (ullong)pack8888(vdest, (Vector4x16)c.mmx_zero);
+ }
+
+ w--;
+ mask++;
+ dst++;
+ }
+ }
+
+ emms();
+}
+
+
+void
+fbCompositeSolidMask_nx8x0565mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ CARD32 src, srca;
+ CARD16 *dstLine, *dst;
+ CARD8 *maskLine, *mask;
+ FbStride dstStride, maskStride;
+ CARD16 w;
+ Vector4x16 vsrc, vsrca;
+ unsigned long long srcsrcsrcsrc, src16;
+
+ CHECKPOINT();
+
+ fbComposeGetSolid(pSrc, src);
+
+ srca = src >> 24;
+ if (srca == 0)
+ return;
+
+ fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1);
+ fbComposeGetStart (pMask, xMask, yMask, CARD8, maskStride, maskLine, 1);
+
+ vsrc = load8888 (src);
+ vsrca = expand_alpha (vsrc);
+
+ src16 = (ullong)pack565(vsrc, (Vector4x16)c.mmx_zero, 0);
+
+ srcsrcsrcsrc = (ullong)src16 << 48 | (ullong)src16 << 32 |
+ (ullong)src16 << 16 | (ullong)src16;
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ mask = maskLine;
+ maskLine += maskStride;
+ w = width;
+
+ CHECKPOINT();
+
+ while (w && (unsigned long)dst & 7)
+ {
+ ullong m = *mask;
+
+ if (m)
+ {
+ ullong d = *dst;
+ Vector4x16 vd = (Vector4x16)d;
+ Vector4x16 vdest = in_over(vsrc, vsrca, expand_alpha_rev ((Vector4x16)m), expand565(vd, 0));
+ *dst = (ullong)pack565(vdest, (Vector4x16)c.mmx_zero, 0);
+ }
+
+ w--;
+ mask++;
+ dst++;
+ }
+
+ CHECKPOINT();
+
+ while (w >= 4)
+ {
+ ullong m0, m1, m2, m3;
+ m0 = *mask;
+ m1 = *(mask + 1);
+ m2 = *(mask + 2);
+ m3 = *(mask + 3);
+
+ if (srca == 0xff && (m0 & m1 & m2 & m3) == 0xff)
+ {
+ *(unsigned long long *)dst = srcsrcsrcsrc;
+ }
+ else if (m0 | m1 | m2 | m3)
+ {
+ Vector4x16 vdest;
+ Vector4x16 vm0, vm1, vm2, vm3;
+
+ vdest = *(Vector4x16 *)dst;
+
+ vm0 = (Vector4x16)m0;
+ vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm0), expand565(vdest, 0)), vdest, 0);
+ vm1 = (Vector4x16)m1;
+ vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm1), expand565(vdest, 1)), vdest, 1);
+ vm2 = (Vector4x16)m2;
+ vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm2), expand565(vdest, 2)), vdest, 2);
+ vm3 = (Vector4x16)m3;
+ vdest = pack565(in_over(vsrc, vsrca, expand_alpha_rev(vm3), expand565(vdest, 3)), vdest, 3);
+
+ *(Vector4x16 *)dst = vdest;
+ }
+
+ w -= 4;
+ mask += 4;
+ dst += 4;
+ }
+
+ CHECKPOINT();
+
+ while (w)
+ {
+ ullong m = *mask;
+
+ if (m)
+ {
+ ullong d = *dst;
+ Vector4x16 vd = (Vector4x16)d;
+ Vector4x16 vdest = in_over(vsrc, vsrca, expand_alpha_rev ((Vector4x16)m), expand565(vd, 0));
+ *dst = (ullong)pack565(vdest, (Vector4x16)c.mmx_zero, 0);
+ }
+
+ w--;
+ mask++;
+ dst++;
+ }
+ }
+
+ emms();
+}
+
+void
+fbCompositeSrc_8888RevNPx0565mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ CARD16 *dstLine, *dst;
+ CARD32 *srcLine, *src;
+ FbStride dstStride, srcStride;
+ CARD16 w;
+
+ CHECKPOINT();
+
+ fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1);
+ fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
+
+ assert (pSrc->pDrawable == pMask->pDrawable);
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ src = srcLine;
+ srcLine += srcStride;
+ w = width;
+
+ CHECKPOINT();
+
+ while (w && (unsigned long)dst & 7)
+ {
+ Vector4x16 vsrc = load8888 (*src);
+ ullong d = *dst;
+ Vector4x16 vdest = expand565 ((Vector4x16)d, 0);
+
+ vdest = pack565(over_rev_non_pre(vsrc, vdest), vdest, 0);
+
+ *dst = (ullong)vdest;
+
+ w--;
+ dst++;
+ src++;
+ }
+
+ CHECKPOINT();
+
+ while (w >= 4)
+ {
+ CARD32 s0, s1, s2, s3;
+ unsigned char a0, a1, a2, a3;
+
+ s0 = *src;
+ s1 = *(src + 1);
+ s2 = *(src + 2);
+ s3 = *(src + 3);
+
+ a0 = (s0 >> 24);
+ a1 = (s1 >> 24);
+ a2 = (s2 >> 24);
+ a3 = (s3 >> 24);
+
+ if ((a0 & a1 & a2 & a3) == 0xFF)
+ {
+ Vector4x16 vdest;
+ vdest = pack565(invert_colors(load8888(s0)), (Vector4x16)c.mmx_zero, 0);
+ vdest = pack565(invert_colors(load8888(s1)), vdest, 1);
+ vdest = pack565(invert_colors(load8888(s2)), vdest, 2);
+ vdest = pack565(invert_colors(load8888(s3)), vdest, 3);
+
+ *(Vector4x16 *)dst = vdest;
+ }
+ else if (a0 | a1 | a2 | a3)
+ {
+ Vector4x16 vdest = *(Vector4x16 *)dst;
+
+ vdest = pack565(over_rev_non_pre(load8888(s0), expand565(vdest, 0)), vdest, 0);
+ vdest = pack565(over_rev_non_pre(load8888(s1), expand565(vdest, 1)), vdest, 1);
+ vdest = pack565(over_rev_non_pre(load8888(s2), expand565(vdest, 2)), vdest, 2);
+ vdest = pack565(over_rev_non_pre(load8888(s3), expand565(vdest, 3)), vdest, 3);
+
+ *(Vector4x16 *)dst = vdest;
+ }
+
+ w -= 4;
+ dst += 4;
+ src += 4;
+ }
+
+ CHECKPOINT();
+
+ while (w)
+ {
+ Vector4x16 vsrc = load8888 (*src);
+ ullong d = *dst;
+ Vector4x16 vdest = expand565 ((Vector4x16)d, 0);
+
+ vdest = pack565(over_rev_non_pre(vsrc, vdest), vdest, 0);
+
+ *dst = (ullong)vdest;
+
+ w--;
+ dst++;
+ src++;
+ }
+ }
+
+ emms();
+}
+
+/* "888RevNP" is GdkPixbuf's format: ABGR, non premultiplied */
+
+void
+fbCompositeSrc_8888RevNPx8888mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ CARD32 *dstLine, *dst;
+ CARD32 *srcLine, *src;
+ FbStride dstStride, srcStride;
+ CARD16 w;
+
+ CHECKPOINT();
+
+ fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
+ fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
+
+ assert (pSrc->pDrawable == pMask->pDrawable);
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ src = srcLine;
+ srcLine += srcStride;
+ w = width;
+
+ while (w && (unsigned long)dst & 7)
+ {
+ Vector4x16 s = load8888 (*src);
+ Vector4x16 d = load8888 (*dst);
+
+ *dst = (ullong)pack8888 (over_rev_non_pre (s, d), (Vector4x16)c.mmx_zero);
+
+ w--;
+ dst++;
+ src++;
+ }
+
+ while (w >= 2)
+ {
+ ullong s0, s1;
+ unsigned char a0, a1;
+ Vector4x16 d0, d1;
+
+ s0 = *src;
+ s1 = *(src + 1);
+
+ a0 = (s0 >> 24);
+ a1 = (s1 >> 24);
+
+ if ((a0 & a1) == 0xFF)
+ {
+ d0 = invert_colors(load8888(s0));
+ d1 = invert_colors(load8888(s1));
+
+ *(Vector8x8 *)dst = pack8888 (d0, d1);
+ }
+ else if (a0 | a1)
+ {
+ Vector4x16 vdest = *(Vector4x16 *)dst;
+
+ d0 = over_rev_non_pre (load8888(s0), expand8888 (vdest, 0));
+ d1 = over_rev_non_pre (load8888(s1), expand8888 (vdest, 1));
+
+ *(Vector8x8 *)dst = pack8888 (d0, d1);
+ }
+
+ w -= 2;
+ dst += 2;
+ src += 2;
+ }
+
+ while (w)
+ {
+ Vector4x16 s = load8888 (*src);
+ Vector4x16 d = load8888 (*dst);
+
+ *dst = (ullong)pack8888 (over_rev_non_pre (s, d), (Vector4x16)c.mmx_zero);
+
+ w--;
+ dst++;
+ src++;
+ }
+ }
+
+ emms();
+}
+
+void
+fbCompositeSolidMask_nx8888x0565Cmmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ CARD32 src, srca;
+ CARD16 *dstLine;
+ CARD32 *maskLine;
+ FbStride dstStride, maskStride;
+ Vector4x16 vsrc, vsrca;
+
+ CHECKPOINT();
+
+ fbComposeGetSolid(pSrc, src);
+
+ srca = src >> 24;
+ if (srca == 0)
+ return;
+
+ fbComposeGetStart (pDst, xDst, yDst, CARD16, dstStride, dstLine, 1);
+ fbComposeGetStart (pMask, xMask, yMask, CARD32, maskStride, maskLine, 1);
+
+ vsrc = load8888 (src);
+ vsrca = expand_alpha (vsrc);
+
+ while (height--)
+ {
+ int twidth = width;
+ CARD32 *p = (CARD32 *)maskLine;
+ CARD16 *q = (CARD16 *)dstLine;
+
+ while (twidth && ((unsigned long)q & 7))
+ {
+ CARD32 m = *(CARD32 *)p;
+
+ if (m)
+ {
+ ullong d = *q;
+ Vector4x16 vdest = expand565 ((Vector4x16)d, 0);
+ vdest = pack565 (in_over (vsrc, vsrca, load8888 (m), vdest), vdest, 0);
+ *q = (ullong)vdest;
+ }
+
+ twidth--;
+ p++;
+ q++;
+ }
+
+ while (twidth >= 4)
+ {
+ CARD32 m0, m1, m2, m3;
+
+ m0 = *p;
+ m1 = *(p + 1);
+ m2 = *(p + 2);
+ m3 = *(p + 3);
+
+ if ((m0 | m1 | m2 | m3))
+ {
+ Vector4x16 vdest = *(Vector4x16 *)q;
+
+ vdest = pack565(in_over(vsrc, vsrca, load8888(m0), expand565(vdest, 0)), vdest, 0);
+ vdest = pack565(in_over(vsrc, vsrca, load8888(m1), expand565(vdest, 1)), vdest, 1);
+ vdest = pack565(in_over(vsrc, vsrca, load8888(m2), expand565(vdest, 2)), vdest, 2);
+ vdest = pack565(in_over(vsrc, vsrca, load8888(m3), expand565(vdest, 3)), vdest, 3);
+
+ *(Vector4x16 *)q = vdest;
+ }
+ twidth -= 4;
+ p += 4;
+ q += 4;
+ }
+
+ while (twidth)
+ {
+ CARD32 m;
+
+ m = *(CARD32 *)p;
+ if (m)
+ {
+ ullong d = *q;
+ Vector4x16 vdest = expand565((Vector4x16)d, 0);
+ vdest = pack565 (in_over(vsrc, vsrca, load8888(m), vdest), vdest, 0);
+ *q = (ullong)vdest;
+ }
+
+ twidth--;
+ p++;
+ q++;
+ }
+
+ maskLine += maskStride;
+ dstLine += dstStride;
+ }
+
+ emms ();
+}
+
+void
+fbCompositeSrcAdd_8000x8000mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ CARD8 *dstLine, *dst;
+ CARD8 *srcLine, *src;
+ FbStride dstStride, srcStride;
+ CARD16 w;
+ CARD8 s, d;
+ CARD16 t;
+
+ CHECKPOINT();
+
+ fbComposeGetStart (pSrc, xSrc, ySrc, CARD8, srcStride, srcLine, 1);
+ fbComposeGetStart (pDst, xDst, yDst, CARD8, dstStride, dstLine, 1);
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ src = srcLine;
+ srcLine += srcStride;
+ w = width;
+
+ while (w && (unsigned long)dst & 7)
+ {
+ s = *src;
+ d = *dst;
+ t = d + s;
+ s = t | (0 - (t >> 8));
+ *dst = s;
+
+ dst++;
+ src++;
+ w--;
+ }
+
+ while (w >= 8)
+ {
+ __asm__ __volatile__ (
+ "movq (%0), %%mm2\n\t"
+ "movq (%1), %%mm3\n\t"
+ "paddusb %%mm2, %%mm3\n\t"
+ "movq %%mm3, (%1)\n\t"
+ : /* no output */ : "r" (src), "r" (dst));
+
+ dst += 8;
+ src += 8;
+ w -= 8;
+ }
+
+ while (w)
+ {
+ s = *src;
+ d = *dst;
+ t = d + s;
+ s = t | (0 - (t >> 8));
+ *dst = s;
+
+ dst++;
+ src++;
+ w--;
+ }
+ }
+
+ emms();
+}
+
+void
+fbCompositeSrcAdd_8888x8888mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ CARD32 *dstLine, *dst;
+ CARD32 *srcLine, *src;
+ FbStride dstStride, srcStride;
+ CARD16 w;
+
+ CHECKPOINT();
+
+ fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1);
+ fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1);
+
+ while (height--)
+ {
+ dst = dstLine;
+ dstLine += dstStride;
+ src = srcLine;
+ srcLine += srcStride;
+ w = width;
+
+ while (w && (unsigned long)dst & 7)
+ {
+ __asm__ __volatile__ (
+ "movd %0, %%mm2\n\t"
+ "movd %1, %%mm3\n\t"
+ "paddusb %%mm2, %%mm3\n\t"
+ "movd %%mm3, %1\n\t"
+ : /* no output */ : "m" (*src), "m" (*dst));
+
+ dst++;
+ src++;
+ w--;
+ }
+
+ while (w >= 2)
+ {
+ __asm__ __volatile__ (
+ "movq (%0), %%mm2\n\t"
+ "movq (%1), %%mm3\n\t"
+ "paddusb %%mm2, %%mm3\n\t"
+ "movq %%mm3, (%1)\n\t"
+ : /* no output */ : "r" (src), "r" (dst));
+
+ dst += 2;
+ src += 2;
+ w -= 2;
+ }
+
+ if (w)
+ {
+ __asm__ __volatile__ (
+ "movd %0, %%mm2\n\t"
+ "movd %1, %%mm3\n\t"
+ "paddusb %%mm2, %%mm3\n\t"
+ "movd %%mm3, %1\n\t"
+ : /* no output */ : "m" (*src), "m" (*dst));
+ }
+ }
+
+ emms();
+}
+
+#define GetStart(drw,x,y,type,stride,line,bpp) {\
+ FbBits *__bits__; \
+ FbStride __stride__; \
+ int __xoff__,__yoff__; \
+ \
+ fbGetDrawable((drw),__bits__,__stride__,bpp,__xoff__,__yoff__); \
+ (stride) = __stride__ * sizeof (FbBits) / sizeof (type); \
+ (line) = ((type *) __bits__) + (stride) * ((y) - __yoff__) + ((x) - __xoff__); \
+}
+
+Bool
+fbSolidFillmmx (DrawablePtr pDraw,
+ int x,
+ int y,
+ int width,
+ int height,
+ FbBits xor)
+{
+ FbStride stride;
+ int bpp;
+ ullong fill;
+ Vector8x8 vfill;
+ CARD32 byte_width;
+ CARD8 *byte_line;
+ FbBits *bits;
+ int xoff, yoff;
+
+ CHECKPOINT();
+
+ fbGetDrawable(pDraw, bits, stride, bpp, xoff, yoff);
+
+ if (bpp == 16 && (xor >> 16 != (xor & 0xffff)))
+ return FALSE;
+
+ if (bpp != 16 && bpp != 32)
+ return FALSE;
+
+ if (bpp == 16)
+ {
+ stride = stride * sizeof (FbBits) / 2;
+ byte_line = (CARD8 *)(((CARD16 *)bits) + stride * (y - yoff) + (x - xoff));
+ byte_width = 2 * width;
+ stride *= 2;
+ }
+ else
+ {
+ stride = stride * sizeof (FbBits) / 4;
+ byte_line = (CARD8 *)(((CARD32 *)bits) + stride * (y - yoff) + (x - xoff));
+ byte_width = 4 * width;
+ stride *= 4;
+ }
+
+ fill = ((ullong)xor << 32) | xor;
+ vfill = (Vector8x8)fill;
+
+ while (height--)
+ {
+ int w;
+ CARD8 *d = byte_line;
+ byte_line += stride;
+ w = byte_width;
+
+ while (w >= 2 && ((unsigned long)d & 3))
+ {
+ *(CARD16 *)d = xor;
+ w -= 2;
+ d += 2;
+ }
+
+ while (w >= 4 && ((unsigned int)d & 7))
+ {
+ *(CARD32 *)d = xor;
+
+ w -= 4;
+ d += 4;
+ }
+
+ while (w >= 64)
+ {
+ __asm__ __volatile (
+ "movq %0, (%1)\n\t"
+ "movq %0, 8(%1)\n\t"
+ "movq %0, 16(%1)\n\t"
+ "movq %0, 24(%1)\n\t"
+ "movq %0, 32(%1)\n\t"
+ "movq %0, 40(%1)\n\t"
+ "movq %0, 48(%1)\n\t"
+ "movq %0, 56(%1)\n\t"
+ : /* no output */
+ : "y" (vfill), "r" (d)
+ : "memory");
+ w -= 64;
+ d += 64;
+ }
+ while (w >= 4)
+ {
+ *(CARD32 *)d = xor;
+
+ w -= 4;
+ d += 4;
+ }
+ if (w >= 2)
+ {
+ *(CARD16 *)d = xor;
+ w -= 2;
+ d += 2;
+ }
+ }
+
+ emms();
+ return TRUE;
+}
+
+Bool
+fbHaveMMX (void)
+{
+ static Bool initialized = FALSE;
+ static Bool mmx_present;
+
+ if (!initialized)
+ {
+ int tmp; /* static variables are accessed through %ebx,
+ * but we mess around with the registers below,
+ * so we need a temporary variable that can
+ * be accessed directly.
+ */
+
+ __asm__ __volatile__ (
+/* Check if bit 21 in flags word is writeable */
+
+ "pusha \n\t"
+ "pushfl \n\t"
+ "popl %%eax \n\t"
+ "movl %%eax, %%ebx \n\t"
+ "xorl $0x00200000, %%eax \n\t"
+ "pushl %%eax \n\t"
+ "popfl \n\t"
+ "pushfl \n\t"
+ "popl %%eax \n\t"
+
+ "cmpl %%eax, %%ebx \n\t"
+
+ "je .notfound \n\t"
+
+/* OK, we have CPUID */
+
+ "movl $1, %%eax \n\t"
+ "cpuid \n\t"
+
+ "test $0x00800000, %%edx \n\t"
+ "jz .notfound \n\t"
+
+ "movl $1, %0 \n\t"
+ "jmp .out \n\t"
+
+ ".notfound: \n\t"
+ "movl $0, %0 \n\t"
+
+ ".out: \n\t"
+ "popa \n\t"
+ :
+ "=m" (tmp)
+ : /* no input */);
+
+ initialized = TRUE;
+
+ mmx_present = tmp;
+ }
+
+ return mmx_present;
+}
+
+
+#endif /* RENDER */
+#endif /* USE_GCC34_MMX */
diff --git a/fb/fbmmx.h b/fb/fbmmx.h
new file mode 100644
index 000000000..dd8538cc4
--- /dev/null
+++ b/fb/fbmmx.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright © 2004 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Red Hat not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Red Hat makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT
+ * 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.
+ *
+ * Author: Søren Sandmann (sandmann@redhat.com)
+ *
+ * Based on work by Owen Taylor
+ */
+#ifdef USE_GCC34_MMX
+Bool fbHaveMMX(void);
+#else
+#define fbHaveMMX FALSE
+#endif
+
+#ifdef USE_GCC34_MMX
+
+void fbCompositeSolidMask_nx8888x0565Cmmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+void fbCompositeSrcAdd_8888x8888mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+void fbCompositeSolidMask_nx8888x8888Cmmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+void fbCompositeSolidMask_nx8x8888mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+void fbCompositeSrcAdd_8000x8000mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+void fbCompositeSrc_8888RevNPx8888mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+void fbCompositeSrc_8888RevNPx0565mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+void fbCompositeSolid_nx8888mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+void fbCompositeSolid_nx0565mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+void fbCompositeSolidMask_nx8x0565mmx (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+Bool fbSolidFillmmx (DrawablePtr pDraw,
+ int x,
+ int y,
+ int width,
+ int height,
+ FbBits xor);
+
+#endif /* USE_GCC34_MMX */
diff --git a/fb/fbpseudocolor.c b/fb/fbpseudocolor.c
new file mode 100644
index 000000000..c06233692
--- /dev/null
+++ b/fb/fbpseudocolor.c
@@ -0,0 +1,2330 @@
+#include "X.h"
+#include "Xproto.h"
+#include "scrnintstr.h"
+#include "colormapst.h"
+#include "resource.h"
+#include "font.h"
+#include "dixfontstr.h"
+#include "fontstruct.h"
+#include "micmap.h"
+#include "fb.h"
+#include "fbpseudocolor.h"
+
+static Bool xxCreateGC(GCPtr pGC);
+static void xxValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw);
+static void xxDestroyGC(GCPtr pGC);
+static void xxChangeGC (GCPtr pGC, unsigned long mask);
+static void xxCopyGC (GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
+static void xxChangeClip (GCPtr pGC, int type, pointer pvalue, int nrects);
+
+static void xxCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
+static void xxDestroyClip(GCPtr pGC);
+static void xxFillSpans(DrawablePtr pDraw, GC *pGC, int nInit,
+ DDXPointPtr pptInit, int *pwidthInit, int fSorted);
+static void xxSetSpans(DrawablePtr pDraw, GCPtr pGC, char *pcharsrc,
+ DDXPointPtr pptInit, int *pwidthInit, int nspans,
+ int fSorted);
+static void xxPutImage(DrawablePtr pDraw, GCPtr pGC, int depth, int x, int y,
+ int w, int h,int leftPad, int format, char *pImage);
+static RegionPtr xxCopyPlane(DrawablePtr pSrc,
+ DrawablePtr pDst, GCPtr pGC,int srcx, int srcy,
+ int width, int height, int dstx, int dsty,
+ unsigned long bitPlane);
+static void xxPolyPoint(DrawablePtr pDraw, GCPtr pGC, int mode, int npt,
+ xPoint *pptInit);
+static void xxPolylines(DrawablePtr pDraw, GCPtr pGC, int mode,
+ int npt, DDXPointPtr pptInit);
+static void xxPolySegment(DrawablePtr pDraw, GCPtr pGC, int nseg,
+ xSegment *pSeg);
+static void xxPolyRectangle(DrawablePtr pDraw, GCPtr pGC, int nRects,
+ xRectangle *pRects);
+static void xxPolyArc( DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs);
+static void xxFillPolygon(DrawablePtr pDraw, GCPtr pGC, int shape,
+ int mode, int count, DDXPointPtr pptInit);
+static void xxPolyFillRect(DrawablePtr pDraw, GCPtr pGC, int nRectsInit,
+ xRectangle *pRectsInit);
+static RegionPtr xxCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GC *pGC,
+ int srcx, int srcy, int width, int height,
+ int dstx, int dsty);
+static void xxPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs,
+ xArc *parcs);
+static int xxPolyText8(DrawablePtr pDraw, GCPtr pGC, int x, int y, int count,
+ char *chars);
+static int xxPolyText16(DrawablePtr pDraw, GCPtr pGC, int x, int y,
+ int count, unsigned short *chars);
+static void xxImageText8(DrawablePtr pDraw, GCPtr pGC, int x,
+ int y, int count, char *chars);
+static void xxImageText16(DrawablePtr pDraw, GCPtr pGC, int x, int y,
+ int count, unsigned short *chars);
+static void xxImageGlyphBlt(DrawablePtr pDraw, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci,
+ pointer pglyphBase);
+static void xxPolyGlyphBlt(DrawablePtr pDraw, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci,
+ pointer pglyphBase);
+static void xxPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDraw,
+ int dx, int dy, int xOrg, int yOrg);
+static void
+xxComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
+static void
+xxGlyphs (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist,
+ GlyphListPtr list, GlyphPtr *glyphs);
+
+
+typedef struct _xxCmapPrivRec {
+ CARD32* cmap;
+ ColormapPtr pmap;
+ Bool dirty;
+ struct _xxCmapPrivRec *next;
+} xxCmapPrivRec, *xxCmapPrivPtr;
+
+
+typedef struct {
+ CloseScreenProcPtr CloseScreen;
+ CreateScreenResourcesProcPtr CreateScreenResources;
+ CreateWindowProcPtr CreateWindow;
+ CopyWindowProcPtr CopyWindow;
+ PaintWindowProcPtr PaintWindowBackground;
+ PaintWindowProcPtr PaintWindowBorder;
+ WindowExposuresProcPtr WindowExposures;
+ CreateGCProcPtr CreateGC;
+ CreateColormapProcPtr CreateColormap;
+ DestroyColormapProcPtr DestroyColormap;
+ InstallColormapProcPtr InstallColormap;
+ UninstallColormapProcPtr UninstallColormap;
+ ListInstalledColormapsProcPtr ListInstalledColormaps;
+ StoreColorsProcPtr StoreColors;
+#ifdef RENDER
+ CompositeProcPtr Composite;
+ GlyphsProcPtr Glyphs;
+#endif
+ PixmapPtr pPixmap;
+ char * addr;
+ pointer pBits;
+ RegionRec region;
+ VisualPtr bVisual;
+ RegionRec bRegion;
+ int myDepth;
+ int depth;
+ ColormapPtr baseCmap;
+ ColormapPtr* InstalledCmaps;
+ xxCmapPrivPtr Cmaps;
+ int numInstalledColormaps;
+ int colormapDirty;
+ xxSyncFunc sync;
+} xxScrPrivRec, *xxScrPrivPtr;
+
+#define xxGetScrPriv(s) ((xxScrPrivPtr) \
+ (xxScrPrivateIndex != -1) \
+ ? (s)->devPrivates[xxScrPrivateIndex].ptr\
+ : NULL)
+#define xxScrPriv(s) xxScrPrivPtr pScrPriv = xxGetScrPriv(s)
+
+#define xxGetCmapPriv(s) ((xxCmapPrivPtr) \
+ (s)->devPrivates[xxColormapPrivateIndex].ptr)
+#define xxCmapPriv(s) xxCmapPrivPtr pCmapPriv = xxGetCmapPriv(s);
+
+typedef struct _xxGCPriv {
+ GCOps *ops;
+ GCFuncs *funcs;
+} xxGCPrivRec, *xxGCPrivPtr;
+
+#define xxGetGCPriv(pGC) ((xxGCPrivPtr) \
+ (pGC)->devPrivates[xxGCPrivateIndex].ptr)
+#define xxGCPriv(pGC) xxGCPrivPtr pGCPriv = xxGetGCPriv(pGC)
+
+int xxScrPrivateIndex = -1;
+int xxGCPrivateIndex;
+int xxColormapPrivateIndex = -1;
+int xxGeneration;
+
+
+#define wrap(priv,real,mem,func) {\
+ priv->mem = real->mem; \
+ real->mem = func; \
+}
+
+#define unwrap(priv,real,mem) {\
+ real->mem = priv->mem; \
+}
+
+#define MARK_DIRTY (1 << 31)
+
+#define MAX_NUM_XX_INSTALLED_CMAPS 255
+/* #define DEBUG */
+#ifdef DEBUG
+# define DBG ErrorF
+# define DBG_ARGS(x) ErrorF x
+# define PRINT_RECTS(rec) {\
+ int i;\
+ BoxPtr box;\
+ ErrorF("RECTS: %i\n",REGION_NUM_RECTS(&rec));\
+ if (REGION_NUM_RECTS(&rec) > 1) { \
+ for (i = 0; i < REGION_NUM_RECTS(&rec); i++ ) {\
+ box = REGION_BOX(&rec,i);\
+ ErrorF("x1: %hi x2: %hi y1: %hi y2: %hi\n", \
+ box->x1,box->x2,box->y1,box->y2);\
+ }\
+ } else { \
+ box = &(rec.extents); \
+ ErrorF("x1: %hi x2: %hi y1: %hi y2: %hi\n", \
+ box->x1,box->x2,box->y1,box->y2);\
+ } \
+}
+#else
+# define DBG(x)
+# define DBG_ARGS(x)
+# define PRINT_RECTS(rec)
+#endif
+
+#if 0
+static void xxCopyPseudocolorRegion(ScreenPtr pScreen, RegionPtr pReg,
+ xxCmapPrivPtr pCmapPriv);
+static void xxUpdateFb(ScreenPtr pScreen);
+
+
+static void
+xxUpdateWindowImmediately(WindowPtr pWin)
+{
+ xxScrPriv(pWin->drawable.pScreen);
+ xxCmapPrivPtr pCmapPriv;
+ ColormapPtr pmap;
+
+ pmap = (ColormapPtr)LookupIDByType(wColormap(pWin),RT_COLORMAP);
+
+ if (pmap && (pCmapPriv = xxGetCmapPriv(pmap)) != (pointer)-1) {
+ xxCopyPseudocolorRegion(pWin->drawable.pScreen,
+ &pScrPriv->region, pCmapPriv);
+ }
+}
+#else
+# define xxUpdateWindowImmediately(x)
+#endif
+
+static ColormapPtr
+xxGetBaseColormap(ScreenPtr pScreen)
+{
+ xxScrPriv(pScreen);
+ DepthPtr pDepth = pScreen->allowedDepths;
+ int i,j,k;
+ ColormapPtr pDefMap
+ = (ColormapPtr) LookupIDByType(pScreen->defColormap,RT_COLORMAP);
+ ColormapPtr cmap = NULL;
+ VisualPtr pVisual = NULL;
+
+ for (i = 0; i < pScreen->numDepths; i++, pDepth++)
+ if (pDepth->depth == pScrPriv->depth) {
+ for (j = 0; j < pDepth->numVids; j++) {
+ if (pDefMap->pVisual->vid == pDepth->vids[j]
+ && pDefMap->pVisual->class == TrueColor) {
+ cmap = pDefMap;
+ break;
+ }
+ if (!pVisual) {
+ for (k = 0; k < pScreen->numVisuals; k++) {
+ if (pScreen->visuals[k].class == TrueColor
+ && pScreen->visuals[k].vid
+ == pDepth->vids[j]) {
+ pVisual = &pScreen->visuals[k];
+ break;
+ }
+ }
+ }
+ }
+ if (cmap)
+ break;
+ }
+
+ if (!cmap) {
+ CreateColormap(FakeClientID(0),pScreen,pVisual,&cmap,AllocNone,0);
+ }
+
+ return cmap;
+}
+
+static Bool
+xxCreateScreenResources(ScreenPtr pScreen)
+{
+ PixmapPtr pPix;
+ xxScrPriv(pScreen);
+ Bool ret;
+ PixmapPtr pPixmap;
+ BoxRec box;
+ int depth = pScrPriv->myDepth;
+ pointer pBits;
+
+ unwrap (pScrPriv,pScreen, CreateScreenResources);
+ ret = pScreen->CreateScreenResources(pScreen);
+ wrap(pScrPriv,pScreen,CreateScreenResources,xxCreateScreenResources);
+
+ if (!ret) return FALSE;
+
+ pScrPriv->pBits = NULL;
+ if (pScrPriv->addr)
+ pBits = pScrPriv->addr;
+ else
+ pBits = xalloc(pScreen->width * pScreen->height
+ * (BitsPerPixel(depth) >> 3));
+ if (!pBits) return FALSE;
+
+ pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth);
+ if (!pPixmap) {
+ xfree(pBits);
+ return FALSE;
+ }
+ if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width,
+ pScreen->height, depth,
+ BitsPerPixel(depth),
+ PixmapBytePad(pScreen->width, depth),
+ pBits)) {
+ xfree(pBits);
+ return FALSE;
+ }
+ if (pScreen->rootDepth == pScrPriv->myDepth) {
+ pPix = (PixmapPtr)pScreen->devPrivate;
+ if (!(*pScreen->ModifyPixmapHeader)(pPix, 0,0, pScrPriv->depth,
+ BitsPerPixel(pScrPriv->depth),
+ PixmapBytePad(pScreen->width,
+ pScrPriv->depth),
+ 0)) {
+ xfree(pBits);
+ return FALSE;
+ }
+ }
+
+ pScrPriv->baseCmap = xxGetBaseColormap(pScreen);
+
+ pScrPriv->pBits = pBits;
+ pScrPriv->pPixmap = pPixmap;
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+ REGION_NULL(pScreen, &pScrPriv->region);
+ REGION_INIT(pScreen, &pScrPriv->bRegion, &box, 0);
+
+ return TRUE;
+}
+
+static Bool
+xxCloseScreen (int iScreen, ScreenPtr pScreen)
+{
+ xxScrPriv(pScreen);
+ Bool ret;
+
+ (*pScreen->DestroyPixmap)(pScrPriv->pPixmap);
+ /* We don't need to free the baseColormap as FreeClientResourcess
+ will have taken care of it. */
+ REGION_UNINIT (pScreen, &pScrPriv->region);
+
+ unwrap (pScrPriv,pScreen, CloseScreen);
+ ret = pScreen->CloseScreen(iScreen,pScreen);
+
+ xfree(pScrPriv->pBits);
+ xfree(pScrPriv->InstalledCmaps);
+ xfree(pScrPriv);
+
+ return TRUE;
+}
+
+static Bool
+xxMyVisual(ScreenPtr pScreen, VisualID vid)
+{
+ xxScrPriv(pScreen);
+ DepthPtr pDepth = pScreen->allowedDepths;
+ int i,j;
+
+ for (i = 0; i < pScreen->numDepths; i++, pDepth++)
+ if (pDepth->depth == pScrPriv->myDepth) {
+ for (j = 0; j < pDepth->numVids; j++) {
+ if (vid == pDepth->vids[j]) {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+static Bool
+xxInitColormapDummy(ColormapPtr pmap, int index)
+{
+ return TRUE;
+}
+
+static Bool
+xxInitColormapPrivate(ColormapPtr pmap)
+{
+ xxScrPriv(pmap->pScreen);
+ xxCmapPrivPtr pCmapPriv;
+ pointer cmap;
+
+ pmap->devPrivates[xxColormapPrivateIndex].ptr = (pointer) -1;
+
+ if (xxMyVisual(pmap->pScreen,pmap->pVisual->vid)) {
+ DBG("CreateColormap\n");
+ pCmapPriv = (xxCmapPrivPtr) xalloc (sizeof (xxCmapPrivRec));
+ if (!pCmapPriv)
+ return FALSE;
+ pmap->devPrivates[xxColormapPrivateIndex].ptr = (pointer) pCmapPriv;
+ cmap = xalloc(sizeof (CARD32) * (1 << pScrPriv->myDepth));
+ if (!cmap)
+ return FALSE;
+
+ memset(cmap,0,sizeof (CARD32) * (1 << pScrPriv->myDepth));
+
+ pCmapPriv->cmap = cmap;
+ pCmapPriv->dirty = FALSE;
+ pCmapPriv->pmap = pmap;
+ pCmapPriv->next = pScrPriv->Cmaps;
+ pScrPriv->Cmaps = pCmapPriv;
+ }
+ return TRUE;
+}
+
+
+static Bool
+xxCreateColormap(ColormapPtr pmap)
+{
+ xxScrPriv(pmap->pScreen);
+ Bool ret;
+
+ if (!xxInitColormapPrivate(pmap)) return FALSE;
+
+ unwrap(pScrPriv,pmap->pScreen, CreateColormap);
+ ret = pmap->pScreen->CreateColormap(pmap);
+ wrap(pScrPriv,pmap->pScreen,CreateColormap,xxCreateColormap);
+
+ return ret;
+}
+
+static int
+xxCmapInstalled(ColormapPtr pmap)
+{
+ xxScrPriv(pmap->pScreen);
+ int i;
+
+ for (i = 0; i < pScrPriv->numInstalledColormaps; i++)
+ if (pScrPriv->InstalledCmaps[i] == pmap)
+ break;
+ if (i == pScrPriv->numInstalledColormaps) /* not installed */
+ return -1;
+ return i;
+}
+
+static void
+xxInstalledCmapDelete(ScreenPtr pScreen, int num)
+{
+ xxScrPriv(pScreen);
+ int i;
+
+ pScrPriv->numInstalledColormaps--;
+
+ for (i = num; i < pScrPriv->numInstalledColormaps; i++)
+ pScrPriv->InstalledCmaps[i] = pScrPriv->InstalledCmaps[i+1];
+}
+
+static void
+xxDestroyColormap(ColormapPtr pmap)
+{
+ xxScrPriv(pmap->pScreen);
+ xxCmapPriv(pmap);
+
+ if (pCmapPriv != (pointer) -1) {
+ xxCmapPrivPtr tmpCmapPriv = pScrPriv->Cmaps;
+ xxCmapPrivPtr *prevCmapPriv = &pScrPriv->Cmaps;
+ int n;
+
+ DBG("DestroyColormap\n");
+
+ if ((n = xxCmapInstalled(pmap)) != -1)
+ xxInstalledCmapDelete(pmap->pScreen,n);
+
+ while (tmpCmapPriv) {
+ if (tmpCmapPriv->pmap == pmap) {
+ *prevCmapPriv = tmpCmapPriv->next;
+ break;
+ }
+ prevCmapPriv = &tmpCmapPriv->next;
+ tmpCmapPriv = tmpCmapPriv->next;
+ }
+
+ xfree(pCmapPriv->cmap);
+ xfree(pCmapPriv);
+ }
+
+ unwrap(pScrPriv,pmap->pScreen, DestroyColormap);
+ pmap->pScreen->DestroyColormap(pmap);
+ wrap(pScrPriv,pmap->pScreen,DestroyColormap,xxDestroyColormap);
+}
+
+#define Shift(v,d) ((d) < 0 ? ((v) >> (-d)) : ((v) << (d)))
+
+static int
+xxComputeCmapShift (unsigned long mask)
+{
+ int shift;
+ unsigned long bit;
+
+ shift = 16;
+ bit = 0x80000000;
+ while (!(mask & bit))
+ {
+ shift--;
+ bit >>= 1;
+ }
+ return shift;
+}
+
+static void
+xxStoreColors(ColormapPtr pmap, int nColors, xColorItem *pColors)
+{
+ xxScrPriv(pmap->pScreen);
+ xxCmapPriv(pmap);
+
+ if (pCmapPriv != (pointer) -1) {
+
+ xColorItem *expanddefs;
+ int i;
+ VisualPtr bVisual;
+ int rs, gs, bs;
+
+ if (nColors == 0) return;
+
+ DBG("StoreColors\n");
+
+ expanddefs = ALLOCATE_LOCAL(sizeof(xColorItem)
+ * (1 << pScrPriv->myDepth));
+ if (!expanddefs) return;
+
+ bVisual = pScrPriv->bVisual;
+
+ DBG("StoreColors\n");
+
+ rs = xxComputeCmapShift(bVisual->redMask);
+ gs = xxComputeCmapShift(bVisual->greenMask);
+ bs = xxComputeCmapShift(bVisual->blueMask);
+
+ if ((pmap->pVisual->class | DynamicClass) == DirectColor) {
+ nColors = miExpandDirectColors(pmap, nColors, pColors, expanddefs);
+ pColors = expanddefs;
+ }
+
+ for (i = 0; i < nColors; i++) {
+ DBG_ARGS(("index: %i r 0x%x g 0x%x b 0x%x\n", pColors->pixel,
+ pColors->red, pColors->green, pColors->blue));
+ pCmapPriv->cmap[pColors->pixel] = MARK_DIRTY
+ | (Shift(pColors->red, rs) & bVisual->redMask)
+ | (Shift(pColors->green, gs) & bVisual->greenMask)
+ | (Shift(pColors->blue, bs) & bVisual->blueMask);
+ pColors++;
+ }
+
+ DEALLOCATE_LOCAL(expanddefs);
+
+ pCmapPriv->dirty = TRUE;
+ pScrPriv->colormapDirty = TRUE;
+
+ return;
+ }
+
+ unwrap(pScrPriv,pmap->pScreen, StoreColors);
+ pmap->pScreen->StoreColors(pmap,nColors,pColors);
+ wrap(pScrPriv,pmap->pScreen,StoreColors,xxStoreColors);
+}
+
+static void
+xxInstallColormap(ColormapPtr pmap)
+{
+ int i;
+ xxScrPriv(pmap->pScreen);
+ xxCmapPriv(pmap);
+
+ if (pCmapPriv != (pointer) -1) {
+ Pixel *pixels;
+ xrgb *colors;
+ int i;
+ VisualPtr pVisual;
+ xColorItem *defs;
+
+ DBG("InstallColormap\n");
+
+ if (xxCmapInstalled(pmap) != -1)
+ return;
+
+ if (!pScrPriv->numInstalledColormaps) {
+ unwrap(pScrPriv,pmap->pScreen, InstallColormap);
+ pmap->pScreen->InstallColormap(pScrPriv->baseCmap);
+ wrap(pScrPriv,pmap->pScreen,InstallColormap,xxInstallColormap);
+ }
+
+ pixels = ALLOCATE_LOCAL(sizeof(Pixel) * (1 << pScrPriv->myDepth));
+ colors = ALLOCATE_LOCAL(sizeof(xrgb) * (1 << pScrPriv->myDepth));
+ defs = ALLOCATE_LOCAL(sizeof(xColorItem) * (1 << pScrPriv->myDepth));
+
+ if (!pixels || !colors)
+ return;
+
+ /* if we have more than max installed delete the oldest */
+ if (pScrPriv->numInstalledColormaps == MAX_NUM_XX_INSTALLED_CMAPS)
+ xxInstalledCmapDelete(pmap->pScreen,0);
+
+ pScrPriv->InstalledCmaps[pScrPriv->numInstalledColormaps] = pmap;
+ pScrPriv->numInstalledColormaps++;
+
+ pVisual = pScrPriv->bVisual;
+
+ for (i = 0; i < (1 << pScrPriv->myDepth); i++)
+ pixels[i] = i;
+
+ QueryColors (pmap, (1 << pScrPriv->myDepth), pixels, colors);
+
+ for (i = 0; i < (1 << pScrPriv->myDepth); i++) {
+ defs[i].pixel = pixels[i];
+ defs[i].red = colors[i].red;
+ defs[i].green = colors[i].green;
+ defs[i].blue = colors[i].blue;
+ defs[i].flags = DoRed|DoGreen|DoBlue;
+ }
+ xxStoreColors(pmap,(1 << pScrPriv->myDepth),defs);
+
+ DEALLOCATE_LOCAL(pixels);
+ DEALLOCATE_LOCAL(colors);
+ DEALLOCATE_LOCAL(defs);
+
+ return;
+ }
+
+ for (i = pScrPriv->numInstalledColormaps; i ; i--)
+ WalkTree(pmap->pScreen, TellLostMap,
+ (char *)&pScrPriv->InstalledCmaps[i-1]->mid);
+
+ pScrPriv->numInstalledColormaps = 0;
+
+ unwrap(pScrPriv,pmap->pScreen, InstallColormap);
+ pmap->pScreen->InstallColormap(pmap);
+ wrap(pScrPriv,pmap->pScreen,InstallColormap,xxInstallColormap);
+}
+
+static void
+xxUninstallColormap(ColormapPtr pmap)
+{
+ xxScrPriv(pmap->pScreen);
+ xxCmapPriv(pmap);
+
+ if (pCmapPriv != (pointer) -1) {
+ int num;
+
+ if ((num = xxCmapInstalled(pmap)) == -1)
+ return;
+
+ DBG("UninstallColormap\n");
+ xxInstalledCmapDelete(pmap->pScreen,num);
+
+ return;
+ }
+
+ unwrap(pScrPriv,pmap->pScreen, UninstallColormap);
+ pmap->pScreen->UninstallColormap(pmap);
+ wrap(pScrPriv,pmap->pScreen,UninstallColormap,xxUninstallColormap);
+
+}
+
+static int
+xxListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIds)
+{
+ int n,i;
+ xxScrPriv(pScreen);
+
+ unwrap(pScrPriv,pScreen, ListInstalledColormaps);
+ n = pScreen->ListInstalledColormaps(pScreen, pCmapIds);
+ wrap (pScrPriv,pScreen,ListInstalledColormaps,xxListInstalledColormaps);
+
+ pCmapIds += n;
+
+ for (i = 0; i < pScrPriv->numInstalledColormaps; i++) {
+ *pCmapIds++ = pScrPriv->InstalledCmaps[i]->mid;
+ n++;
+ }
+
+ return n;
+}
+
+static Bool
+xxCreateWindow(WindowPtr pWin)
+{
+ xxScrPriv(pWin->drawable.pScreen);
+
+ if (pWin->drawable.class != InputOutput
+ || pScrPriv->myDepth != pWin->drawable.depth) {
+ Bool ret;
+ DBG("CreateWindow NoPseudo\n");
+ unwrap (pScrPriv, pWin->drawable.pScreen, CreateWindow);
+ ret = pWin->drawable.pScreen->CreateWindow(pWin);
+ wrap(pScrPriv, pWin->drawable.pScreen, CreateWindow, xxCreateWindow);
+
+ return ret;
+ }
+
+ DBG("CreateWindow\n");
+
+ pWin->devPrivates[fbWinPrivateIndex].ptr = (pointer) pScrPriv->pPixmap;
+ PRINT_RECTS(pScrPriv->region);
+ if (!pWin->parent) {
+ REGION_EMPTY (pWin->drawable.pScreen, &pScrPriv->region);
+ }
+ PRINT_RECTS(pScrPriv->region);
+
+ return TRUE;
+}
+
+static void
+xxWalkChildren(WindowPtr pWin, RegionPtr pReg, PixmapPtr pPixmap)
+{
+
+ WindowPtr pCurWin = pWin;
+
+ do {
+ if (fbGetWindowPixmap(pCurWin) == pPixmap) {
+ DBG("WalkWindow Add\n");
+ REGION_UNION(pWin->drawable.pScreen,pReg,pReg,
+ &pCurWin->borderClip);
+ } else {
+ DBG("WalkWindow Sub\n");
+ REGION_SUBTRACT(pWin->drawable.pScreen,pReg,pReg,
+ &pCurWin->borderClip);
+ }
+ if (pCurWin->lastChild)
+ xxWalkChildren(pCurWin->lastChild,pReg, pPixmap);
+ } while ((pCurWin = pCurWin->prevSib));
+}
+
+static void
+xxPickMyWindows(WindowPtr pWin, RegionPtr pRgn)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ xxScrPriv(pScreen);
+
+ if (fbGetWindowPixmap(pWin) == pScrPriv->pPixmap) {
+ REGION_UNION(pWin->drawable.pScreen,pRgn,pRgn,&pWin->borderClip);
+ }
+ if (pWin->lastChild)
+ xxWalkChildren(pWin->lastChild,pRgn,pScrPriv->pPixmap);
+}
+
+static void
+xxCopyWindow(WindowPtr pWin,
+ DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ xxScrPriv(pScreen);
+ RegionRec rgn;
+ RegionRec rgn_new;
+ int dx, dy;
+ PixmapPtr pPixmap = fbGetWindowPixmap(pWin);
+
+ DBG("xxCopyWindow\n");
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+
+ REGION_NULL(pScreen, &rgn_new);
+ REGION_UNION(pScreen, &rgn_new,&rgn_new,prgnSrc);
+ REGION_TRANSLATE(pScreen,&rgn_new,-dx,-dy);
+
+ REGION_NULL(pScreen, &rgn);
+ xxPickMyWindows(pWin,&rgn);
+
+ unwrap (pScrPriv, pScreen, CopyWindow);
+ pWin->devPrivates[fbWinPrivateIndex].ptr = fbGetScreenPixmap(pScreen);
+ pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc);
+ pWin->devPrivates[fbWinPrivateIndex].ptr = pPixmap;
+ wrap(pScrPriv, pScreen, CopyWindow, xxCopyWindow);
+
+ REGION_INTERSECT(pScreen,&rgn,&rgn,&rgn_new);
+ if (REGION_NOTEMPTY (pScreen,&rgn)) {
+ fbCopyRegion(&pScrPriv->pPixmap->drawable,&pScrPriv->pPixmap->drawable,
+ 0,&rgn,dx,dy,fbCopyWindowProc,0,(void*)0);
+ REGION_TRANSLATE(pScreen,&rgn,dx,dy);
+ REGION_INTERSECT(pScreen,&rgn_new,&pScrPriv->region,&rgn);
+ REGION_SUBTRACT(pScreen,&pScrPriv->region,&pScrPriv->region,&rgn);
+ REGION_TRANSLATE(pScreen,&rgn_new,-dx,-dy);
+ REGION_UNION(pScreen,&pScrPriv->region,&pScrPriv->region,&rgn_new);
+ }
+#if 1
+ REGION_UNINIT(pScreen,&rgn_new);
+ REGION_UNINIT(pScreen,&rgn);
+#endif
+}
+
+static void
+xxWindowExposures (WindowPtr pWin,
+ RegionPtr prgn,
+ RegionPtr other_exposed)
+{
+ xxScrPriv(pWin->drawable.pScreen);
+
+ if (fbGetWindowPixmap(pWin) == pScrPriv->pPixmap) {
+ DBG("WindowExposures\n");
+ PRINT_RECTS(pScrPriv->region);
+ REGION_UNION(pWin->drawable.pScreen,&pScrPriv->region,
+ &pScrPriv->region,
+ prgn);
+ PRINT_RECTS(pScrPriv->region);
+ } else {
+ DBG("WindowExposures NonPseudo\n");
+ PRINT_RECTS(pScrPriv->region);
+ REGION_SUBTRACT(pWin->drawable.pScreen,&pScrPriv->region,
+ &pScrPriv->region,
+ prgn);
+ PRINT_RECTS(pScrPriv->region);
+ }
+ unwrap (pScrPriv, pWin->drawable.pScreen, WindowExposures);
+ pWin->drawable.pScreen->WindowExposures(pWin, prgn, other_exposed);
+ wrap(pScrPriv, pWin->drawable.pScreen, WindowExposures, xxWindowExposures);
+}
+
+static void
+xxPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ xxScrPriv(pWin->drawable.pScreen);
+ RegionRec rgni;
+
+ DBG("xxPaintWindow\n");
+
+ REGION_NULL (pWin->drawable.pScreen, &rgni);
+#if 0
+ REGION_UNION (pWin->drawable.pScreen, &rgni, &rgni, &pWin->borderClip);
+ REGION_INTERSECT(pWin->drawable.pScreen, &rgni, &rgni, pRegion);
+#else
+ REGION_UNION (pWin->drawable.pScreen, &rgni, &rgni, pRegion);
+#endif
+ switch (what) {
+ case PW_BORDER:
+ REGION_SUBTRACT (pWin->drawable.pScreen, &rgni, &rgni, &pWin->winSize);
+ if (fbGetWindowPixmap(pWin) == pScrPriv->pPixmap) {
+ DBG("PaintWindowBorder\n");
+ REGION_UNION (pWin->drawable.pScreen, &pScrPriv->region,
+ &pScrPriv->region, &rgni);
+ } else {
+ DBG("PaintWindowBorder NoOverlay\n");
+ REGION_SUBTRACT (pWin->drawable.pScreen, &pScrPriv->region,
+ &pScrPriv->region, &rgni);
+ }
+ unwrap (pScrPriv, pWin->drawable.pScreen, PaintWindowBorder);
+ pWin->drawable.pScreen->PaintWindowBorder (pWin, pRegion, what);
+ wrap(pScrPriv, pWin->drawable.pScreen, PaintWindowBorder,
+ xxPaintWindow);
+ break;
+ case PW_BACKGROUND:
+ switch (pWin->backgroundState) {
+ case None:
+ break;
+ default:
+ REGION_INTERSECT (pWin->drawable.pScreen, &rgni,
+ &rgni,&pWin->winSize);
+ if (fbGetWindowPixmap(pWin) == pScrPriv->pPixmap) {
+ DBG("PaintWindowBackground\n");
+ REGION_UNION (pWin->drawable.pScreen, &pScrPriv->region,
+ &pScrPriv->region, &rgni);
+ } else {
+ DBG("PaintWindowBackground NoOverlay\n");
+ REGION_SUBTRACT (pWin->drawable.pScreen, &pScrPriv->region,
+ &pScrPriv->region, &rgni);
+ }
+ break;
+ }
+
+ unwrap (pScrPriv, pWin->drawable.pScreen, PaintWindowBackground);
+ pWin->drawable.pScreen->PaintWindowBackground (pWin, pRegion, what);
+ wrap(pScrPriv, pWin->drawable.pScreen, PaintWindowBackground,
+ xxPaintWindow);
+ break;
+ }
+ PRINT_RECTS(rgni);
+ PRINT_RECTS(pScrPriv->region);
+#if 1
+ REGION_UNINIT(pWin->drawable.pScreen,&rgni);
+#endif
+}
+
+static void
+xxCopyPseudocolorRegion(ScreenPtr pScreen, RegionPtr pReg,
+ xxCmapPrivPtr pCmapPriv)
+{
+ xxScrPriv(pScreen);
+ CARD32 mask = (1 << pScrPriv->myDepth) - 1;
+ int num = REGION_NUM_RECTS(pReg);
+ BoxPtr pbox = REGION_RECTS(pReg);
+ int width, height;
+ CARD8 *src;
+ CARD16 *dst, *dst_base;
+ int dst_stride;
+ register CARD32 *cmap = pCmapPriv->cmap;
+ register CARD8 *s;
+ register CARD16 *d;
+ int w;
+
+ dst_base = (CARD16*) ((PixmapPtr)pScreen->devPrivate)->devPrivate.ptr;
+ dst_stride = (int)((PixmapPtr)pScreen->devPrivate)->devKind
+ / sizeof (CARD16);
+
+ while (num--) {
+ height = pbox->y2 - pbox->y1;
+ width = pbox->x2 - pbox->x1;
+
+ src = (unsigned char *) pScrPriv->pBits
+ + (pbox->y1 * pScreen->width) + pbox->x1;
+ dst = dst_base + (pbox->y1 * dst_stride) + pbox->x1;
+ while (height--) {
+ w = width;
+ s = src;
+ d = dst;
+
+ while(w--) {
+ *(d++) = (CARD16)*(cmap + ((*(s++)) & mask));
+ }
+ src += pScreen->width;
+ dst += dst_stride;
+ }
+ pbox++;
+ }
+}
+
+static void
+xxUpdateCmapPseudocolorRegion(ScreenPtr pScreen, RegionPtr pReg,
+ xxCmapPrivPtr pCmapPriv)
+{
+ xxScrPriv(pScreen);
+ CARD32 mask = (1 << pScrPriv->myDepth) - 1;
+ int num = REGION_NUM_RECTS(pReg);
+ BoxPtr pbox = REGION_RECTS(pReg);
+ int width, height;
+ CARD8 *src;
+ CARD16 *dst, *dst_base;
+ int dst_stride;
+ register CARD32 val;
+ register CARD32 *cmap = pCmapPriv->cmap;
+ register CARD8 *s;
+ register CARD16 *d;
+ int w;
+
+ dst_base = (CARD16*) ((PixmapPtr)pScreen->devPrivate)->devPrivate.ptr;
+ dst_stride = (int)((PixmapPtr)pScreen->devPrivate)->devKind
+ / sizeof (CARD16);
+
+ while (num--) {
+
+ height = pbox->y2 - pbox->y1;
+ width = pbox->x2 - pbox->x1;
+
+ src = (unsigned char *) pScrPriv->pBits
+ + (pbox->y1 * pScreen->width) + pbox->x1;
+ dst = dst_base + (pbox->y1 * dst_stride) + pbox->x1;
+ while (height--) {
+ w = width;
+ s = src;
+ d = dst;
+ while(w--) {
+ val = *(cmap + ((*(s++)) & mask));
+ if (val & MARK_DIRTY) {
+ *d = (CARD16) val;
+ }
+ d++;
+ }
+ src += pScreen->width;
+ dst += dst_stride;
+ }
+ pbox++;
+ }
+}
+
+static void
+xxGetWindowRegion(WindowPtr pWin,RegionPtr winreg)
+{
+ REGION_NULL(pWin->drawable.pScreen,winreg);
+ /* get visible part of the border ...Argh */
+ REGION_SUBTRACT(pWin->drawable.pScreen,winreg,&pWin->borderSize,
+ &pWin->winSize);
+ REGION_INTERSECT(pWin->drawable.pScreen,winreg,winreg,
+ &pWin->borderClip);
+ /* add window interior excluding children */
+ REGION_UNION(pWin->drawable.pScreen,winreg,winreg,
+ &pWin->clipList);
+}
+
+static int
+xxUpdateRegion(WindowPtr pWin, pointer unused)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ xxScrPriv(pScreen);
+ ColormapPtr pmap = (pointer) -1;
+ RegionRec winreg, rgni;
+
+ if (pScrPriv->myDepth == pWin->drawable.depth) {
+ xxCmapPrivPtr pCmapPriv = (pointer)-1;
+ xxGetWindowRegion(pWin,&winreg);
+
+ if (pScrPriv->colormapDirty) {
+
+ pmap = (ColormapPtr)LookupIDByType(wColormap(pWin),RT_COLORMAP);
+ if (!pmap)
+ goto CONTINUE; /* return ? */
+
+ pCmapPriv = xxGetCmapPriv(pmap);
+ if (pCmapPriv == (pointer) -1)
+ return WT_WALKCHILDREN;
+ if (!pCmapPriv->dirty)
+ goto CONTINUE;
+
+ REGION_NULL (pScreen, &rgni);
+ /* This will be taken care of when damaged regions are updated */
+ REGION_SUBTRACT(pScreen, &rgni, &winreg, &pScrPriv->region);
+ if (REGION_NOTEMPTY (pScreen,&rgni))
+ xxUpdateCmapPseudocolorRegion(pScreen,&rgni, pCmapPriv);
+ }
+ CONTINUE:
+
+ REGION_NULL (pScreen, &rgni);
+ REGION_INTERSECT (pScreen, &rgni, &winreg, &pScrPriv->region);
+
+ if (REGION_NOTEMPTY (pScreen,&rgni)) {
+ if (pmap == (pointer) -1) {
+ pmap =
+ (ColormapPtr)LookupIDByType(wColormap(pWin),RT_COLORMAP);
+ if (!pmap) /* return ? */
+ pmap = (ColormapPtr)LookupIDByType(pScreen->defColormap,
+ RT_COLORMAP);
+ pCmapPriv = xxGetCmapPriv(pmap);
+ }
+
+ if (pCmapPriv != (pointer)-1)
+ xxCopyPseudocolorRegion(pScreen,&rgni, pCmapPriv);
+ REGION_SUBTRACT(pScreen, &pScrPriv->region, &pScrPriv->region,
+ &rgni);
+ }
+#if 1
+ REGION_UNINIT(pScreen,&rgni);
+ REGION_UNINIT(pScreen,&winreg);
+#endif
+ }
+ return WT_WALKCHILDREN;
+}
+
+
+static void
+xxUpdateFb(ScreenPtr pScreen)
+{
+ xxScrPriv(pScreen);
+
+ DBG("Update FB\n");
+ PRINT_RECTS(pScrPriv->region);
+
+ if (pScrPriv->sync)
+ pScrPriv->sync(pScreen); /*@!@*/
+
+ WalkTree(pScreen,xxUpdateRegion,NULL);
+#if 0
+ if (REGION_NOTEMPTY (pScreen,&pScrPriv->region)) {
+ ColormapPtr pmap = (pointer) -1;
+ xxCmapPrivPtr pCmapPriv;
+
+ pmap = (ColormapPtr)LookupIDByType(pScreen->defColormap,
+ RT_COLORMAP);
+ pCmapPriv = xxGetCmapPriv(pmap);
+ if (pCmapPriv != (pointer)-1)
+ xxCopyPseudocolorRegion(pScreen,&pScrPriv->region, pCmapPriv);
+ REGION_SUBTRACT(pScreen, &pScrPriv->region, &pScrPriv->region,
+ &pScrPriv->region);
+ }
+#endif
+ if (pScrPriv->colormapDirty) {
+ xxCmapPrivPtr pCmap = pScrPriv->Cmaps;
+
+ while (pCmap) {
+ int j;
+
+ if (pCmap->dirty) {
+ for (j = 0; j < (1 << pScrPriv->myDepth); j++)
+ pCmap->cmap[j] &= ~MARK_DIRTY;
+ pCmap->dirty = FALSE;
+ }
+ pCmap = pCmap->next;
+ }
+ pScrPriv->colormapDirty = FALSE;
+ }
+}
+
+static void
+xxBlockHandler (pointer data,
+ OSTimePtr pTimeout,
+ pointer pRead)
+{
+ ScreenPtr pScreen = (ScreenPtr) data;
+ xxScrPriv(pScreen);
+
+ if (REGION_NOTEMPTY (pScreen,&pScrPriv->region) || pScrPriv->colormapDirty)
+ xxUpdateFb (pScreen);
+}
+
+static void
+xxWakeupHandler (pointer data, int i, pointer LastSelectMask)
+{
+}
+
+Bool
+xxSetup(ScreenPtr pScreen, int myDepth, int baseDepth, char* addr, xxSyncFunc sync)
+{
+ xxScrPrivPtr pScrPriv;
+ DepthPtr pDepths;
+ ColormapPtr pDefMap;
+ int i,j,k;
+
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif
+
+ if (xxGeneration != serverGeneration) {
+ xxScrPrivateIndex = AllocateScreenPrivateIndex ();
+ if (xxScrPrivateIndex == -1)
+ return FALSE;
+ xxColormapPrivateIndex
+ = AllocateColormapPrivateIndex (xxInitColormapDummy);
+ if (xxColormapPrivateIndex == -1)
+ return FALSE;
+ xxGCPrivateIndex = AllocateGCPrivateIndex ();
+ if (xxGCPrivateIndex == -1)
+ return FALSE;
+ xxGeneration = serverGeneration;
+ }
+
+ if (!AllocateGCPrivate (pScreen, xxGCPrivateIndex, sizeof (xxGCPrivRec)))
+ return FALSE;
+
+ pScrPriv = (xxScrPrivPtr) xalloc (sizeof (xxScrPrivRec));
+ if (!pScrPriv)
+ return FALSE;
+
+ if (baseDepth)
+ pScrPriv->depth = baseDepth;
+ else {
+ pDepths = pScreen->allowedDepths;
+ for (i = 0; i < pScreen->numDepths; i++, pDepths++)
+ if (pDepths->depth != myDepth)
+ pScrPriv->depth = pDepths->depth;
+ }
+ if (!pScrPriv->depth)
+ return FALSE;
+
+ pDepths = pScreen->allowedDepths;
+ for (i = 0; i < pScreen->numDepths; i++, pDepths++)
+ if (pDepths->depth == pScrPriv->depth) {
+ for (j = 0; i < pDepths->numVids; j++) {
+ for (k = 0; k < pScreen->numVisuals; k++) {
+ if (pScreen->visuals[k].vid
+ == pDepths[i].vids[j]
+ && pScreen->visuals[k].class == TrueColor) {
+ pScrPriv->bVisual = &pScreen->visuals[k];
+ goto DONE;
+ }
+ }
+ }
+ }
+
+ DONE:
+ if (!pScrPriv->bVisual)
+ return FALSE;
+
+ pScrPriv->myDepth = myDepth;
+ pScrPriv->numInstalledColormaps = 0;
+ pScrPriv->colormapDirty = FALSE;
+ pScrPriv->Cmaps = NULL;
+ pScrPriv->sync = sync;
+
+ pScreen->maxInstalledCmaps += MAX_NUM_XX_INSTALLED_CMAPS;
+ pScrPriv->InstalledCmaps = xcalloc(MAX_NUM_XX_INSTALLED_CMAPS,
+ sizeof(ColormapPtr));
+ if (!pScrPriv->InstalledCmaps)
+ return FALSE;
+
+
+ if (!RegisterBlockAndWakeupHandlers (xxBlockHandler,
+ xxWakeupHandler,
+ (pointer) pScreen))
+ return FALSE;
+
+ wrap (pScrPriv, pScreen, CloseScreen, xxCloseScreen);
+ wrap (pScrPriv, pScreen, CreateScreenResources, xxCreateScreenResources);
+ wrap (pScrPriv, pScreen, CreateWindow, xxCreateWindow);
+ wrap (pScrPriv, pScreen, CopyWindow, xxCopyWindow);
+ wrap (pScrPriv, pScreen, PaintWindowBorder, xxPaintWindow);
+ wrap (pScrPriv, pScreen, PaintWindowBackground, xxPaintWindow);
+#if 0 /* can we leave this out even with backing store enabled ? */
+ wrap (pScrPriv, pScreen, WindowExposures, xxWindowExposures);
+#endif
+ wrap (pScrPriv, pScreen, CreateGC, xxCreateGC);
+ wrap (pScrPriv, pScreen, CreateColormap, xxCreateColormap);
+ wrap (pScrPriv, pScreen, DestroyColormap, xxDestroyColormap);
+ wrap (pScrPriv, pScreen, InstallColormap, xxInstallColormap);
+ wrap (pScrPriv, pScreen, UninstallColormap, xxUninstallColormap);
+ wrap (pScrPriv, pScreen, ListInstalledColormaps, xxListInstalledColormaps);
+ wrap (pScrPriv, pScreen, StoreColors, xxStoreColors);
+#ifdef RENDER
+ if (ps) {
+ wrap (pScrPriv, ps, Glyphs, xxGlyphs);
+ wrap (pScrPriv, ps, Composite, xxComposite);
+ }
+#endif
+ pScrPriv->addr = addr;
+ pScreen->devPrivates[xxScrPrivateIndex].ptr = (pointer) pScrPriv;
+
+ pDefMap = (ColormapPtr) LookupIDByType(pScreen->defColormap, RT_COLORMAP);
+ if (!xxInitColormapPrivate(pDefMap))
+ return FALSE;
+
+ return TRUE;
+}
+
+GCFuncs xxGCFuncs = {
+ xxValidateGC, xxChangeGC, xxCopyGC, xxDestroyGC,
+ xxChangeClip, xxDestroyClip, xxCopyClip
+};
+
+GCOps xxGCOps = {
+ xxFillSpans, xxSetSpans,
+ xxPutImage, xxCopyArea,
+ xxCopyPlane, xxPolyPoint,
+ xxPolylines, xxPolySegment,
+ xxPolyRectangle, xxPolyArc,
+ xxFillPolygon, xxPolyFillRect,
+ xxPolyFillArc, xxPolyText8,
+ xxPolyText16, xxImageText8,
+ xxImageText16, xxImageGlyphBlt,
+ xxPolyGlyphBlt, xxPushPixels,
+#ifdef NEED_LINEHELPER
+ NULL,
+#endif
+ {NULL} /* devPrivate */
+};
+
+#define IS_VISIBLE(pDraw) (pDraw->type == DRAWABLE_WINDOW \
+ && (fbGetWindowPixmap((WindowPtr) pDraw) == pScrPriv->pPixmap))
+
+#define TRANSLATE_BOX(box, pDraw) { \
+ box.x1 += pDraw->x; \
+ box.x2 += pDraw->x; \
+ box.y1 += pDraw->y; \
+ box.y2 += pDraw->y; \
+ }
+
+#define TRIM_BOX(box, pGC) { \
+ BoxPtr extents = &pGC->pCompositeClip->extents;\
+ if(box.x1 < extents->x1) box.x1 = extents->x1; \
+ if(box.x2 > extents->x2) box.x2 = extents->x2; \
+ if(box.y1 < extents->y1) box.y1 = extents->y1; \
+ if(box.y2 > extents->y2) box.y2 = extents->y2; \
+ }
+
+#define BOX_NOT_EMPTY(box) \
+ (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
+
+
+#define _ADD_BOX(box,pGC) {\
+ if (BOX_NOT_EMPTY(box)) { \
+ RegionRec region; \
+ ScreenPtr pScreen = pGC->pScreen;\
+ REGION_INIT (pScreen, &region, &box, 1); \
+ REGION_INTERSECT(pScreen,&region,&region,\
+ (pGC)->pCompositeClip);\
+ if (REGION_NOTEMPTY(pScreen,&region)) { \
+ xxScrPriv(pScreen);\
+ PRINT_RECTS(pScrPriv->region);\
+ REGION_UNION(pScreen,&pScrPriv->region,&pScrPriv->region,&region);\
+ PRINT_RECTS(pScrPriv->region);\
+ REGION_UNINIT(pScreen,&region);\
+ }\
+ }\
+}
+
+#define TRANSLATE_AND_ADD_BOX(box,pGC) {\
+ TRANSLATE_BOX(box,pDraw); \
+ TRIM_BOX(box,pGC); \
+ _ADD_BOX(box,pGC); \
+}
+
+#define ADD_BOX(box,pGC) { \
+ TRIM_BOX(box,pGC); \
+ _ADD_BOX(box,pGC); \
+}
+
+#define XX_GC_FUNC_PROLOGUE(pGC) \
+ xxGCPriv(pGC); \
+ unwrap(pGCPriv, pGC, funcs); \
+ if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
+
+#define XX_GC_FUNC_EPILOGUE(pGC) \
+ wrap(pGCPriv, pGC, funcs, &xxGCFuncs); \
+ if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &xxGCOps)
+
+static Bool
+xxCreateGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ xxScrPriv(pScreen);
+ xxGCPriv(pGC);
+ Bool ret;
+
+ unwrap (pScrPriv, pScreen, CreateGC);
+ if((ret = (*pScreen->CreateGC) (pGC))) {
+ pGCPriv->ops = NULL;
+ pGCPriv->funcs = pGC->funcs;
+ pGC->funcs = &xxGCFuncs;
+ }
+ wrap (pScrPriv, pScreen, CreateGC, xxCreateGC);
+
+ return ret;
+}
+
+static void
+xxValidateGC(
+ GCPtr pGC,
+ unsigned long changes,
+ DrawablePtr pDraw
+){
+ XX_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
+ if(pDraw->type == DRAWABLE_WINDOW)
+ pGCPriv->ops = pGC->ops; /* just so it's not NULL */
+ else
+ pGCPriv->ops = NULL;
+ XX_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+xxDestroyGC(GCPtr pGC)
+{
+ XX_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->DestroyGC)(pGC);
+ XX_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+xxChangeGC (
+ GCPtr pGC,
+ unsigned long mask
+){
+ XX_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->ChangeGC) (pGC, mask);
+ XX_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+xxCopyGC (
+ GCPtr pGCSrc,
+ unsigned long mask,
+ GCPtr pGCDst
+){
+ XX_GC_FUNC_PROLOGUE (pGCDst);
+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
+ XX_GC_FUNC_EPILOGUE (pGCDst);
+}
+
+static void
+xxChangeClip (
+ GCPtr pGC,
+ int type,
+ pointer pvalue,
+ int nrects
+){
+ XX_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
+ XX_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+xxCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ XX_GC_FUNC_PROLOGUE (pgcDst);
+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
+ XX_GC_FUNC_EPILOGUE (pgcDst);
+}
+
+static void
+xxDestroyClip(GCPtr pGC)
+{
+ XX_GC_FUNC_PROLOGUE (pGC);
+ (* pGC->funcs->DestroyClip)(pGC);
+ XX_GC_FUNC_EPILOGUE (pGC);
+}
+
+#define XX_GC_OP_PROLOGUE(pGC,pDraw) \
+ xxScrPriv(pDraw->pScreen); \
+ xxGCPriv(pGC); \
+ GCFuncs *oldFuncs = pGC->funcs; \
+ unwrap(pGCPriv, pGC, funcs); \
+ unwrap(pGCPriv, pGC, ops); \
+
+#define XX_GC_OP_EPILOGUE(pGC,pDraw) \
+ wrap(pGCPriv, pGC, funcs, oldFuncs); \
+ wrap(pGCPriv, pGC, ops, &xxGCOps)
+
+static void
+xxFillSpans(
+ DrawablePtr pDraw,
+ GC *pGC,
+ int nInit,
+ DDXPointPtr pptInit,
+ int *pwidthInit,
+ int fSorted
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && nInit) {
+ DDXPointPtr ppt = pptInit;
+ int *pwidth = pwidthInit;
+ int i = nInit;
+ BoxRec box;
+
+ DBG("FillSpans\n");
+ box.x1 = ppt->x;
+ box.x2 = box.x1 + *pwidth;
+ box.y2 = box.y1 = ppt->y;
+
+ while(--i) {
+ ppt++;
+ pwidthInit++;
+ if(box.x1 > ppt->x) box.x1 = ppt->x;
+ if(box.x2 < (ppt->x + *pwidth))
+ box.x2 = ppt->x + *pwidth;
+ if(box.y1 > ppt->y) box.y1 = ppt->y;
+ else if(box.y2 < ppt->y) box.y2 = ppt->y;
+ }
+
+ box.y2++;
+
+ (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
+
+
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ } else
+ (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
+
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xxSetSpans(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ char *pcharsrc,
+ DDXPointPtr pptInit,
+ int *pwidthInit,
+ int nspans,
+ int fSorted
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && nspans) {
+ DDXPointPtr ppt = pptInit;
+ int *pwidth = pwidthInit;
+ int i = nspans;
+ BoxRec box;
+
+ DBG("SetSpans\n");
+ box.x1 = ppt->x;
+ box.x2 = box.x1 + *pwidth;
+ box.y2 = box.y1 = ppt->y;
+
+ while(--i) {
+ ppt++;
+ pwidth++;
+ if(box.x1 > ppt->x) box.x1 = ppt->x;
+ if(box.x2 < (ppt->x + *pwidth))
+ box.x2 = ppt->x + *pwidth;
+ if(box.y1 > ppt->y) box.y1 = ppt->y;
+ else if(box.y2 < ppt->y) box.y2 = ppt->y;
+ }
+
+ box.y2++;
+
+ (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit,
+ pwidthInit, nspans, fSorted);
+
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ } else
+ (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit,
+ pwidthInit, nspans, fSorted);
+
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xxPutImage(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int depth,
+ int x, int y, int w, int h,
+ int leftPad,
+ int format,
+ char *pImage
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h,
+ leftPad, format, pImage);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+ if(IS_VISIBLE(pDraw)) {
+ BoxRec box;
+
+ DBG("PutImage\n");
+ box.x1 = x + pDraw->x;
+ box.x2 = box.x1 + w;
+ box.y1 = y + pDraw->y;
+ box.y2 = box.y1 + h;
+
+ ADD_BOX(box, pGC);
+ }
+}
+
+static RegionPtr
+xxCopyArea(
+ DrawablePtr pSrc,
+ DrawablePtr pDst,
+ GC *pGC,
+ int srcx, int srcy,
+ int width, int height,
+ int dstx, int dsty
+){
+ RegionPtr ret;
+ XX_GC_OP_PROLOGUE(pGC, pDst);
+ DBG("xxCopyArea\n");
+ ret = (*pGC->ops->CopyArea)(pSrc, pDst,
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ XX_GC_OP_EPILOGUE(pGC, pDst);
+
+ if(IS_VISIBLE(pDst)) {
+ BoxRec box;
+
+ DBG("CopyArea\n");
+ box.x1 = dstx + pDst->x;
+ box.x2 = box.x1 + width;
+ box.y1 = dsty + pDst->y;
+ box.y2 = box.y1 + height;
+
+ ADD_BOX(box, pGC);
+ }
+
+ return ret;
+}
+
+static RegionPtr
+xxCopyPlane(
+ DrawablePtr pSrc,
+ DrawablePtr pDst,
+ GCPtr pGC,
+ int srcx, int srcy,
+ int width, int height,
+ int dstx, int dsty,
+ unsigned long bitPlane
+){
+ RegionPtr ret;
+ XX_GC_OP_PROLOGUE(pGC, pDst);
+ ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
+ pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
+ XX_GC_OP_EPILOGUE(pGC, pDst);
+
+ if(IS_VISIBLE(pDst)) {
+ BoxRec box;
+
+ DBG("CopyPlane\n");
+ box.x1 = dstx + pDst->x;
+ box.x2 = box.x1 + width;
+ box.y1 = dsty + pDst->y;
+ box.y2 = box.y1 + height;
+
+ ADD_BOX(box, pGC);
+ }
+
+ return ret;
+}
+
+static void
+xxPolyPoint(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int mode,
+ int npt,
+ xPoint *pptInit
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && npt) {
+ BoxRec box;
+
+ DBG("PolyPoint\n");
+ box.x2 = box.x1 = pptInit->x;
+ box.y2 = box.y1 = pptInit->y;
+
+ /* this could be slow if the points were spread out */
+
+ while(--npt) {
+ pptInit++;
+ if(box.x1 > pptInit->x) box.x1 = pptInit->x;
+ else if(box.x2 < pptInit->x) box.x2 = pptInit->x;
+ if(box.y1 > pptInit->y) box.y1 = pptInit->y;
+ else if(box.y2 < pptInit->y) box.y2 = pptInit->y;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ }
+}
+
+static void
+xxPolylines(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int mode,
+ int npt,
+ DDXPointPtr pptInit
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+
+ if(IS_VISIBLE(pDraw) && npt) {
+ BoxRec box;
+ int extra = pGC->lineWidth >> 1;
+
+ DBG("PolyLine\n");
+ box.x2 = box.x1 = pptInit->x;
+ box.y2 = box.y1 = pptInit->y;
+
+ if(npt > 1) {
+ if(pGC->joinStyle == JoinMiter)
+ extra = 6 * pGC->lineWidth;
+ else if(pGC->capStyle == CapProjecting)
+ extra = pGC->lineWidth;
+ }
+
+ if(mode == CoordModePrevious) {
+ int x = box.x1;
+ int y = box.y1;
+ while(--npt) {
+ pptInit++;
+ x += pptInit->x;
+ y += pptInit->y;
+ if(box.x1 > x) box.x1 = x;
+ else if(box.x2 < x) box.x2 = x;
+ if(box.y1 > y) box.y1 = y;
+ else if(box.y2 < y) box.y2 = y;
+ }
+ } else {
+ while(--npt) {
+ pptInit++;
+ if(box.x1 > pptInit->x) box.x1 = pptInit->x;
+ else if(box.x2 < pptInit->x) box.x2 = pptInit->x;
+ if(box.y1 > pptInit->y) box.y1 = pptInit->y;
+ else if(box.y2 < pptInit->y) box.y2 = pptInit->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ }
+}
+
+static void
+xxPolySegment(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int nseg,
+ xSegment *pSeg
+ ){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && nseg) {
+ BoxRec box;
+ int extra = pGC->lineWidth;
+
+ DBG("PolySegment\n");
+ if(pGC->capStyle != CapProjecting)
+ extra >>= 1;
+
+ if(pSeg->x2 > pSeg->x1) {
+ box.x1 = pSeg->x1;
+ box.x2 = pSeg->x2;
+ } else {
+ box.x2 = pSeg->x1;
+ box.x1 = pSeg->x2;
+ }
+
+ if(pSeg->y2 > pSeg->y1) {
+ box.y1 = pSeg->y1;
+ box.y2 = pSeg->y2;
+ } else {
+ box.y2 = pSeg->y1;
+ box.y1 = pSeg->y2;
+ }
+
+ while(--nseg) {
+ pSeg++;
+ if(pSeg->x2 > pSeg->x1) {
+ if(pSeg->x1 < box.x1) box.x1 = pSeg->x1;
+ if(pSeg->x2 > box.x2) box.x2 = pSeg->x2;
+ } else {
+ if(pSeg->x2 < box.x1) box.x1 = pSeg->x2;
+ if(pSeg->x1 > box.x2) box.x2 = pSeg->x1;
+ }
+ if(pSeg->y2 > pSeg->y1) {
+ if(pSeg->y1 < box.y1) box.y1 = pSeg->y1;
+ if(pSeg->y2 > box.y2) box.y2 = pSeg->y2;
+ } else {
+ if(pSeg->y2 < box.y1) box.y1 = pSeg->y2;
+ if(pSeg->y1 > box.y2) box.y2 = pSeg->y1;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ }
+}
+
+static void
+xxPolyRectangle(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int nRects,
+ xRectangle *pRects
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolyRectangle)(pDraw, pGC, nRects, pRects);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && nRects)
+ {
+ BoxRec box;
+ int offset1, offset2, offset3;
+
+ DBG("PolyRectangle\n");
+ offset2 = pGC->lineWidth;
+ if(!offset2) offset2 = 1;
+ offset1 = offset2 >> 1;
+ offset3 = offset2 - offset1;
+
+ while(nRects--)
+ {
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y - offset1;
+ box.x2 = box.x1 + pRects->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRects->height - offset2;
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ box.x1 = pRects->x + pRects->width - offset1;
+ box.y1 = pRects->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRects->height - offset2;
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y + pRects->height - offset1;
+ box.x2 = box.x1 + pRects->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+
+ pRects++;
+ }
+ }
+}
+
+static void
+xxPolyArc(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int narcs,
+ xArc *parcs
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && narcs) {
+ int extra = pGC->lineWidth >> 1;
+ BoxRec box;
+
+ DBG("PolyArc\n");
+ box.x1 = parcs->x;
+ box.x2 = box.x1 + parcs->width;
+ box.y1 = parcs->y;
+ box.y2 = box.y1 + parcs->height;
+
+ /* should I break these up instead ? */
+
+ while(--narcs) {
+ parcs++;
+ if(box.x1 > parcs->x) box.x1 = parcs->x;
+ if(box.x2 < (parcs->x + parcs->width))
+ box.x2 = parcs->x + parcs->width;
+ if(box.y1 > parcs->y) box.y1 = parcs->y;
+ if(box.y2 < (parcs->y + parcs->height))
+ box.y2 = parcs->y + parcs->height;
+ }
+
+ if(extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ }
+}
+
+static void
+xxFillPolygon(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int shape,
+ int mode,
+ int count,
+ DDXPointPtr pptInit
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && (count > 2)) {
+ DDXPointPtr ppt = pptInit;
+ int i = count;
+ BoxRec box;
+
+ DBG("FillPolygon\n");
+ box.x2 = box.x1 = ppt->x;
+ box.y2 = box.y1 = ppt->y;
+
+ if(mode != CoordModeOrigin) {
+ int x = box.x1;
+ int y = box.y1;
+ while(--i) {
+ ppt++;
+ x += ppt->x;
+ y += ppt->y;
+ if(box.x1 > x) box.x1 = x;
+ else if(box.x2 < x) box.x2 = x;
+ if(box.y1 > y) box.y1 = y;
+ else if(box.y2 < y) box.y2 = y;
+ }
+ } else {
+ while(--i) {
+ ppt++;
+ if(box.x1 > ppt->x) box.x1 = ppt->x;
+ else if(box.x2 < ppt->x) box.x2 = ppt->x;
+ if(box.y1 > ppt->y) box.y1 = ppt->y;
+ else if(box.y2 < ppt->y) box.y2 = ppt->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
+
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ } else
+ (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
+
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xxPolyFillRect(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int nRectsInit,
+ xRectangle *pRectsInit
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && nRectsInit) {
+ BoxRec box;
+ xRectangle *pRects = pRectsInit;
+ int nRects = nRectsInit;
+
+ DBG("PolyFillRect\n");
+ box.x1 = pRects->x;
+ box.x2 = box.x1 + pRects->width;
+ box.y1 = pRects->y;
+ box.y2 = box.y1 + pRects->height;
+
+ while(--nRects) {
+ pRects++;
+ if(box.x1 > pRects->x) box.x1 = pRects->x;
+ if(box.x2 < (pRects->x + pRects->width))
+ box.x2 = pRects->x + pRects->width;
+ if(box.y1 > pRects->y) box.y1 = pRects->y;
+ if(box.y2 < (pRects->y + pRects->height))
+ box.y2 = pRects->y + pRects->height;
+ }
+
+ /* cfb messes with the pRectsInit so we have to do our
+ calculations first */
+
+ (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
+
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ } else
+ (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
+
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xxPolyFillArc(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int narcs,
+ xArc *parcs
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && narcs) {
+ BoxRec box;
+
+ DBG("PolyFillArc\n");
+ box.x1 = parcs->x;
+ box.x2 = box.x1 + parcs->width;
+ box.y1 = parcs->y;
+ box.y2 = box.y1 + parcs->height;
+
+ /* should I break these up instead ? */
+
+ while(--narcs) {
+ parcs++;
+ if(box.x1 > parcs->x) box.x1 = parcs->x;
+ if(box.x2 < (parcs->x + parcs->width))
+ box.x2 = parcs->x + parcs->width;
+ if(box.y1 > parcs->y) box.y1 = parcs->y;
+ if(box.y2 < (parcs->y + parcs->height))
+ box.y2 = parcs->y + parcs->height;
+ }
+
+ TRANSLATE_AND_ADD_BOX(box, pGC);
+ }
+}
+
+static int
+xxPolyText8(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ char *chars
+){
+ int width;
+
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ width = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ width -= x;
+
+ if(IS_VISIBLE(pDraw) && (width > 0)) {
+ BoxRec box;
+
+ DBG("PolyText8\n");
+ /* ugh */
+ box.x1 = pDraw->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = pDraw->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ if(count > 1) {
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ ADD_BOX(box, pGC);
+ }
+
+ return (width + x);
+}
+
+static int
+xxPolyText16(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ unsigned short *chars
+){
+ int width;
+
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ width = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ width -= x;
+
+ if(IS_VISIBLE(pDraw) && (width > 0)) {
+ BoxRec box;
+
+ DBG("PolyText16\n");
+ /* ugh */
+ box.x1 = pDraw->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = pDraw->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ if(count > 1) {
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ ADD_BOX(box, pGC);
+ }
+
+ return (width + x);
+}
+
+static void
+xxImageText8(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ char *chars
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && count) {
+ int top, bot, Min, Max;
+ BoxRec box;
+
+ DBG("ImageText8\n");
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+ if(Min > 0) Min = 0;
+ Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
+ if(Max < 0) Max = 0;
+
+ /* ugh */
+ box.x1 = pDraw->x + x + Min +
+ FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = pDraw->x + x + Max +
+ FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ box.y1 = pDraw->y + y - top;
+ box.y2 = pDraw->y + y + bot;
+
+ ADD_BOX(box, pGC);
+ }
+}
+
+static void
+xxImageText16(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ unsigned short *chars
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && count) {
+ int top, bot, Min, Max;
+ BoxRec box;
+
+ DBG("ImageText16\n");
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+ if(Min > 0) Min = 0;
+ Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
+ if(Max < 0) Max = 0;
+
+ /* ugh */
+ box.x1 = pDraw->x + x + Min +
+ FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = pDraw->x + x + Max +
+ FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ box.y1 = pDraw->y + y - top;
+ box.y2 = pDraw->y + y + bot;
+
+ ADD_BOX(box, pGC);
+ }
+}
+
+static void
+xxImageGlyphBlt(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, nglyph,
+ ppci, pglyphBase);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && nglyph) {
+ int top, bot, width = 0;
+ BoxRec box;
+
+ DBG("ImageGlyphBlt\n");
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ box.x1 = ppci[0]->metrics.leftSideBearing;
+ if(box.x1 > 0) box.x1 = 0;
+ box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing -
+ ppci[nglyph - 1]->metrics.characterWidth;
+ if(box.x2 < 0) box.x2 = 0;
+
+ box.x2 += pDraw->x + x;
+ box.x1 += pDraw->x + x;
+
+ while(nglyph--) {
+ width += (*ppci)->metrics.characterWidth;
+ ppci++;
+ }
+
+ if(width > 0)
+ box.x2 += width;
+ else
+ box.x1 += width;
+
+ box.y1 = pDraw->y + y - top;
+ box.y2 = pDraw->y + y + bot;
+
+ ADD_BOX(box, pGC);
+ }
+}
+
+static void
+xxPolyGlyphBlt(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, nglyph,
+ ppci, pglyphBase);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw) && nglyph) {
+ BoxRec box;
+
+ DBG("PolyGlyphBlt\n");
+ /* ugh */
+ box.x1 = pDraw->x + x + ppci[0]->metrics.leftSideBearing;
+ box.x2 = pDraw->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
+
+ if(nglyph > 1) {
+ int width = 0;
+
+ while(--nglyph) {
+ width += (*ppci)->metrics.characterWidth;
+ ppci++;
+ }
+
+ if(width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ ADD_BOX(box, pGC);
+ }
+}
+
+static void
+xxPushPixels(
+ GCPtr pGC,
+ PixmapPtr pBitMap,
+ DrawablePtr pDraw,
+ int dx, int dy, int xOrg, int yOrg
+){
+ XX_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg);
+ XX_GC_OP_EPILOGUE(pGC, pDraw);
+
+ if(IS_VISIBLE(pDraw)) {
+ BoxRec box;
+
+ DBG("PushPixels\n");
+ box.x1 = xOrg + pDraw->x;
+ box.x2 = box.x1 + dx;
+ box.y1 = yOrg + pDraw->y;
+ box.y2 = box.y1 + dy;
+
+ ADD_BOX(box, pGC);
+ }
+}
+
+
+#ifdef RENDER
+#define RENDER_MAKE_BOX(pDrawable,X,Y,W,H) { \
+ box.x1 = X + pDrawable->x; \
+ box.x2 = X + pDrawable->x + W; \
+ box.y1 = Y + pDrawable->y; \
+ box.y2 = Y + pDrawable->y + H; \
+}
+
+#define RENDER_ADD_BOX(pScreen,box) {\
+ if (BOX_NOT_EMPTY(box)) { \
+ RegionRec region; \
+ xxScrPriv(pScreen);\
+ ScreenPtr pScreen = pScreen;\
+ REGION_INIT (pScreen, &region, &box, 1); \
+ PRINT_RECTS(pScrPriv->region);\
+ REGION_UNION(pScreen,&pScrPriv->region,&pScrPriv->region,&region);\
+ PRINT_RECTS(pScrPriv->region);\
+ REGION_UNINIT(pScreen,&region);\
+ }\
+}
+
+static void
+xxComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ xxScrPriv(pScreen);
+ BoxRec box;
+
+ unwrap (pScrPriv, ps, Composite);
+ (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height);
+ wrap (pScrPriv, ps, Composite, xxComposite);
+ if (pDst->pDrawable->type == DRAWABLE_WINDOW) {
+ RENDER_MAKE_BOX(pDst->pDrawable, xDst, yDst, width, height);
+ RENDER_ADD_BOX(pScreen,box);
+ }
+}
+
+
+static void
+xxGlyphs (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist,
+ GlyphListPtr list, GlyphPtr *glyphs)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ xxScrPriv(pScreen);
+ int x, y;
+ int n;
+ GlyphPtr glyph;
+ BoxRec box;
+
+ unwrap (pScrPriv, ps, Glyphs);
+ (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc,
+ nlist, list, glyphs);
+ wrap (pScrPriv, ps, Glyphs, xxGlyphs);
+ if (pDst->pDrawable->type == DRAWABLE_WINDOW)
+ {
+ x = xSrc;
+ y = ySrc;
+ while (nlist--)
+ {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ while (n--)
+ {
+ glyph = *glyphs++;
+ RENDER_MAKE_BOX(pDst->pDrawable,
+ x - glyph->info.x, y - glyph->info.y,
+ glyph->info.width, glyph->info.height);
+ RENDER_ADD_BOX(pScreen,box);
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ list++;
+ }
+ }
+}
+#endif
+
+void
+xxPrintVisuals(void)
+{
+ int k,i,j;
+ DepthPtr pDepth;
+ VisualPtr pVisual;
+
+ for (k = 0; k < screenInfo.numScreens; k++) {
+ ScreenPtr pScreen = screenInfo.screens[k];
+
+ pDepth = pScreen->allowedDepths;
+ for (i = 0; i < pScreen->numDepths; i++, pDepth++)
+ for (j = 0; j < pDepth->numVids; j++) {
+ ErrorF("depth: %i vid: 0x%lx\n",
+ pDepth->depth, pDepth->vids[j]);
+ }
+
+ pVisual = pScreen->visuals;
+ for (i = 0; i < pScreen->numVisuals; i++, pVisual++)
+ ErrorF("vid: 0x%x rm: 0x%lx gm: 0x%lx bm: 0x%lx\n",
+ (unsigned int)pVisual->vid,
+ pVisual->redMask,
+ pVisual->greenMask,
+ pVisual->blueMask);
+ }
+}
+
+
diff --git a/fb/fbpseudocolor.h b/fb/fbpseudocolor.h
new file mode 100644
index 000000000..64de71db8
--- /dev/null
+++ b/fb/fbpseudocolor.h
@@ -0,0 +1,20 @@
+#ifndef _FB_XX_H_
+# define _FB_XX_H_
+
+typedef void (*xxSyncFunc)(ScreenPtr);
+extern Bool xxSetup(ScreenPtr pScreen, int myDepth,
+ int baseDepth, char *addr, xxSyncFunc sync);
+extern void xxPrintVisuals(void);
+
+
+#endif /* _FB_XX_H_ */
+
+
+
+
+
+
+
+
+
+
diff --git a/hw/darwin/darwinXinput.c b/hw/darwin/darwinXinput.c
new file mode 100644
index 000000000..aab10981c
--- /dev/null
+++ b/hw/darwin/darwinXinput.c
@@ -0,0 +1,310 @@
+/* $Xorg: stubs.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */
+
+/*
+ * X server support of the XINPUT extension for Darwin
+ *
+ * This is currently a copy of mi/stubs.c, but eventually this
+ * should include more complete XINPUT support.
+ */
+
+/************************************************************
+
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 THE
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
+
+ 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 name of Hewlett-Packard not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+HEWLETT-PACKARD 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.
+
+********************************************************/
+/* $XFree86: xc/programs/Xserver/hw/darwin/darwinXinput.c,v 1.1 2004/05/28 07:44:00 torrey Exp $ */
+
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "inputstr.h"
+#include "XI.h"
+#include "XIproto.h"
+#include "XIstubs.h"
+
+/***********************************************************************
+ *
+ * Caller: ProcXChangeKeyboardDevice
+ *
+ * This procedure does the implementation-dependent portion of the work
+ * needed to change the keyboard device.
+ *
+ * The X keyboard device has a FocusRec. If the device that has been
+ * made into the new X keyboard did not have a FocusRec,
+ * ProcXChangeKeyboardDevice will allocate one for it.
+ *
+ * If you do not want clients to be able to focus the old X keyboard
+ * device, call DeleteFocusClassDeviceStruct to free the FocusRec.
+ *
+ * If you support input devices with keys that you do not want to be
+ * used as the X keyboard, you need to check for them here and return
+ * a BadDevice error.
+ *
+ * The default implementation is to do nothing (assume you do want
+ * clients to be able to focus the old X keyboard). The commented-out
+ * sample code shows what you might do if you don't want the default.
+ *
+ */
+
+int
+ChangeKeyboardDevice (old_dev, new_dev)
+ DeviceIntPtr old_dev;
+ DeviceIntPtr new_dev;
+ {
+ /***********************************************************************
+ DeleteFocusClassDeviceStruct(old_dev); * defined in xchgptr.c *
+ **********************************************************************/
+ return BadMatch;
+ }
+
+
+/***********************************************************************
+ *
+ * Caller: ProcXChangePointerDevice
+ *
+ * This procedure does the implementation-dependent portion of the work
+ * needed to change the pointer device.
+ *
+ * The X pointer device does not have a FocusRec. If the device that
+ * has been made into the new X pointer had a FocusRec,
+ * ProcXChangePointerDevice will free it.
+ *
+ * If you want clients to be able to focus the old pointer device that
+ * has now become accessible through the input extension, you need to
+ * add a FocusRec to it here.
+ *
+ * The XChangePointerDevice protocol request also allows the client
+ * to choose which axes of the new pointer device are used to move
+ * the X cursor in the X- and Y- directions. If the axes are different
+ * than the default ones, you need to keep track of that here.
+ *
+ * If you support input devices with valuators that you do not want to be
+ * used as the X pointer, you need to check for them here and return a
+ * BadDevice error.
+ *
+ * The default implementation is to do nothing (assume you don't want
+ * clients to be able to focus the old X pointer). The commented-out
+ * sample code shows what you might do if you don't want the default.
+ *
+ */
+
+int
+ChangePointerDevice (
+ DeviceIntPtr old_dev,
+ DeviceIntPtr new_dev,
+ unsigned char x,
+ unsigned char y)
+ {
+ /***********************************************************************
+ InitFocusClassDeviceStruct(old_dev); * allow focusing old ptr*
+
+ x_axis = x; * keep track of new x-axis*
+ y_axis = y; * keep track of new y-axis*
+ if (x_axis != 0 || y_axis != 1)
+ axes_changed = TRUE; * remember axes have changed*
+ else
+ axes_changed = FALSE;
+ *************************************************************************/
+ return BadMatch;
+ }
+
+/***********************************************************************
+ *
+ * Caller: ProcXCloseDevice
+ *
+ * Take care of implementation-dependent details of closing a device.
+ * Some implementations may actually close the device, others may just
+ * remove this clients interest in that device.
+ *
+ * The default implementation is to do nothing (assume all input devices
+ * are initialized during X server initialization and kept open).
+ *
+ */
+
+void
+CloseInputDevice (d, client)
+ DeviceIntPtr d;
+ ClientPtr client;
+ {
+ }
+
+/***********************************************************************
+ *
+ * Caller: ProcXListInputDevices
+ *
+ * This is the implementation-dependent routine to initialize an input
+ * device to the point that information about it can be listed.
+ * Some implementations open all input devices when the server is first
+ * initialized, and never close them. Other implementations open only
+ * the X pointer and keyboard devices during server initialization,
+ * and only open other input devices when some client makes an
+ * XOpenDevice request. If some other process has the device open, the
+ * server may not be able to get information about the device to list it.
+ *
+ * This procedure should be used by implementations that do not initialize
+ * all input devices at server startup. It should do device-dependent
+ * initialization for any devices not previously initialized, and call
+ * AddInputDevice for each of those devices so that a DeviceIntRec will be
+ * created for them.
+ *
+ * The default implementation is to do nothing (assume all input devices
+ * are initialized during X server initialization and kept open).
+ * The commented-out sample code shows what you might do if you don't want
+ * the default.
+ *
+ */
+
+void
+AddOtherInputDevices ()
+ {
+ /**********************************************************************
+ for each uninitialized device, do something like:
+
+ DeviceIntPtr dev;
+ DeviceProc deviceProc;
+ pointer private;
+
+ dev = (DeviceIntPtr) AddInputDevice(deviceProc, TRUE);
+ dev->public.devicePrivate = private;
+ RegisterOtherDevice(dev);
+ dev->inited = ((*dev->deviceProc)(dev, DEVICE_INIT) == Success);
+ ************************************************************************/
+
+ }
+
+/***********************************************************************
+ *
+ * Caller: ProcXOpenDevice
+ *
+ * This is the implementation-dependent routine to open an input device.
+ * Some implementations open all input devices when the server is first
+ * initialized, and never close them. Other implementations open only
+ * the X pointer and keyboard devices during server initialization,
+ * and only open other input devices when some client makes an
+ * XOpenDevice request. This entry point is for the latter type of
+ * implementation.
+ *
+ * If the physical device is not already open, do it here. In this case,
+ * you need to keep track of the fact that one or more clients has the
+ * device open, and physically close it when the last client that has
+ * it open does an XCloseDevice.
+ *
+ * The default implementation is to do nothing (assume all input devices
+ * are opened during X server initialization and kept open).
+ *
+ */
+
+void
+OpenInputDevice (dev, client, status)
+ DeviceIntPtr dev;
+ ClientPtr client;
+ int *status;
+ {
+ }
+
+/****************************************************************************
+ *
+ * Caller: ProcXSetDeviceMode
+ *
+ * Change the mode of an extension device.
+ * This function is used to change the mode of a device from reporting
+ * relative motion to reporting absolute positional information, and
+ * vice versa.
+ * The default implementation below is that no such devices are supported.
+ *
+ */
+
+int
+SetDeviceMode (client, dev, mode)
+ register ClientPtr client;
+ DeviceIntPtr dev;
+ int mode;
+ {
+ return BadMatch;
+ }
+
+/****************************************************************************
+ *
+ * Caller: ProcXSetDeviceValuators
+ *
+ * Set the value of valuators on an extension input device.
+ * This function is used to set the initial value of valuators on
+ * those input devices that are capable of reporting either relative
+ * motion or an absolute position, and allow an initial position to be set.
+ * The default implementation below is that no such devices are supported.
+ *
+ */
+
+int
+SetDeviceValuators (client, dev, valuators, first_valuator, num_valuators)
+ register ClientPtr client;
+ DeviceIntPtr dev;
+ int *valuators;
+ int first_valuator;
+ int num_valuators;
+ {
+ return BadMatch;
+ }
+
+/****************************************************************************
+ *
+ * Caller: ProcXChangeDeviceControl
+ *
+ * Change the specified device controls on an extension input device.
+ *
+ */
+
+int
+ChangeDeviceControl (client, dev, control)
+ register ClientPtr client;
+ DeviceIntPtr dev;
+ xDeviceCtl *control;
+ {
+ switch (control->control)
+ {
+ case DEVICE_RESOLUTION:
+ return (BadMatch);
+ default:
+ return (BadMatch);
+ }
+ }
diff --git a/hw/dmx/dmx.h b/hw/dmx/dmx.h
new file mode 100644
index 000000000..18e75de90
--- /dev/null
+++ b/hw/dmx/dmx.h
@@ -0,0 +1,374 @@
+/* $XFree86$ */
+/*
+ * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <kem@redhat.com>
+ * David H. Dawes <dawes@xfree86.org>
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ * Main header file included by all other DMX-related files.
+ */
+
+/** \mainpage
+ * - <a href="http://dmx.sourceforge.net">DMX Home Page</a>
+ * - <a href="http://sourceforge.net/projects/dmx">DMX Project Page (on
+ * Source Forge)</a>
+ * - <a href="http://dmx.sourceforge.net/dmx.html">Distributed Multihead
+ * X design</a>, the design document for DMX
+ * - <a href="http://dmx.sourceforge.net/DMXSpec.txt">Client-to-Server
+ * DMX Extension to the X Protocol</a>
+ */
+
+#ifndef DMX_H
+#define DMX_H
+
+#include "gcstruct.h"
+
+/* Handle client-side include files in one place. */
+#include "dmxclient.h"
+
+#include "globals.h"
+#include "scrnintstr.h"
+
+#ifdef RENDER
+#include "picturestr.h"
+#endif
+
+#ifdef GLXEXT
+#include <GL/glx.h>
+#include <GL/glxint.h>
+#endif
+
+typedef enum {
+ PosNone = -1,
+ PosAbsolute = 0,
+ PosRightOf,
+ PosLeftOf,
+ PosAbove,
+ PosBelow,
+ PosRelative
+} PositionType;
+
+/** Provide the typedef globally, but keep the contents opaque outside
+ * of the input routines. \see dmxinput.h */
+typedef struct _DMXInputInfo DMXInputInfo;
+
+/** Provide the typedef globally, but keep the contents opaque outside
+ * of the XSync statistic routines. \see dmxstat.c */
+typedef struct _DMXStatInfo DMXStatInfo;
+
+/** Global structure containing information about each backend screen. */
+typedef struct _DMXScreenInfo {
+ const char *name; /**< Name from command line or config file */
+ int index; /**< Index into dmxScreens global */
+
+ /*---------- Back-end X server information ----------*/
+
+ Display *beDisplay; /**< Back-end X server's display */
+ int beWidth; /**< Width of BE display */
+ int beHeight; /**< Height of BE display */
+ int beDepth; /**< Depth of BE display */
+ int beBPP; /**< Bits per pixel of BE display */
+ int beXDPI; /**< Horizontal dots per inch of BE */
+ int beYDPI; /**< Vertical dots per inch of BE */
+
+ int beNumDepths; /**< Number of depths on BE server */
+ int *beDepths; /**< Depths from BE server */
+
+ int beNumPixmapFormats; /**< Number of pixmap formats on BE */
+ XPixmapFormatValues *bePixmapFormats; /**< Pixmap formats on BE */
+
+ int beNumVisuals; /**< Number of visuals on BE */
+ XVisualInfo *beVisuals; /**< Visuals from BE server */
+ int beDefVisualIndex; /**< Default visual index of BE */
+
+ int beNumDefColormaps; /**< Number of default colormaps */
+ Colormap *beDefColormaps; /**< Default colormaps for DMX server */
+
+ Pixel beBlackPixel; /**< Default black pixel for BE */
+ Pixel beWhitePixel; /**< Default white pixel for BE */
+
+ /*---------- Screen window information ----------*/
+
+ Window scrnWin; /**< "Screen" window on backend display */
+ int scrnX; /**< X offset of "screen" WRT BE display */
+ int scrnY; /**< Y offset of "screen" WRT BE display */
+ int scrnWidth; /**< Width of "screen" */
+ int scrnHeight; /**< Height of "screen" */
+ int scrnXSign; /**< X offset sign of "screen" */
+ int scrnYSign; /**< Y offset sign of "screen" */
+
+ /** Default drawables for "screen" */
+ Drawable scrnDefDrawables[MAXFORMATS];
+
+ struct _DMXScreenInfo *next; /**< List of "screens" on same display */
+ struct _DMXScreenInfo *over; /**< List of "screens" that overlap */
+
+ /*---------- Root window information ----------*/
+
+ Window rootWin; /**< "Root" window on backend display */
+ int rootX; /**< X offset of "root" window WRT "screen"*/
+ int rootY; /**< Y offset of "root" window WRT "screen"*/
+ int rootWidth; /**< Width of "root" window */
+ int rootHeight; /**< Height of "root" window */
+
+ int rootXOrigin; /**< Global X origin of "root" window */
+ int rootYOrigin; /**< Global Y origin of "root" window */
+
+ /*---------- Shadow framebuffer information ----------*/
+
+ void *shadow; /**< Shadow framebuffer data (if enabled) */
+ XlibGC shadowGC; /**< Default GC used by shadow FB code */
+ XImage *shadowFBImage; /**< Screen image used by shadow FB code */
+
+ /*---------- Other related information ----------*/
+
+ int shared; /**< Non-zero if another Xdmx is running */
+
+ Bool WMRunningOnBE;
+
+ Cursor noCursor;
+ Cursor curCursor;
+ /* Support for cursors on overlapped
+ * backend displays. */
+ CursorPtr cursor;
+ int cursorVisible;
+ int cursorNotShared; /* for overlapping screens on a backend */
+
+ PositionType where; /**< Relative layout information */
+ int whereX; /**< Relative layout information */
+ int whereY; /**< Relative layout information */
+ int whereRefScreen; /**< Relative layout information */
+
+ int savedTimeout; /**< Original screen saver timeout */
+ int dpmsCapable; /**< Non-zero if backend is DPMS capable */
+ int dpmsEnabled; /**< Non-zero if DPMS enabled */
+ int dpmsStandby; /**< Original DPMS standby value */
+ int dpmsSuspend; /**< Original DPMS suspend value */
+ int dpmsOff; /**< Original DPMS off value */
+
+ DMXStatInfo *stat; /**< Statistics about XSync */
+ Bool needsSync; /**< True if an XSync is pending */
+
+#ifdef GLXEXT
+ /** Visual information for glxProxy */
+ int numGlxVisuals;
+ __GLXvisualConfig *glxVisuals;
+ int glxMajorOpcode;
+ int glxErrorBase;
+
+ /** FB config information for glxProxy */
+ __GLXFBConfig *fbconfigs;
+ int numFBConfigs;
+#endif
+
+ /** Function pointers to wrapped screen
+ * functions */
+ CloseScreenProcPtr CloseScreen;
+ SaveScreenProcPtr SaveScreen;
+
+ CreateGCProcPtr CreateGC;
+
+ CreateWindowProcPtr CreateWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ PositionWindowProcPtr PositionWindow;
+ ChangeWindowAttributesProcPtr ChangeWindowAttributes;
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ RestackWindowProcPtr RestackWindow;
+ WindowExposuresProcPtr WindowExposures;
+ PaintWindowBackgroundProcPtr PaintWindowBackground;
+ PaintWindowBorderProcPtr PaintWindowBorder;
+ CopyWindowProcPtr CopyWindow;
+
+ ResizeWindowProcPtr ResizeWindow;
+ ReparentWindowProcPtr ReparentWindow;
+
+ ChangeBorderWidthProcPtr ChangeBorderWidth;
+
+ GetImageProcPtr GetImage;
+ GetSpansProcPtr GetSpans;
+
+ CreatePixmapProcPtr CreatePixmap;
+ DestroyPixmapProcPtr DestroyPixmap;
+ BitmapToRegionProcPtr BitmapToRegion;
+
+ RealizeFontProcPtr RealizeFont;
+ UnrealizeFontProcPtr UnrealizeFont;
+
+ CreateColormapProcPtr CreateColormap;
+ DestroyColormapProcPtr DestroyColormap;
+ InstallColormapProcPtr InstallColormap;
+ StoreColorsProcPtr StoreColors;
+
+#ifdef SHAPE
+ SetShapeProcPtr SetShape;
+#endif
+
+#ifdef RENDER
+ CreatePictureProcPtr CreatePicture;
+ DestroyPictureProcPtr DestroyPicture;
+ ChangePictureClipProcPtr ChangePictureClip;
+ DestroyPictureClipProcPtr DestroyPictureClip;
+
+ ChangePictureProcPtr ChangePicture;
+ ValidatePictureProcPtr ValidatePicture;
+
+ CompositeProcPtr Composite;
+ GlyphsProcPtr Glyphs;
+ CompositeRectsProcPtr CompositeRects;
+
+ InitIndexedProcPtr InitIndexed;
+ CloseIndexedProcPtr CloseIndexed;
+ UpdateIndexedProcPtr UpdateIndexed;
+
+ TrapezoidsProcPtr Trapezoids;
+ TrianglesProcPtr Triangles;
+ TriStripProcPtr TriStrip;
+ TriFanProcPtr TriFan;
+#endif
+} DMXScreenInfo;
+
+/* Global variables available to all Xserver/hw/dmx routines. */
+extern int dmxNumScreens; /**< Number of dmxScreens */
+extern DMXScreenInfo *dmxScreens; /**< List of outputs */
+extern int dmxShadowFB; /**< Non-zero if using
+ * shadow frame-buffer
+ * (deprecated) */
+extern XErrorEvent dmxLastErrorEvent; /**< Last error that
+ * occurred */
+extern Bool dmxErrorOccurred; /**< True if an error
+ * occurred */
+extern Bool dmxOffScreenOpt; /**< True if using off
+ * screen
+ * optimizations */
+extern Bool dmxSubdividePrimitives; /**< True if using the
+ * primitive subdivision
+ * optimization */
+extern Bool dmxLazyWindowCreation; /**< True if using the
+ * lazy window creation
+ * optimization */
+extern Bool dmxUseXKB; /**< True if the XKB
+ * extension should be
+ * used with the backend
+ * servers */
+extern int dmxDepth; /**< Requested depth if
+ * non-zero */
+#ifdef GLXEXT
+extern Bool dmxGLXProxy; /**< True if glxProxy
+ * support is enabled */
+extern Bool dmxGLXSwapGroupSupport; /**< True if glxProxy
+ * support for swap
+ * groups and barriers
+ * is enabled */
+extern Bool dmxGLXSyncSwap; /**< True if glxProxy
+ * should force an XSync
+ * request after each
+ * swap buffers call */
+extern Bool dmxGLXFinishSwap; /**< True if glxProxy
+ * should force a
+ * glFinish request
+ * after each swap
+ * buffers call */
+#endif
+extern char *dmxFontPath; /**< NULL if no font
+ * path is set on the
+ * command line;
+ * otherwise, a string
+ * of comma separated
+ * paths built from the
+ * command line
+ * specified font
+ * paths */
+extern Bool dmxIgnoreBadFontPaths; /**< True if bad font
+ * paths should be
+ * ignored during server
+ * init */
+extern Bool dmxAddRemoveScreens; /**< True if add and
+ * remove screens support
+ * is enabled */
+
+/** Wrap screen or GC function pointer */
+#define DMX_WRAP(_entry, _newfunc, _saved, _actual) \
+do { \
+ (_saved)->_entry = (_actual)->_entry; \
+ (_actual)->_entry = (_newfunc); \
+} while (0)
+
+/** Unwrap screen or GC function pointer */
+#define DMX_UNWRAP(_entry, _saved, _actual) \
+do { \
+ (_actual)->_entry = (_saved)->_entry; \
+} while (0)
+
+/* Define the MAXSCREENSALLOC/FREE macros, when MAXSCREENS patch has not
+ * been applied to sources. */
+#ifdef MAXSCREENS
+#define MAXSCREEN_MAKECONSTSTR1(x) #x
+#define MAXSCREEN_MAKECONSTSTR2(x) MAXSCREEN_MAKECONSTSTR1(x)
+
+#define MAXSCREEN_FAILED_TXT "Failed at [" \
+ MAXSCREEN_MAKECONSTSTR2(__LINE__) ":" __FILE__ "] to allocate object: "
+
+#define _MAXSCREENSALLOCF(o,size,fatal) \
+ do { \
+ if (!o) { \
+ o = xalloc((size) * sizeof(*(o))); \
+ if (o) memset(o, 0, (size) * sizeof(*(o))); \
+ if (!o && fatal) FatalError(MAXSCREEN_FAILED_TXT #o); \
+ } \
+ } while (0)
+#define _MAXSCREENSALLOCR(o,size,retval) \
+ do { \
+ if (!o) { \
+ o = xalloc((size) * sizeof(*(o))); \
+ if (o) memset(o, 0, (size) * sizeof(*(o))); \
+ if (!o) return retval; \
+ } \
+ } while (0)
+
+#define MAXSCREENSFREE(o) \
+ do { \
+ if (o) xfree(o); \
+ o = NULL; \
+ } while (0)
+
+#define MAXSCREENSALLOC(o) _MAXSCREENSALLOCF(o,MAXSCREENS, 0)
+#define MAXSCREENSALLOC_FATAL(o) _MAXSCREENSALLOCF(o,MAXSCREENS, 1)
+#define MAXSCREENSALLOC_RETURN(o,r) _MAXSCREENSALLOCR(o,MAXSCREENS, (r))
+#define MAXSCREENSALLOCPLUSONE(o) _MAXSCREENSALLOCF(o,MAXSCREENS+1,0)
+#define MAXSCREENSALLOCPLUSONE_FATAL(o) _MAXSCREENSALLOCF(o,MAXSCREENS+1,1)
+#define MAXSCREENSCALLOC(o,m) _MAXSCREENSALLOCF(o,MAXSCREENS*(m),0)
+#define MAXSCREENSCALLOC_FATAL(o,m) _MAXSCREENSALLOCF(o,MAXSCREENS*(m),1)
+#endif
+
+#endif /* DMX_H */
diff --git a/hw/dmx/dmxextension.c b/hw/dmx/dmxextension.c
new file mode 100644
index 000000000..92de9815a
--- /dev/null
+++ b/hw/dmx/dmxextension.c
@@ -0,0 +1,1493 @@
+/* $XFree86$ */
+/*
+ * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Author:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ * Kevin E. Martin <kem@redhat.com>
+ *
+ */
+
+/** \file
+ * This file provides the only interface to the X server extension support
+ * in programs/Xserver/Xext. Those programs should only include dmxext.h
+ */
+
+#include "dmx.h"
+#include "dmxinit.h"
+#include "dmxextension.h"
+#include "dmxwindow.h"
+#include "dmxcb.h"
+#include "dmxcursor.h"
+#include "dmxpixmap.h"
+#include "dmxgc.h"
+#include "dmxfont.h"
+#include "dmxcmap.h"
+#ifdef RENDER
+#include "dmxpict.h"
+#endif
+#include "dmxinput.h"
+#include "dmxsync.h"
+#include "dmxscrinit.h"
+#include "input/dmxinputinit.h"
+
+#include "windowstr.h"
+#include "inputstr.h" /* For DeviceIntRec */
+#include "dmxproto.h" /* For DMX_BAD_* */
+#include "cursorstr.h"
+
+/* The default font is declared in dix/globals.c, but is not included in
+ * _any_ header files. */
+extern FontPtr defaultFont;
+
+/** This routine provides information to the DMX protocol extension
+ * about a particular screen. */
+Bool dmxGetScreenAttributes(int physical, DMXScreenAttributesPtr attr)
+{
+ DMXScreenInfo *dmxScreen;
+
+ if (physical < 0 || physical >= dmxNumScreens) return FALSE;
+
+ dmxScreen = &dmxScreens[physical];
+ attr->displayName = dmxScreen->name;
+#ifdef PANORAMIX
+ attr->logicalScreen = noPanoramiXExtension ? dmxScreen->index : 0;
+#else
+ attr->logicalScreen = dmxScreen->index;
+#endif
+
+ attr->screenWindowWidth = dmxScreen->scrnWidth;
+ attr->screenWindowHeight = dmxScreen->scrnHeight;
+ attr->screenWindowXoffset = dmxScreen->scrnX;
+ attr->screenWindowYoffset = dmxScreen->scrnY;
+
+ attr->rootWindowWidth = dmxScreen->rootWidth;
+ attr->rootWindowHeight = dmxScreen->rootHeight;
+ attr->rootWindowXoffset = dmxScreen->rootX;
+ attr->rootWindowYoffset = dmxScreen->rootY;
+
+ attr->rootWindowXorigin = dmxScreen->rootXOrigin;
+ attr->rootWindowYorigin = dmxScreen->rootYOrigin;
+
+ return TRUE;
+}
+
+/** This routine provides information to the DMX protocol extension
+ * about a particular window. */
+Bool dmxGetWindowAttributes(WindowPtr pWindow, DMXWindowAttributesPtr attr)
+{
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+
+ attr->screen = pWindow->drawable.pScreen->myNum;
+ attr->window = pWinPriv->window;
+
+ attr->pos.x = pWindow->drawable.x;
+ attr->pos.y = pWindow->drawable.y;
+ attr->pos.width = pWindow->drawable.width;
+ attr->pos.height = pWindow->drawable.height;
+
+ if (!pWinPriv->window || pWinPriv->offscreen) {
+ attr->vis.x = 0;
+ attr->vis.y = 0;
+ attr->vis.height = 0;
+ attr->vis.width = 0;
+ return pWinPriv->window ? TRUE : FALSE;
+ }
+
+ /* Compute display-relative coordinates */
+ attr->vis.x = pWindow->drawable.x;
+ attr->vis.y = pWindow->drawable.y;
+ attr->vis.width = pWindow->drawable.width;
+ attr->vis.height = pWindow->drawable.height;
+
+ if (attr->pos.x < 0) {
+ attr->vis.x -= attr->pos.x;
+ attr->vis.width = attr->pos.x + attr->pos.width - attr->vis.x;
+ }
+ if (attr->pos.x + attr->pos.width > pWindow->drawable.pScreen->width) {
+ if (attr->pos.x < 0)
+ attr->vis.width = pWindow->drawable.pScreen->width;
+ else
+ attr->vis.width = pWindow->drawable.pScreen->width - attr->pos.x;
+ }
+ if (attr->pos.y < 0) {
+ attr->vis.y -= attr->pos.y;
+ attr->vis.height = attr->pos.y + attr->pos.height - attr->vis.y;
+ }
+ if (attr->pos.y + attr->pos.height > pWindow->drawable.pScreen->height) {
+ if (attr->pos.y < 0)
+ attr->vis.height = pWindow->drawable.pScreen->height;
+ else
+ attr->vis.height = pWindow->drawable.pScreen->height - attr->pos.y;
+ }
+
+ /* Convert to window-relative coordinates */
+ attr->vis.x -= attr->pos.x;
+ attr->vis.y -= attr->pos.y;
+
+ return TRUE;
+}
+
+void dmxGetDesktopAttributes(DMXDesktopAttributesPtr attr)
+{
+ attr->width = dmxGlobalWidth;
+ attr->height = dmxGlobalHeight;
+ attr->shiftX = 0; /* NOTE: The upper left hand corner of */
+ attr->shiftY = 0; /* the desktop is always <0,0>. */
+}
+
+/** Return the total number of devices, not just #dmxNumInputs. The
+ * number returned should be the same as that returned by
+ * XListInputDevices. */
+int dmxGetInputCount(void)
+{
+ int i, total;
+
+ for (total = i = 0; i < dmxNumInputs; i++) total += dmxInputs[i].numDevs;
+ return total;
+}
+
+/** Return information about the device with id = \a deviceId. This
+ * information is primarily for the #ProcDMXGetInputAttributes()
+ * function, which does not have access to the appropriate data
+ * structure. */
+int dmxGetInputAttributes(int deviceId, DMXInputAttributesPtr attr)
+{
+ int i, j;
+ DMXInputInfo *dmxInput;
+
+ if (deviceId < 0) return -1;
+ for (i = 0; i < dmxNumInputs; i++) {
+ dmxInput = &dmxInputs[i];
+ for (j = 0; j < dmxInput->numDevs; j++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
+ if (deviceId != dmxLocal->pDevice->id) continue;
+ attr->isCore = !!dmxLocal->isCore;
+ attr->sendsCore = !!dmxLocal->sendsCore;
+ attr->detached = !!dmxInput->detached;
+ attr->physicalScreen = -1;
+ attr->physicalId = -1;
+ attr->name = NULL;
+ switch (dmxLocal->extType) {
+ case DMX_LOCAL_TYPE_LOCAL:
+ attr->inputType = 0;
+ break;
+ case DMX_LOCAL_TYPE_CONSOLE:
+ attr->inputType = 1;
+ attr->name = dmxInput->name;
+ attr->physicalId = dmxLocal->deviceId;
+ break;
+ case DMX_LOCAL_TYPE_BACKEND:
+ case DMX_LOCAL_TYPE_COMMON:
+ attr->inputType = 2;
+ attr->physicalScreen = dmxInput->scrnIdx;
+ attr->name = dmxInput->name;
+ attr->physicalId = dmxLocal->deviceId;
+ break;
+ }
+ return 0; /* Success */
+ }
+ }
+ return -1; /* Failure */
+}
+
+/** Reinitialized the cursor boundaries. */
+static void dmxAdjustCursorBoundaries(void)
+{
+ int i;
+
+ dmxReInitOrigins();
+ dmxInitOverlap();
+ dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX);
+ dmxConnectionBlockCallback();
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (!dmxInput->detached) dmxInputReInit(dmxInput);
+ }
+
+ dmxCheckCursor();
+
+ for (i = 0; i < dmxNumInputs; i++) {
+ DMXInputInfo *dmxInput = &dmxInputs[i];
+ if (!dmxInput->detached) dmxInputLateReInit(dmxInput);
+ }
+}
+
+/** Add an input with the specified attributes. If the input is added,
+ * the physical id is returned in \a deviceId. */
+int dmxAddInput(DMXInputAttributesPtr attr, int *id)
+{
+ int retcode = BadValue;
+
+ if (attr->inputType == 1) /* console */
+ retcode = dmxInputAttachConsole(attr->name, attr->sendsCore, id);
+ else if (attr->inputType == 2) /* backend */
+ retcode = dmxInputAttachBackend(attr->physicalScreen,
+ attr->sendsCore,id);
+
+ if (retcode == Success) {
+ /* Adjust the cursor boundaries */
+ dmxAdjustCursorBoundaries();
+
+ /* Force completion of the changes */
+ dmxSync(NULL, TRUE);
+ }
+
+ return retcode;
+}
+
+/** Remove the input with physical id \a id. */
+int dmxRemoveInput(int id)
+{
+ return dmxInputDetachId(id);
+}
+
+/** Return the value of #dmxNumScreens -- the total number of backend
+ * screens in use (these are logical screens and may be larger than the
+ * number of backend displays). */
+unsigned long dmxGetNumScreens(void)
+{
+ return dmxNumScreens;
+}
+
+/** Make sure that #dmxCreateAndRealizeWindow has been called for \a
+ * pWindow. */
+void dmxForceWindowCreation(WindowPtr pWindow)
+{
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ if (!pWinPriv->window) dmxCreateAndRealizeWindow(pWindow, TRUE);
+}
+
+/** Flush pending syncs for all screens. */
+void dmxFlushPendingSyncs(void)
+{
+ dmxSync(NULL, TRUE);
+}
+
+/** Update DMX's screen resources to match those of the newly moved
+ * and/or resized "root" window. */
+void dmxUpdateScreenResources(ScreenPtr pScreen, int x, int y, int w, int h)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ WindowPtr pRoot = WindowTable[pScreen->myNum];
+ WindowPtr pChild;
+ Bool anyMarked = FALSE;
+
+ /* Handle special case where width and/or height are zero */
+ if (w == 0 || h == 0) {
+ w = 1;
+ h = 1;
+ }
+
+ /* Change screen size */
+ pScreen->width = w;
+ pScreen->height = h;
+
+ /* Reset the root window's drawable's size */
+ pRoot->drawable.width = w;
+ pRoot->drawable.height = h;
+
+ /* Set the root window's new winSize and borderSize */
+ pRoot->winSize.extents.x1 = 0;
+ pRoot->winSize.extents.y1 = 0;
+ pRoot->winSize.extents.x2 = w;
+ pRoot->winSize.extents.y2 = h;
+
+ pRoot->borderSize.extents.x1 = 0;
+ pRoot->borderSize.extents.y1 = 0;
+ pRoot->borderSize.extents.x2 = w;
+ pRoot->borderSize.extents.y2 = h;
+
+ /* Recompute this screen's mmWidth & mmHeight */
+ pScreen->mmWidth =
+ (w * 254 + dmxScreen->beXDPI * 5) / (dmxScreen->beXDPI * 10);
+ pScreen->mmHeight =
+ (h * 254 + dmxScreen->beYDPI * 5) / (dmxScreen->beYDPI * 10);
+
+ /* Recompute this screen's window's clip rects as follows: */
+ /* 1. Mark all of root's children's windows */
+ for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib)
+ anyMarked |= pScreen->MarkOverlappedWindows(pChild, pChild,
+ (WindowPtr *)NULL);
+
+ /* 2. Set the root window's borderClip */
+ pRoot->borderClip.extents.x1 = 0;
+ pRoot->borderClip.extents.y1 = 0;
+ pRoot->borderClip.extents.x2 = w;
+ pRoot->borderClip.extents.y2 = h;
+
+ /* 3. Set the root window's clipList */
+ if (anyMarked) {
+ /* If any windows have been marked, set the root window's
+ * clipList to be broken since it will be recalculated in
+ * ValidateTree()
+ */
+ REGION_BREAK(pScreen, &pRoot->clipList);
+ } else {
+ /* Otherwise, we just set it directly since there are no
+ * windows visible on this screen
+ */
+ pRoot->clipList.extents.x1 = 0;
+ pRoot->clipList.extents.y1 = 0;
+ pRoot->clipList.extents.x2 = w;
+ pRoot->clipList.extents.y2 = h;
+ }
+
+ /* 4. Revalidate all clip rects and generate expose events */
+ if (anyMarked) {
+ pScreen->ValidateTree(pRoot, NULL, VTBroken);
+ pScreen->HandleExposures(pRoot);
+ if (pScreen->PostValidateTree)
+ pScreen->PostValidateTree(pRoot, NULL, VTBroken);
+ }
+}
+
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+
+/* Defined in dix/events.c */
+extern void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff);
+
+/** Change the "screen" window attributes by resizing the actual window
+ * on the back-end display (if necessary). */
+static void dmxConfigureScreenWindow(int idx,
+ int x, int y, int w, int h)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ ScreenPtr pScreen = screenInfo.screens[idx];
+
+ /* Resize "screen" window */
+ if (dmxScreen->scrnX != x ||
+ dmxScreen->scrnY != y ||
+ dmxScreen->scrnWidth != w ||
+ dmxScreen->scrnHeight != h) {
+ dmxResizeScreenWindow(pScreen, x, y, w, h);
+ }
+
+ /* Change "screen" window values */
+ dmxScreen->scrnX = x;
+ dmxScreen->scrnY = y;
+ dmxScreen->scrnWidth = w;
+ dmxScreen->scrnHeight = h;
+}
+
+/** Change the "root" window position and size by resizing the actual
+ * window on the back-end display (if necessary) and updating all of
+ * DMX's resources by calling #dmxUpdateScreenResources. */
+static void dmxConfigureRootWindow(int idx, int x, int y, int w, int h)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ WindowPtr pRoot = WindowTable[idx];
+
+ /* NOTE: Either this function or the ones that it calls must handle
+ * the case where w == 0 || h == 0. Currently, the functions that
+ * this one calls handle that case. */
+
+ /* 1. Resize "root" window */
+ if (dmxScreen->rootX != x ||
+ dmxScreen->rootY != y ||
+ dmxScreen->rootWidth != w ||
+ dmxScreen->rootHeight != h) {
+ dmxResizeRootWindow(pRoot, x, y, w, h);
+ }
+
+ /* 2. Update all of the screen's resources associated with this root
+ * window */
+ if (dmxScreen->rootWidth != w ||
+ dmxScreen->rootHeight != h) {
+ dmxUpdateScreenResources(screenInfo.screens[idx], x, y, w, h);
+ }
+
+ /* Change "root" window values */
+ dmxScreen->rootX = x;
+ dmxScreen->rootY = y;
+ dmxScreen->rootWidth = w;
+ dmxScreen->rootHeight = h;
+}
+
+/** Change the "root" window's origin by updating DMX's internal data
+ * structures (dix and Xinerama) to use the new origin and adjust the
+ * positions of windows that overlap this "root" window. */
+static void dmxSetRootWindowOrigin(int idx, int x, int y)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ ScreenPtr pScreen = screenInfo.screens[idx];
+ WindowPtr pRoot = WindowTable[idx];
+ WindowPtr pChild;
+ int xoff;
+ int yoff;
+
+ /* Change "root" window's origin */
+ dmxScreen->rootXOrigin = x;
+ dmxScreen->rootYOrigin = y;
+
+ /* Compute offsets here in case <x,y> has been changed above */
+ xoff = x - dixScreenOrigins[idx].x;
+ yoff = y - dixScreenOrigins[idx].y;
+
+ /* Adjust the root window's position in dixScreenOrigins */
+ dixScreenOrigins[idx].x = dmxScreen->rootXOrigin;
+ dixScreenOrigins[idx].y = dmxScreen->rootYOrigin;
+
+ /* Recalculate the Xinerama regions and data structs */
+ XineramaReinitData(pScreen);
+
+ /* Adjust each of the root window's children */
+ if (!idx) ReinitializeRootWindow(WindowTable[0], xoff, yoff);
+ pChild = pRoot->firstChild;
+ while (pChild) {
+ /* Adjust child window's position */
+ pScreen->MoveWindow(pChild,
+ pChild->origin.x - wBorderWidth(pChild) - xoff,
+ pChild->origin.y - wBorderWidth(pChild) - yoff,
+ pChild->nextSib,
+ VTMove);
+
+ /* Note that the call to MoveWindow will eventually call
+ * dmxPositionWindow which will automatically create a
+ * window if it is now exposed on screen (for lazy window
+ * creation optimization) and it will properly set the
+ * offscreen flag.
+ */
+
+ pChild = pChild->nextSib;
+ }
+}
+
+/** Configure the attributes of each "screen" and "root" window. */
+int dmxConfigureScreenWindows(int nscreens,
+ CARD32 *screens,
+ DMXScreenAttributesPtr attribs,
+ int *errorScreen)
+{
+ int i;
+
+ for (i = 0; i < nscreens; i++) {
+ DMXScreenAttributesPtr attr = &attribs[i];
+ int idx = screens[i];
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+
+ if (errorScreen) *errorScreen = i;
+
+ if (!dmxScreen->beDisplay) return DMX_BAD_VALUE;
+
+ /* Check for illegal values */
+ if (idx < 0 || idx >= dmxNumScreens) return BadValue;
+
+ /* The "screen" and "root" windows must have valid sizes */
+ if (attr->screenWindowWidth <= 0 || attr->screenWindowHeight <= 0 ||
+ attr->rootWindowWidth < 0 || attr->rootWindowHeight < 0)
+ return DMX_BAD_VALUE;
+
+ /* The "screen" window must fit entirely within the BE display */
+ if (attr->screenWindowXoffset < 0 ||
+ attr->screenWindowYoffset < 0 ||
+ attr->screenWindowXoffset
+ + attr->screenWindowWidth > (unsigned)dmxScreen->beWidth ||
+ attr->screenWindowYoffset
+ + attr->screenWindowHeight > (unsigned)dmxScreen->beHeight)
+ return DMX_BAD_VALUE;
+
+ /* The "root" window must fit entirely within the "screen" window */
+ if (attr->rootWindowXoffset < 0 ||
+ attr->rootWindowYoffset < 0 ||
+ attr->rootWindowXoffset
+ + attr->rootWindowWidth > attr->screenWindowWidth ||
+ attr->rootWindowYoffset
+ + attr->rootWindowHeight > attr->screenWindowHeight)
+ return DMX_BAD_VALUE;
+
+ /* The "root" window must not expose unaddressable coordinates */
+ if (attr->rootWindowXorigin < 0 ||
+ attr->rootWindowYorigin < 0 ||
+ attr->rootWindowXorigin + attr->rootWindowWidth > 32767 ||
+ attr->rootWindowYorigin + attr->rootWindowHeight > 32767)
+ return DMX_BAD_VALUE;
+
+ /* The "root" window must fit within the global bounding box */
+ if (attr->rootWindowXorigin
+ + attr->rootWindowWidth > (unsigned)dmxGlobalWidth ||
+ attr->rootWindowYorigin
+ + attr->rootWindowHeight > (unsigned)dmxGlobalHeight)
+ return DMX_BAD_VALUE;
+
+ /* FIXME: Handle the rest of the illegal value checking */
+ }
+
+ /* No illegal values found */
+ if (errorScreen) *errorScreen = 0;
+
+ for (i = 0; i < nscreens; i++) {
+ DMXScreenAttributesPtr attr = &attribs[i];
+ int idx = screens[i];
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+
+ dmxLog(dmxInfo, "Changing screen #%d attributes "
+ "from %dx%d+%d+%d %dx%d+%d+%d +%d+%d "
+ "to %dx%d+%d+%d %dx%d+%d+%d +%d+%d\n",
+ idx,
+ dmxScreen->scrnWidth, dmxScreen->scrnHeight,
+ dmxScreen->scrnX, dmxScreen->scrnY,
+ dmxScreen->rootWidth, dmxScreen->rootHeight,
+ dmxScreen->rootX, dmxScreen->rootY,
+ dmxScreen->rootXOrigin, dmxScreen->rootYOrigin,
+ attr->screenWindowWidth, attr->screenWindowHeight,
+ attr->screenWindowXoffset, attr->screenWindowYoffset,
+ attr->rootWindowWidth, attr->rootWindowHeight,
+ attr->rootWindowXoffset, attr->rootWindowYoffset,
+ attr->rootWindowXorigin, attr->rootWindowYorigin);
+
+ /* Configure "screen" window */
+ dmxConfigureScreenWindow(idx,
+ attr->screenWindowXoffset,
+ attr->screenWindowYoffset,
+ attr->screenWindowWidth,
+ attr->screenWindowHeight);
+
+ /* Configure "root" window */
+ dmxConfigureRootWindow(idx,
+ attr->rootWindowXoffset,
+ attr->rootWindowYoffset,
+ attr->rootWindowWidth,
+ attr->rootWindowHeight);
+
+
+ /* Set "root" window's origin */
+ dmxSetRootWindowOrigin(idx,
+ attr->rootWindowXorigin,
+ attr->rootWindowYorigin);
+ }
+
+ /* Adjust the cursor boundaries */
+ dmxAdjustCursorBoundaries();
+
+ /* Force completion of the changes */
+ dmxSync(NULL, TRUE);
+
+ return Success;
+}
+
+/** Configure the attributes of the global desktop. */
+int dmxConfigureDesktop(DMXDesktopAttributesPtr attribs)
+{
+ if (attribs->width <= 0 || attribs->width >= 32767 ||
+ attribs->height <= 0 || attribs->height >= 32767)
+ return DMX_BAD_VALUE;
+
+ /* If the desktop is shrinking, adjust the "root" windows on each
+ * "screen" window to only show the visible desktop. Also, handle
+ * the special case where the desktop shrinks such that the it no
+ * longer overlaps an portion of a "screen" window. */
+ if (attribs->width < dmxGlobalWidth || attribs->height < dmxGlobalHeight) {
+ int i;
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+ if (dmxScreen->rootXOrigin
+ + dmxScreen->rootWidth > attribs->width ||
+ dmxScreen->rootYOrigin
+ + dmxScreen->rootHeight > attribs->height) {
+ int w, h;
+ if ((w = attribs->width - dmxScreen->rootXOrigin) < 0) w = 0;
+ if ((h = attribs->height - dmxScreen->rootYOrigin) < 0) h = 0;
+ if (w > dmxScreen->scrnWidth) w = dmxScreen->scrnWidth;
+ if (h > dmxScreen->scrnHeight) h = dmxScreen->scrnHeight;
+ if (w > dmxScreen->rootWidth) w = dmxScreen->rootWidth;
+ if (h > dmxScreen->rootHeight) h = dmxScreen->rootHeight;
+ dmxConfigureRootWindow(i,
+ dmxScreen->rootX,
+ dmxScreen->rootY,
+ w, h);
+ }
+ }
+ }
+
+ /* Set the global width/height */
+ dmxSetWidthHeight(attribs->width, attribs->height);
+
+ /* Handle shift[XY] changes */
+ if (attribs->shiftX || attribs->shiftY) {
+ int i;
+ for (i = 0; i < dmxNumScreens; i++) {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ WindowPtr pChild = WindowTable[i]->firstChild;
+ while (pChild) {
+ /* Adjust child window's position */
+ pScreen->MoveWindow(pChild,
+ pChild->origin.x - wBorderWidth(pChild)
+ - attribs->shiftX,
+ pChild->origin.y - wBorderWidth(pChild)
+ - attribs->shiftY,
+ pChild->nextSib,
+ VTMove);
+
+ /* Note that the call to MoveWindow will eventually call
+ * dmxPositionWindow which will automatically create a
+ * window if it is now exposed on screen (for lazy
+ * window creation optimization) and it will properly
+ * set the offscreen flag.
+ */
+
+ pChild = pChild->nextSib;
+ }
+ }
+ }
+
+ /* Update connection block, Xinerama, etc. -- these appears to
+ * already be handled in dmxConnectionBlockCallback(), which is
+ * called from dmxAdjustCursorBoundaries() [below]. */
+
+ /* Adjust the cursor boundaries */
+ dmxAdjustCursorBoundaries();
+
+ /* Force completion of the changes */
+ dmxSync(NULL, TRUE);
+
+ return Success;
+}
+#endif
+
+/** Create the scratch GCs per depth. */
+static void dmxBECreateScratchGCs(int scrnNum)
+{
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+ GCPtr *ppGC = pScreen->GCperDepth;
+ int i;
+
+ for (i = 0; i <= pScreen->numDepths; i++)
+ dmxBECreateGC(pScreen, ppGC[i]);
+}
+
+#ifdef PANORAMIX
+static Bool FoundPixImage;
+
+/** Search the Xinerama XRT_PIXMAP resources for the pixmap that needs
+ * to have its image restored. When it is found, see if there is
+ * another screen with the same image. If so, copy the pixmap image
+ * from the existing screen to the newly created pixmap. */
+static void dmxBERestorePixmapImage(pointer value, XID id, RESTYPE type,
+ pointer p)
+{
+ if ((type & TypeMask) == (XRT_PIXMAP & TypeMask)) {
+ PixmapPtr pDst = (PixmapPtr)p;
+ int idx = pDst->drawable.pScreen->myNum;
+ PanoramiXRes *pXinPix = (PanoramiXRes *)value;
+ PixmapPtr pPix;
+ int i;
+
+ pPix = (PixmapPtr)LookupIDByType(pXinPix->info[idx].id, RT_PIXMAP);
+ if (pPix != pDst) return; /* Not a match.... Next! */
+
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ PixmapPtr pSrc;
+ dmxPixPrivPtr pSrcPriv = NULL;
+
+ if (i == idx) continue; /* Self replication is bad */
+
+ pSrc =
+ (PixmapPtr)LookupIDByType(pXinPix->info[i].id, RT_PIXMAP);
+ pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
+ if (pSrcPriv->pixmap) {
+ DMXScreenInfo *dmxSrcScreen = &dmxScreens[i];
+ DMXScreenInfo *dmxDstScreen = &dmxScreens[idx];
+ dmxPixPrivPtr pDstPriv = DMX_GET_PIXMAP_PRIV(pDst);
+ XImage *img;
+ int j;
+ XlibGC gc = NULL;
+
+ /* This should never happen, but just in case.... */
+ if (pSrc->drawable.width != pDst->drawable.width ||
+ pSrc->drawable.height != pDst->drawable.height)
+ return;
+
+ /* Copy from src pixmap to dst pixmap */
+ img = XGetImage(dmxSrcScreen->beDisplay,
+ pSrcPriv->pixmap,
+ 0, 0,
+ pSrc->drawable.width, pSrc->drawable.height,
+ -1,
+ ZPixmap);
+
+ for (j = 0; j < dmxDstScreen->beNumPixmapFormats; j++) {
+ if (dmxDstScreen->bePixmapFormats[j].depth == img->depth) {
+ unsigned long m;
+ XGCValues v;
+
+ m = GCFunction | GCPlaneMask | GCClipMask;
+ v.function = GXcopy;
+ v.plane_mask = AllPlanes;
+ v.clip_mask = None;
+
+ gc = XCreateGC(dmxDstScreen->beDisplay,
+ dmxDstScreen->scrnDefDrawables[j],
+ m, &v);
+ break;
+ }
+ }
+
+ if (gc) {
+ XPutImage(dmxDstScreen->beDisplay,
+ pDstPriv->pixmap,
+ gc, img, 0, 0, 0, 0,
+ pDst->drawable.width, pDst->drawable.height);
+ XFreeGC(dmxDstScreen->beDisplay, gc);
+ FoundPixImage = True;
+ } else {
+ dmxLog(dmxWarning, "Could not create GC\n");
+ }
+
+ XDestroyImage(img);
+ return;
+ }
+ }
+ }
+}
+#endif
+
+/** Restore the pixmap image either from another screen or from an image
+ * that was saved when the screen was previously detached. */
+static void dmxBERestorePixmap(PixmapPtr pPixmap)
+{
+#ifdef PANORAMIX
+ int i;
+
+ /* If Xinerama is not active, there's nothing we can do (see comment
+ * in #else below for more info). */
+ if (noPanoramiXExtension) {
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ return;
+ }
+
+ FoundPixImage = False;
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBERestorePixmapImage,
+ (pointer)pPixmap);
+
+ /* No corresponding pixmap image was found on other screens, so we
+ * need to copy it from the saved image when the screen was detached
+ * (if available). */
+ if (!FoundPixImage) {
+ dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
+
+ if (pPixPriv->detachedImage) {
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ XlibGC gc = NULL;
+
+ for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
+ if (dmxScreen->bePixmapFormats[i].depth ==
+ pPixPriv->detachedImage->depth) {
+ unsigned long m;
+ XGCValues v;
+
+ m = GCFunction | GCPlaneMask | GCClipMask;
+ v.function = GXcopy;
+ v.plane_mask = AllPlanes;
+ v.clip_mask = None;
+
+ gc = XCreateGC(dmxScreen->beDisplay,
+ dmxScreen->scrnDefDrawables[i],
+ m, &v);
+ break;
+ }
+ }
+
+ if (gc) {
+ XPutImage(dmxScreen->beDisplay,
+ pPixPriv->pixmap,
+ gc,
+ pPixPriv->detachedImage,
+ 0, 0, 0, 0,
+ pPixmap->drawable.width, pPixmap->drawable.height);
+ XFreeGC(dmxScreen->beDisplay, gc);
+ } else {
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ }
+
+ XDestroyImage(pPixPriv->detachedImage);
+ pPixPriv->detachedImage = NULL;
+ } else {
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ }
+ }
+#else
+ /* If Xinerama is not enabled, then there is no other copy of the
+ * pixmap image that we can restore. Saving all pixmap data is not
+ * a feasible option since there is no mechanism for updating pixmap
+ * data when a screen is detached, which means that the data that
+ * was previously saved would most likely be out of date. */
+ dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+ return;
+#endif
+}
+
+/** Create resources on the back-end server. This function is called
+ * from #dmxAttachScreen() via the dix layer's FindAllResources
+ * function. It walks all resources, compares them to the screen
+ * number passed in as \a n and calls the appropriate DMX function to
+ * create the associated resource on the back-end server. */
+static void dmxBECreateResources(pointer value, XID id, RESTYPE type,
+ pointer n)
+{
+ int scrnNum = (int)n;
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+
+ if ((type & TypeMask) == (RT_WINDOW & TypeMask)) {
+ /* Window resources are created below in dmxBECreateWindowTree */
+ } else if ((type & TypeMask) == (RT_PIXMAP & TypeMask)) {
+ PixmapPtr pPix = value;
+ if (pPix->drawable.pScreen->myNum == scrnNum) {
+ dmxBECreatePixmap(pPix);
+ dmxBERestorePixmap(pPix);
+ }
+ } else if ((type & TypeMask) == (RT_GC & TypeMask)) {
+ GCPtr pGC = value;
+ if (pGC->pScreen->myNum == scrnNum) {
+ /* Create the GC on the back-end server */
+ dmxBECreateGC(pScreen, pGC);
+ /* Create any pixmaps associated with this GC */
+ if (!pGC->tileIsPixel) {
+ dmxBECreatePixmap(pGC->tile.pixmap);
+ dmxBERestorePixmap(pGC->tile.pixmap);
+ }
+ if (pGC->stipple != pScreen->PixmapPerDepth[0]) {
+ dmxBECreatePixmap(pGC->stipple);
+ dmxBERestorePixmap(pGC->stipple);
+ }
+ if (pGC->font != defaultFont) {
+ (void)dmxBELoadFont(pScreen, pGC->font);
+ }
+ /* Update the GC on the back-end server */
+ dmxChangeGC(pGC, -1L);
+ }
+ } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
+ (void)dmxBELoadFont(pScreen, (FontPtr)value);
+ } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
+ dmxBECreateCursor(pScreen, (CursorPtr)value);
+ } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
+ ColormapPtr pCmap = value;
+ if (pCmap->pScreen->myNum == scrnNum)
+ (void)dmxBECreateColormap((ColormapPtr)value);
+#if 0
+#ifdef RENDER
+ /* TODO: Recreate Picture and GlyphSet resources */
+ } else if ((type & TypeMask) == (PictureType & TypeMask)) {
+ /* Picture resources are created when windows are created */
+ } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
+ dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
+#endif
+#endif
+ } else {
+ /* Other resource types??? */
+ }
+}
+
+/** Create window hierachy on back-end server. The window tree is
+ * created in a special order (bottom most subwindow first) so that the
+ * #dmxCreateNonRootWindow() function does not need to recursively call
+ * itself to create each window's parents. This is required so that we
+ * have the opportunity to create each window's border and background
+ * pixmaps (where appropriate) before the window is created. */
+static void dmxBECreateWindowTree(int idx)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ WindowPtr pRoot = WindowTable[idx];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot);
+ WindowPtr pWin;
+
+ /* Create the pixmaps associated with the root window */
+ if (!pRoot->borderIsPixel) {
+ dmxBECreatePixmap(pRoot->border.pixmap);
+ dmxBERestorePixmap(pRoot->border.pixmap);
+ }
+ if (pRoot->backgroundState == BackgroundPixmap) {
+ dmxBECreatePixmap(pRoot->background.pixmap);
+ dmxBERestorePixmap(pRoot->background.pixmap);
+ }
+
+ /* Create root window first */
+ dmxScreen->rootWin = pWinPriv->window = dmxCreateRootWindow(pRoot);
+ XMapWindow(dmxScreen->beDisplay, dmxScreen->rootWin);
+
+ pWin = pRoot->lastChild;
+ while (pWin) {
+ pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
+
+ /* Create the pixmaps regardless of whether or not the
+ * window is created or not due to lazy window creation.
+ */
+ if (!pWin->borderIsPixel) {
+ dmxBECreatePixmap(pWin->border.pixmap);
+ dmxBERestorePixmap(pWin->border.pixmap);
+ }
+ if (pWin->backgroundState == BackgroundPixmap) {
+ dmxBECreatePixmap(pWin->background.pixmap);
+ dmxBERestorePixmap(pWin->background.pixmap);
+ }
+
+ /* Reset the window attributes */
+ dmxGetDefaultWindowAttributes(pWin,
+ &pWinPriv->cmap,
+ &pWinPriv->visual);
+
+ /* Create the window */
+ if (pWinPriv->mapped && !pWinPriv->offscreen)
+ dmxCreateAndRealizeWindow(pWin, TRUE);
+
+ /* Next, create the bottom-most child */
+ if (pWin->lastChild) {
+ pWin = pWin->lastChild;
+ continue;
+ }
+
+ /* If the window has no children, move on to the next higher window */
+ while (!pWin->prevSib && (pWin != pRoot))
+ pWin = pWin->parent;
+
+ if (pWin->prevSib) {
+ pWin = pWin->prevSib;
+ continue;
+ }
+
+ /* When we reach the root window, we are finished */
+ if (pWin == pRoot)
+ break;
+ }
+}
+
+/* Refresh screen by generating exposure events for all windows */
+static void dmxForceExposures(int idx)
+{
+ ScreenPtr pScreen = screenInfo.screens[idx];
+ WindowPtr pRoot = WindowTable[idx];
+ Bool anyMarked = FALSE;
+ WindowPtr pChild;
+
+ for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib)
+ anyMarked |= pScreen->MarkOverlappedWindows(pChild, pChild,
+ (WindowPtr *)NULL);
+ if (anyMarked) {
+ /* If any windows have been marked, set the root window's
+ * clipList to be broken since it will be recalculated in
+ * ValidateTree()
+ */
+ REGION_BREAK(pScreen, &pRoot->clipList);
+ pScreen->ValidateTree(pRoot, NULL, VTBroken);
+ pScreen->HandleExposures(pRoot);
+ if (pScreen->PostValidateTree)
+ pScreen->PostValidateTree(pRoot, NULL, VTBroken);
+ }
+}
+
+/** Compare the new and old screens to see if they are compatible. */
+static Bool dmxCompareScreens(DMXScreenInfo *new, DMXScreenInfo *old)
+{
+ int i;
+
+ if (new->beWidth != old->beWidth) return FALSE;
+ if (new->beHeight != old->beHeight) return FALSE;
+ if (new->beDepth != old->beDepth) return FALSE;
+ if (new->beBPP != old->beBPP) return FALSE;
+
+ if (new->beNumDepths != old->beNumDepths) return FALSE;
+ for (i = 0; i < old->beNumDepths; i++)
+ if (new->beDepths[i] != old->beDepths[i]) return FALSE;
+
+ if (new->beNumPixmapFormats != old->beNumPixmapFormats) return FALSE;
+ for (i = 0; i < old->beNumPixmapFormats; i++) {
+ if (new->bePixmapFormats[i].depth !=
+ old->bePixmapFormats[i].depth) return FALSE;
+ if (new->bePixmapFormats[i].bits_per_pixel !=
+ old->bePixmapFormats[i].bits_per_pixel) return FALSE;
+ if (new->bePixmapFormats[i].scanline_pad !=
+ old->bePixmapFormats[i].scanline_pad) return FALSE;
+ }
+
+ if (new->beNumVisuals != old->beNumVisuals) return FALSE;
+ for (i = 0; i < old->beNumVisuals; i++) {
+ if (new->beVisuals[i].visualid !=
+ old->beVisuals[i].visualid) return FALSE;
+ if (new->beVisuals[i].screen !=
+ old->beVisuals[i].screen) return FALSE;
+ if (new->beVisuals[i].depth !=
+ old->beVisuals[i].depth) return FALSE;
+ if (new->beVisuals[i].class !=
+ old->beVisuals[i].class) return FALSE;
+ if (new->beVisuals[i].red_mask !=
+ old->beVisuals[i].red_mask) return FALSE;
+ if (new->beVisuals[i].green_mask !=
+ old->beVisuals[i].green_mask) return FALSE;
+ if (new->beVisuals[i].blue_mask !=
+ old->beVisuals[i].blue_mask) return FALSE;
+ if (new->beVisuals[i].colormap_size !=
+ old->beVisuals[i].colormap_size) return FALSE;
+ if (new->beVisuals[i].bits_per_rgb !=
+ old->beVisuals[i].bits_per_rgb) return FALSE;
+ }
+
+ if (new->beDefVisualIndex != old->beDefVisualIndex) return FALSE;
+
+ return TRUE;
+}
+
+/** Reattach previously detached back-end screen. */
+int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
+{
+ ScreenPtr pScreen = screenInfo.screens[idx];
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ CARD32 scrnNum = idx;
+ DMXScreenInfo oldDMXScreen;
+ int i;
+
+ /* Return failure if dynamic addition/removal of screens is disabled */
+ if (!dmxAddRemoveScreens) {
+ dmxLog(dmxWarning,
+ "Attempting to add a screen, but the AddRemoveScreen\n");
+ dmxLog(dmxWarning,
+ "extension has not been enabled. To enable this extension\n");
+ dmxLog(dmxWarning,
+ "add the \"-addremovescreens\" option either to the command\n");
+ dmxLog(dmxWarning,
+ "line or in the configuration file.\n");
+ return 1;
+ }
+
+ /* Cannot add a screen that does not exist */
+ if (idx < 0 || idx >= dmxNumScreens) return 1;
+
+ /* Cannot attach to a screen that is already opened */
+ if (dmxScreen->beDisplay) {
+ dmxLog(dmxWarning,
+ "Attempting to add screen #%d but a screen already exists\n",
+ idx);
+ return 1;
+ }
+
+ dmxLogOutput(dmxScreen, "Attaching screen #%d\n", idx);
+
+ /* Save old info */
+ oldDMXScreen = *dmxScreen;
+
+ /* Copy the name to the new screen */
+ dmxScreen->name = strdup(attr->displayName);
+
+ /* Open display and get all of the screen info */
+ if (!dmxOpenDisplay(dmxScreen)) {
+ dmxLog(dmxWarning,
+ "dmxOpenDisplay: Unable to open display %s\n",
+ dmxScreen->name);
+
+ /* Restore the old screen */
+ *dmxScreen = oldDMXScreen;
+ return 1;
+ }
+
+ dmxSetErrorHandler(dmxScreen);
+ dmxCheckForWM(dmxScreen);
+ dmxGetScreenAttribs(dmxScreen);
+
+ if (!dmxGetVisualInfo(dmxScreen)) {
+ dmxLog(dmxWarning, "dmxGetVisualInfo: No matching visuals found\n");
+ XFree(dmxScreen->beVisuals);
+ XCloseDisplay(dmxScreen->beDisplay);
+
+ /* Restore the old screen */
+ *dmxScreen = oldDMXScreen;
+ return 1;
+ }
+
+ dmxGetColormaps(dmxScreen);
+ dmxGetPixmapFormats(dmxScreen);
+
+ /* Verify that the screen to be added has the same info as the
+ * previously added screen. */
+ if (!dmxCompareScreens(dmxScreen, &oldDMXScreen)) {
+ dmxLog(dmxWarning,
+ "New screen data (%s) does not match previously\n",
+ dmxScreen->name);
+ dmxLog(dmxWarning,
+ "attached screen data (%s)\n",
+ oldDMXScreen.name);
+ dmxLog(dmxWarning,
+ "All data must match in order to attach to screen #%d\n",
+ idx);
+ XFree(dmxScreen->beVisuals);
+ XFree(dmxScreen->beDepths);
+ XFree(dmxScreen->bePixmapFormats);
+ XCloseDisplay(dmxScreen->beDisplay);
+
+ /* Restore the old screen */
+ *dmxScreen = oldDMXScreen;
+ return 1;
+ }
+
+ /* Initialize the BE screen resources */
+ dmxBEScreenInit(idx, screenInfo.screens[idx]);
+
+ /* TODO: Handle GLX visual initialization. GLXProxy needs to be
+ * updated to handle dynamic addition/removal of screens. */
+
+ /* Create default stipple */
+ dmxBECreatePixmap(pScreen->PixmapPerDepth[0]);
+ dmxBERestorePixmap(pScreen->PixmapPerDepth[0]);
+
+ /* Create the scratch GCs */
+ dmxBECreateScratchGCs(idx);
+
+ /* Create the default font */
+ (void)dmxBELoadFont(pScreen, defaultFont);
+
+ /* Create all resources that don't depend on windows */
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBECreateResources,
+ (pointer)idx);
+
+ /* Create window hierarchy (top down) */
+ dmxBECreateWindowTree(idx);
+
+ /* Refresh screen by generating exposure events for all windows */
+ dmxForceExposures(idx);
+
+ dmxSync(&dmxScreens[idx], TRUE);
+
+ /* We used these to compare the old and new screens. They are no
+ * longer needed since we have a newly attached screen, so we can
+ * now free the old screen's resources. */
+ XFree(oldDMXScreen.beVisuals);
+ XFree(oldDMXScreen.beDepths);
+ XFree(oldDMXScreen.bePixmapFormats);
+ /* TODO: should oldDMXScreen.name be freed?? */
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ return dmxConfigureScreenWindows(1, &scrnNum, attr, NULL);
+ else
+#endif
+ return 0; /* Success */
+}
+
+/*
+ * Resources that may have state on the BE server and need to be freed:
+ *
+ * RT_NONE
+ * RT_WINDOW
+ * RT_PIXMAP
+ * RT_GC
+ * RT_FONT
+ * RT_CURSOR
+ * RT_COLORMAP
+ * RT_CMAPENTRY
+ * RT_OTHERCLIENT
+ * RT_PASSIVEGRAB
+ * XRT_WINDOW
+ * XRT_PIXMAP
+ * XRT_GC
+ * XRT_COLORMAP
+ * XRT_PICTURE
+ * PictureType
+ * PictFormatType
+ * GlyphSetType
+ * ClientType
+ * EventType
+ * RT_INPUTCLIENT
+ * XETrapType
+ * RTCounter
+ * RTAwait
+ * RTAlarmClient
+ * RT_XKBCLIENT
+ * RTContext
+ * TagResType
+ * StalledResType
+ * RT_APPGROUP
+ * SecurityAuthorizationResType
+ * RTEventClient
+ * __glXContextRes
+ * __glXClientRes
+ * __glXPixmapRes
+ * __glXWindowRes
+ * __glXPbufferRes
+ */
+
+#ifdef PANORAMIX
+/** Search the Xinerama XRT_PIXMAP resources for the pixmap that needs
+ * to have its image saved. */
+static void dmxBEFindPixmapImage(pointer value, XID id, RESTYPE type,
+ pointer p)
+{
+ if ((type & TypeMask) == (XRT_PIXMAP & TypeMask)) {
+ PixmapPtr pDst = (PixmapPtr)p;
+ int idx = pDst->drawable.pScreen->myNum;
+ PanoramiXRes *pXinPix = (PanoramiXRes *)value;
+ PixmapPtr pPix;
+ int i;
+
+ pPix = (PixmapPtr)LookupIDByType(pXinPix->info[idx].id, RT_PIXMAP);
+ if (pPix != pDst) return; /* Not a match.... Next! */
+
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ PixmapPtr pSrc;
+ dmxPixPrivPtr pSrcPriv = NULL;
+
+ if (i == idx) continue; /* Self replication is bad */
+
+ pSrc =
+ (PixmapPtr)LookupIDByType(pXinPix->info[i].id, RT_PIXMAP);
+ pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
+ if (pSrcPriv->pixmap) {
+ FoundPixImage = True;
+ return;
+ }
+ }
+ }
+}
+#endif
+
+/** Save the pixmap image only when there is not another screen with
+ * that pixmap from which the image can be read when the screen is
+ * reattached. To do this, we first try to find a pixmap on another
+ * screen corresponding to the one we are trying to save. If we find
+ * one, then we do not need to save the image data since during
+ * reattachment, the image data can be read from that other pixmap.
+ * However, if we do not find one, then we need to save the image data.
+ * The common case for these are for the default stipple and root
+ * tile. */
+static void dmxBESavePixmap(PixmapPtr pPixmap)
+{
+#ifdef PANORAMIX
+ int i;
+
+ /* If Xinerama is not active, there's nothing we can do (see comment
+ * in #else below for more info). */
+ if (noPanoramiXExtension) return;
+
+ FoundPixImage = False;
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBEFindPixmapImage,
+ (pointer)pPixmap);
+
+ /* Save the image only if there is no other screens that have a
+ * pixmap that corresponds to the one we are trying to save. */
+ if (!FoundPixImage) {
+ dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
+
+ if (!pPixPriv->detachedImage) {
+ ScreenPtr pScreen = pPixmap->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+ pPixPriv->detachedImage = XGetImage(dmxScreen->beDisplay,
+ pPixPriv->pixmap,
+ 0, 0,
+ pPixmap->drawable.width,
+ pPixmap->drawable.height,
+ -1,
+ ZPixmap);
+ if (!pPixPriv->detachedImage)
+ dmxLog(dmxWarning, "Cannot save pixmap image\n");
+ }
+ }
+#else
+ /* NOTE: The only time there is a pixmap on another screen that
+ * corresponds to the one we are trying to save is when Xinerama is
+ * active. Otherwise, the pixmap image data is only stored on a
+ * single screen, which means that once it is detached, that data is
+ * lost. We could save the data here, but then that would require
+ * us to implement the ability for Xdmx to keep the pixmap up to
+ * date while the screen is detached, which is beyond the scope of
+ * the current project. */
+ return;
+#endif
+}
+
+/** Destroy resources on the back-end server. This function is called
+ * from #dmxDetachScreen() via the dix layer's FindAllResources
+ * function. It walks all resources, compares them to the screen
+ * number passed in as \a n and calls the appropriate DMX function to
+ * free the associated resource on the back-end server. */
+static void dmxBEDestroyResources(pointer value, XID id, RESTYPE type,
+ pointer n)
+{
+ int scrnNum = (int)n;
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+
+ if ((type & TypeMask) == (RT_WINDOW & TypeMask)) {
+ /* Window resources are destroyed below in dmxBEDestroyWindowTree */
+ } else if ((type & TypeMask) == (RT_PIXMAP & TypeMask)) {
+ PixmapPtr pPix = value;
+ if (pPix->drawable.pScreen->myNum == scrnNum) {
+ dmxBESavePixmap(pPix);
+ dmxBEFreePixmap(pPix);
+ }
+ } else if ((type & TypeMask) == (RT_GC & TypeMask)) {
+ GCPtr pGC = value;
+ if (pGC->pScreen->myNum == scrnNum)
+ dmxBEFreeGC(pGC);
+ } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
+ dmxBEFreeFont(pScreen, (FontPtr)value);
+ } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
+ dmxBEFreeCursor(pScreen, (CursorPtr)value);
+ } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
+ ColormapPtr pCmap = value;
+ if (pCmap->pScreen->myNum == scrnNum)
+ dmxBEFreeColormap((ColormapPtr)value);
+#ifdef RENDER
+ } else if ((type & TypeMask) == (PictureType & TypeMask)) {
+ PicturePtr pPict = value;
+ if (pPict->pDrawable->pScreen->myNum == scrnNum)
+ dmxBEFreePicture((PicturePtr)value);
+ } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
+ dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
+#endif
+ } else {
+ /* Other resource types??? */
+ }
+}
+
+/** Destroy the scratch GCs that are created per depth. */
+static void dmxBEDestroyScratchGCs(int scrnNum)
+{
+ ScreenPtr pScreen = screenInfo.screens[scrnNum];
+ GCPtr *ppGC = pScreen->GCperDepth;
+ int i;
+
+ for (i = 0; i <= pScreen->numDepths; i++)
+ dmxBEFreeGC(ppGC[i]);
+}
+
+/** Destroy window hierachy on back-end server. To ensure that all
+ * XDestroyWindow() calls succeed, they must be performed in a bottom
+ * up order so that windows are not destroyed before their children.
+ * XDestroyWindow(), which is called from #dmxBEDestrowWindow(), will
+ * destroy a window as well as all of it's children. */
+static void dmxBEDestroyWindowTree(int idx)
+{
+ WindowPtr pWin = WindowTable[idx];
+ WindowPtr pChild = pWin;
+
+ while (1) {
+ if (pChild->firstChild) {
+ pChild = pChild->firstChild;
+ continue;
+ }
+
+ /* Destroy the window */
+ dmxBEDestroyWindow(pChild);
+
+ /* Make sure we destroy the window's border and background
+ * pixmaps if they exist */
+ if (!pChild->borderIsPixel) {
+ dmxBESavePixmap(pChild->border.pixmap);
+ dmxBEFreePixmap(pChild->border.pixmap);
+ }
+ if (pChild->backgroundState == BackgroundPixmap) {
+ dmxBESavePixmap(pChild->background.pixmap);
+ dmxBEFreePixmap(pChild->background.pixmap);
+ }
+
+ while (!pChild->nextSib && (pChild != pWin)) {
+ pChild = pChild->parent;
+ dmxBEDestroyWindow(pChild);
+ if (!pChild->borderIsPixel) {
+ dmxBESavePixmap(pChild->border.pixmap);
+ dmxBEFreePixmap(pChild->border.pixmap);
+ }
+ if (pChild->backgroundState == BackgroundPixmap) {
+ dmxBESavePixmap(pChild->background.pixmap);
+ dmxBEFreePixmap(pChild->background.pixmap);
+ }
+ }
+
+ if (pChild == pWin)
+ break;
+
+ pChild = pChild->nextSib;
+ }
+}
+
+/** Detach back-end screen. */
+int dmxDetachScreen(int idx)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ int i;
+
+ /* Return failure if dynamic addition/removal of screens is disabled */
+ if (!dmxAddRemoveScreens) {
+ dmxLog(dmxWarning,
+ "Attempting to remove a screen, but the AddRemoveScreen\n");
+ dmxLog(dmxWarning,
+ "extension has not been enabled. To enable this extension\n");
+ dmxLog(dmxWarning,
+ "add the \"-addremovescreens\" option either to the command\n");
+ dmxLog(dmxWarning,
+ "line or in the configuration file.\n");
+ return 1;
+ }
+
+ /* Cannot remove a screen that does not exist */
+ if (idx < 0 || idx >= dmxNumScreens) return 1;
+
+ /* Cannot detach from a screen that is not opened */
+ if (!dmxScreen->beDisplay) {
+ dmxLog(dmxWarning,
+ "Attempting to remove screen #%d but it has not been opened\n",
+ idx);
+ return 1;
+ }
+
+ dmxLogOutput(dmxScreen, "Detaching screen #%d\n", idx);
+
+ /* Detach input */
+ dmxInputDetachAll(dmxScreen);
+
+ /* Save all relevant state (TODO) */
+
+ /* Free all non-window resources related to this screen */
+ for (i = currentMaxClients; --i >= 0; )
+ if (clients[i])
+ FindAllClientResources(clients[i], dmxBEDestroyResources,
+ (pointer)idx);
+
+ /* Free scratch GCs */
+ dmxBEDestroyScratchGCs(idx);
+
+ /* Free window resources related to this screen */
+ dmxBEDestroyWindowTree(idx);
+
+ /* Free default stipple */
+ dmxBESavePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
+ dmxBEFreePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
+
+ /* Free the remaining screen resources and close the screen */
+ dmxBECloseScreen(screenInfo.screens[idx]);
+
+ /* Adjust the cursor boundaries (paints detached console window) */
+ dmxAdjustCursorBoundaries();
+
+ return 0; /* Success */
+}
diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c
new file mode 100644
index 000000000..00ce18425
--- /dev/null
+++ b/hw/dmx/dmxinit.c
@@ -0,0 +1,1058 @@
+/* $XFree86$ */
+/*
+ * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <kem@redhat.com>
+ * David H. Dawes <dawes@xfree86.org>
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ * Provide expected functions for initialization from the ddx layer and
+ * global variables for the DMX server. */
+
+#include "dmx.h"
+#include "dmxinit.h"
+#include "dmxsync.h"
+#include "dmxlog.h"
+#include "dmxinput.h"
+#include "dmxscrinit.h"
+#include "dmxcursor.h"
+#include "dmxfont.h"
+#include "config/dmxconfig.h"
+#include "dmxcb.h"
+#include "dmxprop.h"
+#include "dmxstat.h"
+#ifdef RENDER
+#include "dmxpict.h"
+#endif
+
+#include "Xos.h" /* For gettimeofday */
+#include "dixstruct.h"
+#include "panoramiXsrv.h"
+
+#include <signal.h> /* For SIGQUIT */
+
+#ifdef GLXEXT
+#include <GL/glx.h>
+#include <GL/glxint.h>
+#include "dmx_glxvisuals.h"
+#include "Xext.h"
+#include "extutil.h"
+
+extern void GlxSetVisualConfigs(
+ int nconfigs,
+ __GLXvisualConfig *configs,
+ void **configprivs
+);
+#endif /* GLXEXT */
+
+extern void SetVendorRelease(int release); /* in dix/main.c */
+extern void SetVendorString(char *string); /* in dix/main.c */
+
+/* Global variables available to all Xserver/hw/dmx routines. */
+int dmxNumScreens;
+DMXScreenInfo *dmxScreens;
+
+int dmxNumInputs;
+DMXInputInfo *dmxInputs;
+
+int dmxShadowFB = FALSE;
+
+XErrorEvent dmxLastErrorEvent;
+Bool dmxErrorOccurred = FALSE;
+
+char *dmxFontPath = NULL;
+
+Bool dmxOffScreenOpt = TRUE;
+
+Bool dmxSubdividePrimitives = TRUE;
+
+Bool dmxLazyWindowCreation = TRUE;
+
+Bool dmxUseXKB = TRUE;
+
+int dmxDepth = 0;
+
+#ifndef GLXEXT
+static Bool dmxGLXProxy = FALSE;
+#else
+Bool dmxGLXProxy = TRUE;
+
+Bool dmxGLXSwapGroupSupport = TRUE;
+
+Bool dmxGLXSyncSwap = FALSE;
+
+Bool dmxGLXFinishSwap = FALSE;
+#endif
+
+Bool dmxIgnoreBadFontPaths = FALSE;
+
+Bool dmxAddRemoveScreens = FALSE;
+
+/* dmxErrorHandler catches errors that occur when calling one of the
+ * back-end servers. Some of this code is based on _XPrintDefaultError
+ * in xc/lib/X11/XlibInt.c */
+static int dmxErrorHandler(Display *dpy, XErrorEvent *ev)
+{
+#define DMX_ERROR_BUF_SIZE 256
+ /* RATS: these buffers are only used in
+ * length-limited calls. */
+ char buf[DMX_ERROR_BUF_SIZE];
+ char request[DMX_ERROR_BUF_SIZE];
+ _XExtension *ext = NULL;
+
+ dmxErrorOccurred = TRUE;
+ dmxLastErrorEvent = *ev;
+
+ XGetErrorText(dpy, ev->error_code, buf, sizeof(buf));
+ dmxLog(dmxWarning, "dmxErrorHandler: %s\n", buf);
+
+ /* Find major opcode name */
+ if (ev->request_code < 128) {
+ XmuSnprintf(request, sizeof(request), "%d", ev->request_code);
+ XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf));
+ } else {
+ for (ext = dpy->ext_procs;
+ ext && ext->codes.major_opcode != ev->request_code;
+ ext = ext->next);
+ if (ext) strncpy(buf, ext->name, sizeof(buf));
+ else buf[0] = '\0';
+ }
+ dmxLog(dmxWarning, " Major opcode: %d (%s)\n",
+ ev->request_code, buf);
+
+ /* Find minor opcode name */
+ if (ev->request_code >= 128 && ext) {
+ XmuSnprintf(request, sizeof(request), "%d", ev->request_code);
+ XmuSnprintf(request, sizeof(request), "%s.%d",
+ ext->name, ev->minor_code);
+ XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf));
+ dmxLog(dmxWarning, " Minor opcode: %d (%s)\n",
+ ev->minor_code, buf);
+ }
+
+ /* Provide value information */
+ switch (ev->error_code) {
+ case BadValue:
+ dmxLog(dmxWarning, " Value: 0x%x\n",
+ ev->resourceid);
+ break;
+ case BadAtom:
+ dmxLog(dmxWarning, " AtomID: 0x%x\n",
+ ev->resourceid);
+ break;
+ default:
+ dmxLog(dmxWarning, " ResourceID: 0x%x\n",
+ ev->resourceid);
+ break;
+ }
+
+ /* Provide serial number information */
+ dmxLog(dmxWarning, " Failed serial number: %d\n",
+ ev->serial);
+ dmxLog(dmxWarning, " Current serial number: %d\n",
+ dpy->request);
+ return 0;
+}
+
+#ifdef GLXEXT
+static int dmxNOPErrorHandler(Display *dpy, XErrorEvent *ev)
+{
+ return 0;
+}
+#endif
+
+Bool dmxOpenDisplay(DMXScreenInfo *dmxScreen)
+{
+ if (!(dmxScreen->beDisplay = XOpenDisplay(dmxScreen->name)))
+ return FALSE;
+
+ dmxPropertyDisplay(dmxScreen);
+ return TRUE;
+}
+
+void dmxSetErrorHandler(DMXScreenInfo *dmxScreen)
+{
+ XSetErrorHandler(dmxErrorHandler);
+}
+
+static void dmxPrintScreenInfo(DMXScreenInfo *dmxScreen)
+{
+ XWindowAttributes attribs;
+ int ndepths = 0, *depths = NULL;
+ int i;
+ Display *dpy = dmxScreen->beDisplay;
+ Screen *s = DefaultScreenOfDisplay(dpy);
+ int scr = DefaultScreen(dpy);
+
+ XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &attribs);
+ if (!(depths = XListDepths(dpy, scr, &ndepths))) ndepths = 0;
+
+ dmxLogOutput(dmxScreen, "Name of display: %s\n", DisplayString(dpy));
+ dmxLogOutput(dmxScreen, "Version number: %d.%d\n",
+ ProtocolVersion(dpy), ProtocolRevision(dpy));
+ dmxLogOutput(dmxScreen, "Vendor string: %s\n", ServerVendor(dpy));
+ if (!strstr(ServerVendor(dpy), "XFree86")) {
+ dmxLogOutput(dmxScreen, "Vendor release: %d\n", VendorRelease(dpy));
+ } else {
+ /* This code based on xdpyinfo.c */
+ int v = VendorRelease(dpy);
+ int major = -1, minor = -1, patch = -1, subpatch = -1;
+
+ if (v < 336)
+ major = v / 100, minor = (v / 10) % 10, patch = v % 10;
+ else if (v < 3900) {
+ major = v / 1000;
+ minor = (v / 100) % 10;
+ if (((v / 10) % 10) || (v % 10)) {
+ patch = (v / 10) % 10;
+ if (v % 10) subpatch = v % 10;
+ }
+ } else if (v < 40000000) {
+ major = v / 1000;
+ minor = (v / 10) % 10;
+ if (v % 10) patch = v % 10;
+ } else {
+ major = v / 10000000;
+ minor = (v / 100000) % 100;
+ patch = (v / 1000) % 100;
+ if (v % 1000) subpatch = v % 1000;
+ }
+ dmxLogOutput(dmxScreen, "Vendor release: %d (XFree86 version: %d.%d",
+ v, major, minor);
+ if (patch > 0) dmxLogOutputCont(dmxScreen, ".%d", patch);
+ if (subpatch > 0) dmxLogOutputCont(dmxScreen, ".%d", subpatch);
+ dmxLogOutputCont(dmxScreen, ")\n");
+ }
+
+
+ dmxLogOutput(dmxScreen, "Dimensions: %dx%d pixels\n",
+ attribs.width, attribs.height);
+ dmxLogOutput(dmxScreen, "%d depths on screen %d: ", ndepths, scr);
+ for (i = 0; i < ndepths; i++)
+ dmxLogOutputCont(dmxScreen, "%c%d", i ? ',' : ' ', depths[i]);
+ dmxLogOutputCont(dmxScreen, "\n");
+ dmxLogOutput(dmxScreen, "Depth of root window: %d plane%s (%d)\n",
+ attribs.depth, attribs.depth == 1 ? "" : "s",
+ DisplayPlanes(dpy, scr));
+ dmxLogOutput(dmxScreen, "Number of colormaps: %d min, %d max\n",
+ MinCmapsOfScreen(s), MaxCmapsOfScreen(s));
+ dmxLogOutput(dmxScreen, "Options: backing-store %s, save-unders %s\n",
+ (DoesBackingStore (s) == NotUseful) ? "no" :
+ ((DoesBackingStore (s) == Always) ? "yes" : "when mapped"),
+ DoesSaveUnders (s) ? "yes" : "no");
+ dmxLogOutput(dmxScreen, "Window Manager running: %s\n",
+ (dmxScreen->WMRunningOnBE) ? "yes" : "no");
+
+ if (dmxScreen->WMRunningOnBE) {
+ dmxLogOutputWarning(dmxScreen,
+ "Window manager running "
+ "-- colormaps not supported\n");
+ }
+ XFree(depths);
+}
+
+void dmxGetScreenAttribs(DMXScreenInfo *dmxScreen)
+{
+ XWindowAttributes attribs;
+ Display *dpy = dmxScreen->beDisplay;
+#ifdef GLXEXT
+ int dummy;
+#endif
+
+ XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &attribs);
+
+ dmxScreen->beWidth = attribs.width;
+ dmxScreen->beHeight = attribs.height;
+
+ /* Fill in missing geometry information */
+ if (dmxScreen->scrnXSign < 0) {
+ if (dmxScreen->scrnWidth) {
+ dmxScreen->scrnX = (attribs.width - dmxScreen->scrnWidth
+ - dmxScreen->scrnX);
+ } else {
+ dmxScreen->scrnWidth = attribs.width - dmxScreen->scrnX;
+ dmxScreen->scrnX = 0;
+ }
+ }
+ if (dmxScreen->scrnYSign < 0) {
+ if (dmxScreen->scrnHeight) {
+ dmxScreen->scrnY = (attribs.height - dmxScreen->scrnHeight
+ - dmxScreen->scrnY);
+ } else {
+ dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY;
+ dmxScreen->scrnY = 0;
+ }
+ }
+ if (!dmxScreen->scrnWidth)
+ dmxScreen->scrnWidth = attribs.width - dmxScreen->scrnX;
+ if (!dmxScreen->scrnHeight)
+ dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY;
+
+ if (!dmxScreen->rootWidth) dmxScreen->rootWidth = dmxScreen->scrnWidth;
+ if (!dmxScreen->rootHeight) dmxScreen->rootHeight = dmxScreen->scrnHeight;
+ if (dmxScreen->rootWidth + dmxScreen->rootX > dmxScreen->scrnWidth)
+ dmxScreen->rootWidth = dmxScreen->scrnWidth - dmxScreen->rootX;
+ if (dmxScreen->rootHeight + dmxScreen->rootY > dmxScreen->scrnHeight)
+ dmxScreen->rootHeight = dmxScreen->scrnHeight - dmxScreen->rootY;
+
+ /* FIXME: Get these from the back-end server */
+ dmxScreen->beXDPI = 75;
+ dmxScreen->beYDPI = 75;
+
+ dmxScreen->beDepth = attribs.depth; /* FIXME: verify that this
+ * works always. In
+ * particular, this will work
+ * well for depth=16, will fail
+ * because of colormap issues
+ * at depth 8. More work needs
+ * to be done here. */
+
+ if (dmxScreen->beDepth <= 8) dmxScreen->beBPP = 8;
+ else if (dmxScreen->beDepth <= 16) dmxScreen->beBPP = 16;
+ else dmxScreen->beBPP = 32;
+
+#ifdef GLXEXT
+ /* get the majorOpcode for the back-end GLX extension */
+ XQueryExtension(dpy, "GLX", &dmxScreen->glxMajorOpcode,
+ &dummy, &dmxScreen->glxErrorBase);
+#endif
+
+ dmxPrintScreenInfo(dmxScreen);
+ dmxLogOutput(dmxScreen, "%dx%d+%d+%d on %dx%d at depth=%d, bpp=%d\n",
+ dmxScreen->scrnWidth, dmxScreen->scrnHeight,
+ dmxScreen->scrnX, dmxScreen->scrnY,
+ dmxScreen->beWidth, dmxScreen->beHeight,
+ dmxScreen->beDepth, dmxScreen->beBPP);
+ if (dmxScreen->beDepth == 8)
+ dmxLogOutputWarning(dmxScreen,
+ "Support for depth == 8 is not complete\n");
+}
+
+Bool dmxGetVisualInfo(DMXScreenInfo *dmxScreen)
+{
+ int i;
+ XVisualInfo visinfo;
+
+ visinfo.screen = DefaultScreen(dmxScreen->beDisplay);
+ dmxScreen->beVisuals = XGetVisualInfo(dmxScreen->beDisplay,
+ VisualScreenMask,
+ &visinfo,
+ &dmxScreen->beNumVisuals);
+
+ dmxScreen->beDefVisualIndex = -1;
+
+ if (defaultColorVisualClass >= 0 || dmxDepth > 0) {
+ for (i = 0; i < dmxScreen->beNumVisuals; i++)
+ if (defaultColorVisualClass >= 0) {
+ if (dmxScreen->beVisuals[i].class == defaultColorVisualClass) {
+ if (dmxDepth > 0) {
+ if (dmxScreen->beVisuals[i].depth == dmxDepth) {
+ dmxScreen->beDefVisualIndex = i;
+ break;
+ }
+ } else {
+ dmxScreen->beDefVisualIndex = i;
+ break;
+ }
+ }
+ } else if (dmxScreen->beVisuals[i].depth == dmxDepth) {
+ dmxScreen->beDefVisualIndex = i;
+ break;
+ }
+ } else {
+ visinfo.visualid =
+ XVisualIDFromVisual(DefaultVisual(dmxScreen->beDisplay,
+ visinfo.screen));
+
+ for (i = 0; i < dmxScreen->beNumVisuals; i++)
+ if (visinfo.visualid == dmxScreen->beVisuals[i].visualid) {
+ dmxScreen->beDefVisualIndex = i;
+ break;
+ }
+ }
+
+ for (i = 0; i < dmxScreen->beNumVisuals; i++)
+ dmxLogVisual(dmxScreen, &dmxScreen->beVisuals[i],
+ (i == dmxScreen->beDefVisualIndex));
+
+ return (dmxScreen->beDefVisualIndex >= 0);
+}
+
+void dmxGetColormaps(DMXScreenInfo *dmxScreen)
+{
+ int i;
+
+ dmxScreen->beNumDefColormaps = dmxScreen->beNumVisuals;
+ dmxScreen->beDefColormaps = xalloc(dmxScreen->beNumDefColormaps *
+ sizeof(*dmxScreen->beDefColormaps));
+
+ for (i = 0; i < dmxScreen->beNumDefColormaps; i++)
+ dmxScreen->beDefColormaps[i] =
+ XCreateColormap(dmxScreen->beDisplay,
+ DefaultRootWindow(dmxScreen->beDisplay),
+ dmxScreen->beVisuals[i].visual,
+ AllocNone);
+
+ dmxScreen->beBlackPixel = BlackPixel(dmxScreen->beDisplay,
+ DefaultScreen(dmxScreen->beDisplay));
+ dmxScreen->beWhitePixel = WhitePixel(dmxScreen->beDisplay,
+ DefaultScreen(dmxScreen->beDisplay));
+}
+
+void dmxGetPixmapFormats(DMXScreenInfo *dmxScreen)
+{
+ dmxScreen->beDepths =
+ XListDepths(dmxScreen->beDisplay, DefaultScreen(dmxScreen->beDisplay),
+ &dmxScreen->beNumDepths);
+
+ dmxScreen->bePixmapFormats =
+ XListPixmapFormats(dmxScreen->beDisplay,
+ &dmxScreen->beNumPixmapFormats);
+}
+
+static Bool dmxSetPixmapFormats(ScreenInfo *pScreenInfo,
+ DMXScreenInfo *dmxScreen)
+{
+ XPixmapFormatValues *bePixmapFormat;
+ PixmapFormatRec *format;
+ int i, j;
+
+ pScreenInfo->imageByteOrder = ImageByteOrder(dmxScreen->beDisplay);
+ pScreenInfo->bitmapScanlineUnit = BitmapUnit(dmxScreen->beDisplay);
+ pScreenInfo->bitmapScanlinePad = BitmapPad(dmxScreen->beDisplay);
+ pScreenInfo->bitmapBitOrder = BitmapBitOrder(dmxScreen->beDisplay);
+
+ pScreenInfo->numPixmapFormats = 0;
+ for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
+ bePixmapFormat = &dmxScreen->bePixmapFormats[i];
+ for (j = 0; j < dmxScreen->beNumDepths; j++)
+ if ((bePixmapFormat->depth == 1) ||
+ (bePixmapFormat->depth == dmxScreen->beDepths[j])) {
+ format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats];
+
+ format->depth = bePixmapFormat->depth;
+ format->bitsPerPixel = bePixmapFormat->bits_per_pixel;
+ format->scanlinePad = bePixmapFormat->scanline_pad;
+
+ pScreenInfo->numPixmapFormats++;
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+void dmxCheckForWM(DMXScreenInfo *dmxScreen)
+{
+ Status status;
+ XWindowAttributes xwa;
+
+ status = XGetWindowAttributes(dmxScreen->beDisplay,
+ DefaultRootWindow(dmxScreen->beDisplay),
+ &xwa);
+ dmxScreen->WMRunningOnBE =
+ (status &&
+ ((xwa.all_event_masks & SubstructureRedirectMask) ||
+ (xwa.all_event_masks & SubstructureNotifyMask)));
+}
+
+/** Initialize the display and collect relevant information about the
+ * display properties */
+static void dmxDisplayInit(DMXScreenInfo *dmxScreen)
+{
+ if (!dmxOpenDisplay(dmxScreen))
+ dmxLog(dmxFatal,
+ "dmxOpenDisplay: Unable to open display %s\n",
+ dmxScreen->name);
+
+ dmxSetErrorHandler(dmxScreen);
+ dmxCheckForWM(dmxScreen);
+ dmxGetScreenAttribs(dmxScreen);
+
+ if (!dmxGetVisualInfo(dmxScreen))
+ dmxLog(dmxFatal, "dmxGetVisualInfo: No matching visuals found\n");
+
+ dmxGetColormaps(dmxScreen);
+ dmxGetPixmapFormats(dmxScreen);
+}
+
+/* If this doesn't compile, just add || defined(yoursystem) to the line
+ * below. This information is to help with bug reports and is not
+ * critical. */
+#if !defined(_POSIX_SOURCE) && !defined(__sgi)
+static const char *dmxExecOS(void) { return ""; }
+#else
+#include <sys/utsname.h>
+static const char *dmxExecOS(void)
+{
+ static char buffer[128];
+ static int initialized = 0;
+ struct utsname u;
+
+ if (!initialized++) {
+ memset(buffer, 0, sizeof(buffer));
+ uname(&u);
+ XmuSnprintf(buffer, sizeof(buffer)-1, "%s %s %s",
+ u.sysname, u.release, u.version);
+ }
+ return buffer;
+}
+#endif
+
+static const char *dmxBuildCompiler(void)
+{
+ static char buffer[128];
+ static int initialized = 0;
+
+ if (!initialized++) {
+ memset(buffer, 0, sizeof(buffer));
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) &&defined(__GNUC_PATCHLEVEL__)
+ XmuSnprintf(buffer, sizeof(buffer)-1, "gcc %d.%d.%d",
+ __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
+#elif defined(__sgi) && defined(_COMPILER_VERSION) && !defined(__GNUC__)
+ {
+ int a = _COMPILER_VERSION / 100;
+ int b = (_COMPILER_VERSION - a * 100) / 10;
+ int c = _COMPILER_VERSION - a * 100 - b * 10;
+ XmuSnprintf(buffer, sizeof(buffer)-1, "SGI MIPSpro %d.%d.%d",
+ a, b, c);
+ }
+#endif
+ }
+ return buffer;
+}
+
+static const char *dmxExecHost(void)
+{
+ static char buffer[128];
+ static int initialized = 0;
+
+ if (!initialized++) {
+ memset(buffer, 0, sizeof(buffer));
+ XmuGetHostname(buffer, sizeof(buffer) - 1);
+ }
+ return buffer;
+}
+
+/** This routine is called in Xserver/dix/main.c from \a main(). */
+void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
+{
+ int i;
+ static unsigned long dmxGeneration = 0;
+#ifdef GLXEXT
+ Bool glxSupported = TRUE;
+#endif
+
+ if (dmxGeneration != serverGeneration) {
+ int vendrel = VENDOR_RELEASE;
+ int major, minor, year, month, day;
+
+ dmxGeneration = serverGeneration;
+
+ major = vendrel / 100000000;
+ vendrel -= major * 100000000;
+ minor = vendrel / 1000000;
+ vendrel -= minor * 1000000;
+ year = vendrel / 10000;
+ vendrel -= year * 10000;
+ month = vendrel / 100;
+ vendrel -= month * 100;
+ day = vendrel;
+
+ /* Add other epoch tests here */
+ if (major > 0 && minor > 0) year += 2000;
+
+ dmxLog(dmxInfo, "Generation: %d\n", dmxGeneration);
+ dmxLog(dmxInfo, "DMX version: %d.%d.%02d%02d%02d (%s)\n",
+ major, minor, year, month, day, VENDOR_STRING);
+
+ SetVendorRelease(VENDOR_RELEASE);
+ SetVendorString(VENDOR_STRING);
+
+ if (dmxGeneration == 1) {
+ dmxLog(dmxInfo, "DMX Build OS: %s (%s)\n", OSNAME, OSVENDOR);
+ dmxLog(dmxInfo, "DMX Build Compiler: %s\n", dmxBuildCompiler());
+ dmxLog(dmxInfo, "DMX Execution OS: %s\n", dmxExecOS());
+ dmxLog(dmxInfo, "DMX Execution Host: %s\n", dmxExecHost());
+ }
+ dmxLog(dmxInfo, "MAXSCREENS: %d\n", MAXSCREENS);
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ if (dmxScreens[i].beDisplay)
+ dmxLog(dmxWarning, "Display \"%s\" still open\n",
+ dmxScreens[i].name);
+ dmxStatFree(dmxScreens[i].stat);
+ dmxScreens[i].stat = NULL;
+ }
+ for (i = 0; i < dmxNumInputs; i++) dmxInputFree(&dmxInputs[i]);
+ if (dmxScreens) free(dmxScreens);
+ if (dmxInputs) free(dmxInputs);
+ dmxScreens = NULL;
+ dmxInputs = NULL;
+ dmxNumScreens = 0;
+ dmxNumInputs = 0;
+ }
+
+ /* Make sure that the command-line arguments are sane. */
+ if (dmxAddRemoveScreens && (!noRenderExtension || dmxGLXProxy)) {
+ /* Currently it is not possible to support GLX and Render
+ * extensions with dynamic screen addition/removal due to the
+ * state that each extension keeps, which cannot be restored. */
+ dmxLog(dmxWarning,
+ "GLX Proxy and Render extensions do not yet support dynamic\n");
+ dmxLog(dmxWarning,
+ "screen addition and removal. Please specify -noglxproxy\n");
+ dmxLog(dmxWarning,
+ "and -norender on the command line or in the configuration\n");
+ dmxLog(dmxWarning,
+ "file to disable these two extensions if you wish to use\n");
+ dmxLog(dmxWarning,
+ "the dynamic addition and removal of screens support.\n");
+ dmxLog(dmxFatal,
+ "Dynamic screen addition/removal error (see above).\n");
+ }
+
+ /* ddxProcessArgument has been called at this point, but any data
+ * from the configuration file has not been applied. Do so, and be
+ * sure we have at least one back-end display. */
+ dmxConfigConfigure();
+ if (!dmxNumScreens)
+ dmxLog(dmxFatal, "InitOutput: no back-end displays found\n");
+ if (!dmxNumInputs)
+ dmxLog(dmxInfo, "InitOutput: no inputs found\n");
+
+ /* Disable lazy window creation optimization if offscreen
+ * optimization is disabled */
+ if (!dmxOffScreenOpt && dmxLazyWindowCreation) {
+ dmxLog(dmxInfo,
+ "InitOutput: Disabling lazy window creation optimization\n");
+ dmxLog(dmxInfo,
+ " since it requires the offscreen optimization\n");
+ dmxLog(dmxInfo,
+ " to function properly.\n");
+ dmxLazyWindowCreation = FALSE;
+ }
+
+ /* Open each display and gather information about it. */
+ for (i = 0; i < dmxNumScreens; i++)
+ dmxDisplayInit(&dmxScreens[i]);
+
+#if PANORAMIX
+ /* Register a Xinerama callback which will run from within
+ * PanoramiXCreateConnectionBlock. We can use the callback to
+ * determine if Xinerama is loaded and to check the visuals
+ * determined by PanoramiXConsolidate. */
+ XineramaRegisterConnectionBlockCallback(dmxConnectionBlockCallback);
+#endif
+
+ /* Since we only have a single screen thus far, we only need to set
+ the pixmap formats to match that screen. FIXME: this isn't true.*/
+ if (!dmxSetPixmapFormats(pScreenInfo, &dmxScreens[0])) return;
+
+ /* Might want to install a signal handler to allow cleaning up after
+ * unexpected signals. The DIX/OS layer already handles SIGINT and
+ * SIGTERM, so everything is OK for expected signals. --DD
+ *
+ * SIGHUP, SIGINT, and SIGTERM are trapped in os/connection.c
+ * SIGQUIT is another common signal that is sent from the keyboard.
+ * Trap it here, to ensure that the keyboard modifier map and other
+ * state for the input devices are restored. (This makes the
+ * behavior of SIGQUIT somewhat unexpected, since it will be the
+ * same as the behavior of SIGINT. However, leaving the modifier
+ * map of the input devices empty is even more unexpected.) --RF
+ */
+ OsSignal(SIGQUIT, GiveUp);
+
+#ifdef GLXEXT
+ /* Check if GLX extension exists on all back-end servers */
+ for (i = 0; i < dmxNumScreens; i++)
+ glxSupported &= (dmxScreens[i].glxMajorOpcode > 0);
+#endif
+
+ /* Tell dix layer about the backend displays */
+ for (i = 0; i < dmxNumScreens; i++) {
+
+#ifdef GLXEXT
+ if (glxSupported) {
+ /*
+ * Builds GLX configurations from the list of visuals
+ * supported by the back-end server, and give that
+ * configuration list to the glx layer - so that he will
+ * build the visuals accordingly.
+ */
+
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+ __GLXvisualConfig *configs = NULL;
+ dmxGlxVisualPrivate **configprivs = NULL;
+ int nconfigs = 0;
+ int (*oldErrorHandler)(Display *, XErrorEvent *);
+ int i;
+
+ /* Catch errors if when using an older GLX w/o FBconfigs */
+ oldErrorHandler = XSetErrorHandler(dmxNOPErrorHandler);
+
+ /* Get FBConfigs of the back-end server */
+ dmxScreen->fbconfigs = GetGLXFBConfigs(dmxScreen->beDisplay,
+ dmxScreen->glxMajorOpcode,
+ &dmxScreen->numFBConfigs);
+
+ XSetErrorHandler(oldErrorHandler);
+
+ dmxScreen->glxVisuals =
+ GetGLXVisualConfigs(dmxScreen->beDisplay,
+ DefaultScreen(dmxScreen->beDisplay),
+ &dmxScreen->numGlxVisuals);
+
+ if (dmxScreen->fbconfigs) {
+ configs =
+ GetGLXVisualConfigsFromFBConfigs(dmxScreen->fbconfigs,
+ dmxScreen->numFBConfigs,
+ dmxScreen->beVisuals,
+ dmxScreen->beNumVisuals,
+ dmxScreen->glxVisuals,
+ dmxScreen->numGlxVisuals,
+ &nconfigs);
+ } else {
+ configs = dmxScreen->glxVisuals;
+ nconfigs = dmxScreen->numGlxVisuals;
+ }
+
+ configprivs = xalloc(dmxScreen->beNumVisuals *
+ sizeof(dmxGlxVisualPrivate*));
+
+ if (configs != NULL && configprivs != NULL) {
+
+ /* Initialize our private info for each visual
+ * (currently only x_visual_depth and x_visual_class)
+ */
+ for (i = 0; i < nconfigs; i++) {
+
+ configprivs[i] = (dmxGlxVisualPrivate *)
+ xalloc(sizeof(dmxGlxVisualPrivate));
+ configprivs[i]->x_visual_depth = 0;
+ configprivs[i]->x_visual_class = 0;
+
+ /* Find the visual depth */
+ if (configs[i].vid > 0) {
+ int j;
+ for (j = 0; j < dmxScreen->beNumVisuals; j++) {
+ if (dmxScreen->beVisuals[j].visualid ==
+ configs[i].vid) {
+ configprivs[i]->x_visual_depth =
+ dmxScreen->beVisuals[j].depth;
+ configprivs[i]->x_visual_class =
+ dmxScreen->beVisuals[j].class;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Hand out the glx configs to glx extension */
+ GlxSetVisualConfigs(nconfigs, configs, (void**)configprivs);
+ }
+ }
+#endif /* GLXEXT */
+
+ AddScreen(dmxScreenInit, argc, argv);
+ }
+
+ /* Compute origin information. */
+ dmxInitOrigins();
+
+ /* Compute overlap information. */
+ dmxInitOverlap();
+
+ /* Make sure there is a global width/height available */
+ dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX);
+
+ /* FIXME: The following is temporarily placed here. When the DMX
+ * extension is available, it will be move there.
+ */
+ dmxInitFonts();
+
+#ifdef RENDER
+ /* Initialize the render extension */
+ if (!noRenderExtension)
+ dmxInitRender();
+#endif
+
+ /* Initialized things that need timer hooks */
+ dmxStatInit();
+ dmxSyncInit(); /* Calls RegisterBlockAndWakeupHandlers */
+
+ dmxLog(dmxInfo, "Shadow framebuffer support %s\n",
+ dmxShadowFB ? "enabled" : "disabled");
+}
+
+/* RATS: Assuming the fp string (which comes from the command-line argv
+ vector) is NULL-terminated, the buffer is large enough for the
+ strcpy. */
+static void dmxSetDefaultFontPath(char *fp)
+{
+ int fplen = strlen(fp) + 1;
+
+ if (dmxFontPath) {
+ int len;
+
+ len = strlen(dmxFontPath);
+ dmxFontPath = xrealloc(dmxFontPath, len+fplen+1);
+ dmxFontPath[len] = ',';
+ strncpy(&dmxFontPath[len+1], fp, fplen);
+ } else {
+ dmxFontPath = xalloc(fplen);
+ strncpy(dmxFontPath, fp, fplen);
+ }
+
+ defaultFontPath = dmxFontPath;
+}
+
+/** This function is called in Xserver/os/utils.c from \a AbortServer().
+ * We must ensure that backend and console state is restored in the
+ * event the server shutdown wasn't clean. */
+void AbortDDX(void)
+{
+ int i;
+
+ for (i=0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+ if (dmxScreen->beDisplay) XCloseDisplay(dmxScreen->beDisplay);
+ dmxScreen->beDisplay = NULL;
+ }
+}
+
+/** This function is called in Xserver/dix/main.c from \a main() when
+ * dispatchException & DE_TERMINATE (which is the only way to exit the
+ * main loop without an interruption. */
+void ddxGiveUp(void)
+{
+ AbortDDX();
+}
+
+/** This function is called in Xserver/os/osinit.c from \a OsInit(). */
+void OsVendorInit(void)
+{
+}
+
+/** This function is called in Xserver/os/utils.c from \a FatalError()
+ * and \a VFatalError(). (Note that setting the function pointer \a
+ * OsVendorVErrorFProc will cause \a VErrorF() (which is called by the
+ * two routines mentioned here, as well as by others) to use the
+ * referenced routine instead of \a vfprintf().) */
+void OsVendorFatalError(void)
+{
+}
+
+/** This funciton is called by InitGlobals from Xserver/os/utils.c to
+ * initialize any ddx specific globals at a very early point in the
+ * server startup. */
+void ddxInitGlobals(void)
+{
+}
+
+/** Process our command line arguments. */
+int ddxProcessArgument(int argc, char *argv[], int i)
+{
+ int retval = 0;
+
+ if (!strcmp(argv[i], "-display")) {
+ if (++i < argc) dmxConfigStoreDisplay(argv[i]);
+ retval = 2;
+ } else if (!strcmp(argv[i], "-inputfrom") || !strcmp(argv[i], "-input")) {
+ if (++i < argc) dmxConfigStoreInput(argv[i]);
+ retval = 2;
+ } else if (!strcmp(argv[i], "-xinputfrom") || !strcmp(argv[i],"-xinput")) {
+ if (++i < argc) dmxConfigStoreXInput(argv[i]);
+ retval = 2;
+ } else if (!strcmp(argv[i], "-noshadowfb")) {
+ dmxLog(dmxWarning,
+ "-noshadowfb has been deprecated "
+ "since it is now the default\n");
+ dmxShadowFB = FALSE;
+ retval = 1;
+ } else if (!strcmp(argv[i], "-nomulticursor")) {
+ dmxCursorNoMulti();
+ retval = 1;
+ } else if (!strcmp(argv[i], "-shadowfb")) {
+ dmxShadowFB = TRUE;
+ retval = 1;
+ } else if (!strcmp(argv[i], "-configfile")) {
+ if (++i < argc) dmxConfigStoreFile(argv[i]);
+ retval = 2;
+ } else if (!strcmp(argv[i], "-config")) {
+ if (++i < argc) dmxConfigStoreConfig(argv[i]);
+ retval = 2;
+ } else if (!strcmp(argv[i], "-fontpath")) {
+ if (++i < argc) dmxSetDefaultFontPath(argv[i]);
+ retval = 2;
+ } else if (!strcmp(argv[i], "-stat")) {
+ if ((i += 2) < argc) dmxStatActivate(argv[i-1], argv[i]);
+ retval = 3;
+ } else if (!strcmp(argv[i], "-syncbatch")) {
+ if (++i < argc) dmxSyncActivate(argv[i]);
+ retval = 2;
+ } else if (!strcmp(argv[i], "-nooffscreenopt")) {
+ dmxOffScreenOpt = FALSE;
+ retval = 1;
+ } else if (!strcmp(argv[i], "-nosubdivprims")) {
+ dmxSubdividePrimitives = FALSE;
+ retval = 1;
+ } else if (!strcmp(argv[i], "-nowindowopt")) {
+ dmxLazyWindowCreation = FALSE;
+ retval = 1;
+ } else if (!strcmp(argv[i], "-noxkb")) {
+ dmxUseXKB = FALSE;
+ retval = 1;
+ } else if (!strcmp(argv[i], "-depth")) {
+ if (++i < argc) dmxDepth = atoi(argv[i]);
+ retval = 2;
+ } else if (!strcmp(argv[i], "-norender")) {
+ noRenderExtension = TRUE;
+ retval = 1;
+#ifdef GLXEXT
+ } else if (!strcmp(argv[i], "-noglxproxy")) {
+ dmxGLXProxy = FALSE;
+ retval = 1;
+ } else if (!strcmp(argv[i], "-noglxswapgroup")) {
+ dmxGLXSwapGroupSupport = FALSE;
+ retval = 1;
+ } else if (!strcmp(argv[i], "-glxsyncswap")) {
+ dmxGLXSyncSwap = TRUE;
+ retval = 1;
+ } else if (!strcmp(argv[i], "-glxfinishswap")) {
+ dmxGLXFinishSwap = TRUE;
+ retval = 1;
+#endif
+ } else if (!strcmp(argv[i], "-ignorebadfontpaths")) {
+ dmxIgnoreBadFontPaths = TRUE;
+ retval = 1;
+ } else if (!strcmp(argv[i], "-addremovescreens")) {
+ dmxAddRemoveScreens = TRUE;
+ retval = 1;
+ } else if (!strcmp(argv[i], "-param")) {
+ if ((i += 2) < argc) {
+ if (!strcasecmp(argv[i-1], "xkbrules"))
+ dmxConfigSetXkbRules(argv[i]);
+ else if (!strcasecmp(argv[i-1], "xkbmodel"))
+ dmxConfigSetXkbModel(argv[i]);
+ else if (!strcasecmp(argv[i-1], "xkblayout"))
+ dmxConfigSetXkbLayout(argv[i]);
+ else if (!strcasecmp(argv[i-1], "xkbvariant"))
+ dmxConfigSetXkbVariant(argv[i]);
+ else if (!strcasecmp(argv[i-1], "xkboptions"))
+ dmxConfigSetXkbOptions(argv[i]);
+ else
+ dmxLog(dmxWarning,
+ "-param requires: XkbRules, XkbModel, XkbLayout,"
+ " XkbVariant, or XkbOptions\n");
+ }
+ retval = 3;
+ }
+ if (!serverGeneration) dmxConfigSetMaxScreens();
+ return retval;
+}
+
+/** Provide succinct usage information for the DMX server. */
+void ddxUseMsg(void)
+{
+ ErrorF("\n\nDevice Dependent Usage:\n");
+ ErrorF("-display string Specify the back-end display(s)\n");
+ ErrorF("-input string Specify input source for core device\n");
+ ErrorF("-xinput string Specify input source for XInput device\n");
+ ErrorF("-shadowfb Enable shadow frame buffer\n");
+ ErrorF("-configfile file Read from a configuration file\n");
+ ErrorF("-config config Select a specific configuration\n");
+ ErrorF("-nomulticursor Turn of multiple cursor support\n");
+ ErrorF("-fontpath Sets the default font path\n");
+ ErrorF("-stat inter scrns Print out performance statistics\n");
+ ErrorF("-syncbatch inter Set interval for XSync batching\n");
+ ErrorF("-nooffscreenopt Disable offscreen optimization\n");
+ ErrorF("-nosubdivprims Disable primitive subdivision\n");
+ ErrorF(" optimization\n");
+ ErrorF("-nowindowopt Disable lazy window creation optimization\n");
+ ErrorF("-noxkb Disable use of the XKB extension with\n");
+ ErrorF(" backend displays (cf. -kb).\n");
+ ErrorF("-depth Specify the default root window depth\n");
+ ErrorF("-norender Disable RENDER extension support\n");
+#ifdef GLXEXT
+ ErrorF("-noglxproxy Disable GLX Proxy\n");
+ ErrorF("-noglxswapgroup Disable swap group and swap barrier\n");
+ ErrorF(" extensions in GLX proxy\n");
+ ErrorF("-glxsyncswap Force XSync after swap buffers\n");
+ ErrorF("-glxfinishswap Force glFinish after swap buffers\n");
+#endif
+ ErrorF("-ignorebadfontpaths Ignore bad font paths during initialization\n");
+ ErrorF("-addremovescreens Enable dynamic screen addition/removal\n");
+ ErrorF("-param ... Specify configuration parameters (e.g.,\n");
+ ErrorF(" XkbRules, XkbModel, XkbLayout, etc.)\n");
+ ErrorF("\n");
+ ErrorF(" If the -input string matches a -display string, then input\n"
+ " is taken from that backend display. (XInput cannot be taken\n"
+ " from a backend display.) Placing \",console\" after the\n"
+ " display name will force a console window to be opened on\n"
+ " that display in addition to the backend input. This is\n"
+ " useful if the backend window does not cover the whole\n"
+ " physical display.\n\n");
+
+ ErrorF(" Otherwise, if the -input or -xinput string specifies another\n"
+ " X display, then a console window will be created on that\n"
+ " display. Placing \",windows\" or \",nowindows\" after the\n"
+ " display name will control the display of window outlines in\n"
+ " the console.\n\n");
+
+ ErrorF(" -input or -xinput dummy specifies no input.\n");
+ ErrorF(" -input or -xinput local specifies the use of a raw keyboard,\n"
+ " mouse, or other (extension) device:\n"
+ " -input local,kbd,ps2 will use a ps2 mouse\n"
+ " -input local,kbd,ms will use a serial mouse\n"
+ " -input local,usb-kbd,usb-mou will use USB devices \n"
+ " -xinput local,usb-oth will use a non-mouse and\n"
+ " non-keyboard USB device with XInput\n\n");
+
+ ErrorF(" Special Keys:\n");
+ ErrorF(" Ctrl-Alt-g Server grab/ungrab (console only)\n");
+ ErrorF(" Ctrl-Alt-f Fine (1-pixel) mouse mode (console only)\n");
+ ErrorF(" Ctrl-Alt-q Quit (core devices only)\n");
+ ErrorF(" Ctrl-Alt-F* Switch to VC (local only)\n");
+}
+
+#ifdef DDXTIME
+/** Return wall-clock time in milliseconds. */
+CARD32 GetTimeInMillis(void)
+{
+ struct timeval tp;
+
+ gettimeofday(&tp, 0);
+ return tp.tv_sec * 1000 + tp.tv_usec / 1000;
+}
+#endif
diff --git a/hw/dmx/dmxwindow.c b/hw/dmx/dmxwindow.c
new file mode 100644
index 000000000..2db72d795
--- /dev/null
+++ b/hw/dmx/dmxwindow.c
@@ -0,0 +1,1081 @@
+/* $XFree86$ */
+/*
+ * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <kem@redhat.com>
+ *
+ */
+
+/** \file
+ * This file provides support for window-related functions. */
+
+#include "dmx.h"
+#include "dmxsync.h"
+#include "dmxwindow.h"
+#include "dmxpixmap.h"
+#include "dmxcmap.h"
+#include "dmxvisual.h"
+#include "dmxinput.h"
+#include "dmxextension.h"
+#ifdef RENDER
+#include "dmxpict.h"
+#endif
+
+#include "windowstr.h"
+
+static void dmxDoRestackWindow(WindowPtr pWindow);
+static void dmxDoChangeWindowAttributes(WindowPtr pWindow,
+ unsigned long *mask,
+ XSetWindowAttributes *attribs);
+
+#ifdef SHAPE
+static void dmxDoSetShape(WindowPtr pWindow);
+#endif
+
+/** Initialize the private area for the window functions. */
+Bool dmxInitWindow(ScreenPtr pScreen)
+{
+ if (!AllocateWindowPrivate(pScreen, dmxWinPrivateIndex,
+ sizeof(dmxWinPrivRec)))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+Window dmxCreateRootWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ Window parent;
+ Visual *visual;
+ unsigned long mask;
+ XSetWindowAttributes attribs;
+ ColormapPtr pCmap;
+ dmxColormapPrivPtr pCmapPriv;
+
+ /* Create root window */
+
+ parent = dmxScreen->scrnWin; /* This is our "Screen" window */
+ visual = dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual;
+
+ pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), RT_COLORMAP);
+ pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
+
+ mask = CWEventMask | CWBackingStore | CWColormap | CWBorderPixel;
+ attribs.event_mask = ExposureMask;
+ attribs.backing_store = NotUseful;
+ attribs.colormap = pCmapPriv->cmap;
+ attribs.border_pixel = 0;
+
+ /* Incorporate new attributes, if needed */
+ if (pWinPriv->attribMask) {
+ dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs);
+ mask |= pWinPriv->attribMask;
+ }
+
+ return XCreateWindow(dmxScreen->beDisplay,
+ parent,
+ pWindow->origin.x - wBorderWidth(pWindow),
+ pWindow->origin.y - wBorderWidth(pWindow),
+ pWindow->drawable.width,
+ pWindow->drawable.height,
+ pWindow->borderWidth,
+ pWindow->drawable.depth,
+ pWindow->drawable.class,
+ visual,
+ mask,
+ &attribs);
+}
+
+/** Change the location and size of the "screen" window. Called from
+ * #dmxReconfigureScreenWindow(). */
+void dmxResizeScreenWindow(ScreenPtr pScreen,
+ int x, int y, int w, int h)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ unsigned int m;
+ XWindowChanges c;
+
+ if (!dmxScreen->beDisplay)
+ return;
+
+ /* Handle resizing on back-end server */
+ m = CWX | CWY | CWWidth | CWHeight;
+ c.x = x;
+ c.y = y;
+ c.width = w;
+ c.height = h;
+
+ XConfigureWindow(dmxScreen->beDisplay, dmxScreen->scrnWin, m, &c);
+ dmxSync(dmxScreen, False);
+}
+
+/** Change the location and size of the "root" window. Called from
+ * #dmxReconfigureRootWindow(). */
+void dmxResizeRootWindow(WindowPtr pRoot,
+ int x, int y, int w, int h)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pRoot->drawable.pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pRoot);
+ unsigned int m;
+ XWindowChanges c;
+
+ /* Handle resizing on back-end server */
+ if (dmxScreen->beDisplay) {
+ m = CWX | CWY | CWWidth | CWHeight;
+ c.x = x;
+ c.y = y;
+ c.width = (w > 0) ? w : 1;
+ c.height = (h > 0) ? h : 1;
+
+ XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+ }
+
+ if (w == 0 || h == 0) {
+ if (pWinPriv->mapped) {
+ if (dmxScreen->beDisplay)
+ XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window);
+ pWinPriv->mapped = FALSE;
+ }
+ } else if (!pWinPriv->mapped) {
+ if (dmxScreen->beDisplay)
+ XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
+ pWinPriv->mapped = TRUE;
+ }
+
+ if (dmxScreen->beDisplay)
+ dmxSync(dmxScreen, False);
+}
+
+void dmxGetDefaultWindowAttributes(WindowPtr pWindow,
+ Colormap *cmap,
+ Visual **visual)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+
+ if (pWindow->drawable.class != InputOnly &&
+ pWindow->optional &&
+ pWindow->optional->visual != wVisual(pWindow->parent)) {
+
+ /* Find the matching visual */
+ *visual = dmxLookupVisualFromID(pScreen, wVisual(pWindow));
+
+ /* Handle optional colormaps */
+ if (pWindow->optional->colormap) {
+ ColormapPtr pCmap;
+ dmxColormapPrivPtr pCmapPriv;
+
+ pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow),
+ RT_COLORMAP);
+ pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
+ *cmap = pCmapPriv->cmap;
+ } else {
+ *cmap = dmxColormapFromDefaultVisual(pScreen, *visual);
+ }
+ } else {
+ *visual = CopyFromParent;
+ *cmap = (Colormap)0;
+ }
+}
+
+static Window dmxCreateNonRootWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ Window parent;
+ unsigned long mask = 0L;
+ XSetWindowAttributes attribs;
+ dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent);
+
+ /* Create window on back-end server */
+
+ parent = pParentPriv->window;
+
+ /* The parent won't exist if this call to CreateNonRootWindow came
+ from ReparentWindow and the grandparent window has not yet been
+ created */
+ if (!parent) {
+ dmxCreateAndRealizeWindow(pWindow->parent, FALSE);
+ parent = pParentPriv->window;
+ }
+
+ /* Incorporate new attributes, if needed */
+ if (pWinPriv->attribMask) {
+ dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs);
+ mask |= pWinPriv->attribMask;
+ }
+
+ /* Add in default attributes */
+ if (pWindow->drawable.class != InputOnly) {
+ mask |= CWBackingStore;
+ attribs.backing_store = NotUseful;
+
+ if (!(mask & CWColormap) && pWinPriv->cmap) {
+ mask |= CWColormap;
+ attribs.colormap = pWinPriv->cmap;
+ if (!(mask & CWBorderPixel)) {
+ mask |= CWBorderPixel;
+ attribs.border_pixel = 0;
+ }
+ }
+ }
+
+ /* Handle case where subwindows are being mapped, but created out of
+ order -- if current window has a previous sibling, then it cannot
+ be created on top of the stack, so we must restack the windows */
+ pWinPriv->restacked = (pWindow->prevSib != NullWindow);
+
+ return XCreateWindow(dmxScreen->beDisplay,
+ parent,
+ pWindow->origin.x - wBorderWidth(pWindow),
+ pWindow->origin.y - wBorderWidth(pWindow),
+ pWindow->drawable.width,
+ pWindow->drawable.height,
+ pWindow->borderWidth,
+ pWindow->drawable.depth,
+ pWindow->drawable.class,
+ pWinPriv->visual,
+ mask,
+ &attribs);
+}
+
+/** This function handles lazy window creation and realization. Window
+ * creation is handled by #dmxCreateNonRootWindow(). It also handles
+ * any stacking changes that have occured since the window was
+ * originally created by calling #dmxDoRestackWindow(). If the window
+ * is shaped, the shape is set on the back-end server by calling
+ * #dmxDoSetShape(), and if the window has pictures (from RENDER)
+ * associated with it, those pictures are created on the back-end
+ * server by calling #dmxCreatePictureList(). If \a doSync is TRUE,
+ * then #dmxSync() is called. */
+void dmxCreateAndRealizeWindow(WindowPtr pWindow, Bool doSync)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+
+ if (!dmxScreen->beDisplay) return;
+
+ pWinPriv->window = dmxCreateNonRootWindow(pWindow);
+ if (pWinPriv->restacked) dmxDoRestackWindow(pWindow);
+#ifdef SHAPE
+ if (pWinPriv->isShaped) dmxDoSetShape(pWindow);
+#endif
+#ifdef RENDER
+ if (pWinPriv->hasPict) dmxCreatePictureList(pWindow);
+#endif
+ if (pWinPriv->mapped) XMapWindow(dmxScreen->beDisplay,
+ pWinPriv->window);
+ if (doSync) dmxSync(dmxScreen, False);
+}
+
+/** Create \a pWindow on the back-end server. If the lazy window
+ * creation optimization is enabled, then the actual creation and
+ * realization of the window is handled by
+ * #dmxCreateAndRealizeWindow(). */
+Bool dmxCreateWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ Bool ret = TRUE;
+
+ DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
+#if 0
+ if (pScreen->CreateWindow)
+ ret = pScreen->CreateWindow(pWindow);
+#endif
+
+ /* Set up the defaults */
+ pWinPriv->window = (Window)0;
+ pWinPriv->offscreen = TRUE;
+ pWinPriv->mapped = FALSE;
+ pWinPriv->restacked = FALSE;
+ pWinPriv->attribMask = 0;
+#ifdef SHAPE
+ pWinPriv->isShaped = FALSE;
+#endif
+#ifdef RENDER
+ pWinPriv->hasPict = FALSE;
+#endif
+#ifdef GLXEXT
+ pWinPriv->swapGroup = NULL;
+ pWinPriv->barrier = 0;
+#endif
+
+ if (dmxScreen->beDisplay) {
+ /* Only create the root window at this stage -- non-root windows are
+ created when they are mapped and are on-screen */
+ if (!pWindow->parent) {
+ dmxScreen->rootWin = pWinPriv->window
+ = dmxCreateRootWindow(pWindow);
+ if (dmxScreen->scrnX != dmxScreen->rootX
+ || dmxScreen->scrnY != dmxScreen->rootY
+ || dmxScreen->scrnWidth != dmxScreen->rootWidth
+ || dmxScreen->scrnHeight != dmxScreen->rootHeight) {
+ dmxResizeRootWindow(pWindow,
+ dmxScreen->rootX,
+ dmxScreen->rootY,
+ dmxScreen->rootWidth,
+ dmxScreen->rootHeight);
+ dmxUpdateScreenResources(screenInfo.screens[dmxScreen->index],
+ dmxScreen->rootX,
+ dmxScreen->rootY,
+ dmxScreen->rootWidth,
+ dmxScreen->rootHeight);
+ pWindow->origin.x = dmxScreen->rootX;
+ pWindow->origin.y = dmxScreen->rootY;
+ }
+ } else {
+ dmxGetDefaultWindowAttributes(pWindow,
+ &pWinPriv->cmap,
+ &pWinPriv->visual);
+
+ if (dmxLazyWindowCreation) {
+ /* Save parent's visual for use later */
+ if (pWinPriv->visual == CopyFromParent)
+ pWinPriv->visual =
+ dmxLookupVisualFromID(pScreen,
+ wVisual(pWindow->parent));
+ } else {
+ pWinPriv->window = dmxCreateNonRootWindow(pWindow);
+ }
+ }
+
+ dmxSync(dmxScreen, False);
+ }
+
+ DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen);
+
+ return ret;
+}
+
+/** Destroy \a pWindow on the back-end server. */
+Bool dmxBEDestroyWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+
+ if (pWinPriv->window) {
+ XDestroyWindow(dmxScreen->beDisplay, pWinPriv->window);
+ pWinPriv->window = (Window)0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/** Destroy \a pWindow on the back-end server. If any RENDER pictures
+ were created, destroy them as well. */
+Bool dmxDestroyWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ Bool ret = TRUE;
+ Bool needSync = FALSE;
+#ifdef GLXEXT
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+#endif
+
+ DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen);
+
+#ifdef RENDER
+ /* Destroy any picture list associated with this window */
+ needSync |= dmxDestroyPictureList(pWindow);
+#endif
+
+ /* Destroy window on back-end server */
+ needSync |= dmxBEDestroyWindow(pWindow);
+ if (needSync) dmxSync(dmxScreen, FALSE);
+
+#ifdef GLXEXT
+ if (pWinPriv->swapGroup && pWinPriv->windowDestroyed)
+ pWinPriv->windowDestroyed(pWindow);
+#endif
+
+#if 0
+ if (pScreen->DestroyWindow)
+ ret = pScreen->DestroyWindow(pWindow);
+#endif
+ DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
+
+ return ret;
+}
+
+/** Change the position of \a pWindow to be \a x, \a y. */
+Bool dmxPositionWindow(WindowPtr pWindow, int x, int y)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ Bool ret = TRUE;
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ unsigned int m;
+ XWindowChanges c;
+
+ DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
+#if 0
+ if (pScreen->PositionWindow)
+ ret = pScreen->PositionWindow(pWindow, x, y);
+#endif
+
+ /* Determine if the window is completely off the visible portion of
+ the screen */
+ pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
+
+ /* If the window is now on-screen and it is mapped and it has not
+ been created yet, create it and map it */
+ if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
+ dmxCreateAndRealizeWindow(pWindow, TRUE);
+ } else if (pWinPriv->window) {
+ /* Position window on back-end server */
+ m = CWX | CWY | CWWidth | CWHeight;
+ c.x = pWindow->origin.x - wBorderWidth(pWindow);
+ c.y = pWindow->origin.y - wBorderWidth(pWindow);
+ c.width = pWindow->drawable.width;
+ c.height = pWindow->drawable.height;
+ if (pWindow->drawable.class != InputOnly) {
+ m |= CWBorderWidth;
+ c.border_width = pWindow->borderWidth;
+ }
+
+ XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+ dmxSync(dmxScreen, False);
+ }
+
+ DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen);
+
+ return ret;
+}
+
+static void dmxDoChangeWindowAttributes(WindowPtr pWindow,
+ unsigned long *mask,
+ XSetWindowAttributes *attribs)
+{
+ dmxPixPrivPtr pPixPriv;
+
+ if (*mask & CWBackPixmap) {
+ switch (pWindow->backgroundState) {
+ case None:
+ attribs->background_pixmap = None;
+ break;
+
+ case ParentRelative:
+ attribs->background_pixmap = ParentRelative;
+ break;
+
+ case BackgroundPixmap:
+ pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->background.pixmap);
+ attribs->background_pixmap = pPixPriv->pixmap;
+ break;
+
+ case BackgroundPixel:
+ *mask &= ~CWBackPixmap;
+ break;
+ }
+ }
+
+ if (*mask & CWBackPixel) {
+ if (pWindow->backgroundState == BackgroundPixel)
+ attribs->background_pixel = pWindow->background.pixel;
+ else
+ *mask &= ~CWBackPixel;
+ }
+
+ if (*mask & CWBorderPixmap) {
+ if (pWindow->borderIsPixel)
+ *mask &= ~CWBorderPixmap;
+ else {
+ pPixPriv = DMX_GET_PIXMAP_PRIV(pWindow->border.pixmap);
+ attribs->border_pixmap = pPixPriv->pixmap;
+ }
+ }
+
+ if (*mask & CWBorderPixel) {
+ if (pWindow->borderIsPixel)
+ attribs->border_pixel = pWindow->border.pixel;
+ else
+ *mask &= ~CWBorderPixel;
+ }
+
+ if (*mask & CWBitGravity)
+ attribs->bit_gravity = pWindow->bitGravity;
+
+ if (*mask & CWWinGravity)
+ *mask &= ~CWWinGravity; /* Handled by dix */
+
+ if (*mask & CWBackingStore)
+ *mask &= ~CWBackingStore; /* Backing store not supported */
+
+ if (*mask & CWBackingPlanes)
+ *mask &= ~CWBackingPlanes; /* Backing store not supported */
+
+ if (*mask & CWBackingPixel)
+ *mask &= ~CWBackingPixel; /* Backing store not supported */
+
+ if (*mask & CWOverrideRedirect)
+ attribs->override_redirect = pWindow->overrideRedirect;
+
+ if (*mask & CWSaveUnder)
+ *mask &= ~CWSaveUnder; /* Save unders not supported */
+
+ if (*mask & CWEventMask)
+ *mask &= ~CWEventMask; /* Events are handled by dix */
+
+ if (*mask & CWDontPropagate)
+ *mask &= ~CWDontPropagate; /* Events are handled by dix */
+
+ if (*mask & CWColormap) {
+ ColormapPtr pCmap;
+ dmxColormapPrivPtr pCmapPriv;
+
+ pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), RT_COLORMAP);
+ pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
+ attribs->colormap = pCmapPriv->cmap;
+ }
+
+ if (*mask & CWCursor)
+ *mask &= ~CWCursor; /* Handled by the cursor code */
+}
+
+/** Change the window attributes of \a pWindow. */
+Bool dmxChangeWindowAttributes(WindowPtr pWindow, unsigned long mask)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ Bool ret = TRUE;
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ XSetWindowAttributes attribs;
+
+ DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
+#if 0
+ if (pScreen->ChangeWindowAttributes)
+ ret = pScreen->ChangeWindowAttributes(pWindow, mask);
+#endif
+
+ /* Change window attribs on back-end server */
+ dmxDoChangeWindowAttributes(pWindow, &mask, &attribs);
+
+ /* Save mask for lazy window creation optimization */
+ pWinPriv->attribMask |= mask;
+
+ if (mask && pWinPriv->window) {
+ XChangeWindowAttributes(dmxScreen->beDisplay, pWinPriv->window,
+ mask, &attribs);
+ dmxSync(dmxScreen, False);
+ }
+
+ DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
+ pScreen);
+
+ return ret;
+}
+
+/** Realize \a pWindow on the back-end server. If the lazy window
+ * creation optimization is enabled, the window is only realized when
+ * it at least partially overlaps the screen. */
+Bool dmxRealizeWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ Bool ret = TRUE;
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+
+ DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
+#if 0
+ if (pScreen->RealizeWindow)
+ ret = pScreen->RealizeWindow(pWindow);
+#endif
+
+ /* Determine if the window is completely off the visible portion of
+ the screen */
+ pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
+
+ /* If the window hasn't been created and it's not offscreen, then
+ create it */
+ if (!pWinPriv->window && !pWinPriv->offscreen) {
+ dmxCreateAndRealizeWindow(pWindow, FALSE);
+ }
+
+ if (pWinPriv->window) {
+ /* Realize window on back-end server */
+ XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
+ dmxSync(dmxScreen, False);
+ }
+
+ /* Let the other functions know that the window is now mapped */
+ pWinPriv->mapped = TRUE;
+
+ DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
+
+ dmxUpdateWindowInfo(DMX_UPDATE_REALIZE, pWindow);
+ return ret;
+}
+
+/** Unrealize \a pWindow on the back-end server. */
+Bool dmxUnrealizeWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ Bool ret = TRUE;
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+
+ DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
+#if 0
+ if (pScreen->UnrealizeWindow)
+ ret = pScreen->UnrealizeWindow(pWindow);
+#endif
+
+ if (pWinPriv->window) {
+ /* Unrealize window on back-end server */
+ XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window);
+ dmxSync(dmxScreen, False);
+ }
+
+ /* When unrealized (i.e., unmapped), the window is always considered
+ off of the visible portion of the screen */
+ pWinPriv->offscreen = TRUE;
+ pWinPriv->mapped = FALSE;
+
+#ifdef GLXEXT
+ if (pWinPriv->swapGroup && pWinPriv->windowUnmapped)
+ pWinPriv->windowUnmapped(pWindow);
+#endif
+
+ DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
+
+ dmxUpdateWindowInfo(DMX_UPDATE_UNREALIZE, pWindow);
+ return ret;
+}
+
+static void dmxDoRestackWindow(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ WindowPtr pNextSib = pWindow->nextSib;
+ unsigned int m;
+ XWindowChanges c;
+
+ if (pNextSib == NullWindow) {
+ /* Window is at the bottom of the stack */
+ m = CWStackMode;
+ c.sibling = (Window)0;
+ c.stack_mode = Below;
+ XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+ } else {
+ /* Window is not at the bottom of the stack */
+ dmxWinPrivPtr pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib);
+
+ /* Handle case where siblings have not yet been created due to
+ lazy window creation optimization by first finding the next
+ sibling in the sibling list that has been created (if any)
+ and then putting the current window just above that sibling,
+ and if no next siblings have been created yet, then put it at
+ the bottom of the stack (since it might have a previous
+ sibling that should be above it). */
+ while (!pNextSibPriv->window) {
+ pNextSib = pNextSib->nextSib;
+ if (pNextSib == NullWindow) {
+ /* Window is at the bottom of the stack */
+ m = CWStackMode;
+ c.sibling = (Window)0;
+ c.stack_mode = Below;
+ XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+ return;
+ }
+ pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib);
+ }
+
+ m = CWStackMode | CWSibling;
+ c.sibling = pNextSibPriv->window;
+ c.stack_mode = Above;
+ XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+ }
+}
+
+/** Handle window restacking. The actual restacking occurs in
+ * #dmxDoRestackWindow(). */
+void dmxRestackWindow(WindowPtr pWindow, WindowPtr pOldNextSib)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+
+ DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
+#if 0
+ if (pScreen->RestackWindow)
+ pScreen->RestackWindow(pWindow, pOldNextSib);
+#endif
+
+ if (pOldNextSib != pWindow->nextSib) {
+ /* Track restacking for lazy window creation optimization */
+ pWinPriv->restacked = TRUE;
+
+ /* Restack window on back-end server */
+ if (pWinPriv->window) {
+ dmxDoRestackWindow(pWindow);
+ dmxSync(dmxScreen, False);
+ }
+ }
+
+ DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
+ dmxUpdateWindowInfo(DMX_UPDATE_RESTACK, pWindow);
+}
+
+static Bool dmxWindowExposurePredicate(Display *dpy, XEvent *ev, XPointer ptr)
+{
+ return (ev->type == Expose && ev->xexpose.window == *(Window *)ptr);
+}
+
+/** Handle exposures on \a pWindow. Since window exposures are handled
+ * in DMX, the events that are generated by the back-end server are
+ * redundant, so we eat them here. */
+void dmxWindowExposures(WindowPtr pWindow, RegionPtr prgn,
+ RegionPtr other_exposed)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ XEvent ev;
+
+ DMX_UNWRAP(WindowExposures, dmxScreen, pScreen);
+
+ dmxSync(dmxScreen, False);
+
+ if (pWinPriv->window) {
+ while (XCheckIfEvent(dmxScreen->beDisplay, &ev,
+ dmxWindowExposurePredicate,
+ (XPointer)&pWinPriv->window)) {
+ /* Handle expose events -- this should not be necessary
+ since the base window in which the root window was
+ created is guaranteed to be on top (override_redirect),
+ so we should just swallow these events. If for some
+ reason the window is not on top, then we'd need to
+ collect these events and send them to the client later
+ (e.g., during the block handler as Xnest does). */
+ }
+ }
+
+#if 1
+ if (pScreen->WindowExposures)
+ pScreen->WindowExposures(pWindow, prgn, other_exposed);
+#endif
+ DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen);
+}
+
+/** Paint background of \a pWindow in \a pRegion. */
+void dmxPaintWindowBackground(WindowPtr pWindow, RegionPtr pRegion, int what)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ BoxPtr pBox;
+ int nBox;
+
+ DMX_UNWRAP(PaintWindowBackground, dmxScreen, pScreen);
+#if 0
+ if (pScreen->PaintWindowBackground)
+ pScreen->PaintWindowBackground(pWindow, pRegion, what);
+#endif
+
+ if (pWinPriv->window) {
+ /* Paint window background on back-end server */
+ pBox = REGION_RECTS(pRegion);
+ nBox = REGION_NUM_RECTS(pRegion);
+ while (nBox--) {
+ XClearArea(dmxScreen->beDisplay, pWinPriv->window,
+ pBox->x1 - pWindow->drawable.x,
+ pBox->y1 - pWindow->drawable.y,
+ pBox->x2 - pBox->x1,
+ pBox->y2 - pBox->y1,
+ False);
+ pBox++;
+ }
+ dmxSync(dmxScreen, False);
+ }
+
+ DMX_WRAP(PaintWindowBackground, dmxPaintWindowBackground, dmxScreen, pScreen);
+}
+
+/** Paint window border for \a pWindow in \a pRegion. */
+void dmxPaintWindowBorder(WindowPtr pWindow, RegionPtr pRegion, int what)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+ DMX_UNWRAP(PaintWindowBorder, dmxScreen, pScreen);
+#if 0
+ if (pScreen->PaintWindowBorder)
+ pScreen->PaintWindowBorder(pWindow, pRegion, what);
+#endif
+
+ /* Paint window border on back-end server */
+
+ DMX_WRAP(PaintWindowBorder, dmxPaintWindowBorder, dmxScreen, pScreen);
+}
+
+/** Move \a pWindow on the back-end server. Determine whether or not it
+ * is on or offscreen, and realize it if it is newly on screen and the
+ * lazy window creation optimization is enabled. */
+void dmxCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ unsigned int m;
+ XWindowChanges c;
+
+ DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
+#if 0
+ if (pScreen->CopyWindow)
+ pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
+#endif
+
+ /* Determine if the window is completely off the visible portion of
+ the screen */
+ pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
+
+ /* If the window is now on-screen and it is mapped and it has not
+ been created yet, create it and map it */
+ if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
+ dmxCreateAndRealizeWindow(pWindow, TRUE);
+ } else if (pWinPriv->window) {
+ /* Move window on back-end server */
+ m = CWX | CWY | CWWidth | CWHeight;
+ c.x = pWindow->origin.x - wBorderWidth(pWindow);
+ c.y = pWindow->origin.y - wBorderWidth(pWindow);
+ c.width = pWindow->drawable.width;
+ c.height = pWindow->drawable.height;
+
+ XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+ dmxSync(dmxScreen, False);
+ }
+
+ DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
+ dmxUpdateWindowInfo(DMX_UPDATE_COPY, pWindow);
+}
+
+/** Resize \a pWindow on the back-end server. Determine whether or not
+ * it is on or offscreen, and realize it if it is newly on screen and
+ * the lazy window creation optimization is enabled. */
+void dmxResizeWindow(WindowPtr pWindow, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ dmxWinPrivPtr pSibPriv;
+ unsigned int m;
+ XWindowChanges c;
+
+ if (pSib)
+ pSibPriv = DMX_GET_WINDOW_PRIV(pSib);
+
+ DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
+#if 1
+ if (pScreen->ResizeWindow)
+ pScreen->ResizeWindow(pWindow, x, y, w, h, pSib);
+#endif
+
+ /* Determine if the window is completely off the visible portion of
+ the screen */
+ pWinPriv->offscreen = DMX_WINDOW_OFFSCREEN(pWindow);
+
+ /* If the window is now on-screen and it is mapped and it has not
+ been created yet, create it and map it */
+ if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
+ dmxCreateAndRealizeWindow(pWindow, TRUE);
+ } else if (pWinPriv->window) {
+ /* Handle resizing on back-end server */
+ m = CWX | CWY | CWWidth | CWHeight;
+ c.x = pWindow->origin.x - wBorderWidth(pWindow);
+ c.y = pWindow->origin.y - wBorderWidth(pWindow);
+ c.width = pWindow->drawable.width;
+ c.height = pWindow->drawable.height;
+
+ XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+ dmxSync(dmxScreen, False);
+ }
+
+ DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
+ dmxUpdateWindowInfo(DMX_UPDATE_RESIZE, pWindow);
+}
+
+/** Reparent \a pWindow on the back-end server. */
+void dmxReparentWindow(WindowPtr pWindow, WindowPtr pPriorParent)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ dmxWinPrivPtr pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent);
+
+ DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
+#if 0
+ if (pScreen->ReparentWindow)
+ pScreen->ReparentWindow(pWindow, pPriorParent);
+#endif
+
+ if (pWinPriv->window) {
+ if (!pParentPriv->window) {
+ dmxCreateAndRealizeWindow(pWindow->parent, FALSE);
+ }
+
+ /* Handle reparenting on back-end server */
+ XReparentWindow(dmxScreen->beDisplay, pWinPriv->window,
+ pParentPriv->window,
+ pWindow->origin.x - wBorderWidth(pWindow),
+ pWindow->origin.x - wBorderWidth(pWindow));
+ dmxSync(dmxScreen, False);
+ }
+
+ DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
+ dmxUpdateWindowInfo(DMX_UPDATE_REPARENT, pWindow);
+}
+
+/** Change border width for \a pWindow to \a width pixels. */
+void dmxChangeBorderWidth(WindowPtr pWindow, unsigned int width)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ unsigned int m;
+ XWindowChanges c;
+
+ DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
+#if 1
+ if (pScreen->ChangeBorderWidth)
+ pScreen->ChangeBorderWidth(pWindow, width);
+#endif
+
+ /* NOTE: Do we need to check for on/off screen here? */
+
+ if (pWinPriv->window) {
+ /* Handle border width change on back-end server */
+ m = CWBorderWidth;
+ c.border_width = width;
+
+ XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+ dmxSync(dmxScreen, False);
+ }
+
+ DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
+}
+
+#ifdef SHAPE
+static void dmxDoSetShape(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+ int nBox;
+ BoxPtr pBox;
+ int nRect;
+ XRectangle *pRect;
+ XRectangle *pRectFirst;
+
+ /* First, set the bounding shape */
+ if (wBoundingShape(pWindow)) {
+ pBox = REGION_RECTS(wBoundingShape(pWindow));
+ nRect = nBox = REGION_NUM_RECTS(wBoundingShape(pWindow));
+ pRectFirst = pRect = xalloc(nRect * sizeof(*pRect));
+ while (nBox--) {
+ pRect->x = pBox->x1;
+ pRect->y = pBox->y1;
+ pRect->width = pBox->x2 - pBox->x1;
+ pRect->height = pBox->y2 - pBox->y1;
+ pBox++;
+ pRect++;
+ }
+ XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
+ ShapeBounding, 0, 0,
+ pRectFirst, nRect,
+ ShapeSet, YXBanded);
+ xfree(pRectFirst);
+ } else {
+ XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
+ ShapeBounding, 0, 0, None, ShapeSet);
+ }
+
+ /* Next, set the clip shape */
+ if (wClipShape(pWindow)) {
+ pBox = REGION_RECTS(wClipShape(pWindow));
+ nRect = nBox = REGION_NUM_RECTS(wClipShape(pWindow));
+ pRectFirst = pRect = xalloc(nRect * sizeof(*pRect));
+ while (nBox--) {
+ pRect->x = pBox->x1;
+ pRect->y = pBox->y1;
+ pRect->width = pBox->x2 - pBox->x1;
+ pRect->height = pBox->y2 - pBox->y1;
+ pBox++;
+ pRect++;
+ }
+ XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
+ ShapeClip, 0, 0,
+ pRectFirst, nRect,
+ ShapeSet, YXBanded);
+ xfree(pRectFirst);
+ } else {
+ XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
+ ShapeClip, 0, 0, None, ShapeSet);
+ }
+
+ if (XShapeInputSelected(dmxScreen->beDisplay, pWinPriv->window)) {
+ ErrorF("Input selected for window %x on Screen %d\n",
+ (unsigned int)pWinPriv->window, pScreen->myNum);
+ }
+}
+
+/** Set shape of \a pWindow on the back-end server. */
+void dmxSetShape(WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+
+ DMX_UNWRAP(SetShape, dmxScreen, pScreen);
+#if 1
+ if (pScreen->SetShape)
+ pScreen->SetShape(pWindow);
+#endif
+
+ if (pWinPriv->window) {
+ /* Handle setting the current shape on the back-end server */
+ dmxDoSetShape(pWindow);
+ dmxSync(dmxScreen, False);
+ } else {
+ pWinPriv->isShaped = TRUE;
+ }
+
+ DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
+}
+#endif
diff --git a/hw/dmx/input/dmxconsole.c b/hw/dmx/input/dmxconsole.c
new file mode 100644
index 000000000..03d3e2d9e
--- /dev/null
+++ b/hw/dmx/input/dmxconsole.c
@@ -0,0 +1,1019 @@
+/* $XFree86$ */
+/*
+ * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * David H. Dawes <dawes@xfree86.org>
+ * Kevin E. Martin <kem@redhat.com>
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ *
+ * This file implements the console input devices.
+ */
+
+#define DMX_CONSOLE_DEBUG 0
+#define DMX_WINDOW_DEBUG 0
+
+#include "dmxinputinit.h"
+#include "dmxevents.h"
+#include "dmxconsole.h"
+#include "dmxcommon.h"
+#include "dmxscrinit.h"
+#include "dmxcb.h"
+#include "dmxsync.h"
+
+#include "inputstr.h"
+#include "input.h"
+#include "mipointer.h"
+#include "windowstr.h"
+
+#define CONSOLE_NUM 3
+#define CONSOLE_DEN 4
+#define DMX_CONSOLE_NAME "DMX Console"
+#define DMX_RES_NAME "Xdmx"
+#define DMX_RES_CLASS "XDmx"
+#define CONSOLE_BG_COLOR "gray75"
+#define CONSOLE_FG_COLOR "black"
+#define CONSOLE_SCREEN_BG_COLOR "white"
+#define CONSOLE_SCREEN_FG_COLOR "black"
+#define CONSOLE_SCREEN_DET_COLOR "gray75"
+#define CONSOLE_SCREEN_CUR_COLOR "red"
+
+#if DMX_CONSOLE_DEBUG
+#define DMXDBG0(f) dmxLog(dmxDebug,f)
+#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
+#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
+#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
+#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
+#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
+#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
+#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
+#else
+#define DMXDBG0(f)
+#define DMXDBG1(f,a)
+#define DMXDBG2(f,a,b)
+#define DMXDBG3(f,a,b,c)
+#define DMXDBG4(f,a,b,c,d)
+#define DMXDBG5(f,a,b,c,d,e)
+#define DMXDBG6(f,a,b,c,d,e,g)
+#define DMXDBG7(f,a,b,c,d,e,g,h)
+#endif
+
+/* Private area for consoles. */
+typedef struct _myPrivate {
+ DMX_COMMON_PRIVATE;
+ int lastX;
+ int lastY;
+ int globalX;
+ int globalY;
+ int curX;
+ int curY;
+ int width;
+ int height;
+ int consWidth;
+ int consHeight;
+ double xScale;
+ double yScale;
+ XlibGC gc, gcDet, gcRev, gcCur;
+ int grabbed, fine, captured;
+ Cursor cursorNormal, cursorGrabbed, cursorEmpty;
+ Pixmap pixmap;
+
+ CloseScreenProcPtr CloseScreen;
+ struct _myPrivate *next; /* for closing multiple consoles */
+ int initialized;
+ DevicePtr mou, kbd;
+} myPrivate;
+
+static int scalex(myPrivate *priv, int x)
+{
+ return (int)((x * priv->xScale) + .5);
+}
+
+static int scaley(myPrivate *priv, int y)
+{
+ return (int)((y * priv->yScale) + .5);
+}
+
+static int unscalex(myPrivate *priv, int x)
+{
+ return (int)((x / priv->xScale) + .5);
+}
+
+static int unscaley(myPrivate *priv, int y)
+{
+ return (int)((y / priv->yScale) + .5);
+}
+
+/** Create the private area for \a pDevice. */
+pointer dmxConsoleCreatePrivate(DeviceIntPtr pDevice)
+{
+ GETDMXLOCALFROMPDEVICE;
+ myPrivate *priv = xalloc(sizeof(*priv));
+ memset(priv, 0, sizeof(*priv));
+ priv->dmxLocal = dmxLocal;
+ return priv;
+}
+
+/** If \a private is non-NULL, free its associated memory. */
+void dmxConsoleDestroyPrivate(pointer private)
+{
+ if (private) xfree(private);
+}
+
+static void dmxConsoleDrawFineCursor(myPrivate *priv, XRectangle *rect)
+{
+ int size = 6;
+ int x, y;
+
+ XDrawLine(priv->display, priv->pixmap, priv->gcCur,
+ x = scalex(priv, priv->globalX) - size,
+ scaley(priv, priv->globalY),
+ scalex(priv, priv->globalX) + size,
+ scaley(priv, priv->globalY));
+ XDrawLine(priv->display, priv->pixmap, priv->gcCur,
+ scalex(priv, priv->globalX),
+ y = scaley(priv, priv->globalY) - size,
+ scalex(priv, priv->globalX),
+ scaley(priv, priv->globalY) + size);
+ if (priv->grabbed) {
+ XDrawLine(priv->display, priv->pixmap, priv->gcCur,
+ scalex(priv, priv->globalX) - (int)(size / 1.4),
+ scaley(priv, priv->globalY) - (int)(size / 1.4),
+ scalex(priv, priv->globalX) + (int)(size / 1.4),
+ scaley(priv, priv->globalY) + (int)(size / 1.4));
+ XDrawLine(priv->display, priv->pixmap, priv->gcCur,
+ scalex(priv, priv->globalX) - (int)(size / 1.4),
+ scaley(priv, priv->globalY) + (int)(size / 1.4),
+ scalex(priv, priv->globalX) + (int)(size / 1.4),
+ scaley(priv, priv->globalY) - (int)(size / 1.4));
+ }
+ if (rect) {
+ rect->x = x;
+ rect->y = y;
+ rect->width = 2 * size;
+ rect->height = 2 * size;
+ }
+}
+
+static void dmxConsoleDrawWindows(pointer private)
+{
+ GETONLYPRIVFROMPRIVATE;
+ Display *dpy = priv->display;
+ int i;
+ Region whole, used, avail;
+ XRectangle rect;
+
+ whole = XCreateRegion();
+ used = XCreateRegion();
+ avail = XCreateRegion();
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = priv->consWidth;
+ rect.height = priv->consHeight;
+ XUnionRectWithRegion(&rect, whole, whole);
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ WindowPtr pRoot = WindowTable[i];
+ WindowPtr pChild;
+
+#if DMX_WINDOW_DEBUG
+ dmxLog(dmxDebug, "%lu %p %p %p 2\n",
+ pRoot->drawable.id,
+ pRoot->parent, pRoot->firstChild, pRoot->lastChild);
+#endif
+
+ for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib) {
+ if (pChild->mapped
+ && pChild->realized) {
+#if DMX_WINDOW_DEBUG
+ dmxLog(dmxDebug, " %p %d,%d %dx%d %d %d %d RECTS\n",
+ pChild,
+ pChild->drawable.x,
+ pChild->drawable.y,
+ pChild->drawable.width,
+ pChild->drawable.height,
+ pChild->visibility,
+ pChild->overrideRedirect,
+ REGION_NUM_RECTS(&pChild->clipList));
+#endif
+ rect.x = scalex(priv, pChild->drawable.x
+ + dixScreenOrigins[i].x);
+ rect.y = scaley(priv, pChild->drawable.y
+ + dixScreenOrigins[i].y);
+ rect.width = scalex(priv, pChild->drawable.width);
+ rect.height = scaley(priv, pChild->drawable.height);
+ XDrawRectangle(dpy, priv->pixmap, priv->gc,
+ rect.x, rect.y, rect.width, rect.height);
+ XUnionRectWithRegion(&rect, used, used);
+ XSubtractRegion(whole, used, avail);
+ XSetRegion(dpy, priv->gc, avail);
+ }
+ }
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension) break; /* Screen 0 valid with Xinerama */
+#endif
+ }
+ XDestroyRegion(avail);
+ XDestroyRegion(used);
+ XDestroyRegion(whole);
+ XSetClipMask(dpy, priv->gc, None);
+}
+
+static void dmxConsoleDraw(myPrivate *priv, int updateCursor, int update)
+{
+ GETDMXINPUTFROMPRIV;
+ Display *dpy = priv->display;
+ int i;
+
+ XFillRectangle(dpy, priv->pixmap, priv->gc, 0, 0,
+ priv->consWidth, priv->consHeight);
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+ XFillRectangle(dpy, priv->pixmap,
+ dmxScreen->beDisplay ? priv->gcRev : priv->gcDet,
+ scalex(priv, dixScreenOrigins[i].x),
+ scaley(priv, dixScreenOrigins[i].y),
+ scalex(priv, screenInfo.screens[i]->width),
+ scaley(priv, screenInfo.screens[i]->height));
+ }
+ for (i = 0; i < dmxNumScreens; i++) {
+ XDrawRectangle(dpy, priv->pixmap, priv->gc,
+ scalex(priv, dixScreenOrigins[i].x),
+ scaley(priv, dixScreenOrigins[i].y),
+ scalex(priv, screenInfo.screens[i]->width),
+ scaley(priv, screenInfo.screens[i]->height));
+ }
+ if (dmxInput->windows) dmxConsoleDrawWindows(priv);
+ if (priv->fine && updateCursor) dmxConsoleDrawFineCursor(priv, 0);
+ if (update) {
+ XCopyArea(priv->display, priv->pixmap, priv->window, priv->gc,
+ 0, 0, priv->consWidth, priv->consHeight, 0, 0);
+ XSync(priv->display, False); /* Not a backend display */
+ }
+}
+
+static void dmxConsoleClearCursor(myPrivate *priv, int x, int y,
+ XRectangle *rect)
+{
+ int cw = 14, ch = 14; /* Clear width and height */
+
+ rect->x = scalex(priv, x) - cw/2;
+ rect->y = scaley(priv, y) - ch/2;
+ rect->width = cw;
+ rect->height = ch;
+ XSetClipRectangles(priv->display, priv->gc, 0, 0, rect, 1, Unsorted);
+ XSetClipRectangles(priv->display, priv->gcDet, 0, 0, rect, 1, Unsorted);
+ XSetClipRectangles(priv->display, priv->gcRev, 0, 0, rect, 1, Unsorted);
+ dmxConsoleDraw(priv, 0, 0);
+ XSetClipMask(priv->display, priv->gc, None);
+ XSetClipMask(priv->display, priv->gcDet, None);
+ XSetClipMask(priv->display, priv->gcRev, None);
+}
+
+
+static void dmxConsoleUpdateFineCursor(myPrivate *priv)
+{
+ int leave = 0;
+ XRectangle rects[2];
+
+ dmxConsoleClearCursor(priv, priv->globalX, priv->globalY, &rects[0]);
+ if (priv->dmxLocal->sendsCore) {
+ dmxGetGlobalPosition(&priv->globalX, &priv->globalY);
+ } else {
+ priv->globalX = priv->dmxLocal->lastX;
+ priv->globalY = priv->dmxLocal->lastY;
+ }
+
+ priv->lastX = scalex(priv, priv->width / 2);
+ priv->lastY = scaley(priv, priv->height / 2);
+
+ /* Compute new warp position, which may be
+ outside the window */
+ if (priv->globalX < 1 || priv->globalX >= priv->width) {
+ if (priv->globalX < 1) priv->lastX = 0;
+ else priv->lastX = scalex(priv, priv->width);
+ priv->lastY = scaley(priv, priv->globalY);
+ ++leave;
+ }
+ if (priv->globalY < 1 || priv->globalY >= priv->height) {
+ if (priv->globalY < 1) priv->lastY = 0;
+ else priv->lastY = scaley(priv, priv->height);
+ priv->lastX = scalex(priv, priv->globalX);
+ ++leave;
+ }
+
+ /* Draw pseudo cursor in window */
+ dmxConsoleDrawFineCursor(priv, &rects[1]);
+
+ XSetClipRectangles(priv->display, priv->gc, 0, 0, rects, 2, Unsorted);
+ XCopyArea(priv->display, priv->pixmap, priv->window, priv->gc,
+ 0, 0, priv->consWidth, priv->consHeight, 0, 0);
+ XSetClipMask(priv->display, priv->gc, None);
+
+ DMXDBG2("dmxConsoleUpdateFineCursor: WARP %d %d\n",
+ priv->lastX, priv->lastY);
+ XWarpPointer(priv->display, priv->window, priv->window,
+ 0, 0, 0, 0, priv->lastX, priv->lastY);
+ XSync(priv->display, False); /* Not a backend display */
+
+ if (leave) {
+ XEvent X;
+ while (XCheckMaskEvent(priv->display, PointerMotionMask, &X)) {
+ if (X.type == MotionNotify) {
+ if (X.xmotion.x != priv->lastX || X.xmotion.y != priv->lastY) {
+ DMXDBG4("Ignoring motion to %d %d after leave frm %d %d\n",
+ X.xmotion.x, X.xmotion.y,
+ priv->lastX, priv->lastY);
+ }
+ } else {
+ dmxLog(dmxInfo, "Ignoring event (%d): %s ****************\n",
+ X.type, dmxEventName(X.type));
+ }
+ }
+ }
+ DMXDBG6("dmxConsoleUpdateFineCursor: Warp %d %d on %d %d [%d %d]\n",
+ priv->lastX, priv->lastY,
+ scalex(priv, priv->width),
+ scaley(priv, priv->height),
+ priv->globalX, priv->globalY);
+}
+
+/** Whenever the window layout (size, position, stacking order) might be
+ * changed, this routine is called with the \a pWindow that changed and
+ * the \a type of change. This routine is called in a conservative
+ * fashion: the actual layout of the windows of the screen might not
+ * have had any human-visible changes. */
+void dmxConsoleUpdateInfo(pointer private, DMXUpdateType type,
+ WindowPtr pWindow)
+{
+ GETONLYPRIVFROMPRIVATE;
+ dmxConsoleDraw(priv, 1, 1);
+}
+
+static void dmxConsoleMoveAbsolute(myPrivate *priv, int x, int y,
+ DevicePtr pDev, dmxMotionProcPtr motion,
+ DMXBlockType block)
+{
+ int tmpX, tmpY, v[2];
+
+ tmpX = unscalex(priv, x);
+ tmpY = unscalex(priv, y);
+ DMXDBG6("dmxConsoleMoveAbsolute(,%d,%d) %d %d =? %d %d\n",
+ x, y, tmpX, tmpY, priv->curX, priv->curY);
+ if (tmpX == priv->curX && tmpY == priv->curY) return;
+ v[0] = unscalex(priv, x);
+ v[1] = unscaley(priv, y);
+ motion(pDev, v, 0, 2, DMX_ABSOLUTE_CONFINED, block);
+ /* dmxConsoleUpdatePosition gets called here by dmxCoreMotion */
+}
+
+static void dmxConsoleMoveRelative(myPrivate *priv, int x, int y,
+ DevicePtr pDev, dmxMotionProcPtr motion,
+ DMXBlockType block)
+{
+ int v[2];
+ /* Ignore the event generated from * warping back to middle */
+ if (x == priv->lastX && y == priv->lastY) return;
+ v[0] = priv->lastX - x;
+ v[1] = priv->lastY - y;
+ motion(pDev, v, 0, 2, DMX_RELATIVE, block);
+ /* dmxConsoleUpdatePosition gets called here by dmxCoreMotion */
+}
+
+/** This routine gets called from #dmxCoreMotion for each motion. This
+ * allows the console's notion of the cursor postion to change when
+ * another input device actually caused the change. */
+void dmxConsoleUpdatePosition(pointer private, int x, int y)
+{
+ GETONLYPRIVFROMPRIVATE;
+ int tmpX, tmpY;
+ Display *dpy = priv->display;
+ static unsigned long dmxGeneration = 0;
+
+
+ tmpX = scalex(priv, x);
+ tmpY = scaley(priv, y);
+ DMXDBG6("dmxConsoleUpdatePosition(,%d,%d) new=%d,%d dims=%d,%d\n",
+ x, y, tmpX, tmpY, priv->consWidth, priv->consHeight);
+
+ if (priv->fine) dmxConsoleUpdateFineCursor(priv);
+ if (tmpX != priv->curX || tmpY != priv->curY) {
+ if (tmpX < 0) tmpX = 0;
+ if (tmpY < 0) tmpY = 0;
+ if (tmpX >= priv->consWidth) tmpX = priv->consWidth - 1;
+ if (tmpY >= priv->consHeight) tmpY = priv->consHeight - 1;
+ priv->curX = tmpX;
+ priv->curY = tmpY;
+ if (!priv->fine) {
+ DMXDBG2(" WARP B %d %d\n", priv->curX, priv->curY);
+ XWarpPointer(dpy, priv->window,
+ priv->window, 0, 0, 0, 0, tmpX, tmpY);
+ XSync(dpy, False); /* Not a backend display */
+ }
+ }
+
+ if (dmxGeneration != serverGeneration) {
+ dmxGeneration = serverGeneration;
+ dmxConsoleDraw(priv, 1, 1);
+ }
+}
+
+/** Collect all pending events from the console's display. Plase these
+ * events on the server event queue using the \a motion and \a enqueue
+ * routines. The \a checkspecial routine is used to check for special
+ * keys that need handling. \a block tells if signals should be blocked
+ * when updating the event queue. */
+void dmxConsoleCollectEvents(DevicePtr pDev,
+ dmxMotionProcPtr motion,
+ dmxEnqueueProcPtr enqueue,
+ dmxCheckSpecialProcPtr checkspecial,
+ DMXBlockType block)
+{
+ GETPRIVFROMPDEV;
+ GETDMXINPUTFROMPRIV;
+ Display *dpy = priv->display;
+ Window win = priv->window;
+ int width = priv->width;
+ int height = priv->height;
+ XEvent X, N;
+ XSetWindowAttributes attribs;
+ static int rInitialized = 0;
+ static Region r;
+ XRectangle rect;
+ static int raising = 0, raiseX, raiseY; /* FIXME */
+
+ while (XPending(dpy)) {
+ XNextEvent(dpy, &X);
+ switch(X.type) {
+ case VisibilityNotify:
+ break;
+ case Expose:
+ DMXDBG5("dmxConsoleCollectEvents: Expose #%d %d %d %d %d\n",
+ X.xexpose.count,
+ X.xexpose.x, X.xexpose.y,
+ X.xexpose.width, X.xexpose.height);
+ if (!rInitialized++) r = XCreateRegion();
+ rect.x = X.xexpose.x;
+ rect.y = X.xexpose.y;
+ rect.width = X.xexpose.width;
+ rect.height = X.xexpose.height;
+ XUnionRectWithRegion(&rect, r, r);
+ if (X.xexpose.count == 0) {
+ XSetRegion(dpy, priv->gc, r);
+ XSetRegion(dpy, priv->gcDet, r);
+ XSetRegion(dpy, priv->gcRev, r);
+ dmxConsoleDraw(priv, 1, 1);
+ XSetClipMask(dpy, priv->gc, None);
+ XSetClipMask(dpy, priv->gcDet, None);
+ XSetClipMask(dpy, priv->gcRev, None);
+ XDestroyRegion(r);
+ rInitialized = 0;
+ }
+ break;
+ case ResizeRequest:
+ DMXDBG2("dmxConsoleCollectEvents: Resize %d %d\n",
+ X.xresizerequest.width, X.xresizerequest.height);
+ priv->consWidth = X.xresizerequest.width;
+ priv->consHeight = X.xresizerequest.height;
+ priv->xScale = (double)priv->consWidth / width;
+ priv->yScale = (double)priv->consHeight / height;
+ attribs.override_redirect = True;
+ XChangeWindowAttributes(dpy, win, CWOverrideRedirect, &attribs);
+ XResizeWindow(dpy, win, priv->consWidth, priv->consHeight);
+ XFreePixmap(dpy, priv->pixmap);
+ priv->pixmap = XCreatePixmap(dpy,
+ RootWindow(dpy, DefaultScreen(dpy)),
+ priv->consWidth,
+ priv->consHeight,
+ DefaultDepth(dpy,DefaultScreen(dpy)));
+ dmxConsoleDraw(priv, 1, 1);
+ attribs.override_redirect = False;
+ XChangeWindowAttributes(dpy, win, CWOverrideRedirect, &attribs);
+ break;
+ case LeaveNotify:
+ DMXDBG4("dmxConsoleCollectEvents: Leave @ %d,%d; r=%d f=%d\n",
+ X.xcrossing.x, X.xcrossing.y, raising, priv->fine);
+ if (!priv->captured) dmxCommonRestoreState(priv);
+ else {
+ dmxConsoleUncapture(dmxInput);
+ dmxCommonRestoreState(priv);
+ }
+ break;
+ case EnterNotify:
+ DMXDBG6("dmxConsoleCollectEvents: Enter %d,%d r=%d f=%d (%d,%d)\n",
+ X.xcrossing.x, X.xcrossing.y, raising, priv->fine,
+ priv->curX, priv->curY);
+ dmxCommonSaveState(priv);
+ if (raising) {
+ raising = 0;
+ dmxConsoleMoveAbsolute(priv, raiseX, raiseY,
+ priv->mou, motion, block);
+ } else {
+ if (priv->fine) {
+ /* The raise will generate an event near the center,
+ * which is not where the cursor should be. So we
+ * save the real position, do the raise, and move
+ * the cursor here again after the raise generates
+ * the event. */
+ raising = 1;
+ raiseX = X.xcrossing.x;
+ raiseY = X.xcrossing.y;
+ XRaiseWindow(dpy, priv->window);
+ }
+ XSync(dpy, False); /* Not a backend display */
+ if (!X.xcrossing.x && !X.xcrossing.y)
+ dmxConsoleMoveAbsolute(priv, priv->curX, priv->curY,
+ priv->mou, motion, block);
+ }
+ break;
+ case MotionNotify:
+ if (priv->curX == X.xmotion.x && priv->curY == X.xmotion.y)
+ continue;
+ if (XPending(dpy)) { /* do motion compression */
+ XPeekEvent(dpy, &N);
+ if (N.type == MotionNotify) continue;
+ }
+ DMXDBG2("dmxConsoleCollectEvents: Motion %d %d\n",
+ X.xmotion.x, X.xmotion.y);
+ if (raising) {
+ raising = 0;
+ dmxConsoleMoveAbsolute(priv, raiseX, raiseY,
+ priv->mou, motion, block);
+ } else {
+ if (priv->fine)
+ dmxConsoleMoveRelative(priv, X.xmotion.x, X.xmotion.y,
+ priv->mou, motion, block);
+ else
+ dmxConsoleMoveAbsolute(priv, X.xmotion.x, X.xmotion.y,
+ priv->mou, motion, block);
+ }
+ break;
+ case KeyPress:
+ case KeyRelease:
+ enqueue(priv->kbd, X.type, X.xkey.keycode, 0, NULL, block);
+ break;
+ default:
+ /* Pass the whole event here, because
+ * this may be an extension event. */
+ enqueue(priv->mou, X.type, X.xbutton.button, 0, &X, block);
+ break;
+ }
+ }
+}
+
+static void dmxCloseConsole(myPrivate *priv)
+{
+ GETDMXINPUTFROMPRIV;
+ dmxCommonRestoreState(priv);
+ if (priv->display) {
+ XFreeGC(priv->display, priv->gc);
+ XFreeGC(priv->display, priv->gcDet);
+ XFreeGC(priv->display, priv->gcRev);
+ XFreeGC(priv->display, priv->gcCur);
+ if (!dmxInput->console) XCloseDisplay(priv->display);
+ }
+ priv->display = NULL;
+}
+
+static Bool dmxCloseConsoleScreen(int idx, ScreenPtr pScreen)
+{
+ myPrivate *priv, *last;
+
+ for (last = priv = pScreen->devPrivates[dmxScreenPrivateIndex].ptr;
+ priv;
+ priv = priv->next) dmxCloseConsole(last = priv);
+
+ DMX_UNWRAP(CloseScreen, last, pScreen);
+ return pScreen->CloseScreen(idx, pScreen);
+}
+
+static Cursor dmxConsoleCreateEmptyCursor(myPrivate *priv)
+{
+ char noCursorData[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ Pixmap pixmap;
+ Cursor cursor;
+ XColor color, tmpColor;
+ Display *dpy = priv->display;
+
+ /* Create empty cursor for window */
+ pixmap = XCreateBitmapFromData(priv->display, priv->window,
+ noCursorData, 8, 8);
+ if (!XAllocNamedColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
+ "black",
+ &color,
+ &tmpColor))
+ dmxLog(dmxFatal, "Cannot allocate color for cursor\n");
+ cursor = XCreatePixmapCursor(dpy, pixmap, pixmap, &color, &color, 0, 0);
+ XFreePixmap(dpy, pixmap);
+ return cursor;
+}
+
+static void dmxConsoleComputeWidthHeight(myPrivate *priv,
+ int *width, int *height,
+ double *xScale, double *yScale,
+ int *consWidth, int *consHeight)
+{
+ int screen;
+ Display *dpy = priv->display;
+
+ *width = 0;
+ *height = 0;
+ *xScale = 1.0;
+ *yScale = 1.0;
+
+ screen = DefaultScreen(dpy);
+ *consWidth = DisplayWidth(dpy, screen) * CONSOLE_NUM / CONSOLE_DEN;
+ *consHeight = DisplayHeight(dpy, screen) * CONSOLE_NUM / CONSOLE_DEN;
+
+ if (*consWidth < 1) *consWidth = 1;
+ if (*consHeight < 1) *consHeight = 1;
+
+#if 1
+ /* Always keep the console size similar
+ * to the global bounding box. */
+ *width = dmxGlobalWidth;
+ *height = dmxGlobalHeight;
+#else
+ /* Make the console window as big as
+ * possible by computing the visible
+ * bounding box. */
+ for (i = 0; i < dmxNumScreens; i++) {
+ if (dixScreenOrigins[i].x+screenInfo.screens[i]->width > *width)
+ *width = dixScreenOrigins[i].x+screenInfo.screens[i]->width;
+
+ if (dixScreenOrigins[i].y+screenInfo.screens[i]->height > *height)
+ *height = dixScreenOrigins[i].y+screenInfo.screens[i]->height;
+ }
+#endif
+
+ if ((double)*consWidth / *width < (double)*consHeight / *height)
+ *xScale = *yScale = (double)*consWidth / *width;
+ else
+ *xScale = *yScale = (double)*consHeight / *height;
+
+ *consWidth = scalex(priv, *width);
+ *consHeight = scaley(priv, *height);
+ if (*consWidth < 1) *consWidth = 1;
+ if (*consHeight < 1) *consHeight = 1;
+}
+
+/** Re-initialized the console device described by \a pDev (after a
+ * reconfig). */
+void dmxConsoleReInit(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ Display *dpy = priv->display;
+
+ if (!priv || !priv->initialized) return;
+
+ dmxConsoleComputeWidthHeight(priv,
+ &priv->width, &priv->height,
+ &priv->xScale, &priv->yScale,
+ &priv->consWidth, &priv->consHeight);
+ XResizeWindow(dpy, priv->window, priv->consWidth, priv->consHeight);
+ XFreePixmap(dpy, priv->pixmap);
+ priv->pixmap = XCreatePixmap(dpy,
+ RootWindow(dpy, DefaultScreen(dpy)),
+ priv->consWidth,
+ priv->consHeight,
+ DefaultDepth(dpy,DefaultScreen(dpy)));
+ dmxConsoleDraw(priv, 1, 1);
+}
+
+/** Initialized the console device described by \a pDev. */
+void dmxConsoleInit(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
+ int screen;
+ unsigned long mask;
+ XSetWindowAttributes attribs;
+ Display *dpy;
+ Window win;
+ XGCValues gcvals;
+ XColor color;
+ XClassHint class_hints;
+ unsigned long tmp;
+
+ if (dmxLocal->type == DMX_LOCAL_MOUSE) priv->mou = pDev;
+ if (dmxLocal->type == DMX_LOCAL_KEYBOARD) priv->kbd = pDev;
+ if (priv->initialized++) return; /* Only do once for mouse/keyboard pair */
+
+ if (!(dpy = priv->display = XOpenDisplay(dmxInput->name)))
+ dmxLog(dmxFatal,
+ "dmxOpenConsole: cannot open console display %s\n",
+ dmxInput->name);
+
+ /* Set up defaults */
+ dmxConsoleComputeWidthHeight(priv,
+ &priv->width, &priv->height,
+ &priv->xScale, &priv->yScale,
+ &priv->consWidth, &priv->consHeight);
+
+ /* Private initialization using computed values or constants. */
+ screen = DefaultScreen(dpy);
+ priv->initPointerX = scalex(priv, priv->width / 2);
+ priv->initPointerY = scaley(priv, priv->height / 2);
+ priv->eventMask = (ButtonPressMask
+ | ButtonReleaseMask
+ | PointerMotionMask
+ | EnterWindowMask
+ | LeaveWindowMask
+ | KeyPressMask
+ | KeyReleaseMask
+ | ExposureMask
+ | ResizeRedirectMask);
+
+ mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect;
+ attribs.colormap = DefaultColormap(dpy, screen);
+ if (XParseColor(dpy, attribs.colormap, CONSOLE_BG_COLOR, &color)
+ && XAllocColor(dpy, attribs.colormap, &color)) {
+ attribs.background_pixel = color.pixel;
+ } else
+ attribs.background_pixel = WhitePixel(dpy, screen);
+
+ attribs.event_mask = priv->eventMask;
+ attribs.override_redirect = False;
+
+ win = priv->window = XCreateWindow(dpy,
+ RootWindow(dpy, screen),
+ 0, 0, priv->consWidth, priv->consHeight,
+ 0,
+ DefaultDepth(dpy, screen),
+ InputOutput,
+ DefaultVisual(dpy, screen),
+ mask, &attribs);
+ priv->pixmap = XCreatePixmap(dpy, RootWindow(dpy, screen),
+ priv->consWidth, priv->consHeight,
+ DefaultDepth(dpy, screen));
+
+ /* Set up properties */
+ XStoreName(dpy, win, DMX_CONSOLE_NAME);
+ class_hints.res_name = DMX_RES_NAME;
+ class_hints.res_class = DMX_RES_CLASS;
+ XSetClassHint(dpy, win, &class_hints);
+
+
+ /* Map the window */
+ XMapWindow(dpy, win);
+
+ /* Create cursors */
+ priv->cursorNormal = XCreateFontCursor(dpy, XC_circle);
+ priv->cursorGrabbed = XCreateFontCursor(dpy, XC_spider);
+ priv->cursorEmpty = dmxConsoleCreateEmptyCursor(priv);
+ XDefineCursor(dpy, priv->window, priv->cursorNormal);
+
+ /* Create GC */
+ mask = (GCFunction | GCPlaneMask | GCClipMask | GCForeground |
+ GCBackground | GCLineWidth | GCLineStyle | GCCapStyle |
+ GCFillStyle | GCGraphicsExposures);
+ gcvals.function = GXcopy;
+ gcvals.plane_mask = AllPlanes;
+ gcvals.clip_mask = None;
+ if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_FG_COLOR, &color)
+ && XAllocColor(dpy, attribs.colormap, &color)) {
+ gcvals.foreground = color.pixel;
+ } else
+ gcvals.foreground = BlackPixel(dpy, screen);
+ if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_BG_COLOR, &color)
+ && XAllocColor(dpy, attribs.colormap, &color)) {
+ gcvals.background = color.pixel;
+ } else
+ gcvals.background = WhitePixel(dpy, screen);
+ gcvals.line_width = 0;
+ gcvals.line_style = LineSolid;
+ gcvals.cap_style = CapNotLast;
+ gcvals.fill_style = FillSolid;
+ gcvals.graphics_exposures = False;
+
+ priv->gc = XCreateGC(dpy, win, mask, &gcvals);
+
+ tmp = gcvals.foreground;
+ if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_DET_COLOR, &color)
+ && XAllocColor(dpy, attribs.colormap, &color)) {
+ gcvals.foreground = color.pixel;
+ } else
+ gcvals.foreground = BlackPixel(dpy, screen);
+ priv->gcDet = XCreateGC(dpy, win, mask, &gcvals);
+ gcvals.foreground = tmp;
+
+ tmp = gcvals.background;
+ gcvals.background = gcvals.foreground;
+ gcvals.foreground = tmp;
+ priv->gcRev = XCreateGC(dpy, win, mask, &gcvals);
+
+ gcvals.background = gcvals.foreground;
+ if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_CUR_COLOR, &color)
+ && XAllocColor(dpy, attribs.colormap, &color)) {
+ gcvals.foreground = color.pixel;
+ } else
+ gcvals.foreground = BlackPixel(dpy, screen);
+ priv->gcCur = XCreateGC(dpy, win, mask, &gcvals);
+
+ dmxConsoleDraw(priv, 1, 1);
+
+ if (screenInfo.screens[0]->devPrivates[dmxScreenPrivateIndex].ptr)
+ priv->next = (screenInfo.screens[0]
+ ->devPrivates[dmxScreenPrivateIndex].ptr);
+ else
+ DMX_WRAP(CloseScreen, dmxCloseConsoleScreen,
+ priv, screenInfo.screens[0]);
+ screenInfo.screens[0]->devPrivates[dmxScreenPrivateIndex].ptr = priv;
+}
+
+/** Fill in the \a info structure for the specified \a pDev. Only used
+ * for pointers. */
+void dmxConsoleMouGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ info->buttonClass = 1;
+ dmxCommonMouGetMap(pDev, info->map, &info->numButtons);
+ info->valuatorClass = 1;
+ info->numRelAxes = 2;
+ info->minval[0] = 0;
+ info->maxval[0] = 0;
+ info->res[0] = 1;
+ info->minres[0] = 0;
+ info->maxres[0] = 1;
+ info->ptrFeedbackClass = 1;
+}
+
+/** Fill in the \a info structure for the specified \a pDev. Only used
+ * for keyboard. */
+void dmxConsoleKbdGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ dmxCommonKbdGetInfo(pDev, info);
+ info->keyboard = 1;
+ info->keyClass = 1;
+ dmxCommonKbdGetMap(pDev, &info->keySyms, info->modMap);
+ info->freemap = 1;
+ info->focusClass = 1;
+ info->kbdFeedbackClass = 1;
+}
+
+/** Handle special console-only keys. */
+int dmxConsoleFunctions(pointer private, DMXFunctionType function)
+{
+ GETONLYPRIVFROMPRIVATE;
+ XRectangle rect;
+ Display *dpy = priv->display;
+
+ switch (function) {
+ case DMX_FUNCTION_FINE:
+ if (priv->fine) {
+ priv->fine = 0;
+ dmxConsoleClearCursor(priv, priv->globalX, priv->globalY, &rect);
+ XSetClipRectangles(dpy, priv->gc, 0, 0, &rect, 1, Unsorted);
+ XCopyArea(dpy, priv->pixmap, priv->window, priv->gc,
+ 0, 0, priv->consWidth, priv->consHeight, 0, 0);
+ XSetClipMask(dpy, priv->gc, None);
+
+ XDefineCursor(dpy, priv->window,
+ priv->grabbed
+ ? priv->cursorGrabbed
+ : priv->cursorNormal);
+ XWarpPointer(dpy, priv->window, priv->window,
+ 0, 0, 0, 0,
+ scalex(priv, priv->globalX),
+ scaley(priv, priv->globalY));
+ XSync(dpy, False); /* Not a backend display */
+ } else {
+ priv->fine = 1;
+ XRaiseWindow(dpy, priv->window);
+ XDefineCursor(dpy, priv->window, priv->cursorEmpty);
+ dmxConsoleUpdateFineCursor(priv);
+ }
+ return 1;
+ case DMX_FUNCTION_GRAB:
+ if (priv->grabbed) {
+ XUngrabKeyboard(dpy, CurrentTime);
+ XUngrabPointer(dpy, CurrentTime);
+ XDefineCursor(dpy, priv->window,
+ priv->fine
+ ? priv->cursorEmpty
+ : priv->cursorNormal);
+ } else {
+ if (XGrabPointer(dpy, priv->window, True,
+ 0, GrabModeAsync, GrabModeAsync, priv->window,
+ None, CurrentTime)) {
+ dmxLog(dmxError, "XGrabPointer failed\n");
+ return 0;
+ }
+ if (XGrabKeyboard(dpy, priv->window, True,
+ GrabModeAsync, GrabModeAsync, CurrentTime)) {
+ dmxLog(dmxError, "XGrabKeyboard failed\n");
+ XUngrabPointer(dpy, CurrentTime);
+ return 0;
+ }
+ XDefineCursor(dpy, priv->window,
+ priv->fine
+ ? priv->cursorEmpty
+ : priv->cursorGrabbed);
+ }
+ priv->grabbed = !priv->grabbed;
+ if (priv->fine) dmxConsoleUpdateFineCursor(priv);
+ return 1;
+ case DMX_FUNCTION_TERMINATE:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static void dmxDump(void)
+{
+ int i, j;
+ DMXInputInfo *dmxInput;
+ XEvent X;
+
+ for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) {
+ for (j = 0; j < dmxInput->numDevs; j++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
+ myPrivate *priv = dmxLocal->private;
+ while (priv
+ && priv->display
+ && XCheckTypedEvent(priv->display, MotionNotify, &X)) {
+ DMXDBG4("dmxDump: %s/%d threw event away %d %s\n",
+ dmxInput->name, j, X.type, dmxEventName(X.type));
+ }
+ }
+ }
+}
+
+/** This routine is used to warp the pointer into the console window
+ * from anywhere on the screen. It is used when backend and console
+ * input are both being taken from the same X display. */
+void dmxConsoleCapture(DMXInputInfo *dmxInput)
+{
+ int i;
+ XEvent X;
+
+ DMXDBG0("dmxConsoleCapture\n");
+ dmxSync(NULL, TRUE);
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ myPrivate *priv = dmxLocal->private;
+ if (dmxLocal->extType != DMX_LOCAL_TYPE_CONSOLE) continue;
+ if (dmxLocal->type != DMX_LOCAL_MOUSE) continue;
+ if (priv->captured) continue;
+ priv->captured = 2; /* Ungrab only after proximal events. */
+ XRaiseWindow(priv->display, priv->window);
+ XSync(priv->display, False); /* Not a backend display */
+ while (XCheckTypedEvent(priv->display, MotionNotify, &X)) {
+ DMXDBG3(" Ignoring motion to %d %d after capture on %s\n",
+ X.xmotion.x, X.xmotion.y, dmxInput->name);
+ }
+ XWarpPointer(priv->display, None,
+ priv->window, 0, 0, 0, 0, priv->curX, priv->curY);
+ XSync(priv->display, False); /* Not a backend display */
+ dmxDump();
+ if (priv->fine) dmxConsoleUpdateFineCursor(priv);
+ }
+}
+
+/** Undo the capture that was done by #dmxConsoleCapture. */
+void dmxConsoleUncapture(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ DMXDBG0("dmxConsoleUncapture\n");
+ dmxSync(NULL, TRUE);
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ myPrivate *priv = dmxLocal->private;
+ if (dmxLocal->extType != DMX_LOCAL_TYPE_CONSOLE) continue;
+ if (dmxLocal->type != DMX_LOCAL_MOUSE) continue;
+ if (!priv->captured) continue;
+ priv->captured = 0;
+ XSync(priv->display, False); /* Not a backend display */
+ }
+}
diff --git a/hw/xfree86/os-support/drm/xf86drm.c b/hw/xfree86/os-support/drm/xf86drm.c
new file mode 100644
index 000000000..2b0b1b9cc
--- /dev/null
+++ b/hw/xfree86/os-support/drm/xf86drm.c
@@ -0,0 +1,2335 @@
+/**
+ * \file xf86drm.c
+ * User-level interface to DRM device
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Kevin E. Martin <martin@valinux.com>
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * 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, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.36 2003/08/24 17:35:35 tsi Exp $ */
+
+#ifdef XFree86Server
+# include "xf86.h"
+# include "xf86_OSproc.h"
+# include "drm.h"
+# include "xf86_ansic.h"
+# define _DRM_MALLOC xalloc
+# define _DRM_FREE xfree
+# ifndef XFree86LOADER
+# include <sys/mman.h>
+# endif
+#else
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
+# include <string.h>
+# include <ctype.h>
+# include <fcntl.h>
+# include <errno.h>
+# include <signal.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# define stat_t struct stat
+# include <sys/ioctl.h>
+# include <sys/mman.h>
+# include <sys/time.h>
+# include <stdarg.h>
+# ifdef DRM_USE_MALLOC
+# define _DRM_MALLOC malloc
+# define _DRM_FREE free
+extern int xf86InstallSIGIOHandler(int fd, void (*f)(int, void *), void *);
+extern int xf86RemoveSIGIOHandler(int fd);
+# else
+# include <X11/Xlibint.h>
+# define _DRM_MALLOC Xmalloc
+# define _DRM_FREE Xfree
+# endif
+# include "drm.h"
+#endif
+
+/* No longer needed with CVS kernel modules on alpha
+#if defined(__alpha__) && defined(__linux__)
+extern unsigned long _bus_base(void);
+#define BUS_BASE _bus_base()
+#endif
+*/
+
+/* Not all systems have MAP_FAILED defined */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#include "xf86drm.h"
+
+#ifdef __FreeBSD__
+#define DRM_MAJOR 145
+#endif
+
+#ifdef __NetBSD__
+#define DRM_MAJOR 34
+#endif
+
+# ifdef __OpenBSD__
+# define DRM_MAJOR 81
+# endif
+
+#ifndef DRM_MAJOR
+#define DRM_MAJOR 226 /* Linux */
+#endif
+
+#ifndef DRM_MAX_MINOR
+#define DRM_MAX_MINOR 16
+#endif
+
+#ifdef __linux__
+#include <sys/sysmacros.h> /* for makedev() */
+#endif
+
+#ifndef makedev
+ /* This definition needs to be changed on
+ some systems if dev_t is a structure.
+ If there is a header file we can get it
+ from, there would be best. */
+#define makedev(x,y) ((dev_t)(((x) << 8) | (y)))
+#endif
+
+#define DRM_MSG_VERBOSITY 3
+
+/**
+ * Output a message to stderr.
+ *
+ * \param format printf() like format string.
+ *
+ * \internal
+ * This function is a wrapper around vfprintf().
+ */
+static void
+drmMsg(const char *format, ...)
+{
+ va_list ap;
+
+#ifndef XFree86Server
+ const char *env;
+ if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose"))
+#endif
+ {
+ va_start(ap, format);
+#ifdef XFree86Server
+ xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap);
+#else
+ vfprintf(stderr, format, ap);
+#endif
+ va_end(ap);
+ }
+}
+
+static void *drmHashTable = NULL; /* Context switch callbacks */
+
+typedef struct drmHashEntry {
+ int fd;
+ void (*f)(int, void *, void *);
+ void *tagTable;
+} drmHashEntry;
+
+void *drmMalloc(int size)
+{
+ void *pt;
+ if ((pt = _DRM_MALLOC(size))) memset(pt, 0, size);
+ return pt;
+}
+
+void drmFree(void *pt)
+{
+ if (pt) _DRM_FREE(pt);
+}
+
+/* drmStrdup can't use strdup(3), since it doesn't call _DRM_MALLOC... */
+static char *drmStrdup(const char *s)
+{
+ char *retval = NULL;
+
+ if (s) {
+ retval = _DRM_MALLOC(strlen(s)+1);
+ strcpy(retval, s);
+ }
+ return retval;
+}
+
+
+static unsigned long drmGetKeyFromFd(int fd)
+{
+ stat_t st;
+
+ st.st_rdev = 0;
+ fstat(fd, &st);
+ return st.st_rdev;
+}
+
+static drmHashEntry *drmGetEntry(int fd)
+{
+ unsigned long key = drmGetKeyFromFd(fd);
+ void *value;
+ drmHashEntry *entry;
+
+ if (!drmHashTable) drmHashTable = drmHashCreate();
+
+ if (drmHashLookup(drmHashTable, key, &value)) {
+ entry = drmMalloc(sizeof(*entry));
+ entry->fd = fd;
+ entry->f = NULL;
+ entry->tagTable = drmHashCreate();
+ drmHashInsert(drmHashTable, key, entry);
+ } else {
+ entry = value;
+ }
+ return entry;
+}
+
+/**
+ * Compare two busid strings
+ *
+ * \param first
+ * \param second
+ *
+ * \return 1 if matched.
+ *
+ * \internal
+ * This function compares two bus ID strings. It understands the older
+ * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is
+ * domain, b is bus, d is device, f is function.
+ */
+static int drmMatchBusID(const char *id1, const char *id2)
+{
+ /* First, check if the IDs are exactly the same */
+ if (strcasecmp(id1, id2) == 0)
+ return 1;
+
+ /* Try to match old/new-style PCI bus IDs. */
+ if (strncasecmp(id1, "pci", 3) == 0) {
+ int o1, b1, d1, f1;
+ int o2, b2, d2, f2;
+ int ret;
+
+ ret = sscanf(id1, "pci:%04x:%02x:%02x.%d", &o1, &b1, &d1, &f1);
+ if (ret != 4) {
+ o1 = 0;
+ ret = sscanf(id1, "PCI:%d:%d:%d", &b1, &d1, &f1);
+ if (ret != 3)
+ return 0;
+ }
+
+ ret = sscanf(id2, "pci:%04x:%02x:%02x.%d", &o2, &b2, &d2, &f2);
+ if (ret != 4) {
+ o2 = 0;
+ ret = sscanf(id2, "PCI:%d:%d:%d", &b2, &d2, &f2);
+ if (ret != 3)
+ return 0;
+ }
+
+ if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
+ return 0;
+ else
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Open the DRM device, creating it if necessary.
+ *
+ * \param dev major and minor numbers of the device.
+ * \param minor minor number of the device.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * Assembles the device name from \p minor and opens it, creating the device
+ * special file node with the major and minor numbers specified by \p dev and
+ * parent directory if necessary and was called by root.
+ */
+static int drmOpenDevice(long dev, int minor)
+{
+ stat_t st;
+ char buf[64];
+ int fd;
+ mode_t devmode = DRM_DEV_MODE;
+ int isroot = !geteuid();
+#if defined(XFree86Server)
+ uid_t user = DRM_DEV_UID;
+ gid_t group = DRM_DEV_GID;
+#endif
+
+ sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+ drmMsg("drmOpenDevice: node name is %s\n", buf);
+
+#if defined(XFree86Server)
+ devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE;
+ devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
+ group = (xf86ConfigDRI.group >= 0) ? xf86ConfigDRI.group : DRM_DEV_GID;
+#endif
+
+ if (stat(DRM_DIR_NAME, &st)) {
+ if (!isroot) return DRM_ERR_NOT_ROOT;
+ mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
+ chown(DRM_DIR_NAME, 0, 0); /* root:root */
+ chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
+ }
+
+ /* Check if the device node exists and create it if necessary. */
+ if (stat(buf, &st)) {
+ if (!isroot) return DRM_ERR_NOT_ROOT;
+ remove(buf);
+ mknod(buf, S_IFCHR | devmode, dev);
+ }
+#if defined(XFree86Server)
+ chown(buf, user, group);
+ chmod(buf, devmode);
+#endif
+
+ fd = open(buf, O_RDWR, 0);
+ drmMsg("drmOpenDevice: open result is %d, (%s)\n",
+ fd, fd < 0 ? strerror(errno) : "OK");
+ if (fd >= 0) return fd;
+
+ /* Check if the device node is not what we expect it to be, and recreate it
+ * and try again if so.
+ */
+ if (st.st_rdev != dev) {
+ if (!isroot) return DRM_ERR_NOT_ROOT;
+ remove(buf);
+ mknod(buf, S_IFCHR | devmode, dev);
+#if defined(XFree86Server)
+ chown(buf, user, group);
+ chmod(buf, devmode);
+#endif
+ }
+ fd = open(buf, O_RDWR, 0);
+ drmMsg("drmOpenDevice: open result is %d, (%s)\n",
+ fd, fd < 0 ? strerror(errno) : "OK");
+ if (fd >= 0) return fd;
+
+ drmMsg("drmOpenDevice: Open failed\n");
+ remove(buf);
+ return -errno;
+}
+
+
+/**
+ * Open the DRM device
+ *
+ * \param minor device minor number.
+ * \param create allow to create the device if set.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
+ * name from \p minor and opens it.
+ */
+static int drmOpenMinor(int minor, int create)
+{
+ int fd;
+ char buf[64];
+
+ if (create) return drmOpenDevice(makedev(DRM_MAJOR, minor), minor);
+
+ sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+ if ((fd = open(buf, O_RDWR, 0)) >= 0) return fd;
+ return -errno;
+}
+
+
+/**
+ * Determine whether the DRM kernel driver has been loaded.
+ *
+ * \return 1 if the DRM driver is loaded, 0 otherwise.
+ *
+ * \internal
+ * Determine the presence of the kernel driver by attempting to open the 0
+ * minor and get version information. For backward compatibility with older
+ * Linux implementations, /proc/dri is also checked.
+ */
+int drmAvailable(void)
+{
+ drmVersionPtr version;
+ int retval = 0;
+ int fd;
+
+ if ((fd = drmOpenMinor(0, 1)) < 0) {
+#ifdef __linux__
+ /* Try proc for backward Linux compatibility */
+ if (!access("/proc/dri/0", R_OK)) return 1;
+#endif
+ return 0;
+ }
+
+ if ((version = drmGetVersion(fd))) {
+ retval = 1;
+ drmFreeVersion(version);
+ }
+ close(fd);
+
+ return retval;
+}
+
+
+/**
+ * Open the device by bus ID.
+ *
+ * \param busid bus ID.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
+ * comparing the device bus ID with the one supplied.
+ *
+ * \sa drmOpenMinor() and drmGetBusid().
+ */
+static int drmOpenByBusid(const char *busid)
+{
+ int i;
+ int fd;
+ const char *buf;
+ drmSetVersion sv;
+
+ drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
+ for (i = 0; i < DRM_MAX_MINOR; i++) {
+ fd = drmOpenMinor(i, 1);
+ drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
+ if (fd >= 0) {
+ sv.drm_di_major = 1;
+ sv.drm_di_minor = 1;
+ sv.drm_dd_major = -1; /* Don't care */
+ drmSetInterfaceVersion(fd, &sv);
+ buf = drmGetBusid(fd);
+ drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
+ if (buf && drmMatchBusID(buf, busid)) {
+ drmFreeBusid(buf);
+ return fd;
+ }
+ if (buf) drmFreeBusid(buf);
+ close(fd);
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Open the device by name.
+ *
+ * \param name driver name.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * This function opens the first minor number that matches the driver name and
+ * isn't already in use. If it's in use it then it will already have a bus ID
+ * assigned.
+ *
+ * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
+ */
+static int drmOpenByName(const char *name)
+{
+ int i;
+ int fd;
+ drmVersionPtr version;
+ char * id;
+
+ if (!drmAvailable()) {
+#if !defined(XFree86Server)
+ return -1;
+#else
+ /* try to load the kernel module now */
+ if (!xf86LoadKernelModule(name)) {
+ ErrorF("[drm] failed to load kernel module \"%s\"\n",
+ name);
+ return -1;
+ }
+#endif
+ }
+
+ /*
+ * Open the first minor number that matches the driver name and isn't
+ * already in use. If it's in use it will have a busid assigned already.
+ */
+ for (i = 0; i < DRM_MAX_MINOR; i++) {
+ if ((fd = drmOpenMinor(i, 1)) >= 0) {
+ if ((version = drmGetVersion(fd))) {
+ if (!strcmp(version->name, name)) {
+ drmFreeVersion(version);
+ id = drmGetBusid(fd);
+ drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
+ if (!id || !*id) {
+ if (id) {
+ drmFreeBusid(id);
+ }
+ return fd;
+ } else {
+ drmFreeBusid(id);
+ }
+ } else {
+ drmFreeVersion(version);
+ }
+ }
+ close(fd);
+ }
+ }
+
+#ifdef __linux__
+ /* Backward-compatibility /proc support */
+ for (i = 0; i < 8; i++) {
+ char proc_name[64], buf[512];
+ char *driver, *pt, *devstring;
+ int retcode;
+
+ sprintf(proc_name, "/proc/dri/%d/name", i);
+ if ((fd = open(proc_name, 0, 0)) >= 0) {
+ retcode = read(fd, buf, sizeof(buf)-1);
+ close(fd);
+ if (retcode) {
+ buf[retcode-1] = '\0';
+ for (driver = pt = buf; *pt && *pt != ' '; ++pt)
+ ;
+ if (*pt) { /* Device is next */
+ *pt = '\0';
+ if (!strcmp(driver, name)) { /* Match */
+ for (devstring = ++pt; *pt && *pt != ' '; ++pt)
+ ;
+ if (*pt) { /* Found busid */
+ return drmOpenByBusid(++pt);
+ } else { /* No busid */
+ return drmOpenDevice(strtol(devstring, NULL, 0),i);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ return -1;
+}
+
+
+/**
+ * Open the DRM device.
+ *
+ * Looks up the specified name and bus ID, and opens the device found. The
+ * entry in /dev/dri is created if necessary and if called by root.
+ *
+ * \param name driver name. Not referenced if bus ID is supplied.
+ * \param busid bus ID. Zero if not known.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
+ * otherwise.
+ */
+int drmOpen(const char *name, const char *busid)
+{
+#ifdef XFree86Server
+ if (!drmAvailable() && name != NULL) {
+ /* try to load the kernel */
+ if (!xf86LoadKernelModule(name)) {
+ ErrorF("[drm] failed to load kernel module \"%s\"\n",
+ name);
+ return -1;
+ }
+ }
+#endif
+
+ if (busid) {
+ int fd;
+
+ fd = drmOpenByBusid(busid);
+ if (fd >= 0)
+ return fd;
+ }
+ if (name)
+ return drmOpenByName(name);
+ return -1;
+}
+
+
+/**
+ * Free the version information returned by drmGetVersion().
+ *
+ * \param v pointer to the version information.
+ *
+ * \internal
+ * It frees the memory pointed by \p %v as well as all the non-null strings
+ * pointers in it.
+ */
+void drmFreeVersion(drmVersionPtr v)
+{
+ if (!v) return;
+ if (v->name) drmFree(v->name);
+ if (v->date) drmFree(v->date);
+ if (v->desc) drmFree(v->desc);
+ drmFree(v);
+}
+
+
+/**
+ * Free the non-public version information returned by the kernel.
+ *
+ * \param v pointer to the version information.
+ *
+ * \internal
+ * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
+ * the non-null strings pointers in it.
+ */
+static void drmFreeKernelVersion(drm_version_t *v)
+{
+ if (!v) return;
+ if (v->name) drmFree(v->name);
+ if (v->date) drmFree(v->date);
+ if (v->desc) drmFree(v->desc);
+ drmFree(v);
+}
+
+
+/**
+ * Copy version information.
+ *
+ * \param d destination pointer.
+ * \param s source pointer.
+ *
+ * \internal
+ * Used by drmGetVersion() to translate the information returned by the ioctl
+ * interface in a private structure into the public structure counterpart.
+ */
+static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
+{
+ d->version_major = s->version_major;
+ d->version_minor = s->version_minor;
+ d->version_patchlevel = s->version_patchlevel;
+ d->name_len = s->name_len;
+ d->name = drmStrdup(s->name);
+ d->date_len = s->date_len;
+ d->date = drmStrdup(s->date);
+ d->desc_len = s->desc_len;
+ d->desc = drmStrdup(s->desc);
+}
+
+
+/**
+ * Query the driver version information.
+ *
+ * \param fd file descriptor.
+ *
+ * \return pointer to a drmVersion structure which should be freed with
+ * drmFreeVersion().
+ *
+ * \note Similar information is available via /proc/dri.
+ *
+ * \internal
+ * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
+ * first with zeros to get the string lengths, and then the actually strings.
+ * It also null-terminates them since they might not be already.
+ */
+drmVersionPtr drmGetVersion(int fd)
+{
+ drmVersionPtr retval;
+ drm_version_t *version = drmMalloc(sizeof(*version));
+
+ /* First, get the lengths */
+ version->name_len = 0;
+ version->name = NULL;
+ version->date_len = 0;
+ version->date = NULL;
+ version->desc_len = 0;
+ version->desc = NULL;
+
+ if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
+ drmFreeKernelVersion(version);
+ return NULL;
+ }
+
+ /* Now, allocate space and get the data */
+ if (version->name_len)
+ version->name = drmMalloc(version->name_len + 1);
+ if (version->date_len)
+ version->date = drmMalloc(version->date_len + 1);
+ if (version->desc_len)
+ version->desc = drmMalloc(version->desc_len + 1);
+
+ if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
+ drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
+ drmFreeKernelVersion(version);
+ return NULL;
+ }
+
+ /* The results might not be null-terminated
+ strings, so terminate them. */
+
+ if (version->name_len) version->name[version->name_len] = '\0';
+ if (version->date_len) version->date[version->date_len] = '\0';
+ if (version->desc_len) version->desc[version->desc_len] = '\0';
+
+ /* Now, copy it all back into the
+ client-visible data structure... */
+ retval = drmMalloc(sizeof(*retval));
+ drmCopyVersion(retval, version);
+ drmFreeKernelVersion(version);
+ return retval;
+}
+
+
+/**
+ * Get version information for the DRM user space library.
+ *
+ * This version number is driver independent.
+ *
+ * \param fd file descriptor.
+ *
+ * \return version information.
+ *
+ * \internal
+ * This function allocates and fills a drm_version structure with a hard coded
+ * version number.
+ */
+drmVersionPtr drmGetLibVersion(int fd)
+{
+ drm_version_t *version = drmMalloc(sizeof(*version));
+
+ /* Version history:
+ * revision 1.0.x = original DRM interface with no drmGetLibVersion
+ * entry point and many drm<Device> extensions
+ * revision 1.1.x = added drmCommand entry points for device extensions
+ * added drmGetLibVersion to identify libdrm.a version
+ * revision 1.2.x = added drmSetInterfaceVersion
+ * modified drmOpen to handle both busid and name
+ */
+ version->version_major = 1;
+ version->version_minor = 2;
+ version->version_patchlevel = 0;
+
+ return (drmVersionPtr)version;
+}
+
+
+/**
+ * Free the bus ID information.
+ *
+ * \param busid bus ID information string as given by drmGetBusid().
+ *
+ * \internal
+ * This function is just frees the memory pointed by \p busid.
+ */
+void drmFreeBusid(const char *busid)
+{
+ drmFree((void *)busid);
+}
+
+
+/**
+ * Get the bus ID of the device.
+ *
+ * \param fd file descriptor.
+ *
+ * \return bus ID string.
+ *
+ * \internal
+ * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
+ * get the string length and data, passing the arguments in a drm_unique
+ * structure.
+ */
+char *drmGetBusid(int fd)
+{
+ drm_unique_t u;
+
+ u.unique_len = 0;
+ u.unique = NULL;
+
+ if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
+ u.unique = drmMalloc(u.unique_len + 1);
+ if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
+ u.unique[u.unique_len] = '\0';
+
+ return u.unique;
+}
+
+
+/**
+ * Set the bus ID of the device.
+ *
+ * \param fd file descriptor.
+ * \param busid bus ID string.
+ *
+ * \return zero on success, negative on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
+ * the arguments in a drm_unique structure.
+ */
+int drmSetBusid(int fd, const char *busid)
+{
+ drm_unique_t u;
+
+ u.unique = (char *)busid;
+ u.unique_len = strlen(busid);
+
+ if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
+ return -errno;
+ }
+ return 0;
+}
+
+int drmGetMagic(int fd, drm_magic_t * magic)
+{
+ drm_auth_t auth;
+
+ *magic = 0;
+ if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) return -errno;
+ *magic = auth.magic;
+ return 0;
+}
+
+int drmAuthMagic(int fd, drm_magic_t magic)
+{
+ drm_auth_t auth;
+
+ auth.magic = magic;
+ if (ioctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) return -errno;
+ return 0;
+}
+
+/**
+ * Specifies a range of memory that is available for mapping by a
+ * non-root process.
+ *
+ * \param fd file descriptor.
+ * \param offset usually the physical address. The actual meaning depends of
+ * the \p type parameter. See below.
+ * \param size of the memory in bytes.
+ * \param type type of the memory to be mapped.
+ * \param flags combination of several flags to modify the function actions.
+ * \param handle will be set to a value that may be used as the offset
+ * parameter for mmap().
+ *
+ * \return zero on success or a negative value on error.
+ *
+ * \par Mapping the frame buffer
+ * For the frame buffer
+ * - \p offset will be the physical address of the start of the frame buffer,
+ * - \p size will be the size of the frame buffer in bytes, and
+ * - \p type will be DRM_FRAME_BUFFER.
+ *
+ * \par
+ * The area mapped will be uncached. If MTRR support is available in the
+ * kernel, the frame buffer area will be set to write combining.
+ *
+ * \par Mapping the MMIO register area
+ * For the MMIO register area,
+ * - \p offset will be the physical address of the start of the register area,
+ * - \p size will be the size of the register area bytes, and
+ * - \p type will be DRM_REGISTERS.
+ * \par
+ * The area mapped will be uncached.
+ *
+ * \par Mapping the SAREA
+ * For the SAREA,
+ * - \p offset will be ignored and should be set to zero,
+ * - \p size will be the desired size of the SAREA in bytes,
+ * - \p type will be DRM_SHM.
+ *
+ * \par
+ * A shared memory area of the requested size will be created and locked in
+ * kernel memory. This area may be mapped into client-space by using the handle
+ * returned.
+ *
+ * \note May only be called by root.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
+ * the arguments in a drm_map structure.
+ */
+int drmAddMap(int fd,
+ drm_handle_t offset,
+ drmSize size,
+ drmMapType type,
+ drmMapFlags flags,
+ drm_handle_t * handle)
+{
+ drm_map_t map;
+
+ map.offset = offset;
+/* No longer needed with CVS kernel modules on alpha
+#ifdef __alpha__
+ if (type != DRM_SHM)
+ map.offset += BUS_BASE;
+#endif
+*/
+ map.size = size;
+ map.handle = 0;
+ map.type = type;
+ map.flags = flags;
+ if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map)) return -errno;
+ if (handle) *handle = (drm_handle_t)map.handle;
+ return 0;
+}
+
+int drmRmMap(int fd, drm_handle_t handle)
+{
+ drm_map_t map;
+
+ map.handle = (void *)handle;
+
+ if(ioctl(fd, DRM_IOCTL_RM_MAP, &map)) return -errno;
+ return 0;
+}
+
+/**
+ * Make buffers available for DMA transfers.
+ *
+ * \param fd file descriptor.
+ * \param count number of buffers.
+ * \param size size of each buffer.
+ * \param flags buffer allocation flags.
+ * \param agp_offset offset in the AGP aperture
+ *
+ * \return number of buffers allocated, negative on error.
+ *
+ * \internal
+ * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
+ *
+ * \sa drm_buf_desc.
+ */
+int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
+ int agp_offset)
+{
+ drm_buf_desc_t request;
+
+ request.count = count;
+ request.size = size;
+ request.low_mark = 0;
+ request.high_mark = 0;
+ request.flags = flags;
+ request.agp_start = agp_offset;
+
+ if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno;
+ return request.count;
+}
+
+int drmMarkBufs(int fd, double low, double high)
+{
+ drm_buf_info_t info;
+ int i;
+
+ info.count = 0;
+ info.list = NULL;
+
+ if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return -EINVAL;
+
+ if (!info.count) return -EINVAL;
+
+ if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
+ return -ENOMEM;
+
+ if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
+ int retval = -errno;
+ drmFree(info.list);
+ return retval;
+ }
+
+ for (i = 0; i < info.count; i++) {
+ info.list[i].low_mark = low * info.list[i].count;
+ info.list[i].high_mark = high * info.list[i].count;
+ if (ioctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
+ int retval = -errno;
+ drmFree(info.list);
+ return retval;
+ }
+ }
+ drmFree(info.list);
+
+ return 0;
+}
+
+/**
+ * Free buffers.
+ *
+ * \param fd file descriptor.
+ * \param count number of buffers to free.
+ * \param list list of buffers to be freed.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \note This function is primarily used for debugging.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
+ * the arguments in a drm_buf_free structure.
+ */
+int drmFreeBufs(int fd, int count, int *list)
+{
+ drm_buf_free_t request;
+
+ request.count = count;
+ request.list = list;
+ if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Close the device.
+ *
+ * \param fd file descriptor.
+ *
+ * \internal
+ * This function closes the file descriptor.
+ */
+int drmClose(int fd)
+{
+ unsigned long key = drmGetKeyFromFd(fd);
+ drmHashEntry *entry = drmGetEntry(fd);
+
+ drmHashDestroy(entry->tagTable);
+ entry->fd = 0;
+ entry->f = NULL;
+ entry->tagTable = NULL;
+
+ drmHashDelete(drmHashTable, key);
+ drmFree(entry);
+
+ return close(fd);
+}
+
+
+/**
+ * Map a region of memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle returned by drmAddMap().
+ * \param size size in bytes. Must match the size used by drmAddMap().
+ * \param address will contain the user-space virtual address where the mapping
+ * begins.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper for mmap().
+ */
+int drmMap(int fd,
+ drm_handle_t handle,
+ drmSize size,
+ drmAddressPtr address)
+{
+ static unsigned long pagesize_mask = 0;
+
+ if (fd < 0) return -EINVAL;
+
+ if (!pagesize_mask)
+ pagesize_mask = getpagesize() - 1;
+
+ size = (size + pagesize_mask) & ~pagesize_mask;
+
+ *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
+ if (*address == MAP_FAILED) return -errno;
+ return 0;
+}
+
+
+/**
+ * Unmap mappings obtained with drmMap().
+ *
+ * \param address address as given by drmMap().
+ * \param size size in bytes. Must match the size used by drmMap().
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper for unmap().
+ */
+int drmUnmap(drmAddress address, drmSize size)
+{
+ return munmap(address, size);
+}
+
+drmBufInfoPtr drmGetBufInfo(int fd)
+{
+ drm_buf_info_t info;
+ drmBufInfoPtr retval;
+ int i;
+
+ info.count = 0;
+ info.list = NULL;
+
+ if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return NULL;
+
+ if (info.count) {
+ if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
+ return NULL;
+
+ if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
+ drmFree(info.list);
+ return NULL;
+ }
+ /* Now, copy it all back into the
+ client-visible data structure... */
+ retval = drmMalloc(sizeof(*retval));
+ retval->count = info.count;
+ retval->list = drmMalloc(info.count * sizeof(*retval->list));
+ for (i = 0; i < info.count; i++) {
+ retval->list[i].count = info.list[i].count;
+ retval->list[i].size = info.list[i].size;
+ retval->list[i].low_mark = info.list[i].low_mark;
+ retval->list[i].high_mark = info.list[i].high_mark;
+ }
+ drmFree(info.list);
+ return retval;
+ }
+ return NULL;
+}
+
+/**
+ * Map all DMA buffers into client-virtual space.
+ *
+ * \param fd file descriptor.
+ *
+ * \return a pointer to a ::drmBufMap structure.
+ *
+ * \note The client may not use these buffers until obtaining buffer indices
+ * with drmDMA().
+ *
+ * \internal
+ * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
+ * information about the buffers in a drm_buf_map structure into the
+ * client-visible data structures.
+ */
+drmBufMapPtr drmMapBufs(int fd)
+{
+ drm_buf_map_t bufs;
+ drmBufMapPtr retval;
+ int i;
+
+ bufs.count = 0;
+ bufs.list = NULL;
+ bufs.virtual = NULL;
+ if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL;
+
+ if (!bufs.count) return NULL;
+
+ if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
+ return NULL;
+
+ if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
+ drmFree(bufs.list);
+ return NULL;
+ }
+ /* Now, copy it all back into the
+ client-visible data structure... */
+ retval = drmMalloc(sizeof(*retval));
+ retval->count = bufs.count;
+ retval->list = drmMalloc(bufs.count * sizeof(*retval->list));
+ for (i = 0; i < bufs.count; i++) {
+ retval->list[i].idx = bufs.list[i].idx;
+ retval->list[i].total = bufs.list[i].total;
+ retval->list[i].used = 0;
+ retval->list[i].address = bufs.list[i].address;
+ }
+
+ drmFree(bufs.list);
+
+ return retval;
+}
+
+
+/**
+ * Unmap buffers allocated with drmMapBufs().
+ *
+ * \return zero on success, or negative value on failure.
+ *
+ * \internal
+ * Calls munmap() for every buffer stored in \p bufs and frees the
+ * memory allocated by drmMapBufs().
+ */
+int drmUnmapBufs(drmBufMapPtr bufs)
+{
+ int i;
+
+ for (i = 0; i < bufs->count; i++) {
+ munmap(bufs->list[i].address, bufs->list[i].total);
+ }
+
+ drmFree(bufs->list);
+ drmFree(bufs);
+
+ return 0;
+}
+
+
+#define DRM_DMA_RETRY 16
+
+/**
+ * Reserve DMA buffers.
+ *
+ * \param fd file descriptor.
+ * \param request
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * Assemble the arguments into a drm_dma structure and keeps issuing the
+ * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
+ */
+int drmDMA(int fd, drmDMAReqPtr request)
+{
+ drm_dma_t dma;
+ int ret, i = 0;
+
+ /* Copy to hidden structure */
+ dma.context = request->context;
+ dma.send_count = request->send_count;
+ dma.send_indices = request->send_list;
+ dma.send_sizes = request->send_sizes;
+ dma.flags = request->flags;
+ dma.request_count = request->request_count;
+ dma.request_size = request->request_size;
+ dma.request_indices = request->request_list;
+ dma.request_sizes = request->request_sizes;
+ dma.granted_count = 0;
+
+ do {
+ ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
+ } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
+
+ if ( ret == 0 ) {
+ request->granted_count = dma.granted_count;
+ return 0;
+ } else {
+ return -errno;
+ }
+}
+
+
+/**
+ * Obtain heavyweight hardware lock.
+ *
+ * \param fd file descriptor.
+ * \param context context.
+ * \param flags flags that determine the sate of the hardware when the function
+ * returns.
+ *
+ * \return always zero.
+ *
+ * \internal
+ * This function translates the arguments into a drm_lock structure and issue
+ * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
+ */
+int drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
+{
+ drm_lock_t lock;
+
+ lock.context = context;
+ lock.flags = 0;
+ if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY;
+ if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT;
+ if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH;
+ if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
+ if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
+ if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
+
+ while (ioctl(fd, DRM_IOCTL_LOCK, &lock))
+ ;
+ return 0;
+}
+
+/**
+ * Release the hardware lock.
+ *
+ * \param fd file descriptor.
+ * \param context context.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
+ * argument in a drm_lock structure.
+ */
+int drmUnlock(int fd, drm_context_t context)
+{
+ drm_lock_t lock;
+
+ lock.context = context;
+ lock.flags = 0;
+ return ioctl(fd, DRM_IOCTL_UNLOCK, &lock);
+}
+
+drm_context_t * drmGetReservedContextList(int fd, int *count)
+{
+ drm_ctx_res_t res;
+ drm_ctx_t *list;
+ drm_context_t * retval;
+ int i;
+
+ res.count = 0;
+ res.contexts = NULL;
+ if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL;
+
+ if (!res.count) return NULL;
+
+ if (!(list = drmMalloc(res.count * sizeof(*list)))) return NULL;
+ if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
+ drmFree(list);
+ return NULL;
+ }
+
+ res.contexts = list;
+ if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL;
+
+ for (i = 0; i < res.count; i++) retval[i] = list[i].handle;
+ drmFree(list);
+
+ *count = res.count;
+ return retval;
+}
+
+void drmFreeReservedContextList(drm_context_t * pt)
+{
+ drmFree(pt);
+}
+
+/**
+ * Create context.
+ *
+ * Used by the X server during GLXContext initialization. This causes
+ * per-context kernel-level resources to be allocated.
+ *
+ * \param fd file descriptor.
+ * \param handle is set on success. To be used by the client when requesting DMA
+ * dispatch with drmDMA().
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \note May only be called by root.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
+ * argument in a drm_ctx structure.
+ */
+int drmCreateContext(int fd, drm_context_t * handle)
+{
+ drm_ctx_t ctx;
+
+ ctx.flags = 0; /* Modified with functions below */
+ if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) return -errno;
+ *handle = ctx.handle;
+ return 0;
+}
+
+int drmSwitchToContext(int fd, drm_context_t context)
+{
+ drm_ctx_t ctx;
+
+ ctx.handle = context;
+ if (ioctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) return -errno;
+ return 0;
+}
+
+int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
+{
+ drm_ctx_t ctx;
+
+ /* Context preserving means that no context
+ switched are done between DMA buffers
+ from one context and the next. This is
+ suitable for use in the X server (which
+ promises to maintain hardware context,
+ or in the client-side library when
+ buffers are swapped on behalf of two
+ threads. */
+ ctx.handle = context;
+ ctx.flags = 0;
+ if (flags & DRM_CONTEXT_PRESERVED) ctx.flags |= _DRM_CONTEXT_PRESERVED;
+ if (flags & DRM_CONTEXT_2DONLY) ctx.flags |= _DRM_CONTEXT_2DONLY;
+ if (ioctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) return -errno;
+ return 0;
+}
+
+int drmGetContextFlags(int fd, drm_context_t context, drm_context_tFlagsPtr flags)
+{
+ drm_ctx_t ctx;
+
+ ctx.handle = context;
+ if (ioctl(fd, DRM_IOCTL_GET_CTX, &ctx)) return -errno;
+ *flags = 0;
+ if (ctx.flags & _DRM_CONTEXT_PRESERVED) *flags |= DRM_CONTEXT_PRESERVED;
+ if (ctx.flags & _DRM_CONTEXT_2DONLY) *flags |= DRM_CONTEXT_2DONLY;
+ return 0;
+}
+
+/**
+ * Destroy context.
+ *
+ * Free any kernel-level resources allocated with drmCreateContext() associated
+ * with the context.
+ *
+ * \param fd file descriptor.
+ * \param handle handle given by drmCreateContext().
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \note May only be called by root.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
+ * argument in a drm_ctx structure.
+ */
+int drmDestroyContext(int fd, drm_context_t handle)
+{
+ drm_ctx_t ctx;
+ ctx.handle = handle;
+ if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx)) return -errno;
+ return 0;
+}
+
+int drmCreateDrawable(int fd, drm_drawable_t * handle)
+{
+ drm_draw_t draw;
+ if (ioctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) return -errno;
+ *handle = draw.handle;
+ return 0;
+}
+
+int drmDestroyDrawable(int fd, drm_drawable_t handle)
+{
+ drm_draw_t draw;
+ draw.handle = handle;
+ if (ioctl(fd, DRM_IOCTL_RM_DRAW, &draw)) return -errno;
+ return 0;
+}
+
+/**
+ * Acquire the AGP device.
+ *
+ * Must be called before any of the other AGP related calls.
+ *
+ * \param fd file descriptor.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
+ */
+int drmAgpAcquire(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Release the AGP device.
+ *
+ * \param fd file descriptor.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
+ */
+int drmAgpRelease(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Set the AGP mode.
+ *
+ * \param fd file descriptor.
+ * \param mode AGP mode.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
+ * argument in a drm_agp_mode structure.
+ */
+int drmAgpEnable(int fd, unsigned long mode)
+{
+ drm_agp_mode_t m;
+
+ m.mode = mode;
+ if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Allocate a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param size requested memory size in bytes. Will be rounded to page boundary.
+ * \param type type of memory to allocate.
+ * \param address if not zero, will be set to the physical address of the
+ * allocated memory.
+ * \param handle on success will be set to a handle of the allocated memory.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
+ * arguments in a drm_agp_buffer structure.
+ */
+int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
+ unsigned long *address, unsigned long *handle)
+{
+ drm_agp_buffer_t b;
+
+ *handle = DRM_AGP_NO_HANDLE;
+ b.size = size;
+ b.handle = 0;
+ b.type = type;
+ if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) return -errno;
+ if (address != 0UL) *address = b.physical;
+ *handle = b.handle;
+ return 0;
+}
+
+
+/**
+ * Free a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
+ * argument in a drm_agp_buffer structure.
+ */
+int drmAgpFree(int fd, unsigned long handle)
+{
+ drm_agp_buffer_t b;
+
+ b.size = 0;
+ b.handle = handle;
+ if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Bind a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ * \param offset offset in bytes. It will round to page boundary.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
+ * argument in a drm_agp_binding structure.
+ */
+int drmAgpBind(int fd, unsigned long handle, unsigned long offset)
+{
+ drm_agp_binding_t b;
+
+ b.handle = handle;
+ b.offset = offset;
+ if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Unbind a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
+ * the argument in a drm_agp_binding structure.
+ */
+int drmAgpUnbind(int fd, unsigned long handle)
+{
+ drm_agp_binding_t b;
+
+ b.handle = handle;
+ b.offset = 0;
+ if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Get AGP driver major version number.
+ *
+ * \param fd file descriptor.
+ *
+ * \return major version number on success, or a negative value on failure..
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+int drmAgpVersionMajor(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+ return i.agp_version_major;
+}
+
+
+/**
+ * Get AGP driver minor version number.
+ *
+ * \param fd file descriptor.
+ *
+ * \return minor version number on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+int drmAgpVersionMinor(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+ return i.agp_version_minor;
+}
+
+
+/**
+ * Get AGP mode.
+ *
+ * \param fd file descriptor.
+ *
+ * \return mode on success, or zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpGetMode(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.mode;
+}
+
+
+/**
+ * Get AGP aperture base.
+ *
+ * \param fd file descriptor.
+ *
+ * \return aperture base on success, zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpBase(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.aperture_base;
+}
+
+
+/**
+ * Get AGP aperture size.
+ *
+ * \param fd file descriptor.
+ *
+ * \return aperture size on success, zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpSize(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.aperture_size;
+}
+
+
+/**
+ * Get used AGP memory.
+ *
+ * \param fd file descriptor.
+ *
+ * \return memory used on success, or zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpMemoryUsed(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.memory_used;
+}
+
+
+/**
+ * Get available AGP memory.
+ *
+ * \param fd file descriptor.
+ *
+ * \return memory available on success, or zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpMemoryAvail(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.memory_allowed;
+}
+
+
+/**
+ * Get hardware vendor ID.
+ *
+ * \param fd file descriptor.
+ *
+ * \return vendor ID on success, or zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned int drmAgpVendorId(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.id_vendor;
+}
+
+
+/**
+ * Get hardware device ID.
+ *
+ * \param fd file descriptor.
+ *
+ * \return zero on success, or zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned int drmAgpDeviceId(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.id_device;
+}
+
+int drmScatterGatherAlloc(int fd, unsigned long size, unsigned long *handle)
+{
+ drm_scatter_gather_t sg;
+
+ *handle = 0;
+ sg.size = size;
+ sg.handle = 0;
+ if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno;
+ *handle = sg.handle;
+ return 0;
+}
+
+int drmScatterGatherFree(int fd, unsigned long handle)
+{
+ drm_scatter_gather_t sg;
+
+ sg.size = 0;
+ sg.handle = handle;
+ if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno;
+ return 0;
+}
+
+/**
+ * Wait for VBLANK.
+ *
+ * \param fd file descriptor.
+ * \param vbl pointer to a drmVBlank structure.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
+ */
+int drmWaitVBlank(int fd, drmVBlankPtr vbl)
+{
+ int ret;
+
+ do {
+ ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
+ vbl->request.type &= ~DRM_VBLANK_RELATIVE;
+ } while (ret && errno == EINTR);
+
+ return ret;
+}
+
+int drmError(int err, const char *label)
+{
+ switch (err) {
+ case DRM_ERR_NO_DEVICE: fprintf(stderr, "%s: no device\n", label); break;
+ case DRM_ERR_NO_ACCESS: fprintf(stderr, "%s: no access\n", label); break;
+ case DRM_ERR_NOT_ROOT: fprintf(stderr, "%s: not root\n", label); break;
+ case DRM_ERR_INVALID: fprintf(stderr, "%s: invalid args\n", label);break;
+ default:
+ if (err < 0) err = -err;
+ fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
+ break;
+ }
+
+ return 1;
+}
+
+/**
+ * Install IRQ handler.
+ *
+ * \param fd file descriptor.
+ * \param irq IRQ number.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
+ * argument in a drm_control structure.
+ */
+int drmCtlInstHandler(int fd, int irq)
+{
+ drm_control_t ctl;
+
+ ctl.func = DRM_INST_HANDLER;
+ ctl.irq = irq;
+ if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Uninstall IRQ handler.
+ *
+ * \param fd file descriptor.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
+ * argument in a drm_control structure.
+ */
+int drmCtlUninstHandler(int fd)
+{
+ drm_control_t ctl;
+
+ ctl.func = DRM_UNINST_HANDLER;
+ ctl.irq = 0;
+ if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
+ return 0;
+}
+
+int drmFinish(int fd, int context, drmLockFlags flags)
+{
+ drm_lock_t lock;
+
+ lock.context = context;
+ lock.flags = 0;
+ if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY;
+ if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT;
+ if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH;
+ if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
+ if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
+ if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
+ if (ioctl(fd, DRM_IOCTL_FINISH, &lock)) return -errno;
+ return 0;
+}
+
+/**
+ * Get IRQ from bus ID.
+ *
+ * \param fd file descriptor.
+ * \param busnum bus number.
+ * \param devnum device number.
+ * \param funcnum function number.
+ *
+ * \return IRQ number on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
+ * arguments in a drm_irq_busid structure.
+ */
+int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
+{
+ drm_irq_busid_t p;
+
+ p.busnum = busnum;
+ p.devnum = devnum;
+ p.funcnum = funcnum;
+ if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) return -errno;
+ return p.irq;
+}
+
+int drmAddContextTag(int fd, drm_context_t context, void *tag)
+{
+ drmHashEntry *entry = drmGetEntry(fd);
+
+ if (drmHashInsert(entry->tagTable, context, tag)) {
+ drmHashDelete(entry->tagTable, context);
+ drmHashInsert(entry->tagTable, context, tag);
+ }
+ return 0;
+}
+
+int drmDelContextTag(int fd, drm_context_t context)
+{
+ drmHashEntry *entry = drmGetEntry(fd);
+
+ return drmHashDelete(entry->tagTable, context);
+}
+
+void *drmGetContextTag(int fd, drm_context_t context)
+{
+ drmHashEntry *entry = drmGetEntry(fd);
+ void *value;
+
+ if (drmHashLookup(entry->tagTable, context, &value)) return NULL;
+
+ return value;
+}
+
+int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, drm_handle_t handle)
+{
+ drm_ctx_priv_map_t map;
+
+ map.ctx_id = ctx_id;
+ map.handle = (void *)handle;
+
+ if (ioctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map)) return -errno;
+ return 0;
+}
+
+int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, drm_handle_t * handle)
+{
+ drm_ctx_priv_map_t map;
+
+ map.ctx_id = ctx_id;
+
+ if (ioctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) return -errno;
+ if (handle) *handle = (drm_handle_t)map.handle;
+
+ return 0;
+}
+
+int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
+ drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
+ int *mtrr)
+{
+ drm_map_t map;
+
+ map.offset = idx;
+ if (ioctl(fd, DRM_IOCTL_GET_MAP, &map)) return -errno;
+ *offset = map.offset;
+ *size = map.size;
+ *type = map.type;
+ *flags = map.flags;
+ *handle = (unsigned long)map.handle;
+ *mtrr = map.mtrr;
+ return 0;
+}
+
+int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
+ unsigned long *magic, unsigned long *iocs)
+{
+ drm_client_t client;
+
+ client.idx = idx;
+ if (ioctl(fd, DRM_IOCTL_GET_CLIENT, &client)) return -errno;
+ *auth = client.auth;
+ *pid = client.pid;
+ *uid = client.uid;
+ *magic = client.magic;
+ *iocs = client.iocs;
+ return 0;
+}
+
+int drmGetStats(int fd, drmStatsT *stats)
+{
+ drm_stats_t s;
+ int i;
+
+ if (ioctl(fd, DRM_IOCTL_GET_STATS, &s)) return -errno;
+
+ stats->count = 0;
+ memset(stats, 0, sizeof(*stats));
+ if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
+ return -1;
+
+#define SET_VALUE \
+ stats->data[i].long_format = "%-20.20s"; \
+ stats->data[i].rate_format = "%8.8s"; \
+ stats->data[i].isvalue = 1; \
+ stats->data[i].verbose = 0
+
+#define SET_COUNT \
+ stats->data[i].long_format = "%-20.20s"; \
+ stats->data[i].rate_format = "%5.5s"; \
+ stats->data[i].isvalue = 0; \
+ stats->data[i].mult_names = "kgm"; \
+ stats->data[i].mult = 1000; \
+ stats->data[i].verbose = 0
+
+#define SET_BYTE \
+ stats->data[i].long_format = "%-20.20s"; \
+ stats->data[i].rate_format = "%5.5s"; \
+ stats->data[i].isvalue = 0; \
+ stats->data[i].mult_names = "KGM"; \
+ stats->data[i].mult = 1024; \
+ stats->data[i].verbose = 0
+
+
+ stats->count = s.count;
+ for (i = 0; i < s.count; i++) {
+ stats->data[i].value = s.data[i].value;
+ switch (s.data[i].type) {
+ case _DRM_STAT_LOCK:
+ stats->data[i].long_name = "Lock";
+ stats->data[i].rate_name = "Lock";
+ SET_VALUE;
+ break;
+ case _DRM_STAT_OPENS:
+ stats->data[i].long_name = "Opens";
+ stats->data[i].rate_name = "O";
+ SET_COUNT;
+ stats->data[i].verbose = 1;
+ break;
+ case _DRM_STAT_CLOSES:
+ stats->data[i].long_name = "Closes";
+ stats->data[i].rate_name = "Lock";
+ SET_COUNT;
+ stats->data[i].verbose = 1;
+ break;
+ case _DRM_STAT_IOCTLS:
+ stats->data[i].long_name = "Ioctls";
+ stats->data[i].rate_name = "Ioc/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_LOCKS:
+ stats->data[i].long_name = "Locks";
+ stats->data[i].rate_name = "Lck/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_UNLOCKS:
+ stats->data[i].long_name = "Unlocks";
+ stats->data[i].rate_name = "Unl/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_IRQ:
+ stats->data[i].long_name = "IRQs";
+ stats->data[i].rate_name = "IRQ/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_PRIMARY:
+ stats->data[i].long_name = "Primary Bytes";
+ stats->data[i].rate_name = "PB/s";
+ SET_BYTE;
+ break;
+ case _DRM_STAT_SECONDARY:
+ stats->data[i].long_name = "Secondary Bytes";
+ stats->data[i].rate_name = "SB/s";
+ SET_BYTE;
+ break;
+ case _DRM_STAT_DMA:
+ stats->data[i].long_name = "DMA";
+ stats->data[i].rate_name = "DMA/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_SPECIAL:
+ stats->data[i].long_name = "Special DMA";
+ stats->data[i].rate_name = "dma/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_MISSED:
+ stats->data[i].long_name = "Miss";
+ stats->data[i].rate_name = "Ms/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_VALUE:
+ stats->data[i].long_name = "Value";
+ stats->data[i].rate_name = "Value";
+ SET_VALUE;
+ break;
+ case _DRM_STAT_BYTE:
+ stats->data[i].long_name = "Bytes";
+ stats->data[i].rate_name = "B/s";
+ SET_BYTE;
+ break;
+ case _DRM_STAT_COUNT:
+ default:
+ stats->data[i].long_name = "Count";
+ stats->data[i].rate_name = "Cnt/s";
+ SET_COUNT;
+ break;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Issue a set-version ioctl.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index
+ * \param data source pointer of the data to be read and written.
+ * \param size size of the data to be read and written.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a read-write ioctl given by
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmSetInterfaceVersion(int fd, drmSetVersion *version )
+{
+ int retcode = 0;
+ drm_set_version_t sv;
+
+ sv.drm_di_major = version->drm_di_major;
+ sv.drm_di_minor = version->drm_di_minor;
+ sv.drm_dd_major = version->drm_dd_major;
+ sv.drm_dd_minor = version->drm_dd_minor;
+
+ if (ioctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
+ retcode = -errno;
+ }
+
+ version->drm_di_major = sv.drm_di_major;
+ version->drm_di_minor = sv.drm_di_minor;
+ version->drm_dd_major = sv.drm_dd_major;
+ version->drm_dd_minor = sv.drm_dd_minor;
+
+ return retcode;
+}
+
+/**
+ * Send a device-specific command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a ioctl given by
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandNone(int fd, unsigned long drmCommandIndex)
+{
+ void *data = NULL; /* dummy */
+ unsigned long request;
+
+ request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
+
+ if (ioctl(fd, request, data)) {
+ return -errno;
+ }
+ return 0;
+}
+
+
+/**
+ * Send a device-specific read command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index
+ * \param data destination pointer of the data to be read.
+ * \param size size of the data to be read.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a read ioctl given by
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandRead(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size )
+{
+ unsigned long request;
+
+ request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE,
+ DRM_COMMAND_BASE + drmCommandIndex, size);
+
+ if (ioctl(fd, request, data)) {
+ return -errno;
+ }
+ return 0;
+}
+
+
+/**
+ * Send a device-specific write command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index
+ * \param data source pointer of the data to be written.
+ * \param size size of the data to be written.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a write ioctl given by
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandWrite(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size )
+{
+ unsigned long request;
+
+ request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE,
+ DRM_COMMAND_BASE + drmCommandIndex, size);
+
+ if (ioctl(fd, request, data)) {
+ return -errno;
+ }
+ return 0;
+}
+
+
+/**
+ * Send a device-specific read-write command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index
+ * \param data source pointer of the data to be read and written.
+ * \param size size of the data to be read and written.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a read-write ioctl given by
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size )
+{
+ unsigned long request;
+
+ request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE,
+ DRM_COMMAND_BASE + drmCommandIndex, size);
+
+ if (ioctl(fd, request, data)) {
+ return -errno;
+ }
+ return 0;
+}
+
+#if defined(XFree86Server) || defined(DRM_USE_MALLOC)
+static void drmSIGIOHandler(int interrupt, void *closure)
+{
+ unsigned long key;
+ void *value;
+ ssize_t count;
+ drm_ctx_t ctx;
+ typedef void (*_drmCallback)(int, void *, void *);
+ char buf[256];
+ drm_context_t old;
+ drm_context_t new;
+ void *oldctx;
+ void *newctx;
+ char *pt;
+ drmHashEntry *entry;
+
+ if (!drmHashTable) return;
+ if (drmHashFirst(drmHashTable, &key, &value)) {
+ entry = value;
+ do {
+#if 0
+ fprintf(stderr, "Trying %d\n", entry->fd);
+#endif
+ if ((count = read(entry->fd, buf, sizeof(buf))) > 0) {
+ buf[count] = '\0';
+#if 0
+ fprintf(stderr, "Got %s\n", buf);
+#endif
+
+ for (pt = buf; *pt != ' '; ++pt); /* Find first space */
+ ++pt;
+ old = strtol(pt, &pt, 0);
+ new = strtol(pt, NULL, 0);
+ oldctx = drmGetContextTag(entry->fd, old);
+ newctx = drmGetContextTag(entry->fd, new);
+#if 0
+ fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx);
+#endif
+ ((_drmCallback)entry->f)(entry->fd, oldctx, newctx);
+ ctx.handle = new;
+ ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx);
+ }
+ } while (drmHashNext(drmHashTable, &key, &value));
+ }
+}
+
+int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *))
+{
+ drmHashEntry *entry;
+
+ entry = drmGetEntry(fd);
+ entry->f = f;
+
+ return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0);
+}
+
+int drmRemoveSIGIOHandler(int fd)
+{
+ drmHashEntry *entry = drmGetEntry(fd);
+
+ entry->f = NULL;
+
+ return xf86RemoveSIGIOHandler(fd);
+}
+#endif
diff --git a/hw/xfree86/os-support/xf86drm.h b/hw/xfree86/os-support/xf86drm.h
new file mode 100644
index 000000000..0b6e93fd3
--- /dev/null
+++ b/hw/xfree86/os-support/xf86drm.h
@@ -0,0 +1,636 @@
+/**
+ * \file xf86drm.h
+ * OS-independent header for DRM user-level library interface.
+ *
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+
+/*
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * 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, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ *
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h,v 1.26 2003/08/16 19:26:37 dawes Exp $ */
+
+#ifndef _XF86DRM_H_
+#define _XF86DRM_H_
+
+#include <drm.h>
+
+ /* Defaults, if nothing set in xf86config */
+#define DRM_DEV_UID 0
+#define DRM_DEV_GID 0
+/* Default /dev/dri directory permissions 0755 */
+#define DRM_DEV_DIRMODE \
+ (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
+#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
+
+#define DRM_DIR_NAME "/dev/dri"
+#define DRM_DEV_NAME "%s/card%d"
+#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
+
+#define DRM_ERR_NO_DEVICE (-1001)
+#define DRM_ERR_NO_ACCESS (-1002)
+#define DRM_ERR_NOT_ROOT (-1003)
+#define DRM_ERR_INVALID (-1004)
+#define DRM_ERR_NO_FD (-1005)
+
+#define DRM_AGP_NO_HANDLE 0
+
+typedef unsigned int drmSize, *drmSizePtr; /**< For mapped regions */
+typedef void *drmAddress, **drmAddressPtr; /**< For mapped regions */
+
+/**
+ * Driver version information.
+ *
+ * \sa drmGetVersion() and drmSetVersion().
+ */
+typedef struct _drmVersion {
+ int version_major; /**< Major version */
+ int version_minor; /**< Minor version */
+ int version_patchlevel; /**< Patch level */
+ int name_len; /**< Length of name buffer */
+ char *name; /**< Name of driver */
+ int date_len; /**< Length of date buffer */
+ char *date; /**< User-space buffer to hold date */
+ int desc_len; /**< Length of desc buffer */
+ char *desc; /**< User-space buffer to hold desc */
+} drmVersion, *drmVersionPtr;
+
+typedef struct _drmStats {
+ unsigned long count; /**< Number of data */
+ struct {
+ unsigned long value; /**< Value from kernel */
+ const char *long_format; /**< Suggested format for long_name */
+ const char *long_name; /**< Long name for value */
+ const char *rate_format; /**< Suggested format for rate_name */
+ const char *rate_name; /**< Short name for value per second */
+ int isvalue; /**< True if value (vs. counter) */
+ const char *mult_names; /**< Multiplier names (e.g., "KGM") */
+ int mult; /**< Multiplier value (e.g., 1024) */
+ int verbose; /**< Suggest only in verbose output */
+ } data[15];
+} drmStatsT;
+
+
+ /* All of these enums *MUST* match with the
+ kernel implementation -- so do *NOT*
+ change them! (The drmlib implementation
+ will just copy the flags instead of
+ translating them.) */
+typedef enum {
+ DRM_FRAME_BUFFER = 0, /**< WC, no caching, no core dump */
+ DRM_REGISTERS = 1, /**< no caching, no core dump */
+ DRM_SHM = 2, /**< shared, cached */
+ DRM_AGP = 3, /**< AGP/GART */
+ DRM_SCATTER_GATHER = 4 /**< PCI scatter/gather */
+} drmMapType;
+
+typedef enum {
+ DRM_RESTRICTED = 0x0001, /**< Cannot be mapped to client-virtual */
+ DRM_READ_ONLY = 0x0002, /**< Read-only in client-virtual */
+ DRM_LOCKED = 0x0004, /**< Physical pages locked */
+ DRM_KERNEL = 0x0008, /**< Kernel requires access */
+ DRM_WRITE_COMBINING = 0x0010, /**< Use write-combining, if available */
+ DRM_CONTAINS_LOCK = 0x0020, /**< SHM page that contains lock */
+ DRM_REMOVABLE = 0x0040 /**< Removable mapping */
+} drmMapFlags;
+
+/**
+ * \warning These values *MUST* match drm.h
+ */
+typedef enum {
+ /** \name Flags for DMA buffer dispatch */
+ /*@{*/
+ DRM_DMA_BLOCK = 0x01, /**<
+ * Block until buffer dispatched.
+ *
+ * \note the buffer may not yet have been
+ * processed by the hardware -- getting a
+ * hardware lock with the hardware quiescent
+ * will ensure that the buffer has been
+ * processed.
+ */
+ DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
+ DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
+ /*@}*/
+
+ /** \name Flags for DMA buffer request */
+ /*@{*/
+ DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
+ DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
+ DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
+ /*@}*/
+} drmDMAFlags;
+
+typedef enum {
+ DRM_PAGE_ALIGN = 0x01,
+ DRM_AGP_BUFFER = 0x02,
+ DRM_SG_BUFFER = 0x04
+} drmBufDescFlags;
+
+typedef enum {
+ DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
+ DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
+ DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
+ DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
+ /* These *HALT* flags aren't supported yet
+ -- they will be used to support the
+ full-screen DGA-like mode. */
+ DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
+ DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
+} drmLockFlags;
+
+typedef enum {
+ DRM_CONTEXT_PRESERVED = 0x01, /**< This context is preserved and
+ never swapped. */
+ DRM_CONTEXT_2DONLY = 0x02 /**< This context is for 2D rendering only. */
+} drm_context_tFlags, *drm_context_tFlagsPtr;
+
+typedef struct _drmBufDesc {
+ int count; /**< Number of buffers of this size */
+ int size; /**< Size in bytes */
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
+} drmBufDesc, *drmBufDescPtr;
+
+typedef struct _drmBufInfo {
+ int count; /**< Number of buffers described in list */
+ drmBufDescPtr list; /**< List of buffer descriptions */
+} drmBufInfo, *drmBufInfoPtr;
+
+typedef struct _drmBuf {
+ int idx; /**< Index into the master buffer list */
+ int total; /**< Buffer size */
+ int used; /**< Amount of buffer in use (for DMA) */
+ drmAddress address; /**< Address */
+} drmBuf, *drmBufPtr;
+
+/**
+ * Buffer mapping information.
+ *
+ * Used by drmMapBufs() and drmUnmapBufs() to store information about the
+ * mapped buffers.
+ */
+typedef struct _drmBufMap {
+ int count; /**< Number of buffers mapped */
+ drmBufPtr list; /**< Buffers */
+} drmBufMap, *drmBufMapPtr;
+
+typedef struct _drmLock {
+ volatile unsigned int lock;
+ char padding[60];
+ /* This is big enough for most current (and future?) architectures:
+ DEC Alpha: 32 bytes
+ Intel Merced: ?
+ Intel P5/PPro/PII/PIII: 32 bytes
+ Intel StrongARM: 32 bytes
+ Intel i386/i486: 16 bytes
+ MIPS: 32 bytes (?)
+ Motorola 68k: 16 bytes
+ Motorola PowerPC: 32 bytes
+ Sun SPARC: 32 bytes
+ */
+} drmLock, *drmLockPtr;
+
+/**
+ * Indices here refer to the offset into
+ * list in drmBufInfo
+ */
+typedef struct _drmDMAReq {
+ drm_context_t context; /**< Context handle */
+ int send_count; /**< Number of buffers to send */
+ int *send_list; /**< List of handles to buffers */
+ int *send_sizes; /**< Lengths of data to send, in bytes */
+ drmDMAFlags flags; /**< Flags */
+ int request_count; /**< Number of buffers requested */
+ int request_size; /**< Desired size of buffers requested */
+ int *request_list; /**< Buffer information */
+ int *request_sizes; /**< Minimum acceptable sizes */
+ int granted_count; /**< Number of buffers granted at this size */
+} drmDMAReq, *drmDMAReqPtr;
+
+typedef struct _drmRegion {
+ drm_handle_t handle;
+ unsigned int offset;
+ drmSize size;
+ drmAddress map;
+} drmRegion, *drmRegionPtr;
+
+typedef struct _drmTextureRegion {
+ unsigned char next;
+ unsigned char prev;
+ unsigned char in_use;
+ unsigned char padding; /**< Explicitly pad this out */
+ unsigned int age;
+} drmTextureRegion, *drmTextureRegionPtr;
+
+
+typedef enum {
+ DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
+ DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
+ DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */
+} drmVBlankSeqType;
+
+typedef struct _drmVBlankReq {
+ drmVBlankSeqType type;
+ unsigned int sequence;
+ unsigned long signal;
+} drmVBlankReq, *drmVBlankReqPtr;
+
+typedef struct _drmVBlankReply {
+ drmVBlankSeqType type;
+ unsigned int sequence;
+ long tval_sec;
+ long tval_usec;
+} drmVBlankReply, *drmVBlankReplyPtr;
+
+typedef union _drmVBlank {
+ drmVBlankReq request;
+ drmVBlankReply reply;
+} drmVBlank, *drmVBlankPtr;
+
+typedef struct _drmSetVersion {
+ int drm_di_major;
+ int drm_di_minor;
+ int drm_dd_major;
+ int drm_dd_minor;
+} drmSetVersion, *drmSetVersionPtr;
+
+
+#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock)
+
+#define DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */
+#define DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */
+
+#if defined(__GNUC__) && (__GNUC__ >= 2)
+# if defined(__i386) || defined(__AMD64__)
+ /* Reflect changes here to drmP.h */
+#define DRM_CAS(lock,old,new,__ret) \
+ do { \
+ int __dummy; /* Can't mark eax as clobbered */ \
+ __asm__ __volatile__( \
+ "lock ; cmpxchg %4,%1\n\t" \
+ "setnz %0" \
+ : "=d" (__ret), \
+ "=m" (__drm_dummy_lock(lock)), \
+ "=a" (__dummy) \
+ : "2" (old), \
+ "r" (new)); \
+ } while (0)
+
+#elif defined(__alpha__)
+
+#define DRM_CAS(lock, old, new, ret) \
+ do { \
+ int old32; \
+ int cur32; \
+ __asm__ __volatile__( \
+ " mb\n" \
+ " zap %4, 0xF0, %0\n" \
+ " ldl_l %1, %2\n" \
+ " zap %1, 0xF0, %1\n" \
+ " cmpeq %0, %1, %1\n" \
+ " beq %1, 1f\n" \
+ " bis %5, %5, %1\n" \
+ " stl_c %1, %2\n" \
+ "1: xor %1, 1, %1\n" \
+ " stl %1, %3" \
+ : "+r" (old32), \
+ "+&r" (cur32), \
+ "=m" (__drm_dummy_lock(lock)),\
+ "=m" (ret) \
+ : "r" (old), \
+ "r" (new)); \
+ } while(0)
+
+#elif defined(__sparc__)
+
+#define DRM_CAS(lock,old,new,__ret) \
+do { register unsigned int __old __asm("o0"); \
+ register unsigned int __new __asm("o1"); \
+ register volatile unsigned int *__lock __asm("o2"); \
+ __old = old; \
+ __new = new; \
+ __lock = (volatile unsigned int *)lock; \
+ __asm__ __volatile__( \
+ /*"cas [%2], %3, %0"*/ \
+ ".word 0xd3e29008\n\t" \
+ /*"membar #StoreStore | #StoreLoad"*/ \
+ ".word 0x8143e00a" \
+ : "=&r" (__new) \
+ : "0" (__new), \
+ "r" (__lock), \
+ "r" (__old) \
+ : "memory"); \
+ __ret = (__new != __old); \
+} while(0)
+
+#elif defined(__ia64__)
+
+#ifdef __INTEL_COMPILER
+/* this currently generates bad code (missing stop bits)... */
+#include <ia64intrin.h>
+
+#define DRM_CAS(lock,old,new,__ret) \
+ do { \
+ unsigned long __result, __old = (old) & 0xffffffff; \
+ __mf(); \
+ __result = _InterlockedCompareExchange_acq(&__drm_dummy_lock(lock), (new), __old);\
+ __ret = (__result) != (__old); \
+/* __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \
+ (old), (new)) \
+ != (old)); */\
+ } while (0)
+
+#else
+#define DRM_CAS(lock,old,new,__ret) \
+ do { \
+ unsigned int __result, __old = (old); \
+ __asm__ __volatile__( \
+ "mf\n" \
+ "mov ar.ccv=%2\n" \
+ ";;\n" \
+ "cmpxchg4.acq %0=%1,%3,ar.ccv" \
+ : "=r" (__result), "=m" (__drm_dummy_lock(lock)) \
+ : "r" ((unsigned long)__old), "r" (new) \
+ : "memory"); \
+ __ret = (__result) != (__old); \
+ } while (0)
+
+#endif
+
+#elif defined(__powerpc__)
+
+#define DRM_CAS(lock,old,new,__ret) \
+ do { \
+ __asm__ __volatile__( \
+ "sync;" \
+ "0: lwarx %0,0,%1;" \
+ " xor. %0,%3,%0;" \
+ " bne 1f;" \
+ " stwcx. %2,0,%1;" \
+ " bne- 0b;" \
+ "1: " \
+ "sync;" \
+ : "=&r"(__ret) \
+ : "r"(lock), "r"(new), "r"(old) \
+ : "cr0", "memory"); \
+ } while (0)
+
+#endif /* architecture */
+#endif /* __GNUC__ >= 2 */
+
+#ifndef DRM_CAS
+#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */
+#endif
+
+#if defined(__alpha__) || defined(__powerpc__)
+#define DRM_CAS_RESULT(_result) int _result
+#else
+#define DRM_CAS_RESULT(_result) char _result
+#endif
+
+#define DRM_LIGHT_LOCK(fd,lock,context) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \
+ if (__ret) drmGetLock(fd,context,0); \
+ } while(0)
+
+ /* This one counts fast locks -- for
+ benchmarking only. */
+#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \
+ if (__ret) drmGetLock(fd,context,0); \
+ else ++count; \
+ } while(0)
+
+#define DRM_LOCK(fd,lock,context,flags) \
+ do { \
+ if (flags) drmGetLock(fd,context,flags); \
+ else DRM_LIGHT_LOCK(fd,lock,context); \
+ } while(0)
+
+#define DRM_UNLOCK(fd,lock,context) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret); \
+ if (__ret) drmUnlock(fd,context); \
+ } while(0)
+
+ /* Simple spin locks */
+#define DRM_SPINLOCK(spin,val) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ do { \
+ DRM_CAS(spin,0,val,__ret); \
+ if (__ret) while ((spin)->lock); \
+ } while (__ret); \
+ } while(0)
+
+#define DRM_SPINLOCK_TAKE(spin,val) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ int cur; \
+ do { \
+ cur = (*spin).lock; \
+ DRM_CAS(spin,cur,val,__ret); \
+ } while (__ret); \
+ } while(0)
+
+#define DRM_SPINLOCK_COUNT(spin,val,count,__ret) \
+ do { \
+ int __i; \
+ __ret = 1; \
+ for (__i = 0; __ret && __i < count; __i++) { \
+ DRM_CAS(spin,0,val,__ret); \
+ if (__ret) for (;__i < count && (spin)->lock; __i++); \
+ } \
+ } while(0)
+
+#define DRM_SPINUNLOCK(spin,val) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ if ((*spin).lock == val) { /* else server stole lock */ \
+ do { \
+ DRM_CAS(spin,val,0,__ret); \
+ } while (__ret); \
+ } \
+ } while(0)
+
+/* General user-level programmer's API: unprivileged */
+extern int drmAvailable(void);
+extern int drmOpen(const char *name, const char *busid);
+extern int drmClose(int fd);
+extern drmVersionPtr drmGetVersion(int fd);
+extern drmVersionPtr drmGetLibVersion(int fd);
+extern void drmFreeVersion(drmVersionPtr);
+extern int drmGetMagic(int fd, drm_magic_t * magic);
+extern char *drmGetBusid(int fd);
+extern int drmGetInterruptFromBusID(int fd, int busnum, int devnum,
+ int funcnum);
+extern int drmGetMap(int fd, int idx, drm_handle_t *offset,
+ drmSize *size, drmMapType *type,
+ drmMapFlags *flags, drm_handle_t *handle,
+ int *mtrr);
+extern int drmGetClient(int fd, int idx, int *auth, int *pid,
+ int *uid, unsigned long *magic,
+ unsigned long *iocs);
+extern int drmGetStats(int fd, drmStatsT *stats);
+extern int drmSetInterfaceVersion(int fd, drmSetVersion *version);
+extern int drmCommandNone(int fd, unsigned long drmCommandIndex);
+extern int drmCommandRead(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size);
+extern int drmCommandWrite(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size);
+extern int drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size);
+
+/* General user-level programmer's API: X server (root) only */
+extern void drmFreeBusid(const char *busid);
+extern int drmSetBusid(int fd, const char *busid);
+extern int drmAuthMagic(int fd, drm_magic_t magic);
+extern int drmAddMap(int fd,
+ drm_handle_t offset,
+ drmSize size,
+ drmMapType type,
+ drmMapFlags flags,
+ drm_handle_t * handle);
+extern int drmRmMap(int fd, drm_handle_t handle);
+extern int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
+ drm_handle_t handle);
+
+extern int drmAddBufs(int fd, int count, int size,
+ drmBufDescFlags flags,
+ int agp_offset);
+extern int drmMarkBufs(int fd, double low, double high);
+extern int drmCreateContext(int fd, drm_context_t * handle);
+extern int drmSetContextFlags(int fd, drm_context_t context,
+ drm_context_tFlags flags);
+extern int drmGetContextFlags(int fd, drm_context_t context,
+ drm_context_tFlagsPtr flags);
+extern int drmAddContextTag(int fd, drm_context_t context, void *tag);
+extern int drmDelContextTag(int fd, drm_context_t context);
+extern void *drmGetContextTag(int fd, drm_context_t context);
+extern drm_context_t * drmGetReservedContextList(int fd, int *count);
+extern void drmFreeReservedContextList(drm_context_t *);
+extern int drmSwitchToContext(int fd, drm_context_t context);
+extern int drmDestroyContext(int fd, drm_context_t handle);
+extern int drmCreateDrawable(int fd, drm_drawable_t * handle);
+extern int drmDestroyDrawable(int fd, drm_drawable_t handle);
+extern int drmCtlInstHandler(int fd, int irq);
+extern int drmCtlUninstHandler(int fd);
+extern int drmInstallSIGIOHandler(int fd,
+ void (*f)(int fd,
+ void *oldctx,
+ void *newctx));
+extern int drmRemoveSIGIOHandler(int fd);
+
+/* General user-level programmer's API: authenticated client and/or X */
+extern int drmMap(int fd,
+ drm_handle_t handle,
+ drmSize size,
+ drmAddressPtr address);
+extern int drmUnmap(drmAddress address, drmSize size);
+extern drmBufInfoPtr drmGetBufInfo(int fd);
+extern drmBufMapPtr drmMapBufs(int fd);
+extern int drmUnmapBufs(drmBufMapPtr bufs);
+extern int drmDMA(int fd, drmDMAReqPtr request);
+extern int drmFreeBufs(int fd, int count, int *list);
+extern int drmGetLock(int fd,
+ drm_context_t context,
+ drmLockFlags flags);
+extern int drmUnlock(int fd, drm_context_t context);
+extern int drmFinish(int fd, int context, drmLockFlags flags);
+extern int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
+ drm_handle_t * handle);
+
+/* AGP/GART support: X server (root) only */
+extern int drmAgpAcquire(int fd);
+extern int drmAgpRelease(int fd);
+extern int drmAgpEnable(int fd, unsigned long mode);
+extern int drmAgpAlloc(int fd, unsigned long size,
+ unsigned long type, unsigned long *address,
+ unsigned long *handle);
+extern int drmAgpFree(int fd, unsigned long handle);
+extern int drmAgpBind(int fd, unsigned long handle,
+ unsigned long offset);
+extern int drmAgpUnbind(int fd, unsigned long handle);
+
+/* AGP/GART info: authenticated client and/or X */
+extern int drmAgpVersionMajor(int fd);
+extern int drmAgpVersionMinor(int fd);
+extern unsigned long drmAgpGetMode(int fd);
+extern unsigned long drmAgpBase(int fd); /* Physical location */
+extern unsigned long drmAgpSize(int fd); /* Bytes */
+extern unsigned long drmAgpMemoryUsed(int fd);
+extern unsigned long drmAgpMemoryAvail(int fd);
+extern unsigned int drmAgpVendorId(int fd);
+extern unsigned int drmAgpDeviceId(int fd);
+
+/* PCI scatter/gather support: X server (root) only */
+extern int drmScatterGatherAlloc(int fd, unsigned long size,
+ unsigned long *handle);
+extern int drmScatterGatherFree(int fd, unsigned long handle);
+
+extern int drmWaitVBlank(int fd, drmVBlankPtr vbl);
+
+/* Support routines */
+extern int drmError(int err, const char *label);
+extern void *drmMalloc(int size);
+extern void drmFree(void *pt);
+
+/* Hash table routines */
+extern void *drmHashCreate(void);
+extern int drmHashDestroy(void *t);
+extern int drmHashLookup(void *t, unsigned long key, void **value);
+extern int drmHashInsert(void *t, unsigned long key, void *value);
+extern int drmHashDelete(void *t, unsigned long key);
+extern int drmHashFirst(void *t, unsigned long *key, void **value);
+extern int drmHashNext(void *t, unsigned long *key, void **value);
+
+/* PRNG routines */
+extern void *drmRandomCreate(unsigned long seed);
+extern int drmRandomDestroy(void *state);
+extern unsigned long drmRandom(void *state);
+extern double drmRandomDouble(void *state);
+
+/* Skip list routines */
+
+extern void *drmSLCreate(void);
+extern int drmSLDestroy(void *l);
+extern int drmSLLookup(void *l, unsigned long key, void **value);
+extern int drmSLInsert(void *l, unsigned long key, void *value);
+extern int drmSLDelete(void *l, unsigned long key);
+extern int drmSLNext(void *l, unsigned long *key, void **value);
+extern int drmSLFirst(void *l, unsigned long *key, void **value);
+extern void drmSLDump(void *l);
+extern int drmSLLookupNeighbors(void *l, unsigned long key,
+ unsigned long *prev_key, void **prev_value,
+ unsigned long *next_key, void **next_value);
+
+#endif
diff --git a/hw/xfree86/parser/Extensions.c b/hw/xfree86/parser/Extensions.c
new file mode 100644
index 000000000..0c51a6e33
--- /dev/null
+++ b/hw/xfree86/parser/Extensions.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2004 Red Hat Inc., Raleigh, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <kem@redhat.com>
+ *
+ */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static xf86ConfigSymTabRec ExtensionsTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+#define CLEANUP xf86freeExtensions
+
+XF86ConfExtensionsPtr
+xf86parseExtensionsSection (void)
+{
+ int token;
+ parsePrologue (XF86ConfExtensionsPtr, XF86ConfExtensionsRec);
+
+ while ((token = xf86getToken (ExtensionsTab)) != ENDSECTION) {
+ switch (token) {
+ case OPTION:
+ ptr->ext_option_lst = xf86parseOption(ptr->ext_option_lst);
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ case COMMENT:
+ ptr->extensions_comment =
+ xf86addComment(ptr->extensions_comment, val.str);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xf86tokenString ());
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ ErrorF("Extensions section parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xf86printExtensionsSection (FILE * cf, XF86ConfExtensionsPtr ptr)
+{
+ XF86OptionPtr p;
+
+ if (ptr == NULL || ptr->ext_option_lst == NULL)
+ return;
+
+ p = ptr->ext_option_lst;
+ fprintf (cf, "Section \"Extensions\"\n");
+ if (ptr->extensions_comment)
+ fprintf (cf, "%s", ptr->extensions_comment);
+ xf86printOptionList(cf, p, 1);
+ fprintf (cf, "EndSection\n\n");
+}
+
+void
+xf86freeExtensions (XF86ConfExtensionsPtr ptr)
+{
+ if (ptr == NULL)
+ return;
+
+ xf86optionListFree (ptr->ext_option_lst);
+ TestFree (ptr->extensions_comment);
+ xf86conffree (ptr);
+}
diff --git a/hw/xfree86/xaa/xaaWrapper.c b/hw/xfree86/xaa/xaaWrapper.c
new file mode 100644
index 000000000..3bc2db34f
--- /dev/null
+++ b/hw/xfree86/xaa/xaaWrapper.c
@@ -0,0 +1,924 @@
+#include "X.h"
+#include "Xproto.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "glyphstr.h"
+#include "window.h"
+#include "windowstr.h"
+#include "picture.h"
+#include "picturestr.h"
+#include "colormapst.h"
+#include "xaa.h"
+#include "xaalocal.h"
+#include "xaaWrapper.h"
+
+void XAASync(ScreenPtr pScreen);
+
+/* #include "render.h" */
+
+#if 0
+#define COND(pDraw) \
+ ((pDraw)->depth \
+ != (xaaWrapperGetScrPriv(((DrawablePtr)(pDraw))->pScreen))->depth)
+#endif
+#define COND(pDraw) 1
+
+#if 0
+static Bool xaaWrapperPreCreateGC(GCPtr pGC);
+#endif
+static Bool xaaWrapperCreateGC(GCPtr pGC);
+static void xaaWrapperValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw);
+static void xaaWrapperDestroyGC(GCPtr pGC);
+static void xaaWrapperChangeGC (GCPtr pGC, unsigned long mask);
+static void xaaWrapperCopyGC (GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
+static void xaaWrapperChangeClip (GCPtr pGC, int type, pointer pvalue, int nrects);
+
+static void xaaWrapperCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
+static void xaaWrapperDestroyClip(GCPtr pGC);
+
+#if 0
+static void xaaWrapperFillSpans(DrawablePtr pDraw, GC *pGC, int nInit,
+ DDXPointPtr pptInit, int *pwidthInit, int fSorted);
+static void xaaWrapperSetSpans(DrawablePtr pDraw, GCPtr pGC, char *pcharsrc,
+ DDXPointPtr pptInit, int *pwidthInit, int nspans,
+ int fSorted);
+static void xaaWrapperPutImage(DrawablePtr pDraw, GCPtr pGC, int depth, int x, int y,
+ int w, int h,int leftPad, int format, char *pImage);
+static RegionPtr xaaWrapperCopyPlane(DrawablePtr pSrc,
+ DrawablePtr pDst, GCPtr pGC,int srcx, int srcy,
+ int width, int height, int dstx, int dsty,
+ unsigned long bitPlane);
+static void xaaWrapperPolyPoint(DrawablePtr pDraw, GCPtr pGC, int mode, int npt,
+ xPoint *pptInit);
+static void xaaWrapperPolylines(DrawablePtr pDraw, GCPtr pGC, int mode,
+ int npt, DDXPointPtr pptInit);
+static void xaaWrapperPolySegment(DrawablePtr pDraw, GCPtr pGC, int nseg,
+ xSegment *pSeg);
+static void xaaWrapperPolyRectangle(DrawablePtr pDraw, GCPtr pGC, int nRects,
+ xRectangle *pRects);
+static void xaaWrapperPolyArc( DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs);
+static void xaaWrapperFillPolygon(DrawablePtr pDraw, GCPtr pGC, int shape,
+ int mode, int count, DDXPointPtr pptInit);
+static void xaaWrapperPolyFillRect(DrawablePtr pDraw, GCPtr pGC, int nRectsInit,
+ xRectangle *pRectsInit);
+static RegionPtr xaaWrapperCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GC *pGC,
+ int srcx, int srcy, int width, int height,
+ int dstx, int dsty);
+static void xaaWrapperPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs,
+ xArc *parcs);
+static int xaaWrapperPolyText8(DrawablePtr pDraw, GCPtr pGC, int x, int y, int count,
+ char *chars);
+static int xaaWrapperPolyText16(DrawablePtr pDraw, GCPtr pGC, int x, int y,
+ int count, unsigned short *chars);
+static void xaaWrapperImageText8(DrawablePtr pDraw, GCPtr pGC, int x,
+ int y, int count, char *chars);
+static void xaaWrapperImageText16(DrawablePtr pDraw, GCPtr pGC, int x, int y,
+ int count, unsigned short *chars);
+static void xaaWrapperImageGlyphBlt(DrawablePtr pDraw, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci,
+ pointer pglyphBase);
+static void xaaWrapperPolyGlyphBlt(DrawablePtr pDraw, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci,
+ pointer pglyphBase);
+static void xaaWrapperPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDraw,
+ int dx, int dy, int xOrg, int yOrg);
+#endif
+static void
+xaaWrapperComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
+static void
+xaaWrapperGlyphs (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist,
+ GlyphListPtr list, GlyphPtr *glyphs);
+
+
+typedef struct {
+ CloseScreenProcPtr CloseScreen;
+ CreateScreenResourcesProcPtr CreateScreenResources;
+ CreateWindowProcPtr CreateWindow;
+ CopyWindowProcPtr CopyWindow;
+ PaintWindowProcPtr PaintWindowBackground;
+ PaintWindowProcPtr PaintWindowBorder;
+ WindowExposuresProcPtr WindowExposures;
+ CreateGCProcPtr CreateGC;
+ CreateColormapProcPtr CreateColormap;
+ DestroyColormapProcPtr DestroyColormap;
+ InstallColormapProcPtr InstallColormap;
+ UninstallColormapProcPtr UninstallColormap;
+ ListInstalledColormapsProcPtr ListInstalledColormaps;
+ StoreColorsProcPtr StoreColors;
+#ifdef RENDER
+ CompositeProcPtr Composite;
+ GlyphsProcPtr Glyphs;
+#endif
+
+ CloseScreenProcPtr wrapCloseScreen;
+ CreateScreenResourcesProcPtr wrapCreateScreenResources;
+ CreateWindowProcPtr wrapCreateWindow;
+ CopyWindowProcPtr wrapCopyWindow;
+ PaintWindowProcPtr wrapPaintWindowBackground;
+ PaintWindowProcPtr wrapPaintWindowBorder;
+ WindowExposuresProcPtr wrapWindowExposures;
+ CreateGCProcPtr wrapCreateGC;
+ CreateColormapProcPtr wrapCreateColormap;
+ DestroyColormapProcPtr wrapDestroyColormap;
+ InstallColormapProcPtr wrapInstallColormap;
+ UninstallColormapProcPtr wrapUninstallColormap;
+ ListInstalledColormapsProcPtr wrapListInstalledColormaps;
+ StoreColorsProcPtr wrapStoreColors;
+#ifdef RENDER
+ CompositeProcPtr wrapComposite;
+ GlyphsProcPtr wrapGlyphs;
+#endif
+ int depth;
+} xaaWrapperScrPrivRec, *xaaWrapperScrPrivPtr;
+
+#define xaaWrapperGetScrPriv(s) ((xaaWrapperScrPrivPtr)( \
+ (xaaWrapperScrPrivateIndex != -1) \
+ ? (s)->devPrivates[xaaWrapperScrPrivateIndex].ptr\
+ : NULL))
+#define xaaWrapperScrPriv(s) xaaWrapperScrPrivPtr pScrPriv = xaaWrapperGetScrPriv(s)
+
+#define wrap(priv,real,mem,func) {\
+ priv->mem = real->mem; \
+ real->mem = func; \
+}
+
+#if 0
+#define wrap_pre(priv,real,real_func,mem,func) {\
+ priv->mem = real->real_func; \
+ real->real_func = func; \
+}
+#endif
+
+#define get(priv,real,func,wrap) \
+ priv->wrap = real->func;
+
+#define unwrap(priv,real,mem) {\
+ real->mem = priv->mem; \
+}
+
+#if 0
+#define unwrap_pre(priv,real,real_func,mem) {\
+ real->real_func = priv->mem; \
+}
+#endif
+
+typedef struct _xaaWrapperGCPriv {
+ GCOps *ops;
+ Bool wrap;
+ GCFuncs *funcs;
+ GCOps *wrapops;
+} xaaWrapperGCPrivRec, *xaaWrapperGCPrivPtr;
+
+#define xaaWrapperGetGCPriv(pGC) ((xaaWrapperGCPrivPtr) \
+ (pGC)->devPrivates[xaaWrapperGCPrivateIndex].ptr)
+#define xaaWrapperGCPriv(pGC) xaaWrapperGCPrivPtr pGCPriv = xaaWrapperGetGCPriv(pGC)
+
+
+static int xaaWrapperScrPrivateIndex = -1;
+static int xaaWrapperGCPrivateIndex = -1;
+static int xaaWrapperGeneration = -1;
+
+static Bool
+xaaWrapperCreateScreenResources(ScreenPtr pScreen)
+{
+ xaaWrapperScrPriv(pScreen);
+ Bool ret;
+
+ unwrap (pScrPriv,pScreen, CreateScreenResources);
+ ret = pScreen->CreateScreenResources(pScreen);
+ wrap(pScrPriv,pScreen,CreateScreenResources,xaaWrapperCreateScreenResources);
+ return ret;
+}
+
+static Bool
+xaaWrapperCloseScreen (int iScreen, ScreenPtr pScreen)
+{
+ xaaWrapperScrPriv(pScreen);
+ Bool ret;
+
+ unwrap (pScrPriv,pScreen, CloseScreen);
+ ret = pScreen->CloseScreen(iScreen,pScreen);
+ return TRUE;
+}
+
+static Bool
+xaaWrapperCreateWindow(WindowPtr pWin)
+{
+ xaaWrapperScrPriv(pWin->drawable.pScreen);
+ Bool ret;
+
+ unwrap (pScrPriv, pWin->drawable.pScreen, CreateWindow);
+ if (COND(&pWin->drawable))
+ pWin->drawable.pScreen->CreateWindow
+ = pScrPriv->wrapCreateWindow;
+ ret = pWin->drawable.pScreen->CreateWindow(pWin);
+ wrap(pScrPriv, pWin->drawable.pScreen, CreateWindow, xaaWrapperCreateWindow);
+
+ return ret;
+}
+
+static void
+xaaWrapperCopyWindow(WindowPtr pWin,
+ DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ xaaWrapperScrPriv(pScreen);
+
+ unwrap (pScrPriv, pScreen, CopyWindow);
+#if 0
+ if (COND(&pWin->drawable))
+ pWin->drawable.pScreen->CopyWindow = pScrPriv->wrapCopyWindow;
+#endif
+ pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc);
+ wrap(pScrPriv, pScreen, CopyWindow, xaaWrapperCopyWindow);
+}
+
+static void
+xaaWrapperWindowExposures (WindowPtr pWin,
+ RegionPtr prgn,
+ RegionPtr other_exposed)
+{
+ xaaWrapperScrPriv(pWin->drawable.pScreen);
+
+ unwrap (pScrPriv, pWin->drawable.pScreen, WindowExposures);
+ if (COND(&pWin->drawable))
+ pWin->drawable.pScreen->WindowExposures = pScrPriv->wrapWindowExposures;
+ pWin->drawable.pScreen->WindowExposures(pWin, prgn, other_exposed);
+ wrap(pScrPriv, pWin->drawable.pScreen, WindowExposures, xaaWrapperWindowExposures);
+}
+
+static void
+xaaWrapperPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ xaaWrapperScrPriv(pWin->drawable.pScreen);
+
+ switch (what) {
+ case PW_BORDER:
+ unwrap (pScrPriv, pWin->drawable.pScreen, PaintWindowBorder);
+ if (COND(&pWin->drawable)) {
+ pWin->drawable.pScreen->PaintWindowBorder
+ = pScrPriv->wrapPaintWindowBorder;
+ XAASync(pWin->drawable.pScreen);
+ }
+ pWin->drawable.pScreen->PaintWindowBorder (pWin, pRegion, what);
+ wrap(pScrPriv, pWin->drawable.pScreen, PaintWindowBorder,
+ xaaWrapperPaintWindow);
+ break;
+ case PW_BACKGROUND:
+ unwrap (pScrPriv, pWin->drawable.pScreen, PaintWindowBackground);
+ if (COND(&pWin->drawable)) {
+ pWin->drawable.pScreen->PaintWindowBackground
+ = pScrPriv->wrapPaintWindowBackground;
+ XAASync(pWin->drawable.pScreen);
+ }
+ pWin->drawable.pScreen->PaintWindowBackground (pWin, pRegion, what);
+ wrap(pScrPriv, pWin->drawable.pScreen, PaintWindowBackground,
+ xaaWrapperPaintWindow);
+ break;
+ }
+
+}
+
+static Bool
+xaaWrapperCreateColormap(ColormapPtr pmap)
+{
+ xaaWrapperScrPriv(pmap->pScreen);
+ Bool ret;
+ unwrap(pScrPriv,pmap->pScreen, CreateColormap);
+ ret = pmap->pScreen->CreateColormap(pmap);
+ wrap(pScrPriv,pmap->pScreen,CreateColormap,xaaWrapperCreateColormap);
+
+ return ret;
+}
+
+static void
+xaaWrapperDestroyColormap(ColormapPtr pmap)
+{
+ xaaWrapperScrPriv(pmap->pScreen);
+ unwrap(pScrPriv,pmap->pScreen, DestroyColormap);
+ pmap->pScreen->DestroyColormap(pmap);
+ wrap(pScrPriv,pmap->pScreen,DestroyColormap,xaaWrapperDestroyColormap);
+}
+
+static void
+xaaWrapperStoreColors(ColormapPtr pmap, int nColors, xColorItem *pColors)
+{
+ xaaWrapperScrPriv(pmap->pScreen);
+ unwrap(pScrPriv,pmap->pScreen, StoreColors);
+ pmap->pScreen->StoreColors(pmap,nColors,pColors);
+ wrap(pScrPriv,pmap->pScreen,StoreColors,xaaWrapperStoreColors);
+}
+
+static void
+xaaWrapperInstallColormap(ColormapPtr pmap)
+{
+ xaaWrapperScrPriv(pmap->pScreen);
+
+ unwrap(pScrPriv,pmap->pScreen, InstallColormap);
+ pmap->pScreen->InstallColormap(pmap);
+ wrap(pScrPriv,pmap->pScreen,InstallColormap,xaaWrapperInstallColormap);
+}
+
+static void
+xaaWrapperUninstallColormap(ColormapPtr pmap)
+{
+ xaaWrapperScrPriv(pmap->pScreen);
+
+ unwrap(pScrPriv,pmap->pScreen, UninstallColormap);
+ pmap->pScreen->UninstallColormap(pmap);
+ wrap(pScrPriv,pmap->pScreen,UninstallColormap,xaaWrapperUninstallColormap);
+}
+
+static int
+xaaWrapperListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIds)
+{
+ int n;
+ xaaWrapperScrPriv(pScreen);
+
+ unwrap(pScrPriv,pScreen, ListInstalledColormaps);
+ n = pScreen->ListInstalledColormaps(pScreen, pCmapIds);
+ wrap (pScrPriv,pScreen,ListInstalledColormaps,xaaWrapperListInstalledColormaps);
+ return n;
+}
+
+Bool
+xaaSetupWrapper(ScreenPtr pScreen, XAAInfoRecPtr infoPtr, int depth, SyncFunc *func)
+{
+ Bool ret;
+ xaaWrapperScrPrivPtr pScrPriv;
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif
+ if (xaaWrapperGeneration != serverGeneration) {
+ xaaWrapperScrPrivateIndex = AllocateScreenPrivateIndex ();
+ if (xaaWrapperScrPrivateIndex == -1)
+ return FALSE;
+ xaaWrapperGCPrivateIndex = AllocateGCPrivateIndex ();
+ if (xaaWrapperGCPrivateIndex == -1)
+ return FALSE;
+ xaaWrapperGeneration = serverGeneration;
+ }
+
+ if (!AllocateGCPrivate (pScreen, xaaWrapperGCPrivateIndex,
+ sizeof (xaaWrapperGCPrivRec)))
+ return FALSE;
+
+ pScrPriv = (xaaWrapperScrPrivPtr) xalloc (sizeof (xaaWrapperScrPrivRec));
+ if (!pScrPriv)
+ return FALSE;
+
+ get (pScrPriv, pScreen, CloseScreen, wrapCloseScreen);
+ get (pScrPriv, pScreen, CreateScreenResources, wrapCreateScreenResources);
+ get (pScrPriv, pScreen, CreateWindow, wrapCreateWindow);
+ get (pScrPriv, pScreen, CopyWindow, wrapCopyWindow);
+ get (pScrPriv, pScreen, PaintWindowBorder, wrapPaintWindowBorder);
+ get (pScrPriv, pScreen, PaintWindowBackground, wrapPaintWindowBackground);
+ get (pScrPriv, pScreen, WindowExposures, wrapWindowExposures);
+#if 0
+ wrap_pre (pScrPriv, pScreen, CreateGC, wrapCreateGC, xaaWrapperPreCreateGC);
+#else
+ get (pScrPriv, pScreen, CreateGC, wrapCreateGC);
+#endif
+ get (pScrPriv, pScreen, CreateColormap, wrapCreateColormap);
+ get (pScrPriv, pScreen, DestroyColormap, wrapDestroyColormap);
+ get (pScrPriv, pScreen, InstallColormap, wrapInstallColormap);
+ get (pScrPriv, pScreen, UninstallColormap, wrapUninstallColormap);
+ get (pScrPriv, pScreen, ListInstalledColormaps, wrapListInstalledColormaps);
+ get (pScrPriv, pScreen, StoreColors, wrapStoreColors);
+#ifdef RENDER
+ if (ps) {
+ get (pScrPriv, ps, Glyphs, wrapGlyphs);
+ get (pScrPriv, ps, Composite, wrapComposite);
+ }
+#endif
+ if (!(ret = XAAInit(pScreen,infoPtr)))
+ return FALSE;
+
+ wrap (pScrPriv, pScreen, CloseScreen, xaaWrapperCloseScreen);
+ wrap (pScrPriv, pScreen, CreateScreenResources,
+ xaaWrapperCreateScreenResources);
+ wrap (pScrPriv, pScreen, CreateWindow, xaaWrapperCreateWindow);
+ wrap (pScrPriv, pScreen, CopyWindow, xaaWrapperCopyWindow);
+ wrap (pScrPriv, pScreen, PaintWindowBorder, xaaWrapperPaintWindow);
+ wrap (pScrPriv, pScreen, PaintWindowBackground, xaaWrapperPaintWindow);
+ wrap (pScrPriv, pScreen, WindowExposures, xaaWrapperWindowExposures);
+ wrap (pScrPriv, pScreen, CreateGC, xaaWrapperCreateGC);
+ wrap (pScrPriv, pScreen, CreateColormap, xaaWrapperCreateColormap);
+ wrap (pScrPriv, pScreen, DestroyColormap, xaaWrapperDestroyColormap);
+ wrap (pScrPriv, pScreen, InstallColormap, xaaWrapperInstallColormap);
+ wrap (pScrPriv, pScreen, UninstallColormap, xaaWrapperUninstallColormap);
+ wrap (pScrPriv, pScreen, ListInstalledColormaps,
+ xaaWrapperListInstalledColormaps);
+ wrap (pScrPriv, pScreen, StoreColors, xaaWrapperStoreColors);
+
+#ifdef RENDER
+ if (ps) {
+ wrap (pScrPriv, ps, Glyphs, xaaWrapperGlyphs);
+ wrap (pScrPriv, ps, Composite, xaaWrapperComposite);
+ }
+#endif
+ pScrPriv->depth = depth;
+ pScreen->devPrivates[xaaWrapperScrPrivateIndex].ptr = (pointer) pScrPriv;
+
+ *func = XAASync;
+
+ return ret;
+}
+
+GCFuncs xaaWrapperGCFuncs = {
+ xaaWrapperValidateGC, xaaWrapperChangeGC, xaaWrapperCopyGC,
+ xaaWrapperDestroyGC, xaaWrapperChangeClip, xaaWrapperDestroyClip,
+ xaaWrapperCopyClip
+};
+
+#if 0
+GCOps xaaWrapperGCOps = {
+ xaaWrapperFillSpans, xaaWrapperSetSpans,
+ xaaWrapperPutImage, xaaWrapperCopyArea,
+ xaaWrapperCopyPlane, xaaWrapperPolyPoint,
+ xaaWrapperPolylines, xaaWrapperPolySegment,
+ xaaWrapperPolyRectangle, xaaWrapperPolyArc,
+ xaaWrapperFillPolygon, xaaWrapperPolyFillRect,
+ xaaWrapperPolyFillArc, xaaWrapperPolyText8,
+ xaaWrapperPolyText16, xaaWrapperImageText8,
+ xaaWrapperImageText16, xaaWrapperImageGlyphBlt,
+ xaaWrapperPolyGlyphBlt, xaaWrapperPushPixels,
+#ifdef NEED_LINEHELPER
+ NULL,
+#endif
+ {NULL} /* devPrivate */
+};
+#endif
+
+#define XAAWRAPPER_GC_FUNC_PROLOGUE(pGC) \
+ xaaWrapperGCPriv(pGC); \
+ unwrap(pGCPriv, pGC, funcs); \
+ if (pGCPriv->wrap) unwrap(pGCPriv, pGC, ops)
+
+#define XAAWRAPPER_GC_FUNC_EPILOGUE(pGC) \
+ wrap(pGCPriv, pGC, funcs, &xaaWrapperGCFuncs); \
+ if (pGCPriv->wrap) wrap(pGCPriv, pGC, ops, pGCPriv->wrapops)
+
+#if 0
+static Bool
+xaaWrapperPreCreateGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ xaaWrapperScrPriv(pScreen);
+ xaaWrapperGCPriv(pGC);
+ Bool ret;
+
+ unwrap_pre (pScrPriv, pScreen, CreateGC, wrapCreateGC);
+ ret = (*pScreen->CreateGC) (pGC);
+ wrap_pre (pScrPriv, pScreen, CreateGC, wrapCreateGC, xaaWrapperPreCreateGC);
+
+ return ret;
+}
+#endif
+
+static Bool
+xaaWrapperCreateGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ xaaWrapperScrPriv(pScreen);
+ xaaWrapperGCPriv(pGC);
+ Bool ret;
+
+ unwrap (pScrPriv, pScreen, CreateGC);
+ if((ret = (*pScreen->CreateGC) (pGC))) {
+ pGCPriv->wrap = FALSE;
+ pGCPriv->funcs = pGC->funcs;
+ pGCPriv->wrapops = pGC->ops;
+ pGC->funcs = &xaaWrapperGCFuncs;
+ }
+ wrap (pScrPriv, pScreen, CreateGC, xaaWrapperCreateGC);
+
+ return ret;
+}
+
+static void
+xaaWrapperValidateGC(
+ GCPtr pGC,
+ unsigned long changes,
+ DrawablePtr pDraw
+){
+ XAAWRAPPER_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
+
+ if(COND(pDraw))
+ pGCPriv->wrap = TRUE;
+
+ XAAWRAPPER_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+xaaWrapperDestroyGC(GCPtr pGC)
+{
+ XAAWRAPPER_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->DestroyGC)(pGC);
+ XAAWRAPPER_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+xaaWrapperChangeGC (
+ GCPtr pGC,
+ unsigned long mask
+){
+ XAAWRAPPER_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->ChangeGC) (pGC, mask);
+ XAAWRAPPER_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+xaaWrapperCopyGC (
+ GCPtr pGCSrc,
+ unsigned long mask,
+ GCPtr pGCDst
+){
+ XAAWRAPPER_GC_FUNC_PROLOGUE (pGCDst);
+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
+ XAAWRAPPER_GC_FUNC_EPILOGUE (pGCDst);
+}
+
+static void
+xaaWrapperChangeClip (
+ GCPtr pGC,
+ int type,
+ pointer pvalue,
+ int nrects
+){
+ XAAWRAPPER_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
+ XAAWRAPPER_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+xaaWrapperCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ XAAWRAPPER_GC_FUNC_PROLOGUE (pgcDst);
+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
+ XAAWRAPPER_GC_FUNC_EPILOGUE (pgcDst);
+}
+
+static void
+xaaWrapperDestroyClip(GCPtr pGC)
+{
+ XAAWRAPPER_GC_FUNC_PROLOGUE (pGC);
+ (* pGC->funcs->DestroyClip)(pGC);
+ XAAWRAPPER_GC_FUNC_EPILOGUE (pGC);
+}
+
+#if 0
+#define XAAWRAPPER_GC_OP_PROLOGUE(pGC,pDraw) \
+/* xaaWrapperScrPriv(pDraw->pScreen); */\
+ xaaWrapperGCPriv(pGC); \
+ GCFuncs *oldFuncs = pGC->funcs; \
+ unwrap(pGCPriv, pGC, funcs); \
+ unwrap(pGCPriv, pGC, ops); \
+
+#define XAAWRAPPER_GC_OP_EPILOGUE(pGC,pDraw) \
+ wrap(pGCPriv, pGC, funcs, oldFuncs); \
+ wrap(pGCPriv, pGC, ops, &xaaWrapperGCOps)
+
+static void
+xaaWrapperFillSpans(
+ DrawablePtr pDraw,
+ GC *pGC,
+ int nInit,
+ DDXPointPtr pptInit,
+ int *pwidthInit,
+ int fSorted
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperSetSpans(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ char *pcharsrc,
+ DDXPointPtr pptInit,
+ int *pwidthInit,
+ int nspans,
+ int fSorted
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+
+ (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit,
+ pwidthInit, nspans, fSorted);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+
+static void
+xaaWrapperPutImage(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int depth,
+ int x, int y, int w, int h,
+ int leftPad,
+ int format,
+ char *pImage
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h,
+ leftPad, format, pImage);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static RegionPtr
+xaaWrapperCopyArea(
+ DrawablePtr pSrc,
+ DrawablePtr pDst,
+ GC *pGC,
+ int srcx, int srcy,
+ int width, int height,
+ int dstx, int dsty
+){
+ RegionPtr ret;
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDst);
+ ret = (*pGC->ops->CopyArea)(pSrc, pDst,
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDst);
+
+ return ret;
+}
+
+
+static RegionPtr
+xaaWrapperCopyPlane(
+ DrawablePtr pSrc,
+ DrawablePtr pDst,
+ GCPtr pGC,
+ int srcx, int srcy,
+ int width, int height,
+ int dstx, int dsty,
+ unsigned long bitPlane
+){
+ RegionPtr ret;
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDst);
+ ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
+ pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDst);
+ return ret;
+}
+
+static void
+xaaWrapperPolyPoint(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int mode,
+ int npt,
+ xPoint *pptInit
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperPolylines(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int mode,
+ int npt,
+ DDXPointPtr pptInit
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperPolySegment(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int nseg,
+ xSegment *pSeg
+ ){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperPolyRectangle(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int nRects,
+ xRectangle *pRects
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolyRectangle)(pDraw, pGC, nRects, pRects);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperPolyArc(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int narcs,
+ xArc *parcs
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperFillPolygon(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int shape,
+ int mode,
+ int count,
+ DDXPointPtr pptInit
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperPolyFillRect(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int nRectsInit,
+ xRectangle *pRectsInit
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperPolyFillArc(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int narcs,
+ xArc *parcs
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static int
+xaaWrapperPolyText8(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ char *chars
+){
+ int width;
+
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ width = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+
+ return width;
+}
+
+static int
+xaaWrapperPolyText16(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ unsigned short *chars
+){
+ int width;
+
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ width = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+
+ return width;
+}
+
+static void
+xaaWrapperImageText8(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ char *chars
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperImageText16(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ unsigned short *chars
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperImageGlyphBlt(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, nglyph,
+ ppci, pglyphBase);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperPolyGlyphBlt(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ int x, int y,
+ unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, nglyph,
+ ppci, pglyphBase);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+
+static void
+xaaWrapperPushPixels(
+ GCPtr pGC,
+ PixmapPtr pBitMap,
+ DrawablePtr pDraw,
+ int dx, int dy, int xOrg, int yOrg
+){
+ XAAWRAPPER_GC_OP_PROLOGUE(pGC, pDraw);
+ (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg);
+ XAAWRAPPER_GC_OP_EPILOGUE(pGC, pDraw);
+}
+#endif
+
+#ifdef RENDER
+static void
+xaaWrapperComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ xaaWrapperScrPriv(pScreen);
+
+ unwrap (pScrPriv, ps, Composite);
+ (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height);
+ wrap (pScrPriv, ps, Composite, xaaWrapperComposite);
+}
+
+
+static void
+xaaWrapperGlyphs (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist,
+ GlyphListPtr list, GlyphPtr *glyphs)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ xaaWrapperScrPriv(pScreen);
+
+ unwrap (pScrPriv, ps, Glyphs);
+ (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc,
+ nlist, list, glyphs);
+ wrap (pScrPriv, ps, Glyphs, xaaWrapperGlyphs);
+
+}
+#endif
+
+void
+XAASync(ScreenPtr pScreen)
+{
+ XAAScreenPtr pScreenPriv =
+ (XAAScreenPtr) pScreen->devPrivates[XAAScreenIndex].ptr;
+ XAAInfoRecPtr infoRec = pScreenPriv->AccelInfoRec;
+
+ if(infoRec->NeedToSync) {
+ (*infoRec->Sync)(infoRec->pScrn);
+ infoRec->NeedToSync = FALSE;
+ }
+}
diff --git a/hw/xfree86/xaa/xaaWrapper.h b/hw/xfree86/xaa/xaaWrapper.h
new file mode 100644
index 000000000..fbcf17f6f
--- /dev/null
+++ b/hw/xfree86/xaa/xaaWrapper.h
@@ -0,0 +1,9 @@
+#ifndef _XAA_WRAPPER_H
+# define _XAA_WRAPPER_H
+
+typedef void (*SyncFunc)(ScreenPtr);
+
+Bool xaaSetupWrapper(ScreenPtr pScreen,
+ XAAInfoRecPtr infoPtr, int depth, SyncFunc *func);
+
+#endif
diff --git a/hw/xwin/winclipboardthread.c b/hw/xwin/winclipboardthread.c
index 4987c99dd..0996b43f5 100644
--- a/hw/xwin/winclipboardthread.c
+++ b/hw/xwin/winclipboardthread.c
@@ -61,6 +61,7 @@ extern Window g_iClipboardWindow;
static jmp_buf g_jmpEntry;
Bool g_fUnicodeSupport = FALSE;
+Bool g_fUseUnicode = FALSE;
/*
@@ -91,16 +92,19 @@ winClipboardProc (void *pvNotUsed)
Display *pDisplay = NULL;
Window iWindow = None;
int iRetries;
- Bool fUnicodeSupport;
+ Bool fUseUnicode;
char szDisplay[512];
ErrorF ("winClipboardProc - Hello\n");
/* Do we have Unicode support? */
- fUnicodeSupport = g_fUnicodeClipboard && winClipboardDetectUnicodeSupport ();
+ g_fUnicodeSupport = winClipboardDetectUnicodeSupport ();
+
+ /* Do we use Unicode clipboard? */
+ fUseUnicode = g_fUnicodeClipboard && g_fUnicodeSupport;
/* Save the Unicode support flag in a global */
- g_fUnicodeSupport = fUnicodeSupport;
+ g_fUseUnicode = fUseUnicode;
/* Allow multiple threads to access Xlib */
if (XInitThreads () == 0)
@@ -224,9 +228,6 @@ winClipboardProc (void *pvNotUsed)
atomClipboard = XInternAtom (pDisplay, "CLIPBOARD", False);
atomClipboardManager = XInternAtom (pDisplay, "CLIPBOARD_MANAGER", False);
- /* FIXME: Save some values as globals for the window proc */
- g_fUnicodeSupport = fUnicodeSupport;
-
/* Create a messaging window */
iWindow = XCreateSimpleWindow (pDisplay,
DefaultRootWindow (pDisplay),
@@ -296,7 +297,7 @@ winClipboardProc (void *pvNotUsed)
winClipboardFlushXEvents (hwnd,
iWindow,
pDisplay,
- fUnicodeSupport);
+ fUseUnicode);
/* Pre-flush Windows messages */
if (!winClipboardFlushWindowsMessageQueue (hwnd))
@@ -344,7 +345,7 @@ winClipboardProc (void *pvNotUsed)
iReturn = winClipboardFlushXEvents (hwnd,
iWindow,
pDisplay,
- fUnicodeSupport);
+ fUseUnicode);
if (WIN_XEVENTS_SHUTDOWN == iReturn)
{
ErrorF ("winClipboardProc - winClipboardFlushXEvents "
diff --git a/hw/xwin/winclipboardwndproc.c b/hw/xwin/winclipboardwndproc.c
index 947db682c..722141924 100644
--- a/hw/xwin/winclipboardwndproc.c
+++ b/hw/xwin/winclipboardwndproc.c
@@ -43,7 +43,7 @@
* References to external symbols
*/
-extern Bool g_fUnicodeSupport;
+extern Bool g_fUseUnicode;
extern void *g_pClipboardDisplay;
extern Window g_iClipboardWindow;
extern Atom g_atomLastOwnedSelection;
@@ -55,7 +55,7 @@ extern Atom g_atomLastOwnedSelection;
static Bool
winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay,
- Bool fUnicodeSupport, int iTimeoutSec);
+ Bool fUseUnicode, int iTimeoutSec);
/*
@@ -64,7 +64,7 @@ winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay,
static int
winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay,
- Bool fUnicodeSupport, int iTimeoutSec)
+ Bool fUseUnicode, int iTimeoutSec)
{
int iConnNumber;
struct timeval tv;
@@ -115,7 +115,7 @@ winProcessXEventsTimeout (HWND hwnd, int iWindow, Display *pDisplay,
iReturn = winClipboardFlushXEvents (hwnd,
iWindow,
pDisplay,
- fUnicodeSupport);
+ fUseUnicode);
if (WIN_XEVENTS_NOTIFY == iReturn
|| WIN_XEVENTS_CONVERT == iReturn)
{
@@ -445,7 +445,7 @@ winClipboardWindowProc (HWND hwnd, UINT message,
if (message == WM_RENDERALLFORMATS)
fConvertToUnicode = FALSE;
else
- fConvertToUnicode = g_fUnicodeSupport && (CF_UNICODETEXT == wParam);
+ fConvertToUnicode = g_fUseUnicode && (CF_UNICODETEXT == wParam);
/* Request the selection contents */
iReturn = XConvertSelection (pDisplay,
diff --git a/hw/xwin/winclipboardxevents.c b/hw/xwin/winclipboardxevents.c
index 598620c4c..3d4444168 100644
--- a/hw/xwin/winclipboardxevents.c
+++ b/hw/xwin/winclipboardxevents.c
@@ -32,6 +32,13 @@
/*
+ * References to external symbols
+ */
+
+extern Bool g_fUnicodeSupport;
+
+
+/*
* Process any pending X events
*/
@@ -39,7 +46,7 @@ int
winClipboardFlushXEvents (HWND hwnd,
int iWindow,
Display *pDisplay,
- Bool fUnicodeSupport)
+ Bool fUseUnicode)
{
Atom atomLocalProperty = XInternAtom (pDisplay,
WIN_LOCAL_PROPERTY,
@@ -173,7 +180,7 @@ winClipboardFlushXEvents (HWND hwnd,
}
/* Check that clipboard format is available */
- if (fUnicodeSupport
+ if (fUseUnicode
&& !IsClipboardFormatAvailable (CF_UNICODETEXT))
{
ErrorF ("winClipboardFlushXEvents - CF_UNICODETEXT is not "
@@ -183,7 +190,7 @@ winClipboardFlushXEvents (HWND hwnd,
fAbort = TRUE;
goto winClipboardFlushXEvents_SelectionRequest_Done;
}
- else if (!fUnicodeSupport
+ else if (!fUseUnicode
&& !IsClipboardFormatAvailable (CF_TEXT))
{
ErrorF ("winClipboardFlushXEvents - CF_TEXT is not "
@@ -232,7 +239,7 @@ winClipboardFlushXEvents (HWND hwnd,
*/
/* Get a pointer to the clipboard text, in desired format */
- if (fUnicodeSupport)
+ if (fUseUnicode)
{
/* Retrieve clipboard data */
hGlobal = GetClipboardData (CF_UNICODETEXT);
@@ -255,7 +262,7 @@ winClipboardFlushXEvents (HWND hwnd,
pszGlobalData = (char *) GlobalLock (hGlobal);
/* Convert the Unicode string to UTF8 (MBCS) */
- if (fUnicodeSupport)
+ if (fUseUnicode)
{
iConvertDataLen = WideCharToMultiByte (CP_UTF8,
0,
@@ -293,7 +300,7 @@ winClipboardFlushXEvents (HWND hwnd,
xtpText.value = NULL;
/* Create the text property from the text list */
- if (fUnicodeSupport)
+ if (fUseUnicode)
{
#ifdef X_HAVE_UTF8_STRING
iReturn = Xutf8TextListToTextProperty (pDisplay,
@@ -586,7 +593,7 @@ winClipboardFlushXEvents (HWND hwnd,
}
#endif
- if (fUnicodeSupport)
+ if (fUseUnicode)
{
#ifdef X_HAVE_UTF8_STRING
/* Convert the text property to a text list */
@@ -657,7 +664,7 @@ winClipboardFlushXEvents (HWND hwnd,
/* Convert the X clipboard string to DOS format */
winClipboardUNIXtoDOS (&pszReturnData, strlen (pszReturnData));
- if (fUnicodeSupport)
+ if (fUseUnicode)
{
/* Find out how much space needed to convert MBCS to Unicode */
iUnicodeLen = MultiByteToWideChar (CP_UTF8,
@@ -726,7 +733,7 @@ winClipboardFlushXEvents (HWND hwnd,
}
/* Copy the returned string into the global memory */
- if (fUnicodeSupport)
+ if (fUseUnicode)
{
memcpy (pszGlobalData,
pwszUnicodeStr,
@@ -746,7 +753,7 @@ winClipboardFlushXEvents (HWND hwnd,
pszGlobalData = NULL;
/* Push the selection data to the Windows clipboard */
- if (fUnicodeSupport)
+ if (fUseUnicode)
SetClipboardData (CF_UNICODETEXT, hGlobal);
else
SetClipboardData (CF_TEXT, hGlobal);
@@ -771,9 +778,9 @@ winClipboardFlushXEvents (HWND hwnd,
free (pwszUnicodeStr);
if (hGlobal && pszGlobalData)
GlobalUnlock (hGlobal);
- if (fSetClipboardData && fUnicodeSupport)
+ if (fSetClipboardData && g_fUnicodeSupport)
SetClipboardData (CF_UNICODETEXT, NULL);
- if (fSetClipboardData && !fUnicodeSupport)
+ if (fSetClipboardData)
SetClipboardData (CF_TEXT, NULL);
return WIN_XEVENTS_NOTIFY;
diff --git a/hw/xwin/winwin32rootlesswndproc.c b/hw/xwin/winwin32rootlesswndproc.c
index d7fb85075..00d41d101 100755
--- a/hw/xwin/winwin32rootlesswndproc.c
+++ b/hw/xwin/winwin32rootlesswndproc.c
@@ -932,7 +932,7 @@ winMWExtWMWindowProc (HWND hwnd, UINT message,
if ((dwWindowProcessID == dwCurrentProcessID)
&& GetProp (Above, WIN_WINDOW_PROP)
- && !IsIconic (hwnd) ) /* ignore minimized windows */
+ && !IsIconic (hWndAbove) ) /* ignore minimized windows */
break;
}
/* If this is top of X windows in Windows stack,
diff --git a/miext/damage/damage.h b/miext/damage/damage.h
new file mode 100755
index 000000000..7ed1b1823
--- /dev/null
+++ b/miext/damage/damage.h
@@ -0,0 +1,80 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2003 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 _DAMAGE_H_
+#define _DAMAGE_H_
+
+typedef struct _damage *DamagePtr;
+
+typedef enum _damageReportLevel {
+ DamageReportRawRegion,
+ DamageReportDeltaRegion,
+ DamageReportBoundingBox,
+ DamageReportNonEmpty,
+ DamageReportNone
+} DamageReportLevel;
+
+typedef void (*DamageReportFunc) (DamagePtr pDamage, RegionPtr pRegion, void *closure);
+typedef void (*DamageDestroyFunc) (DamagePtr pDamage, void *closure);
+
+Bool
+DamageSetup (ScreenPtr pScreen);
+
+DamagePtr
+DamageCreate (DamageReportFunc damageReport,
+ DamageDestroyFunc damageDestroy,
+ DamageReportLevel damageLevel,
+ Bool isInternal,
+ ScreenPtr pScreen,
+ void * closure);
+
+void
+DamageDrawInternal (ScreenPtr pScreen, Bool enable);
+
+void
+DamageRegister (DrawablePtr pDrawable,
+ DamagePtr pDamage);
+
+void
+DamageUnregister (DrawablePtr pDrawable,
+ DamagePtr pDamage);
+
+void
+DamageDestroy (DamagePtr pDamage);
+
+Bool
+DamageSubtract (DamagePtr pDamage,
+ const RegionPtr pRegion);
+
+void
+DamageEmpty (DamagePtr pDamage);
+
+RegionPtr
+DamageRegion (DamagePtr pDamage);
+
+void
+DamageDamageRegion (DrawablePtr pDrawable,
+ const RegionPtr pRegion);
+
+#endif /* _DAMAGE_H_ */
diff --git a/miext/rootless/README.txt b/miext/rootless/README.txt
new file mode 100644
index 000000000..ffd17902f
--- /dev/null
+++ b/miext/rootless/README.txt
@@ -0,0 +1,403 @@
+ Generic Rootless Layer
+ Version 1.0
+ July 13, 2004
+
+ Torrey T. Lyons
+ torrey@xfree86.org
+
+
+Introduction
+
+ The generic rootless layer allows an X server to be implemented
+on top of another window server in a cooperative manner. This allows the
+X11 windows and native windows of the underlying window server to
+coexist on the same screen. The layer is called "rootless" because the root
+window of the X server is generally not drawn. Instead, each top-level
+child of the root window is represented as a separate on-screen window by
+the underlying window server. The layer is referred to as "generic"
+because it abstracts away the details of the underlying window system and
+contains code that is useful for any rootless X server. The code for the
+generic rootless layer is located in xc/programs/Xserver/miext/rootless. To
+build a complete rootless X server requires a specific rootless
+implementation, which provides functions that allow the generic rootless
+layer to interact with the underlying window system.
+
+
+Concepts
+
+ In the context of a rootless X server the term window is used to
+mean many fundamentally different things. For X11 a window is a DDX
+resource that describes a visible, or potentially visible, rectangle on the
+screen. A top-level window is a direct child of the root window. To avoid
+confusion, an on-screen native window of the underlying window system
+is referred to as a "frame". The generic rootless layer associates each
+mapped top-level X11 window with a frame. An X11 window may be said
+to be "framed" if it or its top-level parent is represented by a frame.
+
+ The generic rootless layer models each frame as being backed at
+all times by a backing buffer, which is periodically flushed to the screen.
+If the underlying window system does not provide a backing buffer for
+frames, this must be done by the rootless implementation. The generic
+rootless layer model does not assume it always has access to the frames'
+backing buffers. Any drawing to the buffer will be proceeded by a call to
+the rootless implementation's StartDrawing() function and StopDrawing()
+will be called when the drawing is concluded. The address of the frame's
+backing buffer is returned by the StartDrawing() function and it can
+change between successive calls.
+
+ Because each frame is assumed to have a backing buffer, the
+generic rootless layer will stop Expose events being generated when the
+regions of visibility of a frame change on screen. This is similar to backing
+store, but backing buffers are different in that they always store a copy of
+the entire window contents, not just the obscured portions. The price paid
+in increased memory consumption is made up by the greatly decreased
+complexity in not having to track and record regions as they are obscured.
+
+
+Rootless Implementation
+
+ The specifics of the underlying window system are provided to the
+generic rootless layer through rootless implementation functions, compile-
+time options, and runtime parameters. The rootless implementation
+functions are a list of functions that allow the generic rootless layer to
+perform operations such as creating, destroying, moving, and resizing
+frames. Some of the implementation functions are optional. A detailed
+description of the rootless implementation functions is provided in
+Appendix A.
+
+ By design, a rootless implementation should only have to include
+the rootless.h header file. The rootlessCommon.h file contains definitions
+internal to the generic rootless layer. (If you find you need to use
+rootlessCommon.h in your implementation, let the generic rootless layer
+maintainers know. This could be an area where the generic rootless layer
+should be generalized.) A rootless implementation should also modify
+rootlessConfig.h to specify compile time options for its platform.
+
+ The following compile-time options are defined in
+rootlessConfig.h:
+
+ o ROOTLESS_ACCEL: If true, use the optional rootless acceleration
+ functions where possible to a accelerate X11 drawing primitives.
+ If false, all drawing will be done with fb.
+
+ o ROOTLESS_GLOBAL_COORDS: This option controls the way that frame
+ coordinates are passed to the rootless implementation. If false,
+ the coordinates are passed per screen relative to the origin of
+ the screen the frame is currently on. Some implementations may
+ prefer to work in a single global coordinate space that spans all
+ screens. If this option is true, the coordinates are passed after
+ adding the coordinates of the screen origin and an overall offset of
+ (rootlessGlobalOffsetX, rootlessGlobalOffsetY).
+
+ o ROOTLESS_PROTECT_ALPHA: By default for a color bit depth of 24 and
+ 32 bits per pixel, fb will overwrite the "unused" 8 bits to optimize
+ drawing speed. If this is true, the alpha channel of frames is
+ protected and is not modified when drawing to them. The bits
+ containing the alpha channel are defined by the macro
+ RootlessAlphaMask(bpp), which should return a bit mask for
+ various bits per pixel.
+
+ o ROOTLESS_REDISPLAY_DELAY: Time in milliseconds between updates to
+ the underlying window server. Most operations will be buffered until
+ this time has expired.
+
+ o ROOTLESS_RESIZE_GRAVITY: If the underlying window system supports it,
+ some frame resizes can be optimized by relying on the frame contents
+ maintaining a particular gravity during the resize. In this way less
+ of the frame contents need to be preserved by the generic rootless
+ layer. If true, the generic rootless layer will pass gravity hints
+ during resizing and rely on the frame contents being preserved
+ accordingly.
+
+ o ROOTLESS_TRACK_DAMAGE: The generic rootless layer draws to the
+ frames' backing buffers and periodically flushes the modified
+ regions to the underlying window server. If this option is true,
+ the generic rootless layer will track these damaged regions.
+ Currently it uses the miRegion code and will not simplify damaged
+ regions even when updating a bounding region would be more
+ efficient. Some window systems provide a more efficient way to
+ track damaged regions. If this option is false, the rootless
+ implementation function DamageRects() is called whenever a
+ backing buffer is modified and the rootless implementation is
+ expected to track the damaged regions itself.
+
+ The following runtime options are defined in rootless.h:
+
+ o rootlessGlobalOffsetX, rootlessGlobalOffsetY: These are only
+ used if ROOTLESS_GLOBAL_COORDS is true. They specify the global
+ offset that is applied to all screens when converting from
+ screen-local to global coordinates.
+
+ o rootless_CopyBytes_threshold, rootless_FillBytes_threshold,
+ rootless_CompositePixels_threshold, rootless_CopyWindow_threshold:
+ The minimum number of bytes or pixels for which to use the rootless
+ implementation's respective acceleration function. The rootless
+ acceleration functions are all optional so these will only be used
+ if the respective acceleration function pointer is not NULL.
+
+
+Accelerated Drawing
+
+ The rootless implementation typically does not have direct access
+to the hardware. Its access to the graphics hardware is generally through
+the API of the underlying window system. This underlying API may not
+overlap well with the X11 drawing primitives. The generic rootless layer
+falls back to using fb for all its 2-D drawing. Providing optional rootless
+implementation acceleration functions can accelerate some graphics
+primitives and some window functions. Typically calling through to the
+underlying window systems API will not speed up these operations for
+small enough areas. The rootless_*_threshold runtime options allow the
+rootless implementation to provide hints for when the acceleration
+functions should be used instead of fb.
+
+
+Alpha Channel Protection
+
+ If the bits per pixel is greater then the color bit depth, the contents
+of the extra bits are undefined by the X11 protocol. Some window systems
+will use these extra bits as an alpha channel. The generic rootless layer can
+be configured to protect these bits and make sure they are not modified by
+other parts of the X server. To protect the alpha channel
+ROOTLESS_PROTECT_ALPHA and RootlessAlphaMask(bpp) must be
+set appropriately as described under the compile time options. This
+ensures that the X11 graphics primitives do not overwrite the alpha
+channel in an attempt to optimize drawing. In addition, the window
+functions PaintWindow() and Composite() must be replaced by alpha
+channel safe variants. These are provided in rootless/safeAlpha.
+
+
+Credits
+
+ The generic rootless layer was originally conceived and developed
+by Greg Parker as part of the XDarwin X server on Mac OS X. John
+Harper made later optimizations to this code but removed its generic
+independence of the underlying window system. Torrey T. Lyons
+reintroduced the generic abstractions and made the rootless code suitable
+for use by other X servers.
+
+
+Appendix A: Rootless Implementation Functions
+
+ The rootless implementation functions are defined in rootless.h. It
+is intended that rootless.h contains the complete interface that is needed by
+rootless implementations. The definitions contained in rootlessCommon.h
+are intended for internal use by the generic rootless layer and are more
+likely to change.
+
+ Most of these functions take a RootlessFrameID as a parameter.
+The RootlessFrameID is an opaque object that is returned by the
+implementation's CreateFrame() function. The generic rootless layer does
+not use this frame id other than to pass it back to the rootless
+implementation to indicate the frame to operate on.
+
+/*
+ * Create a new frame.
+ * The frame is created unmapped.
+ *
+ * pFrame RootlessWindowPtr for this frame should be completely
+ * initialized before calling except for pFrame->wid, which
+ * is set by this function.
+ * pScreen Screen on which to place the new frame
+ * newX, newY Position of the frame. These will be identical to pFrame-x,
+ * pFrame->y unless ROOTLESS_GLOBAL_COORDS is set.
+ * pNewShape Shape for the frame (in frame-local coordinates). NULL for
+ * unshaped frames.
+ */
+typedef Bool (*RootlessCreateFrameProc)
+ (RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX, int newY,
+ RegionPtr pNewShape);
+
+/*
+ * Destroy a frame.
+ * Drawing is stopped and all updates are flushed before this is called.
+ *
+ * wid Frame id
+ */
+typedef void (*RootlessDestroyFrameProc)
+ (RootlessFrameID wid);
+
+/*
+ * Move a frame on screen.
+ * Drawing is stopped and all updates are flushed before this is called.
+ *
+ * wid Frame id
+ * pScreen Screen to move the new frame to
+ * newX, newY New position of the frame
+ */
+typedef void (*RootlessMoveFrameProc)
+ (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
+
+/*
+ * Resize and move a frame.
+ * Drawing is stopped and all updates are flushed before this is called.
+ *
+ * wid Frame id
+ * pScreen Screen to move the new frame to
+ * newX, newY New position of the frame
+ * newW, newH New size of the frame
+ * gravity Gravity for window contents (rl_gravity_enum). This is always
+ * RL_GRAVITY_NONE unless ROOTLESS_RESIZE_GRAVITY is set.
+ */
+typedef void (*RootlessResizeFrameProc)
+ (RootlessFrameID wid, ScreenPtr pScreen,
+ int newX, int newY, unsigned int newW, unsigned int newH,
+ unsigned int gravity);
+
+/*
+ * Change frame ordering (AKA stacking, layering).
+ * Drawing is stopped before this is called. Unmapped frames are mapped by
+ * setting their ordering.
+ *
+ * wid Frame id
+ * nextWid Frame id of frame that is now above this one or NULL if this
+ * frame is at the top.
+ */
+typedef void (*RootlessRestackFrameProc)
+ (RootlessFrameID wid, RootlessFrameID nextWid);
+
+/*
+ * Change frame's shape.
+ * Drawing is stopped before this is called.
+ *
+ * wid Frame id
+ * pNewShape New shape for the frame (in frame-local coordinates)
+ * or NULL if now unshaped.
+ */
+typedef void (*RootlessReshapeFrameProc)
+ (RootlessFrameID wid, RegionPtr pNewShape);
+
+/*
+ * Unmap a frame.
+ *
+ * wid Frame id
+ */
+typedef void (*RootlessUnmapFrameProc)
+ (RootlessFrameID wid);
+
+/*
+ * Start drawing to a frame.
+ * Prepare a frame for direct access to its backing buffer.
+ *
+ * wid Frame id
+ * pixelData Address of the backing buffer (returned)
+ * bytesPerRow Width in bytes of the backing buffer (returned)
+ */
+typedef void (*RootlessStartDrawingProc)
+ (RootlessFrameID wid, char **pixelData, int *bytesPerRow);
+
+/*
+ * Stop drawing to a frame.
+ * No drawing to the frame's backing buffer will occur until drawing
+ * is started again.
+ *
+ * wid Frame id
+ * flush Flush drawing updates for this frame to the screen. This
+ * will always be FALSE if ROOTLESS_TRACK_DAMAGE is set.
+ */
+typedef void (*RootlessStopDrawingProc)
+ (RootlessFrameID wid, Bool flush);
+
+/*
+ * Flush drawing updates to the screen.
+ * Drawing is stopped before this is called.
+ *
+ * wid Frame id
+ * pDamage Region containing all the changed pixels in frame-local
+ * coordinates. This is clipped to the window's clip. This
+ * will be NULL if ROOTLESS_TRACK_DAMAGE is not set.
+ */
+typedef void (*RootlessUpdateRegionProc)
+ (RootlessFrameID wid, RegionPtr pDamage);
+
+/*
+ * Mark damaged rectangles as requiring redisplay to screen.
+ * This will only be called if ROOTLESS_TRACK_DAMAGE is not set.
+ *
+ * wid Frame id
+ * nrects Number of damaged rectangles
+ * rects Array of damaged rectangles in frame-local coordinates
+ * shift_x, Vector to shift rectangles by
+ * shift_y
+ */
+typedef void (*RootlessDamageRectsProc)
+ (RootlessFrameID wid, int nrects, const BoxRec *rects,
+ int shift_x, int shift_y);
+
+/*
+ * Switch the window associated with a frame. (Optional)
+ * When a framed window is reparented, the frame is resized and set to
+ * use the new top-level parent. If defined this function will be called
+ * afterwards for implementation specific bookkeeping.
+ *
+ * pFrame Frame whose window has switched
+ * oldWin Previous window wrapped by this frame
+ */
+typedef void (*RootlessSwitchWindowProc)
+ (RootlessWindowPtr pFrame, WindowPtr oldWin);
+
+/*
+ * Copy bytes. (Optional)
+ * Source and destinate may overlap and the right thing should happen.
+ *
+ * width Bytes to copy per row
+ * height Number of rows
+ * src Source data
+ * srcRowBytes Width of source in bytes
+ * dst Destination data
+ * dstRowBytes Width of destination in bytes
+ */
+typedef void (*RootlessCopyBytesProc)
+ (unsigned int width, unsigned int height,
+ const void *src, unsigned int srcRowBytes,
+ void *dst, unsigned int dstRowBytes);
+
+/*
+ * Fill memory with 32-bit pattern. (Optional)
+ *
+ * width Bytes to fill per row
+ * height Number of rows
+ * value 32-bit pattern to fill with
+ * dst Destination data
+ * dstRowBytes Width of destination in bytes
+ */
+typedef void (*RootlessFillBytesProc)
+ (unsigned int width, unsigned int height, unsigned int value,
+ void *dst, unsigned int dstRowBytes);
+
+/*
+ * Composite pixels from source and mask to destination. (Optional)
+ *
+ * width, height Size of area to composite to in pizels
+ * function Composite function built with RL_COMPOSITE_FUNCTION
+ * src Source data
+ * srcRowBytes Width of source in bytes (Passing NULL means source
+ * is a single pixel.
+ * mask Mask data
+ * maskRowBytes Width of mask in bytes
+ * dst Destination data
+ * dstRowBytes Width of destination in bytes
+ *
+ * For src and dst, the first element of the array is the color data. If
+ * the second element is non-null it implies there is alpha data (which
+ * may be meshed or planar). Data without alpha is assumed to be opaque.
+ *
+ * An X11 error code is returned.
+ */
+typedef int (*RootlessCompositePixelsProc)
+ (unsigned int width, unsigned int height, unsigned int function,
+ void *src[2], unsigned int srcRowBytes[2],
+ void *mask, unsigned int maskRowBytes,
+ void *dst[2], unsigned int dstRowBytes[2]);
+
+/*
+ * Copy area in frame to another part of frame. (Optional)
+ *
+ * wid Frame id
+ * dstNrects Number of rectangles to copy
+ * dstRects Array of rectangles to copy
+ * dx, dy Number of pixels away to copy area
+ */
+typedef void (*RootlessCopyWindowProc)
+ (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
+ int dx, int dy);
+
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
new file mode 100755
index 000000000..2464f1abb
--- /dev/null
+++ b/xfixes/cursor.c
@@ -0,0 +1,752 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "xfixesint.h"
+#include "scrnintstr.h"
+#include "cursorstr.h"
+#include "dixevents.h"
+#include "servermd.h"
+#include "inputstr.h"
+#include "windowstr.h"
+
+static RESTYPE CursorClientType;
+static RESTYPE CursorWindowType;
+static int CursorScreenPrivateIndex = -1;
+static int CursorGeneration;
+static CursorPtr CursorCurrent;
+
+#define VERIFY_CURSOR(pCursor, cursor, client, access) { \
+ pCursor = (CursorPtr)SecurityLookupIDByType((client), (cursor), \
+ RT_CURSOR, (access)); \
+ if (!pCursor) { \
+ (client)->errorValue = (cursor); \
+ return BadCursor; \
+ } \
+}
+
+/*
+ * There is a global list of windows selecting for cursor events
+ */
+
+typedef struct _CursorEvent *CursorEventPtr;
+
+typedef struct _CursorEvent {
+ CursorEventPtr next;
+ CARD32 eventMask;
+ ClientPtr pClient;
+ WindowPtr pWindow;
+ XID clientResource;
+} CursorEventRec;
+
+static CursorEventPtr cursorEvents;
+
+/*
+ * Wrap DisplayCursor to catch cursor change events
+ */
+
+typedef struct _CursorScreen {
+ DisplayCursorProcPtr DisplayCursor;
+ CloseScreenProcPtr CloseScreen;
+} CursorScreenRec, *CursorScreenPtr;
+
+#define GetCursorScreen(s) ((CursorScreenPtr) ((s)->devPrivates[CursorScreenPrivateIndex].ptr))
+#define GetCursorScreenIfSet(s) ((CursorScreenPrivateIndex != -1) ? GetCursorScreen(s) : NULL)
+#define SetCursorScreen(s,p) ((s)->devPrivates[CursorScreenPrivateIndex].ptr = (pointer) (p))
+#define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func)
+#define Unwrap(as,s,elt) ((s)->elt = (as)->elt)
+
+static Bool
+CursorDisplayCursor (ScreenPtr pScreen,
+ CursorPtr pCursor)
+{
+ CursorScreenPtr cs = GetCursorScreen(pScreen);
+ Bool ret;
+
+ Unwrap (cs, pScreen, DisplayCursor);
+ ret = (*pScreen->DisplayCursor) (pScreen, pCursor);
+ if (pCursor != CursorCurrent)
+ {
+ CursorEventPtr e;
+
+ CursorCurrent = pCursor;
+ for (e = cursorEvents; e; e = e->next)
+ {
+ if (e->eventMask & XFixesDisplayCursorNotifyMask)
+ {
+ xXFixesCursorNotifyEvent ev;
+ ev.type = XFixesEventBase + XFixesCursorNotify;
+ ev.subtype = XFixesDisplayCursorNotify;
+ ev.sequenceNumber = e->pClient->sequence;
+ ev.window = e->pWindow->drawable.id;
+ ev.cursorSerial = pCursor->serialNumber;
+ ev.timestamp = currentTime.milliseconds;
+ ev.name = pCursor->name;
+ WriteEventsToClient (e->pClient, 1, (xEvent *) &ev);
+ }
+ }
+ }
+ Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
+ return ret;
+}
+
+static Bool
+CursorCloseScreen (int index, ScreenPtr pScreen)
+{
+ CursorScreenPtr cs = GetCursorScreen (pScreen);
+ Bool ret;
+
+ Unwrap (cs, pScreen, CloseScreen);
+ Unwrap (cs, pScreen, DisplayCursor);
+ ret = (*pScreen->CloseScreen) (index, pScreen);
+ xfree (cs);
+ if (index == 0)
+ CursorScreenPrivateIndex = -1;
+ return ret;
+}
+
+#define CursorAllEvents (XFixesDisplayCursorNotifyMask)
+
+static int
+XFixesSelectCursorInput (ClientPtr pClient,
+ WindowPtr pWindow,
+ CARD32 eventMask)
+{
+ CursorEventPtr *prev, e;
+
+ for (prev = &cursorEvents; (e = *prev); prev = &e->next)
+ {
+ if (e->pClient == pClient &&
+ e->pWindow == pWindow)
+ {
+ break;
+ }
+ }
+ if (!eventMask)
+ {
+ if (e)
+ {
+ FreeResource (e->clientResource, 0);
+ }
+ return Success;
+ }
+ if (!e)
+ {
+ e = (CursorEventPtr) xalloc (sizeof (CursorEventRec));
+ if (!e)
+ return BadAlloc;
+
+ e->next = 0;
+ e->pClient = pClient;
+ e->pWindow = pWindow;
+ e->clientResource = FakeClientID(pClient->index);
+
+ /*
+ * Add a resource hanging from the window to
+ * catch window destroy
+ */
+ if (!LookupIDByType(pWindow->drawable.id, CursorWindowType))
+ if (!AddResource (pWindow->drawable.id, CursorWindowType,
+ (pointer) pWindow))
+ {
+ xfree (e);
+ return BadAlloc;
+ }
+
+ if (!AddResource (e->clientResource, CursorClientType, (pointer) e))
+ return BadAlloc;
+
+ *prev = e;
+ }
+ e->eventMask = eventMask;
+ return Success;
+}
+
+int
+ProcXFixesSelectCursorInput (ClientPtr client)
+{
+ REQUEST (xXFixesSelectCursorInputReq);
+ WindowPtr pWin;
+
+ REQUEST_SIZE_MATCH (xXFixesSelectCursorInputReq);
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+ SecurityReadAccess);
+ if (!pWin)
+ return(BadWindow);
+ if (stuff->eventMask & ~CursorAllEvents)
+ {
+ client->errorValue = stuff->eventMask;
+ return( BadValue );
+ }
+ return XFixesSelectCursorInput (client, pWin, stuff->eventMask);
+}
+
+static int
+GetBit (unsigned char *line, int x)
+{
+ unsigned char mask;
+
+ if (screenInfo.bitmapBitOrder == LSBFirst)
+ mask = (1 << (x & 7));
+ else
+ mask = (0x80 >> (x & 7));
+ /* XXX assumes byte order is host byte order */
+ line += (x >> 3);
+ if (*line & mask)
+ return 1;
+ return 0;
+}
+
+int
+SProcXFixesSelectCursorInput (ClientPtr client)
+{
+ register int n;
+ REQUEST(xXFixesSelectCursorInputReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->window, n);
+ swapl(&stuff->eventMask, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+void
+SXFixesCursorNotifyEvent (xXFixesCursorNotifyEvent *from,
+ xXFixesCursorNotifyEvent *to)
+{
+ to->type = from->type;
+ cpswaps (from->sequenceNumber, to->sequenceNumber);
+ cpswapl (from->window, to->window);
+ cpswapl (from->cursorSerial, to->cursorSerial);
+ cpswapl (from->timestamp, to->timestamp);
+ cpswapl (from->name, to->name);
+}
+
+static void
+CopyCursorToImage (CursorPtr pCursor, CARD32 *image)
+{
+ int width = pCursor->bits->width;
+ int height = pCursor->bits->height;
+ int npixels = width * height;
+
+#ifdef ARGB_CURSOR
+ if (pCursor->bits->argb)
+ memcpy (image, pCursor->bits->argb, npixels * sizeof (CARD32));
+ else
+#endif
+ {
+ unsigned char *srcLine = pCursor->bits->source;
+ unsigned char *mskLine = pCursor->bits->mask;
+ int stride = BitmapBytePad (width);
+ int x, y;
+ CARD32 fg, bg;
+
+ fg = (0xff000000 |
+ ((pCursor->foreRed & 0xff00) << 8) |
+ (pCursor->foreGreen & 0xff00) |
+ (pCursor->foreBlue >> 8));
+ bg = (0xff000000 |
+ ((pCursor->backRed & 0xff00) << 8) |
+ (pCursor->backGreen & 0xff00) |
+ (pCursor->backBlue >> 8));
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < width; x++)
+ {
+ if (GetBit (mskLine, x))
+ {
+ if (GetBit (srcLine, x))
+ *image++ = fg;
+ else
+ *image++ = bg;
+ }
+ else
+ *image++ = 0;
+ }
+ srcLine += stride;
+ mskLine += stride;
+ }
+ }
+}
+
+int
+ProcXFixesGetCursorImage (ClientPtr client)
+{
+/* REQUEST(xXFixesGetCursorImageReq); */
+ xXFixesGetCursorImageReply *rep;
+ CursorPtr pCursor;
+ CARD32 *image;
+ int npixels;
+ int width, height;
+ int x, y;
+
+ REQUEST_SIZE_MATCH(xXFixesGetCursorImageReq);
+ pCursor = CursorCurrent;
+ if (!pCursor)
+ return BadCursor;
+ GetSpritePosition (&x, &y);
+ width = pCursor->bits->width;
+ height = pCursor->bits->height;
+ npixels = width * height;
+ rep = xalloc (sizeof (xXFixesGetCursorImageReply) +
+ npixels * sizeof (CARD32));
+ if (!rep)
+ return BadAlloc;
+
+ rep->type = X_Reply;
+ rep->sequenceNumber = client->sequence;
+ rep->length = npixels;
+ rep->width = width;
+ rep->height = height;
+ rep->x = x;
+ rep->y = y;
+ rep->xhot = pCursor->bits->xhot;
+ rep->yhot = pCursor->bits->yhot;
+ rep->cursorSerial = pCursor->serialNumber;
+
+ image = (CARD32 *) (rep + 1);
+ CopyCursorToImage (pCursor, image);
+ if (client->swapped)
+ {
+ int n;
+ swaps (&rep->sequenceNumber, n);
+ swapl (&rep->length, n);
+ swaps (&rep->x, n);
+ swaps (&rep->y, n);
+ swaps (&rep->width, n);
+ swaps (&rep->height, n);
+ swaps (&rep->xhot, n);
+ swaps (&rep->yhot, n);
+ swapl (&rep->cursorSerial, n);
+ SwapLongs (image, npixels);
+ }
+ (void) WriteToClient(client, sizeof (xXFixesGetCursorImageReply) +
+ (npixels << 2), (char *) rep);
+ xfree (rep);
+ return client->noClientException;
+}
+
+int
+SProcXFixesGetCursorImage (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesGetCursorImageReq);
+ swaps (&stuff->length, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesSetCursorName (ClientPtr client)
+{
+ CursorPtr pCursor;
+ char *tchar;
+ REQUEST(xXFixesSetCursorNameReq);
+ Atom atom;
+
+ REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq);
+ VERIFY_CURSOR(pCursor, stuff->cursor, client, SecurityWriteAccess);
+ tchar = (char *) &stuff[1];
+ atom = MakeAtom (tchar, stuff->nbytes, TRUE);
+ if (atom == BAD_RESOURCE)
+ return BadAlloc;
+
+ pCursor->name = atom;
+ return(client->noClientException);
+}
+
+int
+SProcXFixesSetCursorName (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesSetCursorNameReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq);
+ swapl (&stuff->cursor, n);
+ swaps (&stuff->nbytes, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesGetCursorName (ClientPtr client)
+{
+ CursorPtr pCursor;
+ xXFixesGetCursorNameReply reply;
+ REQUEST(xXFixesGetCursorNameReq);
+ char *str;
+ int len;
+
+ REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
+ VERIFY_CURSOR(pCursor, stuff->cursor, client, SecurityReadAccess);
+ if (pCursor->name)
+ str = NameForAtom (pCursor->name);
+ else
+ str = "";
+ len = strlen (str);
+
+ reply.type = X_Reply;
+ reply.length = (len + 3) >> 2;
+ reply.sequenceNumber = client->sequence;
+ reply.atom = pCursor->name;
+ reply.nbytes = len;
+ if (client->swapped)
+ {
+ int n;
+ swaps (&reply.sequenceNumber, n);
+ swapl (&reply.length, n);
+ swapl (&reply.atom, n);
+ swaps (&reply.nbytes, n);
+ }
+ WriteReplyToClient(client, sizeof(xXFixesGetCursorNameReply), &reply);
+ (void)WriteToClient(client, len, str);
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesGetCursorName (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesSetCursorNameReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
+ swapl (&stuff->cursor, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesGetCursorImageAndName (ClientPtr client)
+{
+/* REQUEST(xXFixesGetCursorImageAndNameReq); */
+ xXFixesGetCursorImageAndNameReply *rep;
+ CursorPtr pCursor;
+ CARD32 *image;
+ int npixels;
+ char *name;
+ int nbytes, nbytesRound;
+ int width, height;
+ int x, y;
+
+ REQUEST_SIZE_MATCH(xXFixesGetCursorImageAndNameReq);
+ pCursor = CursorCurrent;
+ if (!pCursor)
+ return BadCursor;
+ GetSpritePosition (&x, &y);
+ width = pCursor->bits->width;
+ height = pCursor->bits->height;
+ npixels = width * height;
+ name = pCursor->name ? NameForAtom (pCursor->name) : "";
+ nbytes = strlen (name);
+ nbytesRound = (nbytes + 3) & ~3;
+ rep = xalloc (sizeof (xXFixesGetCursorImageAndNameReply) +
+ npixels * sizeof (CARD32) + nbytesRound);
+ if (!rep)
+ return BadAlloc;
+
+ rep->type = X_Reply;
+ rep->sequenceNumber = client->sequence;
+ rep->length = npixels + (nbytesRound >> 2);
+ rep->width = width;
+ rep->height = height;
+ rep->x = x;
+ rep->y = y;
+ rep->xhot = pCursor->bits->xhot;
+ rep->yhot = pCursor->bits->yhot;
+ rep->cursorSerial = pCursor->serialNumber;
+ rep->cursorName = pCursor->name;
+ rep->nbytes = nbytes;
+
+ image = (CARD32 *) (rep + 1);
+ CopyCursorToImage (pCursor, image);
+ memcpy ((image + npixels), name, nbytes);
+ if (client->swapped)
+ {
+ int n;
+ swaps (&rep->sequenceNumber, n);
+ swapl (&rep->length, n);
+ swaps (&rep->x, n);
+ swaps (&rep->y, n);
+ swaps (&rep->width, n);
+ swaps (&rep->height, n);
+ swaps (&rep->xhot, n);
+ swaps (&rep->yhot, n);
+ swapl (&rep->cursorSerial, n);
+ swapl (&rep->cursorName, n);
+ swaps (&rep->nbytes, n);
+ SwapLongs (image, npixels);
+ }
+ (void) WriteToClient(client, sizeof (xXFixesGetCursorImageAndNameReply) +
+ (npixels << 2) + nbytesRound, (char *) rep);
+ xfree (rep);
+ return client->noClientException;
+}
+
+int
+SProcXFixesGetCursorImageAndName (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesGetCursorImageAndNameReq);
+ swaps (&stuff->length, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+/*
+ * Find every cursor reference in the system, ask testCursor
+ * whether it should be replaced with a reference to pCursor.
+ */
+
+typedef Bool (*TestCursorFunc) (CursorPtr pOld, pointer closure);
+
+typedef struct {
+ RESTYPE type;
+ TestCursorFunc testCursor;
+ CursorPtr pNew;
+ pointer closure;
+} ReplaceCursorLookupRec, *ReplaceCursorLookupPtr;
+
+static const RESTYPE CursorRestypes[] = {
+ RT_WINDOW, RT_PASSIVEGRAB, RT_CURSOR
+};
+
+#define NUM_CURSOR_RESTYPES (sizeof (CursorRestypes) / sizeof (CursorRestypes[0]))
+
+static Bool
+ReplaceCursorLookup (pointer value, XID id, pointer closure)
+{
+ ReplaceCursorLookupPtr rcl = (ReplaceCursorLookupPtr) closure;
+ WindowPtr pWin;
+ GrabPtr pGrab;
+ CursorPtr pCursor = 0, *pCursorRef = 0;
+ XID cursor = 0;
+
+ switch (rcl->type) {
+ case RT_WINDOW:
+ pWin = (WindowPtr) value;
+ if (pWin->optional)
+ {
+ pCursorRef = &pWin->optional->cursor;
+ pCursor = *pCursorRef;
+ }
+ break;
+ case RT_PASSIVEGRAB:
+ pGrab = (GrabPtr) value;
+ pCursorRef = &pGrab->cursor;
+ pCursor = *pCursorRef;
+ break;
+ case RT_CURSOR:
+ pCursorRef = 0;
+ pCursor = (CursorPtr) value;
+ cursor = id;
+ break;
+ }
+ if (pCursor && pCursor != rcl->pNew)
+ {
+ if ((*rcl->testCursor) (pCursor, rcl->closure))
+ {
+ rcl->pNew->refcnt++;
+ /* either redirect reference or update resource database */
+ if (pCursorRef)
+ *pCursorRef = rcl->pNew;
+ else
+ ChangeResourceValue (id, RT_CURSOR, rcl->pNew);
+ FreeCursor (pCursor, cursor);
+ }
+ }
+ return FALSE; /* keep walking */
+}
+
+static void
+ReplaceCursor (CursorPtr pCursor,
+ TestCursorFunc testCursor,
+ pointer closure)
+{
+ int clientIndex;
+ int resIndex;
+ ReplaceCursorLookupRec rcl;
+
+ /*
+ * Cursors exist only in the resource database, windows and grabs.
+ * All of these are always pointed at by the resource database. Walk
+ * the whole thing looking for cursors
+ */
+ rcl.testCursor = testCursor;
+ rcl.pNew = pCursor;
+ rcl.closure = closure;
+
+ /* for each client */
+ for (clientIndex = 0; clientIndex < currentMaxClients; clientIndex++)
+ {
+ if (!clients[clientIndex])
+ continue;
+ for (resIndex = 0; resIndex < NUM_CURSOR_RESTYPES; resIndex++)
+ {
+ rcl.type = CursorRestypes[resIndex];
+ /*
+ * This function walks the entire client resource database
+ */
+ LookupClientResourceComplex (clients[clientIndex],
+ rcl.type,
+ ReplaceCursorLookup,
+ (pointer) &rcl);
+ }
+ }
+ /* this "knows" that WindowHasNewCursor doesn't depend on it's argument */
+ WindowHasNewCursor (WindowTable[0]);
+}
+
+static Bool
+TestForCursor (CursorPtr pCursor, pointer closure)
+{
+ return (pCursor == (CursorPtr) closure);
+}
+
+int
+ProcXFixesChangeCursor (ClientPtr client)
+{
+ CursorPtr pSource, pDestination;
+ REQUEST(xXFixesChangeCursorReq);
+
+ REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
+ VERIFY_CURSOR (pSource, stuff->source, client, SecurityReadAccess);
+ VERIFY_CURSOR (pDestination, stuff->destination, client, SecurityWriteAccess);
+
+ ReplaceCursor (pSource, TestForCursor, (pointer) pDestination);
+ return (client->noClientException);
+}
+
+int
+SProcXFixesChangeCursor (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesChangeCursorReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
+ swapl (&stuff->source, n);
+ swapl (&stuff->destination, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+static Bool
+TestForCursorName (CursorPtr pCursor, pointer closure)
+{
+ return (pCursor->name == (Atom) closure);
+}
+
+int
+ProcXFixesChangeCursorByName (ClientPtr client)
+{
+ CursorPtr pSource;
+ Atom name;
+ char *tchar;
+ REQUEST(xXFixesChangeCursorByNameReq);
+
+ REQUEST_FIXED_SIZE(xXFixesChangeCursorByNameReq, stuff->nbytes);
+ VERIFY_CURSOR(pSource, stuff->source, client, SecurityReadAccess);
+ tchar = (char *) &stuff[1];
+ name = MakeAtom (tchar, stuff->nbytes, FALSE);
+ if (name)
+ ReplaceCursor (pSource, TestForCursorName, (pointer) name);
+ return (client->noClientException);
+}
+
+int
+SProcXFixesChangeCursorByName (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesChangeCursorByNameReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE (xXFixesChangeCursorByNameReq);
+ swapl (&stuff->source, n);
+ swaps (&stuff->nbytes, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+static int
+CursorFreeClient (pointer data, XID id)
+{
+ CursorEventPtr old = (CursorEventPtr) data;
+ CursorEventPtr *prev, e;
+
+ for (prev = &cursorEvents; (e = *prev); prev = &e->next)
+ {
+ if (e == old)
+ {
+ *prev = e->next;
+ xfree (e);
+ break;
+ }
+ }
+ return 1;
+}
+
+static int
+CursorFreeWindow (pointer data, XID id)
+{
+ WindowPtr pWindow = (WindowPtr) data;
+ CursorEventPtr e, next;
+
+ for (e = cursorEvents; e; e = next)
+ {
+ next = e->next;
+ if (e->pWindow == pWindow)
+ {
+ FreeResource (e->clientResource, 0);
+ }
+ }
+ return 1;
+}
+
+Bool
+XFixesCursorInit (void)
+{
+ int i;
+
+ if (CursorGeneration != serverGeneration)
+ {
+ CursorScreenPrivateIndex = AllocateScreenPrivateIndex ();
+ if (CursorScreenPrivateIndex < 0)
+ return FALSE;
+ CursorGeneration = serverGeneration;
+ }
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ CursorScreenPtr cs;
+
+ cs = (CursorScreenPtr) xalloc (sizeof (CursorScreenRec));
+ if (!cs)
+ return FALSE;
+ Wrap (cs, pScreen, CloseScreen, CursorCloseScreen);
+ Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
+ SetCursorScreen (pScreen, cs);
+ }
+ CursorClientType = CreateNewResourceType(CursorFreeClient);
+ CursorWindowType = CreateNewResourceType(CursorFreeWindow);
+ return CursorClientType && CursorWindowType;
+}
+
diff --git a/xfixes/region.c b/xfixes/region.c
new file mode 100755
index 000000000..d80776d8c
--- /dev/null
+++ b/xfixes/region.c
@@ -0,0 +1,850 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2003 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "xfixesint.h"
+#include "scrnintstr.h"
+#ifdef RENDER
+#include <picturestr.h>
+extern int RenderErrBase;
+#endif
+#include <regionstr.h>
+#include <gcstruct.h>
+#include <window.h>
+
+RESTYPE RegionResType;
+
+static int
+RegionResFree (pointer data, XID id)
+{
+ RegionPtr pRegion = (RegionPtr) data;
+
+ REGION_DESTROY (0, pRegion);
+ return Success;
+}
+
+RegionPtr
+XFixesRegionCopy (RegionPtr pRegion)
+{
+ RegionPtr pNew = REGION_CREATE (0, REGION_EXTENTS(0, pRegion),
+ REGION_NUM_RECTS(pRegion));
+ if (!pNew)
+ return 0;
+ if (!REGION_COPY (0, pNew, pRegion))
+ {
+ REGION_DESTROY (0, pNew);
+ return 0;
+ }
+ return pNew;
+}
+
+Bool
+XFixesRegionInit (void)
+{
+ RegionResType = CreateNewResourceType(RegionResFree);
+ return TRUE;
+}
+
+int
+ProcXFixesCreateRegion (ClientPtr client)
+{
+ int things;
+ RegionPtr pRegion;
+ REQUEST (xXFixesCreateRegionReq);
+
+ REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq);
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+
+ things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq);
+ if (things & 4)
+ return BadLength;
+ things >>= 3;
+
+ pRegion = RECTS_TO_REGION(0, things, (xRectangle *) (stuff + 1), CT_UNSORTED);
+ if (!pRegion)
+ return BadAlloc;
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesCreateRegion (ClientPtr client)
+{
+ register int n;
+ REQUEST(xXFixesCreateRegionReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq);
+ swapl(&stuff->region, n);
+ SwapRestS(stuff);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCreateRegionFromBitmap (ClientPtr client)
+{
+ RegionPtr pRegion;
+ PixmapPtr pPixmap;
+ REQUEST (xXFixesCreateRegionFromBitmapReq);
+
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromBitmapReq);
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+
+ pPixmap = (PixmapPtr) SecurityLookupIDByType (client, stuff->bitmap,
+ RT_PIXMAP,
+ SecurityReadAccess);
+ if (!pPixmap)
+ {
+ client->errorValue = stuff->bitmap;
+ return BadPixmap;
+ }
+ if (pPixmap->drawable.depth != 1)
+ return BadMatch;
+
+ pRegion = BITMAP_TO_REGION(pPixmap->drawable.pScreen, pPixmap);
+
+ if (!pRegion)
+ return BadAlloc;
+
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesCreateRegionFromBitmap (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCreateRegionFromBitmapReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromBitmapReq);
+ swapl(&stuff->region, n);
+ swapl(&stuff->bitmap, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCreateRegionFromWindow (ClientPtr client)
+{
+ RegionPtr pRegion;
+ Bool copy = TRUE;
+ WindowPtr pWin;
+ REQUEST (xXFixesCreateRegionFromWindowReq);
+
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromWindowReq);
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+ switch (stuff->kind) {
+ case WindowRegionBounding:
+#ifdef SHAPE
+ pRegion = wBoundingShape(pWin);
+ if (!pRegion)
+#endif
+ {
+ pRegion = CreateBoundingShape (pWin);
+ copy = FALSE;
+ }
+ break;
+ case WindowRegionClip:
+#ifdef SHAPE
+ pRegion = wClipShape(pWin);
+ if (!pRegion)
+#endif
+ {
+ pRegion = CreateClipShape (pWin);
+ copy = FALSE;
+ }
+ break;
+ default:
+ client->errorValue = stuff->kind;
+ return BadValue;
+ }
+ if (copy && pRegion)
+ pRegion = XFixesRegionCopy (pRegion);
+ if (!pRegion)
+ return BadAlloc;
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesCreateRegionFromWindow (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCreateRegionFromWindowReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromWindowReq);
+ swapl(&stuff->region, n);
+ swapl(&stuff->window, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCreateRegionFromGC (ClientPtr client)
+{
+ RegionPtr pRegion, pClip;
+ GCPtr pGC;
+ REQUEST (xXFixesCreateRegionFromGCReq);
+
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromGCReq);
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+
+ SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityReadAccess);
+
+ switch (pGC->clientClipType) {
+ case CT_PIXMAP:
+ pRegion = BITMAP_TO_REGION(pGC->pScreen, (PixmapPtr) pGC->clientClip);
+ if (!pRegion)
+ return BadAlloc;
+ break;
+ case CT_REGION:
+ pClip = (RegionPtr) pGC->clientClip;
+ pRegion = XFixesRegionCopy (pClip);
+ if (!pRegion)
+ return BadAlloc;
+ break;
+ default:
+ return BadImplementation; /* assume sane server bits */
+ }
+
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesCreateRegionFromGC (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCreateRegionFromGCReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromGCReq);
+ swapl(&stuff->region, n);
+ swapl(&stuff->gc, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCreateRegionFromPicture (ClientPtr client)
+{
+#ifdef RENDER
+ RegionPtr pRegion;
+ PicturePtr pPicture;
+ REQUEST (xXFixesCreateRegionFromPictureReq);
+
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromPictureReq);
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+
+ VERIFY_PICTURE(pPicture, stuff->picture, client, SecurityReadAccess,
+ RenderErrBase + BadPicture);
+
+ switch (pPicture->clientClipType) {
+ case CT_PIXMAP:
+ pRegion = BITMAP_TO_REGION(pPicture->pDrawable->pScreen,
+ (PixmapPtr) pPicture->clientClip);
+ if (!pRegion)
+ return BadAlloc;
+ break;
+ case CT_REGION:
+ pRegion = XFixesRegionCopy ((RegionPtr) pPicture->clientClip);
+ if (!pRegion)
+ return BadAlloc;
+ break;
+ default:
+ return BadImplementation; /* assume sane server bits */
+ }
+
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+#else
+ return BadRequest;
+#endif
+}
+
+int
+SProcXFixesCreateRegionFromPicture (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCreateRegionFromPictureReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromPictureReq);
+ swapl(&stuff->region, n);
+ swapl(&stuff->picture, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesDestroyRegion (ClientPtr client)
+{
+ REQUEST (xXFixesDestroyRegionReq);
+ RegionPtr pRegion;
+
+ REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq);
+ VERIFY_REGION(pRegion, stuff->region, client, SecurityWriteAccess);
+ FreeResource (stuff->region, RT_NONE);
+ return(client->noClientException);
+}
+
+int
+SProcXFixesDestroyRegion (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesDestroyRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq);
+ swapl (&stuff->region, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesSetRegion (ClientPtr client)
+{
+ int things;
+ RegionPtr pRegion, pNew;
+ REQUEST (xXFixesSetRegionReq);
+
+ REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq);
+ VERIFY_REGION(pRegion, stuff->region, client, SecurityWriteAccess);
+
+ things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq);
+ if (things & 4)
+ return BadLength;
+ things >>= 3;
+
+ pNew = RECTS_TO_REGION(0, things, (xRectangle *) (stuff + 1), CT_UNSORTED);
+ if (!pNew)
+ return BadAlloc;
+ if (!REGION_COPY (0, pRegion, pNew))
+ {
+ REGION_DESTROY (0, pNew);
+ return BadAlloc;
+ }
+ REGION_DESTROY (0, pNew);
+ return(client->noClientException);
+}
+
+int
+SProcXFixesSetRegion (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesSetRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq);
+ swapl (&stuff->region, n);
+ SwapRestS(stuff);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCopyRegion (ClientPtr client)
+{
+ RegionPtr pSource, pDestination;
+ REQUEST (xXFixesCopyRegionReq);
+
+ VERIFY_REGION(pSource, stuff->source, client, SecurityReadAccess);
+ VERIFY_REGION(pDestination, stuff->destination, client, SecurityWriteAccess);
+
+ if (!REGION_COPY(pScreen, pDestination, pSource))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesCopyRegion (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCopyRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xXFixesCopyRegionReq);
+ swapl (&stuff->source, n);
+ swapl (&stuff->destination, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCombineRegion (ClientPtr client)
+{
+ RegionPtr pSource1, pSource2, pDestination;
+ int ret = Success;
+ REQUEST (xXFixesCombineRegionReq);
+
+ REQUEST_SIZE_MATCH (xXFixesCombineRegionReq);
+ VERIFY_REGION(pSource1, stuff->source1, client, SecurityReadAccess);
+ VERIFY_REGION(pSource2, stuff->source2, client, SecurityReadAccess);
+ VERIFY_REGION(pDestination, stuff->destination, client, SecurityWriteAccess);
+
+ switch (stuff->xfixesReqType) {
+ case X_XFixesUnionRegion:
+ if (!REGION_UNION (0, pDestination, pSource1, pSource2))
+ ret = BadAlloc;
+ break;
+ case X_XFixesIntersectRegion:
+ if (!REGION_INTERSECT (0, pDestination, pSource1, pSource2))
+ ret = BadAlloc;
+ break;
+ case X_XFixesSubtractRegion:
+ if (!REGION_SUBTRACT (0, pDestination, pSource1, pSource2))
+ ret = BadAlloc;
+ break;
+ }
+
+ if (ret == Success)
+ ret = client->noClientException;
+ return ret;
+}
+
+int
+SProcXFixesCombineRegion (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCombineRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesCombineRegionReq);
+ swapl (&stuff->source1, n);
+ swapl (&stuff->source2, n);
+ swapl (&stuff->destination, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesInvertRegion (ClientPtr client)
+{
+ RegionPtr pSource, pDestination;
+ BoxRec bounds;
+ int ret = Success;
+ REQUEST(xXFixesInvertRegionReq);
+
+ REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
+ VERIFY_REGION(pSource, stuff->source, client, SecurityReadAccess);
+ VERIFY_REGION(pDestination, stuff->destination, client, SecurityWriteAccess);
+
+ /* Compute bounds, limit to 16 bits */
+ bounds.x1 = stuff->x;
+ bounds.y1 = stuff->y;
+ if ((int) stuff->x + (int) stuff->width > MAXSHORT)
+ bounds.x2 = MAXSHORT;
+ else
+ bounds.x2 = stuff->x + stuff->width;
+
+ if ((int) stuff->y + (int) stuff->height > MAXSHORT)
+ bounds.y2 = MAXSHORT;
+ else
+ bounds.y2 = stuff->y + stuff->height;
+
+ if (!REGION_INVERSE(0, pDestination, pSource, &bounds))
+ ret = BadAlloc;
+
+ if (ret == Success)
+ ret = client->noClientException;
+ return ret;
+}
+
+int
+SProcXFixesInvertRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesInvertRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
+ swapl (&stuff->source, n);
+ swaps (&stuff->x, n);
+ swaps (&stuff->y, n);
+ swaps (&stuff->width, n);
+ swaps (&stuff->height, n);
+ swapl (&stuff->destination, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesTranslateRegion (ClientPtr client)
+{
+ RegionPtr pRegion;
+ REQUEST(xXFixesTranslateRegionReq);
+
+ REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
+ VERIFY_REGION(pRegion, stuff->region, client, SecurityWriteAccess);
+
+ REGION_TRANSLATE(pScreen, pRegion, stuff->dx, stuff->dy);
+ return (client->noClientException);
+}
+
+int
+SProcXFixesTranslateRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesTranslateRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
+ swapl (&stuff->region, n);
+ swaps (&stuff->dx, n);
+ swaps (&stuff->dy, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesRegionExtents (ClientPtr client)
+{
+ RegionPtr pSource, pDestination;
+ REQUEST(xXFixesRegionExtentsReq);
+
+ REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
+ VERIFY_REGION(pSource, stuff->source, client, SecurityReadAccess);
+ VERIFY_REGION(pDestination, stuff->destination, client, SecurityWriteAccess);
+
+ REGION_RESET (0, pDestination, REGION_EXTENTS (0, pSource));
+
+ return (client->noClientException);
+}
+
+int
+SProcXFixesRegionExtents (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesRegionExtentsReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
+ swapl (&stuff->source, n);
+ swapl (&stuff->destination, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesFetchRegion (ClientPtr client)
+{
+ RegionPtr pRegion;
+ xXFixesFetchRegionReply *reply;
+ xRectangle *pRect;
+ BoxPtr pExtent;
+ BoxPtr pBox;
+ int i, nBox;
+ REQUEST(xXFixesFetchRegionReq);
+
+ REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
+ VERIFY_REGION(pRegion, stuff->region, client, SecurityReadAccess);
+
+ pExtent = REGION_EXTENTS (0, pRegion);
+ pBox = REGION_RECTS (pRegion);
+ nBox = REGION_NUM_RECTS (pRegion);
+
+ reply = xalloc (sizeof (xXFixesFetchRegionReply) +
+ nBox * sizeof (xRectangle));
+ if (!reply)
+ return BadAlloc;
+ reply->type = X_Reply;
+ reply->sequenceNumber = client->sequence;
+ reply->length = nBox << 1;
+ reply->x = pExtent->x1;
+ reply->y = pExtent->y1;
+ reply->width = pExtent->x2 - pExtent->x1;
+ reply->height = pExtent->y2 - pExtent->y1;
+
+ pRect = (xRectangle *) (reply + 1);
+ for (i = 0; i < nBox; i++)
+ {
+ pRect[i].x = pBox[i].x1;
+ pRect[i].y = pBox[i].y1;
+ pRect[i].width = pBox[i].x2 - pBox[i].x1;
+ pRect[i].height = pBox[i].y2 - pBox[i].y1;
+ }
+ if (client->swapped)
+ {
+ int n;
+ swaps (&reply->sequenceNumber, n);
+ swapl (&reply->length, n);
+ swaps (&reply->x, n);
+ swaps (&reply->y, n);
+ swaps (&reply->width, n);
+ swaps (&reply->height, n);
+ SwapShorts ((INT16 *) pRect, nBox * 4);
+ }
+ (void) WriteToClient(client, sizeof (xXFixesFetchRegionReply) +
+ nBox * sizeof (xRectangle), (char *) reply);
+ xfree (reply);
+ return (client->noClientException);
+}
+
+int
+SProcXFixesFetchRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesFetchRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
+ swapl (&stuff->region, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesSetGCClipRegion (ClientPtr client)
+{
+ GCPtr pGC;
+ RegionPtr pRegion;
+ XID vals[2];
+ REQUEST(xXFixesSetGCClipRegionReq);
+
+ REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
+ SECURITY_VERIFY_GC(pGC, stuff->gc, client, SecurityWriteAccess);
+ VERIFY_REGION_OR_NONE (pRegion, stuff->region, client, SecurityReadAccess);
+
+ if (pRegion)
+ {
+ pRegion = XFixesRegionCopy (pRegion);
+ if (!pRegion)
+ return BadAlloc;
+ }
+
+ vals[0] = stuff->xOrigin;
+ vals[1] = stuff->yOrigin;
+ DoChangeGC (pGC, GCClipXOrigin|GCClipYOrigin, vals, 0);
+ (*pGC->funcs->ChangeClip)(pGC, pRegion ? CT_REGION : CT_NONE, (pointer)pRegion, 0);
+
+ return (client->noClientException);
+}
+
+int
+SProcXFixesSetGCClipRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesSetGCClipRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
+ swapl (&stuff->gc, n);
+ swapl (&stuff->region, n);
+ swaps (&stuff->xOrigin, n);
+ swaps (&stuff->yOrigin, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+typedef RegionPtr (*CreateDftPtr)(WindowPtr pWin);
+
+int
+ProcXFixesSetWindowShapeRegion (ClientPtr client)
+{
+#ifdef SHAPE
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ RegionPtr pRegion;
+ RegionPtr *pDestRegion;
+ int destBounding;
+ REQUEST(xXFixesSetWindowShapeRegionReq);
+
+ REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->dest, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->dest;
+ return BadWindow;
+ }
+ VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, SecurityWriteAccess);
+ switch (stuff->destKind) {
+ case ShapeBounding:
+ destBounding = 1;
+ break;
+ case ShapeClip:
+ destBounding = 0;
+ break;
+ default:
+ client->errorValue = stuff->destKind;
+ return BadValue;
+ }
+ pScreen = pWin->drawable.pScreen;
+ if (pRegion)
+ {
+ pRegion = XFixesRegionCopy (pRegion);
+ if (!pRegion)
+ return BadAlloc;
+ if (!pWin->optional)
+ MakeWindowOptional (pWin);
+ if (destBounding)
+ pDestRegion = &pWin->optional->boundingShape;
+ else
+ pDestRegion = &pWin->optional->clipShape;
+ if (stuff->xOff || stuff->yOff)
+ REGION_TRANSLATE (0, pRegion, stuff->xOff, stuff->yOff);
+ }
+ else
+ {
+ if (pWin->optional)
+ {
+ if (destBounding)
+ pDestRegion = &pWin->optional->boundingShape;
+ else
+ pDestRegion = &pWin->optional->clipShape;
+ }
+ else
+ pDestRegion = &pRegion; /* a NULL region pointer */
+ }
+ if (*pDestRegion)
+ REGION_DESTROY(pScreen, *pDestRegion);
+ *pDestRegion = pRegion;
+ (*pScreen->SetShape) (pWin);
+ SendShapeNotify (pWin, stuff->destKind);
+ return (client->noClientException);
+#else
+ return BadRequest;
+#endif
+}
+
+int
+SProcXFixesSetWindowShapeRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesSetWindowShapeRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
+ swapl (&stuff->dest, n);
+ swaps (&stuff->xOff, n);
+ swaps (&stuff->yOff, n);
+ swapl (&stuff->region, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesSetPictureClipRegion (ClientPtr client)
+{
+#ifdef RENDER
+ PicturePtr pPicture;
+ RegionPtr pRegion;
+ ScreenPtr pScreen;
+ PictureScreenPtr ps;
+ REQUEST(xXFixesSetPictureClipRegionReq);
+
+ REQUEST_SIZE_MATCH (xXFixesSetPictureClipRegionReq);
+ VERIFY_PICTURE(pPicture, stuff->picture, client, SecurityWriteAccess,
+ RenderErrBase + BadPicture);
+ pScreen = pPicture->pDrawable->pScreen;
+ ps = GetPictureScreen (pScreen);
+ VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, SecurityReadAccess);
+
+ return SetPictureClipRegion (pPicture, stuff->xOrigin, stuff->yOrigin,
+ pRegion);
+#else
+ return BadRequest;
+#endif
+}
+
+int
+SProcXFixesSetPictureClipRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesSetPictureClipRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesSetPictureClipRegionReq);
+ swapl (&stuff->picture, n);
+ swapl (&stuff->region, n);
+ swaps (&stuff->xOrigin, n);
+ swaps (&stuff->yOrigin, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesExpandRegion (ClientPtr client)
+{
+ RegionPtr pSource, pDestination;
+ int ret = Success;
+ REQUEST (xXFixesExpandRegionReq);
+ BoxPtr pTmp;
+ BoxPtr pSrc;
+ int nBoxes;
+ int i;
+
+ REQUEST_SIZE_MATCH (xXFixesExpandRegionReq);
+ VERIFY_REGION(pSource, stuff->source, client, SecurityReadAccess);
+ VERIFY_REGION(pDestination, stuff->destination, client, SecurityWriteAccess);
+
+ nBoxes = REGION_NUM_RECTS(pSource);
+ pSrc = REGION_RECTS(pSource);
+ if (nBoxes)
+ {
+ pTmp = xalloc (nBoxes * sizeof (BoxRec));
+ if (!pTmp)
+ return BadAlloc;
+ for (i = 0; i < nBoxes; i++)
+ {
+ pTmp[i].x1 = pSrc[i].x1 - stuff->left;
+ pTmp[i].x2 = pSrc[i].x2 + stuff->right;
+ pTmp[i].y1 = pSrc[i].y1 - stuff->top;
+ pTmp[i].y2 = pSrc[i].y2 + stuff->bottom;
+ }
+ REGION_EMPTY (pScreen, pDestination);
+ for (i = 0; i < nBoxes; i++)
+ {
+ RegionRec r;
+ REGION_INIT (pScreen, &r, &pTmp[i], 0);
+ REGION_UNION (pScreen, pDestination, pDestination, &r);
+ }
+ }
+ if (ret == Success)
+ ret = client->noClientException;
+ return ret;
+}
+
+int
+SProcXFixesExpandRegion (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesExpandRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesExpandRegionReq);
+ swapl (&stuff->source, n);
+ swapl (&stuff->destination, n);
+ swaps (&stuff->left, n);
+ swaps (&stuff->right, n);
+ swaps (&stuff->top, n);
+ swaps (&stuff->bottom, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
diff --git a/xfixes/saveset.c b/xfixes/saveset.c
new file mode 100755
index 000000000..83d8c12f1
--- /dev/null
+++ b/xfixes/saveset.c
@@ -0,0 +1,78 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "xfixesint.h"
+
+int
+ProcXFixesChangeSaveSet(ClientPtr client)
+{
+ Bool toRoot, remap;
+ int result;
+ WindowPtr pWin;
+ REQUEST(xXFixesChangeSaveSetReq);
+
+ REQUEST_SIZE_MATCH(xXFixesChangeSaveSetReq);
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+ SecurityReadAccess);
+ if (!pWin)
+ return(BadWindow);
+ if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
+ return BadMatch;
+ if ((stuff->mode != SetModeInsert) && (stuff->mode != SetModeDelete))
+ {
+ client->errorValue = stuff->mode;
+ return( BadValue );
+ }
+ if ((stuff->target != SaveSetNearest) && (stuff->target != SaveSetRoot))
+ {
+ client->errorValue = stuff->target;
+ return( BadValue );
+ }
+ if ((stuff->map != SaveSetMap) && (stuff->map != SaveSetUnmap))
+ {
+ client->errorValue = stuff->map;
+ return( BadValue );
+ }
+ toRoot = (stuff->target == SaveSetRoot);
+ remap = (stuff->map == SaveSetMap);
+ result = AlterSaveSetForClient(client, pWin, stuff->mode, toRoot, remap);
+ if (client->noClientException != Success)
+ return(client->noClientException);
+ else
+ return(result);
+}
+
+int
+SProcXFixesChangeSaveSet(ClientPtr client)
+{
+ register int n;
+ REQUEST(xXFixesChangeSaveSetReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->window, n);
+ return ProcXFixesChangeSaveSet(client);
+}
diff --git a/xfixes/select.c b/xfixes/select.c
new file mode 100755
index 000000000..6cccfa504
--- /dev/null
+++ b/xfixes/select.c
@@ -0,0 +1,278 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "xfixesint.h"
+
+static RESTYPE SelectionClientType, SelectionWindowType;
+static Bool SelectionCallbackRegistered = FALSE;
+
+/*
+ * There is a global list of windows selecting for selection events
+ * on every selection. This should be plenty efficient for the
+ * expected usage, if it does become a problem, it should be easily
+ * replaced with a hash table of some kind keyed off the selection atom
+ */
+
+typedef struct _SelectionEvent *SelectionEventPtr;
+
+typedef struct _SelectionEvent {
+ SelectionEventPtr next;
+ Atom selection;
+ CARD32 eventMask;
+ ClientPtr pClient;
+ WindowPtr pWindow;
+ XID clientResource;
+} SelectionEventRec;
+
+static SelectionEventPtr selectionEvents;
+
+static void
+XFixesSelectionCallback (CallbackListPtr *callbacks, pointer data, pointer args)
+{
+ SelectionEventPtr e;
+ SelectionInfoRec *info = (SelectionInfoRec *) args;
+ Selection *selection = info->selection;
+ int subtype;
+ CARD32 eventMask;
+
+ switch (info->kind) {
+ case SelectionSetOwner:
+ subtype = XFixesSetSelectionOwnerNotify;
+ eventMask = XFixesSetSelectionOwnerNotifyMask;
+ break;
+ case SelectionWindowDestroy:
+ subtype = XFixesSelectionWindowDestroyNotify;
+ eventMask = XFixesSelectionWindowDestroyNotifyMask;
+ break;
+ case SelectionClientClose:
+ subtype = XFixesSelectionClientCloseNotify;
+ eventMask = XFixesSelectionClientCloseNotifyMask;
+ break;
+ default:
+ return;
+ }
+ for (e = selectionEvents; e; e = e->next)
+ {
+ if (e->selection == selection->selection && (e->eventMask & eventMask))
+ {
+ xXFixesSelectionNotifyEvent ev;
+
+ ev.type = XFixesEventBase + XFixesSelectionNotify;
+ ev.subtype = subtype;
+ ev.sequenceNumber = e->pClient->sequence;
+ ev.window = e->pWindow->drawable.id;
+ if (subtype == XFixesSetSelectionOwnerNotify)
+ ev.owner = selection->window;
+ else
+ ev.owner = 0;
+ ev.selection = e->selection;
+ ev.timestamp = currentTime.milliseconds;
+ ev.selectionTimestamp = selection->lastTimeChanged.milliseconds;
+ WriteEventsToClient (e->pClient, 1, (xEvent *) &ev);
+ }
+ }
+}
+
+static Bool
+CheckSelectionCallback (void)
+{
+ if (selectionEvents)
+ {
+ if (!SelectionCallbackRegistered)
+ {
+ if (!AddCallback (&SelectionCallback, XFixesSelectionCallback, NULL))
+ return FALSE;
+ SelectionCallbackRegistered = TRUE;
+ }
+ }
+ else
+ {
+ if (SelectionCallbackRegistered)
+ {
+ DeleteCallback (&SelectionCallback, XFixesSelectionCallback, NULL);
+ SelectionCallbackRegistered = FALSE;
+ }
+ }
+ return TRUE;
+}
+
+#define SelectionAllEvents (XFixesSetSelectionOwnerNotifyMask |\
+ XFixesSelectionWindowDestroyNotifyMask |\
+ XFixesSelectionClientCloseNotifyMask)
+
+static int
+XFixesSelectSelectionInput (ClientPtr pClient,
+ Atom selection,
+ WindowPtr pWindow,
+ CARD32 eventMask)
+{
+ SelectionEventPtr *prev, e;
+
+ for (prev = &selectionEvents; (e = *prev); prev = &e->next)
+ {
+ if (e->selection == selection &&
+ e->pClient == pClient &&
+ e->pWindow == pWindow)
+ {
+ break;
+ }
+ }
+ if (!eventMask)
+ {
+ if (e)
+ {
+ FreeResource (e->clientResource, 0);
+ }
+ return Success;
+ }
+ if (!e)
+ {
+ e = (SelectionEventPtr) xalloc (sizeof (SelectionEventRec));
+ if (!e)
+ return BadAlloc;
+
+ e->next = 0;
+ e->selection = selection;
+ e->pClient = pClient;
+ e->pWindow = pWindow;
+ e->clientResource = FakeClientID(pClient->index);
+
+ /*
+ * Add a resource hanging from the window to
+ * catch window destroy
+ */
+ if (!LookupIDByType(pWindow->drawable.id, SelectionWindowType))
+ if (!AddResource (pWindow->drawable.id, SelectionWindowType,
+ (pointer) pWindow))
+ {
+ xfree (e);
+ return BadAlloc;
+ }
+
+ if (!AddResource (e->clientResource, SelectionClientType, (pointer) e))
+ return BadAlloc;
+
+ *prev = e;
+ if (!CheckSelectionCallback ())
+ {
+ FreeResource (e->clientResource, 0);
+ return BadAlloc;
+ }
+ }
+ e->eventMask = eventMask;
+ return Success;
+}
+
+int
+ProcXFixesSelectSelectionInput (ClientPtr client)
+{
+ REQUEST (xXFixesSelectSelectionInputReq);
+ WindowPtr pWin;
+
+ REQUEST_SIZE_MATCH (xXFixesSelectSelectionInputReq);
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+ SecurityReadAccess);
+ if (!pWin)
+ return(BadWindow);
+ if (stuff->eventMask & ~SelectionAllEvents)
+ {
+ client->errorValue = stuff->eventMask;
+ return( BadValue );
+ }
+ return XFixesSelectSelectionInput (client, stuff->selection,
+ pWin, stuff->eventMask);
+}
+
+int
+SProcXFixesSelectSelectionInput (ClientPtr client)
+{
+ register int n;
+ REQUEST(xXFixesSelectSelectionInputReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->window, n);
+ swapl(&stuff->selection, n);
+ swapl(&stuff->eventMask, n);
+ return ProcXFixesSelectSelectionInput(client);
+}
+
+void
+SXFixesSelectionNotifyEvent (xXFixesSelectionNotifyEvent *from,
+ xXFixesSelectionNotifyEvent *to)
+{
+ to->type = from->type;
+ cpswaps (from->sequenceNumber, to->sequenceNumber);
+ cpswapl (from->window, to->window);
+ cpswapl (from->owner, to->owner);
+ cpswapl (from->selection, to->selection);
+ cpswapl (from->timestamp, to->timestamp);
+ cpswapl (from->selectionTimestamp, to->selectionTimestamp);
+}
+
+static int
+SelectionFreeClient (pointer data, XID id)
+{
+ SelectionEventPtr old = (SelectionEventPtr) data;
+ SelectionEventPtr *prev, e;
+
+ for (prev = &selectionEvents; (e = *prev); prev = &e->next)
+ {
+ if (e == old)
+ {
+ *prev = e->next;
+ xfree (e);
+ CheckSelectionCallback ();
+ break;
+ }
+ }
+ return 1;
+}
+
+static int
+SelectionFreeWindow (pointer data, XID id)
+{
+ WindowPtr pWindow = (WindowPtr) data;
+ SelectionEventPtr e, next;
+
+ for (e = selectionEvents; e; e = next)
+ {
+ next = e->next;
+ if (e->pWindow == pWindow)
+ {
+ FreeResource (e->clientResource, 0);
+ }
+ }
+ return 1;
+}
+
+Bool
+XFixesSelectionInit (void)
+{
+ SelectionClientType = CreateNewResourceType(SelectionFreeClient);
+ SelectionWindowType = CreateNewResourceType(SelectionFreeWindow);
+ return SelectionClientType && SelectionWindowType;
+}
diff --git a/xfixes/xfixes.c b/xfixes/xfixes.c
new file mode 100755
index 000000000..82063d6b3
--- /dev/null
+++ b/xfixes/xfixes.c
@@ -0,0 +1,230 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "xfixesint.h"
+
+unsigned char XFixesReqCode;
+int XFixesEventBase;
+int XFixesErrorBase;
+int XFixesClientPrivateIndex;
+
+static int
+ProcXFixesQueryVersion(ClientPtr client)
+{
+ XFixesClientPtr pXFixesClient = GetXFixesClient (client);
+ xXFixesQueryVersionReply rep;
+ register int n;
+ REQUEST(xXFixesQueryVersionReq);
+
+ REQUEST_SIZE_MATCH(xXFixesQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ if (stuff->majorVersion < XFIXES_MAJOR) {
+ rep.majorVersion = stuff->majorVersion;
+ rep.minorVersion = stuff->minorVersion;
+ } else {
+ rep.majorVersion = XFIXES_MAJOR;
+ if (stuff->majorVersion == XFIXES_MAJOR &&
+ stuff->minorVersion < XFIXES_MINOR)
+ rep.minorVersion = stuff->minorVersion;
+ else
+ rep.minorVersion = XFIXES_MINOR;
+ }
+ pXFixesClient->major_version = rep.majorVersion;
+ pXFixesClient->minor_version = rep.minorVersion;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.majorVersion, n);
+ swapl(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof(xXFixesQueryVersionReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+/* Major version controls available requests */
+static const int version_requests[] = {
+ X_XFixesQueryVersion, /* before client sends QueryVersion */
+ X_XFixesGetCursorImage, /* Version 1 */
+ X_XFixesChangeCursorByName, /* Version 2 */
+ X_XFixesExpandRegion, /* Version 3 */
+};
+
+#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
+
+int (*ProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
+/*************** Version 1 ******************/
+ ProcXFixesQueryVersion,
+ ProcXFixesChangeSaveSet,
+ ProcXFixesSelectSelectionInput,
+ ProcXFixesSelectCursorInput,
+ ProcXFixesGetCursorImage,
+/*************** Version 2 ******************/
+ ProcXFixesCreateRegion,
+ ProcXFixesCreateRegionFromBitmap,
+ ProcXFixesCreateRegionFromWindow,
+ ProcXFixesCreateRegionFromGC,
+ ProcXFixesCreateRegionFromPicture,
+ ProcXFixesDestroyRegion,
+ ProcXFixesSetRegion,
+ ProcXFixesCopyRegion,
+ ProcXFixesCombineRegion,
+ ProcXFixesCombineRegion,
+ ProcXFixesCombineRegion,
+ ProcXFixesInvertRegion,
+ ProcXFixesTranslateRegion,
+ ProcXFixesRegionExtents,
+ ProcXFixesFetchRegion,
+ ProcXFixesSetGCClipRegion,
+ ProcXFixesSetWindowShapeRegion,
+ ProcXFixesSetPictureClipRegion,
+ ProcXFixesSetCursorName,
+ ProcXFixesGetCursorName,
+ ProcXFixesGetCursorImageAndName,
+ ProcXFixesChangeCursor,
+ ProcXFixesChangeCursorByName,
+/*************** Version 3 ******************/
+ ProcXFixesExpandRegion,
+};
+
+static int
+ProcXFixesDispatch (ClientPtr client)
+{
+ REQUEST(xXFixesReq);
+ XFixesClientPtr pXFixesClient = GetXFixesClient (client);
+
+ if (pXFixesClient->major_version > NUM_VERSION_REQUESTS)
+ return BadRequest;
+ if (stuff->xfixesReqType > version_requests[pXFixesClient->major_version])
+ return BadRequest;
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+static int
+SProcXFixesQueryVersion(ClientPtr client)
+{
+ register int n;
+ REQUEST(xXFixesQueryVersionReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->majorVersion, n);
+ swapl(&stuff->minorVersion, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int (*SProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
+/*************** Version 1 ******************/
+ SProcXFixesQueryVersion,
+ SProcXFixesChangeSaveSet,
+ SProcXFixesSelectSelectionInput,
+ SProcXFixesSelectCursorInput,
+ SProcXFixesGetCursorImage,
+/*************** Version 2 ******************/
+ SProcXFixesCreateRegion,
+ SProcXFixesCreateRegionFromBitmap,
+ SProcXFixesCreateRegionFromWindow,
+ SProcXFixesCreateRegionFromGC,
+ SProcXFixesCreateRegionFromPicture,
+ SProcXFixesDestroyRegion,
+ SProcXFixesSetRegion,
+ SProcXFixesCopyRegion,
+ SProcXFixesCombineRegion,
+ SProcXFixesCombineRegion,
+ SProcXFixesCombineRegion,
+ SProcXFixesInvertRegion,
+ SProcXFixesTranslateRegion,
+ SProcXFixesRegionExtents,
+ SProcXFixesFetchRegion,
+ SProcXFixesSetGCClipRegion,
+ SProcXFixesSetWindowShapeRegion,
+ SProcXFixesSetPictureClipRegion,
+ SProcXFixesSetCursorName,
+ SProcXFixesGetCursorName,
+ SProcXFixesGetCursorImageAndName,
+ SProcXFixesChangeCursor,
+ SProcXFixesChangeCursorByName,
+/*************** Version 3 ******************/
+ SProcXFixesExpandRegion,
+};
+
+static int
+SProcXFixesDispatch (ClientPtr client)
+{
+ REQUEST(xXFixesReq);
+ if (stuff->xfixesReqType >= XFixesNumberRequests)
+ return BadRequest;
+ return (*SProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+static void
+XFixesClientCallback (CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
+ ClientPtr pClient = clientinfo->client;
+ XFixesClientPtr pXFixesClient = GetXFixesClient (pClient);
+
+ pXFixesClient->major_version = 0;
+ pXFixesClient->minor_version = 0;
+}
+
+/*ARGSUSED*/
+static void
+XFixesResetProc (ExtensionEntry *extEntry)
+{
+ DeleteCallback (&ClientStateCallback, XFixesClientCallback, 0);
+}
+
+void
+XFixesExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+
+ XFixesClientPrivateIndex = AllocateClientPrivateIndex ();
+ if (!AllocateClientPrivate (XFixesClientPrivateIndex,
+ sizeof (XFixesClientRec)))
+ return;
+ if (!AddCallback (&ClientStateCallback, XFixesClientCallback, 0))
+ return;
+
+ if (XFixesSelectionInit() && XFixesCursorInit () && XFixesRegionInit () &&
+ (extEntry = AddExtension(XFIXES_NAME, XFixesNumberEvents,
+ XFixesNumberErrors,
+ ProcXFixesDispatch, SProcXFixesDispatch,
+ XFixesResetProc, StandardMinorOpcode)) != 0)
+ {
+ XFixesReqCode = (unsigned char)extEntry->base;
+ XFixesEventBase = extEntry->eventBase;
+ XFixesErrorBase = extEntry->errorBase;
+ EventSwapVector[XFixesEventBase + XFixesSelectionNotify] =
+ (EventSwapPtr) SXFixesSelectionNotifyEvent;
+ EventSwapVector[XFixesEventBase + XFixesCursorNotify] =
+ (EventSwapPtr) SXFixesCursorNotifyEvent;
+ }
+}
diff --git a/xfixes/xfixes.h b/xfixes/xfixes.h
new file mode 100755
index 000000000..4d329b63a
--- /dev/null
+++ b/xfixes/xfixes.h
@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 _XFIXES_H_
+#define _XFIXES_H_
+
+#include "resource.h"
+
+extern RESTYPE RegionResType;
+extern int XFixesErrorBase;
+
+#define VERIFY_REGION(pRegion, rid, client, mode) { \
+ pRegion = SecurityLookupIDByType (client, rid, RegionResType, mode); \
+ if (!pRegion) { \
+ client->errorValue = rid; \
+ return XFixesErrorBase + BadRegion; \
+ } \
+}
+
+#define VERIFY_REGION_OR_NONE(pRegion, rid, client, mode) { \
+ pRegion = 0; \
+ if (rid) VERIFY_REGION(pRegion, rid, client, mode); \
+}
+
+RegionPtr
+XFixesRegionCopy (RegionPtr pRegion);
+
+
+#endif /* _XFIXES_H_ */
diff --git a/xfixes/xfixesint.h b/xfixes/xfixesint.h
new file mode 100755
index 000000000..5b1786d06
--- /dev/null
+++ b/xfixes/xfixesint.h
@@ -0,0 +1,239 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2002 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 _XFIXESINT_H_
+#define _XFIXESINT_H_
+
+#define NEED_EVENTS
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include <X11/extensions/xfixesproto.h>
+#include "windowstr.h"
+#include "selection.h"
+#include "xfixes.h"
+
+extern unsigned char XFixesReqCode;
+extern int XFixesEventBase;
+extern int XFixesClientPrivateIndex;
+
+typedef struct _XFixesClient {
+ CARD32 major_version;
+ CARD32 minor_version;
+} XFixesClientRec, *XFixesClientPtr;
+
+#define GetXFixesClient(pClient) ((XFixesClientPtr) (pClient)->devPrivates[XFixesClientPrivateIndex].ptr)
+
+extern int (*ProcXFixesVector[XFixesNumberRequests])(ClientPtr);
+extern int (*SProcXFixesVector[XFixesNumberRequests])(ClientPtr);
+
+/* Initialize extension at server startup time */
+
+void
+XFixesExtensionInit(void);
+
+/* Save set */
+int
+ProcXFixesChangeSaveSet(ClientPtr client);
+
+int
+SProcXFixesChangeSaveSet(ClientPtr client);
+
+/* Selection events */
+int
+ProcXFixesSelectSelectionInput (ClientPtr client);
+
+int
+SProcXFixesSelectSelectionInput (ClientPtr client);
+
+void
+SXFixesSelectionNotifyEvent (xXFixesSelectionNotifyEvent *from,
+ xXFixesSelectionNotifyEvent *to);
+Bool
+XFixesSelectionInit (void);
+
+/* Cursor notification */
+Bool
+XFixesCursorInit (void);
+
+int
+ProcXFixesSelectCursorInput (ClientPtr client);
+
+int
+SProcXFixesSelectCursorInput (ClientPtr client);
+
+void
+SXFixesCursorNotifyEvent (xXFixesCursorNotifyEvent *from,
+ xXFixesCursorNotifyEvent *to);
+
+int
+ProcXFixesGetCursorImage (ClientPtr client);
+
+int
+SProcXFixesGetCursorImage (ClientPtr client);
+
+/* Cursor names (Version 2) */
+
+int
+ProcXFixesSetCursorName (ClientPtr client);
+
+int
+SProcXFixesSetCursorName (ClientPtr client);
+
+int
+ProcXFixesGetCursorName (ClientPtr client);
+
+int
+SProcXFixesGetCursorName (ClientPtr client);
+
+int
+ProcXFixesGetCursorImageAndName (ClientPtr client);
+
+int
+SProcXFixesGetCursorImageAndName (ClientPtr client);
+
+/* Cursor replacement (Version 2) */
+
+int
+ProcXFixesChangeCursor (ClientPtr client);
+
+int
+SProcXFixesChangeCursor (ClientPtr client);
+
+int
+ProcXFixesChangeCursorByName (ClientPtr client);
+
+int
+SProcXFixesChangeCursorByName (ClientPtr client);
+
+/* Region objects (Version 2* */
+Bool
+XFixesRegionInit (void);
+
+int
+ProcXFixesCreateRegion (ClientPtr client);
+
+int
+SProcXFixesCreateRegion (ClientPtr client);
+
+int
+ProcXFixesCreateRegionFromBitmap (ClientPtr client);
+
+int
+SProcXFixesCreateRegionFromBitmap (ClientPtr client);
+
+int
+ProcXFixesCreateRegionFromWindow (ClientPtr client);
+
+int
+SProcXFixesCreateRegionFromWindow (ClientPtr client);
+
+int
+ProcXFixesCreateRegionFromGC (ClientPtr client);
+
+int
+SProcXFixesCreateRegionFromGC (ClientPtr client);
+
+int
+ProcXFixesCreateRegionFromPicture (ClientPtr client);
+
+int
+SProcXFixesCreateRegionFromPicture (ClientPtr client);
+
+int
+ProcXFixesDestroyRegion (ClientPtr client);
+
+int
+SProcXFixesDestroyRegion (ClientPtr client);
+
+int
+ProcXFixesSetRegion (ClientPtr client);
+
+int
+SProcXFixesSetRegion (ClientPtr client);
+
+int
+ProcXFixesCopyRegion (ClientPtr client);
+
+int
+SProcXFixesCopyRegion (ClientPtr client);
+
+int
+ProcXFixesCombineRegion (ClientPtr client);
+
+int
+SProcXFixesCombineRegion (ClientPtr client);
+
+int
+ProcXFixesInvertRegion (ClientPtr client);
+
+int
+SProcXFixesInvertRegion (ClientPtr client);
+
+int
+ProcXFixesTranslateRegion (ClientPtr client);
+
+int
+SProcXFixesTranslateRegion (ClientPtr client);
+
+int
+ProcXFixesRegionExtents (ClientPtr client);
+
+int
+SProcXFixesRegionExtents (ClientPtr client);
+
+int
+ProcXFixesFetchRegion (ClientPtr client);
+
+int
+SProcXFixesFetchRegion (ClientPtr client);
+
+int
+ProcXFixesSetGCClipRegion (ClientPtr client);
+
+int
+SProcXFixesSetGCClipRegion (ClientPtr client);
+
+int
+ProcXFixesSetWindowShapeRegion (ClientPtr client);
+
+int
+SProcXFixesSetWindowShapeRegion (ClientPtr client);
+
+int
+ProcXFixesSetPictureClipRegion (ClientPtr client);
+
+int
+SProcXFixesSetPictureClipRegion (ClientPtr client);
+
+int
+ProcXFixesExpandRegion (ClientPtr client);
+
+int
+SProcXFixesExpandRegion (ClientPtr client);
+
+#endif /* _XFIXESINT_H_ */