aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/hw/nxagent/Render.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/hw/nxagent/Render.c')
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Render.c2810
1 files changed, 2810 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Render.c b/nx-X11/programs/Xserver/hw/nxagent/Render.c
new file mode 100644
index 000000000..b1ff219e7
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Render.c
@@ -0,0 +1,2810 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of NoMachine. Redistribution and use of the present */
+/* software is allowed according to terms specified in the file LICENSE */
+/* which comes in the source distribution. */
+/* */
+/* Check http://www.nomachine.com/licensing.html for applicability. */
+/* */
+/* NX and NoMachine are trademarks of NoMachine S.r.l. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#include "NXpicturestr.h"
+#include "NXglyphstr.h"
+
+#include "Render.h"
+
+#include "X.h"
+#include "Xproto.h"
+
+#include "render.h"
+#include "renderproto.h"
+
+#include "mi.h"
+#include "fb.h"
+#include "mipict.h"
+#include "fbpict.h"
+#include "dixstruct.h"
+
+#include "Agent.h"
+#include "Drawable.h"
+#include "Trap.h"
+#include "Args.h"
+
+#define Atom XlibAtom
+#define Pixmap XlibPixmap
+#include "../../../../lib/Xrender/Xrenderint.h"
+#undef Atom
+#undef Pixmap
+
+#include "region.h"
+#include "extutil.h"
+
+#include "Display.h"
+#include "Pixmaps.h"
+#include "Cursor.h"
+#include "Client.h"
+#include "Image.h"
+#include "Pixels.h"
+#include "Handlers.h"
+
+#include "NXproto.h"
+
+#define MAX_FORMATS 255
+
+#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL
+
+/*
+ * Define if you want split multiple glyph lists
+ * into multiple RenderCompositeGlyphs requests.
+ */
+
+#undef SPLIT_GLYPH_LISTS
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+FIXME: Most operations don't seem to produce any visible result
+ but still generate tons of traffic.
+*/
+#undef SKIP_LOUSY_RENDER_OPERATIONS
+#undef SKIP_REALLY_ALL_LOUSY_RENDER_OPERATIONS
+
+/*
+ * Do we split the big trapezoid requests?
+ */
+
+#define TRAPEZOIDS_PER_REQUEST 256
+
+/*
+ * Margin added around the glyphs extent (in pixels).
+ */
+
+#define GLYPH_BOX_MARGIN 2
+
+int nxagentRenderEnable = UNDEFINED;
+int nxagentRenderVersionMajor;
+int nxagentRenderVersionMinor;
+
+int nxagentPicturePrivateIndex = 0;
+
+#ifndef NXAGENT_UPGRADE
+static int picturePrivateCount = 0;
+#endif
+
+static int nxagentNumFormats = 0;
+
+static XRenderPictFormat nxagentArrayFormats[MAX_FORMATS];
+
+XRenderPictFormat *nxagentMatchingFormats(PictFormatPtr pForm);
+
+BoxPtr nxagentGlyphsExtents;
+BoxPtr nxagentTrapezoidExtents;
+
+#ifdef DEBUG
+
+static void nxagentPrintFormat(XRenderPictFormat *pFormat);
+
+#endif
+
+/*
+ * From NXglyph.c.
+ */
+
+extern const CARD8 glyphDepths[];
+
+/*
+ * From NXdispatch.c.
+ */
+
+extern void BitOrderInvert(unsigned char *data, int nbytes);
+
+/*
+ * Other functions defined here.
+ */
+
+void nxagentQueryFormats(void);
+
+void nxagentCreateGlyphSet(GlyphSetPtr pGly);
+
+int nxagentCursorSaveRenderInfo(ScreenPtr pScreen, CursorPtr pCursor);
+
+void nxagentCursorPostSaveRenderInfo(CursorPtr pCursor, ScreenPtr pScreen,
+ PicturePtr pPicture, int x, int y);
+
+int nxagentCreatePicture(PicturePtr pPicture, Mask mask);
+
+void nxagentDestroyPicture(PicturePtr pPicture);
+
+int nxagentChangePictureClip(PicturePtr pPicture, int clipType, int nRects,
+ xRectangle *rects, int xOrigin, int yOrigin);
+
+void nxagentDestroyPictureClip(PicturePtr pPicture);
+
+void nxagentValidatePicture(PicturePtr pPicture, Mask mask);
+
+void nxagentComposite(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 nxagentGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists,
+ XGlyphElt8 *elts, int sizeID, GlyphPtr *glyphsBase);
+
+void nxagentCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color,
+ int nRect, xRectangle *rects);
+
+void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps);
+
+void nxagentRasterizeTrapezoid(PicturePtr pMask, xTrapezoid *trap,
+ int x_off, int y_off);
+
+void nxagentTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle *tris);
+
+void nxagentTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points);
+
+void nxagentChangePicture(PicturePtr pPicture, Mask mask);
+
+void nxagentTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points);
+
+void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet);
+
+void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph);
+
+void nxagentFreeGlyphSet(GlyphSetPtr glyphSet);
+
+void nxagentSetPictureTransform(PicturePtr pPicture, pointer transform);
+
+void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size,
+ pointer params, int nparams);
+
+Bool nxagentReconnectAllGlyphSet(void *p);
+
+Bool nxagentReconnectAllPicture(void *);
+
+Bool nxagentDisconnectAllPicture(void);
+
+void nxagentRenderExtensionInit()
+{
+ int first_event, first_error;
+ int major_version, minor_version;
+
+ if (XRenderQueryExtension(nxagentDisplay, &first_event, &first_error))
+ {
+ XRenderQueryVersion(nxagentDisplay, &major_version, &minor_version);
+
+ /*
+ * As the RENDER requests are passed directly to
+ * the remote X server this can cause problems if
+ * our RENDER version is different from the version
+ * supported by the remote. For this reasos let's
+ * advertise to our clients the lowest between the
+ + two versions.
+ */
+
+ if (major_version > RENDER_MAJOR ||
+ (major_version == RENDER_MAJOR &&
+ minor_version > RENDER_MINOR))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderExtensionInit: Using render version [%d.%d] with "
+ "remote version [%d.%d].\n", RENDER_MAJOR, RENDER_MINOR,
+ major_version, minor_version);
+ #endif
+
+ nxagentRenderVersionMajor = RENDER_MAJOR;
+ nxagentRenderVersionMinor = RENDER_MINOR;
+ }
+ else if (major_version < RENDER_MAJOR ||
+ (major_version == RENDER_MAJOR &&
+ minor_version < RENDER_MINOR))
+ {
+ #ifdef TEST
+ fprintf(stderr, "Info: Local render version %d.%d is higher "
+ "than remote version %d.%d.\n", RENDER_MAJOR, RENDER_MINOR,
+ major_version, minor_version);
+
+ fprintf(stderr, "Info: Lowering the render version reported to clients.\n");
+ #endif
+
+ nxagentRenderVersionMajor = major_version;
+ nxagentRenderVersionMinor = minor_version;
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderExtensionInit: Local render version %d.%d "
+ "matches remote version %d.%d.\n", RENDER_MAJOR, RENDER_MINOR,
+ major_version, minor_version);
+ #endif
+
+ nxagentRenderVersionMajor = major_version;
+ nxagentRenderVersionMinor = minor_version;
+ }
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "Warning: Render not available on the remote display.\n");
+ #endif
+
+ nxagentRenderEnable = False;
+ }
+}
+
+int nxagentCursorSaveRenderInfo(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ pCursor -> devPriv[pScreen -> myNum] = xalloc(sizeof(nxagentPrivCursor));
+
+ if (nxagentCursorPriv(pCursor, pScreen) == NULL)
+ {
+ FatalError("xalloc failed");
+ }
+
+ nxagentCursorUsesRender(pCursor, pScreen) = 1;
+ nxagentCursorPicture(pCursor, pScreen) = NULL;
+
+ return 1;
+}
+
+void nxagentCursorPostSaveRenderInfo(CursorPtr pCursor, ScreenPtr pScreen,
+ PicturePtr pPicture, int x, int y)
+{
+ nxagentCursorPicture(pCursor, pScreen) = pPicture;
+ nxagentCursorXOffset(pCursor, pScreen) = x;
+ nxagentCursorYOffset(pCursor, pScreen) = y;
+}
+
+int nxagentRenderRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ int cid;
+ int x, y;
+
+ PicturePtr pPicture;
+
+ pPicture = nxagentCursorPicture(pCursor, pScreen);
+
+ pPicture -> refcnt++;
+
+ x = nxagentCursorXOffset(pCursor, pScreen);
+ y = nxagentCursorYOffset(pCursor, pScreen);
+
+ /*
+ * Set the lossless trap so that the image functions
+ * will not try to encode the image using a lossy
+ * compression. Drawables should have a quality flag,
+ * telling if they were originally encoded with a
+ * lossy algorithm. This would allow us to skip the
+ * synchronization if the cursor was already encoded
+ * with the best quality.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderRealizeCursor: Forcing the synchronization "
+ "of the cursor.\n");
+ #endif
+
+ nxagentMarkCorruptedRegion(pPicture -> pDrawable, NULL);
+
+ nxagentLosslessTrap = 1;
+
+ nxagentSynchronizeDrawable(pPicture -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+
+ nxagentLosslessTrap = 0;
+
+ cid = XRenderCreateCursor(nxagentDisplay, nxagentPicture(pPicture), x, y);
+
+ nxagentCursor(pCursor, pScreen) = cid;
+
+ return 1;
+}
+
+int nxagentCreatePicture(PicturePtr pPicture, Mask mask)
+{
+ XRenderPictureAttributes attributes;
+ unsigned long valuemask=0;
+ XRenderPictFormat *pForm;
+
+ Picture id;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCreatePicture: Function called with picture at [%p] and mask [%ld].\n",
+ (void *) pPicture, mask);
+ #endif
+
+ if (pPicture == NULL)
+ {
+ return 0;
+ }
+
+ #ifdef DEBUG
+
+ if (pPicture -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ if (nxagentIsShmPixmap((PixmapPtr)pPicture -> pDrawable))
+ {
+ fprintf (stderr, "nxagentCreatePicture: Picture uses a shared pixmap.\n");
+ }
+ else
+ {
+ fprintf (stderr, "nxagentCreatePicture: Picture uses a plain pixmap.\n");
+ }
+ }
+ else
+ {
+ fprintf (stderr, "nxagentCreatePicture: Picture uses a window.\n");
+ }
+
+ #endif
+
+ /*
+ * All the picture default values are 0.
+ */
+
+ memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0, sizeof(XRenderPictureAttributes));
+
+ if (mask & CPRepeat)
+ {
+ attributes.repeat = (Bool)pPicture -> repeat;
+
+ valuemask |= CPRepeat;
+
+ nxagentSetPictureRemoteValue(pPicture, repeat, attributes.repeat);
+ }
+
+ if (mask & CPAlphaMap)
+ {
+ attributes.alpha_map = nxagentPicturePriv(pPicture -> alphaMap) -> picture;
+
+ valuemask |= CPAlphaMap;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_map, attributes.alpha_map);
+ }
+
+ if (mask & CPAlphaXOrigin)
+ {
+ attributes.alpha_x_origin = pPicture -> alphaOrigin.x;
+
+ valuemask |= CPAlphaXOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_x_origin, attributes.alpha_x_origin);
+ }
+
+ if (mask & CPAlphaYOrigin)
+ {
+ attributes.alpha_y_origin = pPicture -> alphaOrigin.y;
+
+ valuemask |= CPAlphaYOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_y_origin, attributes.alpha_y_origin);
+ }
+
+ if (mask & CPClipXOrigin)
+ {
+ attributes.clip_x_origin = pPicture -> clipOrigin.x;
+
+ valuemask |= CPClipXOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_x_origin, attributes.clip_x_origin);
+ }
+
+ if (mask & CPClipYOrigin)
+ {
+ attributes.clip_y_origin = pPicture -> clipOrigin.y;
+
+ valuemask |= CPClipYOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_y_origin, attributes.clip_y_origin);
+ }
+
+ if (mask & CPGraphicsExposure)
+ {
+ attributes.graphics_exposures = (Bool)pPicture -> graphicsExposures;
+
+ valuemask |= CPGraphicsExposure;
+
+ nxagentSetPictureRemoteValue(pPicture, graphics_exposures, attributes.graphics_exposures);
+ }
+
+ if (mask & CPSubwindowMode)
+ {
+ attributes.subwindow_mode = pPicture -> subWindowMode;
+
+ valuemask |= CPSubwindowMode;
+
+ nxagentSetPictureRemoteValue(pPicture, subwindow_mode, attributes.subwindow_mode);
+ }
+
+ if (mask & CPClipMask)
+ {
+ attributes.clip_mask = None;
+
+ valuemask |= CPClipMask;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_mask, attributes.clip_mask);
+ }
+
+ if (mask & CPPolyEdge)
+ {
+ attributes.poly_edge = pPicture -> polyEdge;
+
+ valuemask |= CPPolyEdge;
+
+ nxagentSetPictureRemoteValue(pPicture, poly_edge, attributes.poly_edge);
+ }
+
+ if (mask & CPPolyMode)
+ {
+ attributes.poly_mode = pPicture -> polyMode;
+
+ valuemask |= CPPolyMode;
+
+ nxagentSetPictureRemoteValue(pPicture, poly_mode, attributes.poly_mode);
+ }
+
+ if (mask & CPDither)
+ {
+ attributes.dither = pPicture -> dither;
+
+ valuemask |= CPDither;
+
+ nxagentSetPictureRemoteValue(pPicture, dither, attributes.dither);
+ }
+
+ if (mask & CPComponentAlpha)
+ {
+ attributes.component_alpha = pPicture -> componentAlpha;
+
+ valuemask |= CPComponentAlpha;
+
+ nxagentSetPictureRemoteValue(pPicture, component_alpha, attributes.component_alpha);
+ }
+
+ pForm = NULL;
+
+ if (pPicture -> pFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(pPicture -> pFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+ }
+
+ if (pForm == NULL)
+ {
+ fprintf(stderr, "nxagentCreatePicture: WARNING! The requested format was not found.\n");
+
+ return 0;
+ }
+
+ id = XRenderCreatePicture(nxagentDisplay,
+ nxagentDrawable(pPicture -> pDrawable),
+ pForm,
+ valuemask,
+ &attributes);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreatePicture: Created picture at [%p] with drawable at [%p].\n",
+ (void *) pPicture, (void *) pPicture -> pDrawable);
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ nxagentPicturePriv(pPicture) -> picture = id;
+
+ if (nxagentAlphaEnabled == 1 && pPicture -> pDrawable->depth == 32 &&
+ pPicture -> pFormat -> direct.alpha != 0)
+ {
+ if (pPicture -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) pPicture -> pDrawable)) -> pPicture = pPicture;
+ }
+ else if (pPicture -> pDrawable -> type == DRAWABLE_WINDOW)
+ {
+ nxagentWindowPriv((WindowPtr) pPicture -> pDrawable) -> pPicture = pPicture;
+ }
+ }
+
+ return 1;
+}
+
+XRenderPictFormat *nxagentMatchingFormats(PictFormatPtr pFormat)
+{
+ int i;
+
+ for (i = 0; i < nxagentNumFormats; i++)
+ {
+ if (pFormat -> type == nxagentArrayFormats[i].type &&
+ pFormat -> depth == nxagentArrayFormats[i].depth &&
+ pFormat -> direct.red == nxagentArrayFormats[i].direct.red &&
+ pFormat -> direct.green == nxagentArrayFormats[i].direct.green &&
+ pFormat -> direct.blue == nxagentArrayFormats[i].direct.blue &&
+ pFormat -> direct.redMask == nxagentArrayFormats[i].direct.redMask &&
+ pFormat -> direct.greenMask == nxagentArrayFormats[i].direct.greenMask &&
+ pFormat -> direct.blueMask == nxagentArrayFormats[i].direct.blueMask &&
+ pFormat -> direct.alpha == nxagentArrayFormats[i].direct.alpha &&
+ pFormat -> direct.alphaMask == nxagentArrayFormats[i].direct.alphaMask)
+ {
+ return &nxagentArrayFormats[i];
+ }
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentMatchingFormats: The requested format was not found.\n");
+ #endif
+
+ return NULL;
+}
+
+void nxagentDestroyPicture(PicturePtr pPicture)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyPicture: Going to destroy picture at [%p].\n",
+ (void *) pPicture);
+ #endif
+
+ if (pPicture == NULL)
+ {
+ return;
+ }
+
+ XRenderFreePicture(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+int nxagentChangePictureClip(PicturePtr pPicture, int clipType, int nRects,
+ xRectangle *rects, int xOrigin, int yOrigin)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangePictureClip: Going to change clip of picture at [%p].\n",
+ (void *) pPicture);
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePictureClip: clipType [%d] nRects [%d] xRectangle [%p] "
+ "xOrigin [%d] yOrigin [%d].\n", clipType, nRects, (void *) rects, xOrigin, yOrigin);
+ #endif
+
+ if (pPicture == NULL)
+ {
+ return 0;
+ }
+
+ switch (clipType)
+ {
+ case CT_PIXMAP:
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePictureClip: Clip type is [CT_PIXMAP].\n");
+ #endif
+
+ /*
+ * if(!nRects)
+ * {
+ * return 0;
+ * }
+ */
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ XRenderSetPictureClipRectangles(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ xOrigin,
+ yOrigin,
+ (XRectangle*)rects,
+ nRects);
+
+ nxagentSetPictureRemoteValue(pPicture, clip_x_origin, xOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_y_origin, yOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_mask, 1);
+
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ break;
+ }
+ case CT_NONE:
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePictureClip: Clip type is [CT_NONE].\n");
+ #endif
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ XRenderSetPictureClipRectangles(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ xOrigin,
+ yOrigin,
+ (XRectangle*)rects,
+ nRects);
+
+ nxagentSetPictureRemoteValue(pPicture, clip_x_origin, xOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_y_origin, yOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_mask, 1);
+
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ break;
+ }
+ case CT_REGION:
+ {
+ Region reg;
+ XRectangle rectangle;
+ int index;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePictureClip: Clip type is [CT_REGION].\n");
+ #endif
+
+ reg = XCreateRegion();
+
+ for (index = 0; index <= nRects; index++, rects++)
+ {
+ rectangle.x = rects -> x;
+ rectangle.y = rects -> y;
+ rectangle.width = rects -> width;
+ rectangle.height = rects -> height;
+
+ XUnionRectWithRegion(&rectangle, reg, reg);
+ }
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ XRenderSetPictureClipRegion(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ reg);
+
+ nxagentSetPictureRemoteValue(pPicture, clip_x_origin, xOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_y_origin, yOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_mask, 1);
+
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ XDestroyRegion(reg);
+
+ break;
+ }
+ default:
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePictureClip: clipType not found\n");
+ #endif
+
+ break;
+ }
+ }
+
+ return 1;
+}
+
+void nxagentDestroyPictureClip(PicturePtr pPicture)
+{
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDestroyPictureClip: Nothing to do.\n");
+ #endif
+}
+
+void nxagentChangePicture(PicturePtr pPicture, Mask mask)
+{
+ XRenderPictureAttributes attributes;
+ unsigned long valuemask = 0;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePicture: Going to change picture at [%p] with mask [%ld].\n",
+ (void *) pPicture, mask);
+ #endif
+
+ if (pPicture == NULL)
+ {
+ return;
+ }
+
+ if (mask & CPRepeat)
+ {
+ attributes.repeat = (Bool)pPicture -> repeat;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, repeat, attributes.repeat) == 0)
+ {
+ valuemask |= CPRepeat;
+
+ nxagentSetPictureRemoteValue(pPicture, repeat, attributes.repeat);
+ }
+ }
+
+ if (mask & CPAlphaMap)
+ {
+ attributes.alpha_map = nxagentPicturePriv(pPicture -> alphaMap) -> picture;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, alpha_map, attributes.alpha_map) == 0)
+ {
+ valuemask |= CPAlphaMap;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_map, attributes.alpha_map);
+ }
+ }
+
+ if (mask & CPAlphaXOrigin)
+ {
+ attributes.alpha_x_origin = pPicture -> alphaOrigin.x;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, alpha_x_origin, attributes.alpha_x_origin) == 0)
+ {
+ valuemask |= CPAlphaXOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_x_origin, attributes.alpha_x_origin);
+ }
+ }
+
+ if (mask & CPAlphaYOrigin)
+ {
+ attributes.alpha_y_origin = pPicture -> alphaOrigin.y;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, alpha_y_origin, attributes.alpha_y_origin) == 0)
+ {
+ valuemask |= CPAlphaYOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_y_origin, attributes.alpha_y_origin);
+ }
+ }
+
+ if (mask & CPClipXOrigin)
+ {
+ attributes.clip_x_origin = pPicture -> clipOrigin.x;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, clip_x_origin, attributes.clip_x_origin) == 0)
+ {
+ valuemask |= CPClipXOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_x_origin, attributes.clip_x_origin);
+ }
+ }
+
+ if (mask & CPClipYOrigin)
+ {
+ attributes.clip_y_origin = pPicture -> clipOrigin.y;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, clip_y_origin, attributes.clip_y_origin) == 0)
+ {
+ valuemask |= CPClipYOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_y_origin, attributes.clip_y_origin);
+ }
+ }
+
+ if (mask & CPGraphicsExposure)
+ {
+ attributes.graphics_exposures = (Bool)pPicture -> graphicsExposures;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, graphics_exposures, attributes.graphics_exposures) == 0)
+ {
+ valuemask |= CPGraphicsExposure;
+
+ nxagentSetPictureRemoteValue(pPicture, graphics_exposures, attributes.graphics_exposures);
+ }
+ }
+
+ if (mask & CPSubwindowMode)
+ {
+ attributes.subwindow_mode = pPicture -> subWindowMode;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, subwindow_mode, attributes.subwindow_mode) == 0)
+ {
+ valuemask |= CPSubwindowMode;
+
+ nxagentSetPictureRemoteValue(pPicture, subwindow_mode, attributes.subwindow_mode);
+ }
+ }
+
+ if (mask & CPClipMask)
+ {
+ attributes.clip_mask = None;
+
+ /*
+ * The nxagent doesn't know the remote id of
+ * the picture's clip mask, so the clip_mask
+ * value is used as a boolean: it is set to 0
+ * when the clip_mask is None, otherwise it is
+ * 1.
+ */
+
+ if (nxagentPicturePriv(pPicture) -> lastServerValues.clip_mask != 0)
+ {
+ valuemask |= CPClipMask;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_mask, 0);
+ }
+ }
+
+ if (mask & CPPolyEdge)
+ {
+ attributes.poly_edge = pPicture -> polyEdge;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, poly_edge, attributes.poly_edge) == 0)
+ {
+ valuemask |= CPPolyEdge;
+
+ nxagentSetPictureRemoteValue(pPicture, poly_edge, attributes.poly_edge);
+ }
+ }
+
+ if (mask & CPPolyMode)
+ {
+ attributes.poly_mode = pPicture -> polyMode;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, poly_mode, attributes.poly_mode) == 0)
+ {
+ valuemask |= CPPolyMode;
+
+ nxagentSetPictureRemoteValue(pPicture, poly_mode, attributes.poly_mode);
+ }
+ }
+
+ if (mask & CPDither)
+ {
+ attributes.dither = pPicture -> dither;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, dither, attributes.dither) == 0)
+ {
+ valuemask |= CPDither;
+
+ nxagentSetPictureRemoteValue(pPicture, dither, attributes.dither);
+ }
+ }
+
+ if (mask & CPComponentAlpha)
+ {
+ attributes.component_alpha = pPicture -> componentAlpha;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, component_alpha, attributes.component_alpha) == 0)
+ {
+ valuemask |= CPComponentAlpha;
+
+ nxagentSetPictureRemoteValue(pPicture, component_alpha, attributes.component_alpha);
+ }
+ }
+
+ #ifdef TEST
+
+ if (pPicture -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ fprintf(stderr, "nxagentChangePicture: %sPixmap [%p] Picture [%p][%p].\n",
+ nxagentIsShmPixmap((PixmapPtr)pPicture -> pDrawable) ? "Shared " : "",
+ (void *) pPicture -> pDrawable, (void *) nxagentPicturePriv(pPicture) -> picture,
+ (void *) pPicture);
+ }
+
+ #endif
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+
+ Without this the text is not rendered on GTK/Cairo.
+*/
+ #ifndef SKIP_REALLY_ALL_LOUSY_RENDER_OPERATIONS
+
+ if (valuemask != 0)
+ {
+ XRenderChangePicture(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ valuemask,
+ &attributes);
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentChangePicture: Skipping change of picture [%p] on remote X server.\n",
+ (void *) pPicture);
+ }
+ #endif
+
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentValidatePicture(PicturePtr pPicture, Mask mask)
+{
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentValidatePicture: Nothing to do.\n");
+ #endif
+}
+
+void nxagentComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
+ INT16 yDst, CARD16 width, CARD16 height)
+{
+ RegionPtr pDstRegion;
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+
+ fprintf(stderr, "nxagentComposite: Source Picture [%lu][%p] with drawable [%s%s][%p].\n",
+ nxagentPicturePriv(pSrc) -> picture, (void *) pSrc,
+ (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentIsShmPixmap((PixmapPtr) pSrc -> pDrawable)) ? "Shared " : "",
+ pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window",
+ (void *) pSrc -> pDrawable);
+
+ fprintf(stderr, "nxagentComposite: Destination Picture [%lu][%p] with drawable [%s%s][%p].\n",
+ nxagentPicturePriv(pDst) -> picture, (void *) pDst,
+ (pDst -> pDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentIsShmPixmap((PixmapPtr) pDst -> pDrawable)) ? "Shared " : "",
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window",
+ (void *) pDst -> pDrawable);
+
+ if (pMask)
+ {
+ fprintf(stderr, "nxagentComposite: Mask Picture [%lu][%p] with drawable [%s%s][%p].\n",
+ nxagentPicturePriv(pMask) -> picture, (void *) pMask,
+ (pMask -> pDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentIsShmPixmap((PixmapPtr) pMask -> pDrawable)) ? "Shared " : "",
+ pMask -> pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window",
+ (void *) pMask -> pDrawable);
+ }
+
+ #endif
+
+ if (NXAGENT_SHOULD_DEFER_COMPOSITE(pSrc, pMask, pDst))
+ {
+ pDstRegion = nxagentCreateRegion(pDst -> pDrawable, NULL, xDst, yDst, width, height);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentComposite: WARNING! Prevented operation on region [%d,%d,%d,%d] "
+ "for drawable at [%p] with type [%s].\n", pDstRegion -> extents.x1,
+ pDstRegion -> extents.y1, pDstRegion -> extents.x2, pDstRegion -> extents.y2,
+ (void *) pDst -> pDrawable,
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window");
+
+ #endif
+
+ nxagentMarkCorruptedRegion(pDst -> pDrawable, pDstRegion);
+
+ nxagentFreeRegion(pDst -> pDrawable, pDstRegion);
+
+ return;
+ }
+
+ /*
+ * Synchronize the content of the shared memory pixmap
+ * but pay attention at not doing this more than once.
+ * We need to wait until the image data has been recom-
+ * posed at the X server side or the operation will use
+ * the wrong data.
+ */
+
+ nxagentSynchronizeShmPixmap(pSrc -> pDrawable, xSrc, ySrc, width, height);
+
+ if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentComposite: Synchronizing the source drawable [%p].\n",
+ (void *) pSrc -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ if (pDst -> pDrawable != pSrc -> pDrawable)
+ {
+ nxagentSynchronizeShmPixmap(pDst -> pDrawable, xDst, yDst, width, height);
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentComposite: Synchronizing the destination drawable [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+ }
+
+ if (pMask != NULL && pMask -> pDrawable != pSrc -> pDrawable &&
+ pMask -> pDrawable != pDst -> pDrawable)
+ {
+ nxagentSynchronizeShmPixmap(pMask -> pDrawable, xMask, yMask, width, height);
+
+ if (nxagentDrawableStatus(pMask -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentComposite: Synchronizing the mask drawable [%p].\n",
+ (void *) pMask -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pMask -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+ }
+
+ /*
+ * The glyphs flag have to be propagated between
+ * drawables, in order to avoid to encode the
+ * text with lossy algorithms (like JPEG). Unlu-
+ * ckily we have verified that if the render com-
+ * posite propagates the flag, the deferring of
+ * render trapezoids doesn't work well. Moreover,
+ * by commenting out this code we have not noticed
+ * any visual problems.
+ *
+ * if (nxagentDrawableContainGlyphs(pSrc -> pDrawable) == 1)
+ * {
+ * nxagentSetDrawableContainGlyphs(pDst -> pDrawable, 1);
+ * }
+ */
+
+ XRenderComposite(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ pMask ? nxagentPicturePriv(pMask) -> picture : 0,
+ nxagentPicturePriv(pDst) -> picture,
+ xSrc,
+ ySrc,
+ xMask,
+ yMask,
+ xDst,
+ yDst,
+ width,
+ height);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists,
+ XGlyphElt8 *elts, int sizeID, GlyphPtr *glyphsBase)
+{
+ XRenderPictFormat *pForm;
+
+ BoxRec glyphBox;
+
+ XGlyphElt8 *elements;
+
+ #ifdef SPLIT_GLYPH_LISTS
+
+ GlyphPtr glyph;
+
+ int x;
+ int y;
+ int i;
+ int j;
+
+ #endif /* #ifdef SPLIT_GLYPH_LISTS */
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: Called with source [%s][%p] destination [%s][%p] and size id [%d].\n",
+ (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), (void *) pSrc,
+ (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), (void *) pDst,
+ sizeID);
+ #endif
+
+ pForm = NULL;
+
+ if (maskFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(maskFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+
+ if (nxagentGlyphsExtents != NullBox)
+ {
+ glyphBox.x1 = nxagentGlyphsExtents -> x1;
+ glyphBox.y1 = nxagentGlyphsExtents -> y1;
+ glyphBox.x2 = nxagentGlyphsExtents -> x2;
+ glyphBox.y2 = nxagentGlyphsExtents -> y2;
+
+ /*
+ * By extending the glyph extents the
+ * visual aspect looks nicer because
+ * the synchronized region is not glued
+ * to the fonts.
+ */
+
+ if (glyphBox.x2 != glyphBox.x1)
+ {
+ glyphBox.x1 -= GLYPH_BOX_MARGIN;
+ glyphBox.x2 += GLYPH_BOX_MARGIN;
+ }
+
+ if (glyphBox.y2 != glyphBox.y1)
+ {
+ glyphBox.y1 -= GLYPH_BOX_MARGIN;
+ glyphBox.y2 += GLYPH_BOX_MARGIN;
+ }
+ }
+
+ /*
+ * If the destination window is hidden, the
+ * operation can be prevented.
+ */
+
+ if (pDst -> pDrawable -> type == DRAWABLE_WINDOW)
+ {
+ RegionPtr pRegion;
+
+ pRegion = nxagentCreateRegion(pDst -> pDrawable, NULL, glyphBox.x1, glyphBox.y1,
+ glyphBox.x2 - glyphBox.x1, glyphBox.y2 - glyphBox.y1);
+
+ if (REGION_NIL(pRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: WARNING! Glyphs prevented on hidden window at [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentFreeRegion(pDst -> pDrawable, pRegion);
+
+ return;
+ }
+
+ nxagentFreeRegion(pDst -> pDrawable, pRegion);
+ }
+
+ /*
+ * Need to synchronize the pixmaps involved in
+ * the operation before rendering the glyphs
+ * on the real X server.
+ */
+
+ if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: Synchronizing source [%s] at [%p].\n",
+ pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window",
+ (void *) pSrc -> pDrawable);
+ #endif
+
+ /*
+ * If the source drawable is going to be
+ * repeated over the destination drawable
+ * during the composite operation, we need
+ * to synchronize the whole drawable to
+ * avoid graphical problems.
+ */
+
+ if (pSrc -> repeat == 1 || nxagentGlyphsExtents == NullBox)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGlyphs: Synchronizing source [%s] at [%p] "
+ "with geometry [%d,%d,%d,%d].\n",
+ (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ (void *) pSrc -> pDrawable, pSrc -> pDrawable -> x, pSrc -> pDrawable -> y,
+ pSrc -> pDrawable -> x + pSrc -> pDrawable -> width,
+ pSrc -> pDrawable -> y + pSrc -> pDrawable -> height);
+ #endif
+
+ nxagentSynchronizeBox(pSrc -> pDrawable, NullBox, NEVER_BREAK);
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGlyphs: Synchronizing region [%d,%d,%d,%d] of source [%s] at [%p] "
+ "with geometry [%d,%d,%d,%d].\n", glyphBox.x1, glyphBox.y1, glyphBox.x2, glyphBox.y2,
+ (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ (void *) pSrc -> pDrawable, pSrc -> pDrawable -> x, pSrc -> pDrawable -> y,
+ pSrc -> pDrawable -> x + pSrc -> pDrawable -> width,
+ pSrc -> pDrawable -> y + pSrc -> pDrawable -> height);
+ #endif
+
+ nxagentSynchronizeBox(pSrc -> pDrawable, &glyphBox, NEVER_BREAK);
+ }
+
+ if (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentIncreasePixmapUsageCounter((PixmapPtr) pSrc -> pDrawable);
+ }
+ }
+
+ if (pSrc -> pDrawable != pDst -> pDrawable &&
+ nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: Synchronizing destination [%s] at [%p].\n",
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ if (nxagentGlyphsExtents == NullBox)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGlyphs: Synchronizing destination [%s] at [%p] "
+ "with geometry [%d,%d,%d,%d].\n",
+ (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ (void *) pDst -> pDrawable, pDst -> pDrawable -> x, pDst -> pDrawable -> y,
+ pDst -> pDrawable -> x + pDst -> pDrawable -> width,
+ pDst -> pDrawable -> y + pDst -> pDrawable -> height);
+ #endif
+
+ nxagentSynchronizeBox(pDst -> pDrawable, NullBox, NEVER_BREAK);
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGlyphs: Synchronizing region [%d,%d,%d,%d] of destination [%s] at [%p] "
+ "with geometry [%d,%d,%d,%d].\n", glyphBox.x1, glyphBox.y1, glyphBox.x2, glyphBox.y2,
+ (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ (void *) pDst -> pDrawable, pDst -> pDrawable -> x, pDst -> pDrawable -> y,
+ pDst -> pDrawable -> x + pDst -> pDrawable -> width,
+ pDst -> pDrawable -> y + pDst -> pDrawable -> height);
+ #endif
+
+ nxagentSynchronizeBox(pDst -> pDrawable, &glyphBox, NEVER_BREAK);
+ }
+
+ if (pDst -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentIncreasePixmapUsageCounter((PixmapPtr) pDst -> pDrawable);
+ }
+ }
+
+ nxagentSetDrawableContainGlyphs(pDst -> pDrawable, 1);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: Glyph flag set on drawable [%s][%p].\n",
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ #ifdef SPLIT_GLYPH_LISTS
+
+ /*
+ * We split glyphs lists here and recalculate
+ * the offsets of each list to make them ab-
+ * solute and not relatives to the prior list.
+ * This way each time we call XRenderComposi-
+ * teText it has to deal only with a list of
+ * glyphs. This is done to further improve
+ * caching.
+ */
+
+ elements = elts;
+
+ if (nlists > 1)
+ {
+ for (j = 1; j < nlists; j++)
+ {
+ x = elements -> xOff;
+ y = elements -> yOff;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: Element [%d] of [%d] has offset [%d,%d].\n",
+ j, nlists, elements -> xOff, elements -> yOff);
+ #endif
+
+ for (i = 0; i < elements -> nchars; i++)
+ {
+ glyph = *glyphsBase++;
+
+ x += glyph -> info.xOff;
+ y += glyph -> info.yOff;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: Glyph at index [%d] has offset [%d,%d] and "
+ "position [%d,%d].\n", i, elements -> nchars, glyph -> info.xOff,
+ glyph -> info.yOff, x, y);
+ #endif
+ }
+
+ elements++;
+
+ elements -> xOff += x;
+ elements -> yOff += y;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: New offset for list at [%p] is [%d,%d].\n",
+ elements, elements -> xOff, elements -> yOff);
+ #endif
+ }
+
+ elements = elts;
+ }
+
+ switch (sizeID)
+ {
+ case 1:
+ {
+ for (j = 0; j < nlists; j++)
+ {
+ XRenderCompositeText8(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc)->picture,
+ nxagentPicturePriv(pDst)->picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt8*) elements,
+ 1);
+
+ elements++;
+ }
+
+ break;
+ }
+ case 2:
+ {
+ for (j = 0; j < nlists; j++)
+ {
+ XRenderCompositeText16(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt16*) elements,
+ 1);
+
+ elements++;
+ }
+
+ break;
+ }
+ case 4:
+ {
+ for (j = 0; j < nlists; j++)
+ {
+ XRenderCompositeText32(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt32*) elements,
+ 1);
+
+ elements++;
+ }
+
+ break;
+ }
+ default:
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentGlyphs: WARNING! Invalid size id [%d].\n",
+ sizeID);
+ #endif
+
+ break;
+ }
+ }
+
+ #else /* #ifdef SPLIT_GLYPH_LISTS */
+
+ elements = elts;
+
+ switch (sizeID)
+ {
+ case 1:
+ {
+ XRenderCompositeText8(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc)->picture,
+ nxagentPicturePriv(pDst)->picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt8*) elements,
+ nlists);
+
+ break;
+ }
+ case 2:
+ {
+ XRenderCompositeText16(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt16*) elements,
+ nlists);
+
+ break;
+ }
+ case 4:
+ {
+ XRenderCompositeText32(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt32*) elements,
+ nlists);
+
+ break;
+ }
+ default:
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentGlyphs: WARNING! Invalid size id [%d].\n",
+ sizeID);
+ #endif
+
+ break;
+ }
+ }
+
+ #endif /* #ifdef SPLIT_GLYPH_LISTS */
+}
+
+void nxagentCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color,
+ int nRect, xRectangle *rects)
+{
+ RegionPtr rectRegion;
+
+ if (pDst == NULL)
+ {
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCompositeRects: Called for picture at [%p] with [%s] at [%p].\n",
+ (void *) pDst, (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ (void *) pDst -> pDrawable);
+ #endif
+
+ /*
+ * The CompositeRects() clears the destination's
+ * corrupted region like the PolyFillRects() does.
+ * As this case is harder to handle, at the moment
+ * we only check for two ops.
+ */
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized &&
+ (op == PictOpSrc ||
+ (op == PictOpOver && color -> alpha == 0xffff)))
+ {
+ rectRegion = RECTS_TO_REGION(pDst -> pDrawable -> pScreen, nRect, rects, CT_REGION);
+
+ if (pDst -> clientClipType != CT_NONE)
+ {
+ RegionRec tmpRegion;
+
+ REGION_INIT(pDst -> pDrawable -> pScreen, &tmpRegion, NullBox, 1);
+
+ REGION_COPY(pDst -> pDrawable -> pScreen, &tmpRegion, (RegionPtr) pDst -> clientClip);
+
+ if (pDst -> clipOrigin.x != 0 || pDst -> clipOrigin.y != 0)
+ {
+ REGION_TRANSLATE(pDst -> pDrawable -> pScreen, &tmpRegion, pDst -> clipOrigin.x, pDst -> clipOrigin.y);
+ }
+
+ REGION_INTERSECT(pDst -> pDrawable -> pScreen, rectRegion, rectRegion, &tmpRegion);
+
+ REGION_UNINIT(pDst -> pDrawable -> pScreen, &tmpRegion);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCompositeRects: Going to clean the drawable with extents [%d,%d,%d,%d].\n",
+ rectRegion -> extents.x1, rectRegion -> extents.y1, rectRegion -> extents.x2, rectRegion -> extents.y2);
+ #endif
+
+ nxagentUnmarkCorruptedRegion(pDst -> pDrawable, rectRegion);
+
+ REGION_DESTROY(pDrawable -> pScreen, rectRegion);
+ }
+
+ XRenderFillRectangles(nxagentDisplay,
+ op,
+ (Picture)nxagentPicturePriv(pDst) -> picture,
+ (XRenderColor *) color,
+ (XRectangle *) rects,
+ nRect);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps)
+{
+ XRenderPictFormat *pForm;
+
+ XTrapezoid *current = (XTrapezoid *) traps;
+
+ RegionPtr pDstRegion;
+
+ int remaining = ntrap;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentTrapezoids: Source [%p] destination [%p] coordinates "
+ "[%d,%d] elements [%d].\n", (void *) pSrc, (void *) pDst,
+ xSrc, ySrc, ntrap);
+ #endif
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ pForm = NULL;
+
+ if (maskFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(maskFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ #ifdef TEST
+
+ fprintf(stderr, "nxagentTrapezoids: Source is a [%s] of geometry [%d,%d].\n",
+ (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ pSrc -> pDrawable -> width, pSrc -> pDrawable -> height);
+
+ if (pSrc ->pDrawable != pDst -> pDrawable)
+ {
+ fprintf(stderr, "nxagentTrapezoids: Destination is a [%s] of geometry [%d,%d].\n",
+ (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ pDst -> pDrawable -> width, pDst -> pDrawable -> height);
+ }
+
+ #endif
+
+ /*
+ * If the destination drawable is not synchronized
+ * but the trapezoids extents are included in the
+ * dirty region, we can defer the operation.
+ */
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized &&
+ RECT_IN_REGION(pDst -> pDrawable -> pScreen, nxagentCorruptedRegion(pDst -> pDrawable),
+ nxagentTrapezoidExtents) == rgnIN)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTrapezoids: WARNING! Prevented operation on region [%d,%d,%d,%d] already dirty "
+ "for drawable [%s][%p].\n", nxagentTrapezoidExtents -> x1, nxagentTrapezoidExtents -> y1,
+ nxagentTrapezoidExtents -> x2, nxagentTrapezoidExtents -> y2,
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ if (pDst -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapContainTrapezoids((PixmapPtr) pDst -> pDrawable) = 1;
+ }
+
+ return;
+ }
+
+ /*
+ * If the destination doesn't contain any glyphs,
+ * we can defer the trapezoids drawing by marking
+ * the destination as dirty.
+ */
+
+ if (NXAGENT_SHOULD_DEFER_TRAPEZOIDS(pDst -> pDrawable))
+ {
+ pDstRegion = nxagentCreateRegion(pDst -> pDrawable, NULL,
+ nxagentTrapezoidExtents -> x1,
+ nxagentTrapezoidExtents -> y1,
+ nxagentTrapezoidExtents -> x2 - nxagentTrapezoidExtents -> x1,
+ nxagentTrapezoidExtents -> y2 - nxagentTrapezoidExtents -> y1);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentTrapezoids: WARNING! Prevented operation on region [%d,%d,%d,%d] "
+ "for drawable [%s][%p].\n", pDstRegion -> extents.x1, pDstRegion -> extents.y1,
+ pDstRegion -> extents.x2, pDstRegion -> extents.y2,
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentMarkCorruptedRegion(pDst -> pDrawable, pDstRegion);
+
+ nxagentFreeRegion(pDst -> pDrawable, pDstRegion);
+
+ if (pDst -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapContainTrapezoids((PixmapPtr) pDst -> pDrawable) = 1;
+ }
+
+ return;
+ }
+
+ if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTrapezoids: Going to synchronize the source drawable at [%p].\n",
+ (void *) pSrc -> pDrawable);
+ #endif
+
+ nxagentSynchronizeBox(pSrc -> pDrawable, NullBox, NEVER_BREAK);
+ }
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTrapezoids: Going to synchronize the destination drawable at [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentSynchronizeBox(pDst -> pDrawable, nxagentTrapezoidExtents, NEVER_BREAK);
+ }
+
+ while (remaining > 0)
+ {
+ XRenderCompositeTrapezoids(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ (XTrapezoid *) current,
+ (remaining > TRAPEZOIDS_PER_REQUEST ?
+ TRAPEZOIDS_PER_REQUEST : remaining));
+
+ remaining -= TRAPEZOIDS_PER_REQUEST;
+ current += TRAPEZOIDS_PER_REQUEST;
+ }
+
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentRasterizeTrapezoid(PicturePtr pMask, xTrapezoid *trap,
+ int x_off, int y_off)
+{
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentRasterizeTrapezoids: Nothing to do.\n");
+ #endif
+}
+
+void nxagentTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle *tris)
+{
+ XRenderPictFormat *pForm;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentTriangles: Source [%p] Destination [%p] Coordinates [%d,%d] Elements [%d].\n",
+ (void *) pSrc, (void *) pDst, xSrc, ySrc, ntri);
+ #endif
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ pForm = NULL;
+
+ if (maskFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(maskFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+
+ /*
+ * If the X_RenderCompositeTriangles requests
+ * increment the traffic, we can defer the
+ * operation like nxagentTrapezoids() does.
+ */
+
+ if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriangles: Going to synchronize the source drawable at [%p].\n",
+ (void *) pSrc -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriangles: Going to synchronize the destination drawable at [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ XRenderCompositeTriangles(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ (XTriangle*)tris,
+ ntri);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points)
+{
+ XRenderPictFormat *pForm;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentTriStrip: Source [%p] Destination [%p] Coordinates [%d,%d] Elements [%d].\n",
+ (void *) pSrc, (void *) pDst, xSrc, ySrc, npoint);
+ #endif
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ pForm = NULL;
+
+ if (maskFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(maskFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+
+ /*
+ * If the X_RenderCompositeTriStrip requests
+ * increment the traffic, we can defer the
+ * operation like nxagentTrapezoids() does.
+ */
+
+ if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriStrip: Going to synchronize the source drawable at [%p].\n",
+ (void *) pSrc -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriStrip: Going to synchronize the destination drawable at [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ XRenderCompositeTriStrip(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ (XPointFixed*)points,
+ npoint);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points)
+{
+ XRenderPictFormat *pForm;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentTriFan: Source [%p] Destination [%p] Coordinates [%d,%d] Elements [%d].\n",
+ (void *) pSrc, (void *) pDst, xSrc, ySrc, npoint);
+ #endif
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ pForm = NULL;
+
+ if (maskFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(maskFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+
+ /*
+ * If the X_RenderCompositeTriFan requests
+ * increment the traffic, we can defer the
+ * operation like nxagentTrapezoids() does.
+ */
+
+ if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriFan: Going to synchronize the source drawable at [%p].\n",
+ (void *) pSrc -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriFan: Going to synchronize the destination drawable at [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ XRenderCompositeTriFan(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ (XPointFixed*)points,
+ npoint);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+#ifndef NXAGENT_UPGRADE
+
+/*
+FIXME: In the 3.0.0 port these functions have been moved
+ to Picture.c. We can remove them when the port is
+ is complete.
+*/
+int AllocatePicturePrivateIndex()
+{
+ return picturePrivateCount++;
+}
+
+Bool AllocatePicturePrivate(register ScreenPtr pScreen, int index2, unsigned amount)
+{
+ unsigned oldamount;
+
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ /*
+ * Round up the size for proper alignment.
+ */
+
+ amount = ((amount + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long);
+
+ if (index2 >= ps -> PicturePrivateLen)
+ {
+ unsigned *nsizes = (unsigned *) xrealloc(ps -> PicturePrivateSizes,
+ (index2 + 1) * sizeof(unsigned));
+ if (nsizes == 0)
+ {
+ return 0;
+ }
+
+ while (ps -> PicturePrivateLen <= index2)
+ {
+ nsizes[ps -> PicturePrivateLen++] = 0;
+
+ ps -> totalPictureSize += sizeof(DevUnion);
+ }
+
+ ps -> PicturePrivateSizes = nsizes;
+ }
+
+ oldamount = ps -> PicturePrivateSizes[index2];
+
+ if (amount > oldamount)
+ {
+ ps -> PicturePrivateSizes[index2] = amount;
+
+ ps -> totalPictureSize += (amount - oldamount);
+ }
+
+ return 1;
+}
+#endif
+
+void nxagentQueryFormats()
+{
+ XRenderInfo *xri;
+ XExtDisplayInfo *info = NULL;
+ XRenderPictFormat *pformat=NULL;
+
+ int i;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentQueryFormats.\n");
+ #endif
+
+ if (XRenderQueryFormats(nxagentDisplay))
+ {
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ info = (XExtDisplayInfo *) XRenderFindDisplay(nxagentDisplay);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ xri = (XRenderInfo *) info -> data;
+
+ pformat = xri -> format;
+
+ for (i = 0; i < xri -> nformat; i++)
+ {
+ nxagentArrayFormats[i] = *pformat;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentQueryFormats: Added format type [%d] depth [%d] rgb [%d,%d,%d] "
+ "mask rgb [%d,%d,%d] alpha [%d] alpha mask [%d].\n",
+ nxagentArrayFormats[i].type, nxagentArrayFormats[i].depth, nxagentArrayFormats[i].direct.red,
+ nxagentArrayFormats[i].direct.green, nxagentArrayFormats[i].direct.blue,
+ nxagentArrayFormats[i].direct.redMask, nxagentArrayFormats[i].direct.greenMask,
+ nxagentArrayFormats[i].direct.blueMask, nxagentArrayFormats[i].direct.alpha,
+ nxagentArrayFormats[i].direct.alphaMask);
+ #endif
+
+ pformat++;
+ }
+
+ #ifdef DEBUG
+
+ if (nxagentNumFormats == 0)
+ {
+ fprintf(stderr, "nxagentQueryFormats: Number of formats is [%d].\n",
+ i);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentQueryFormats: Old number of formats is [%d]. New number of formats is [%d].\n",
+ nxagentNumFormats, i);
+ }
+
+ #endif
+
+ nxagentNumFormats = i;
+ }
+}
+
+void nxagentCreateGlyphSet(GlyphSetPtr pGly)
+{
+ XRenderPictFormat *pForm;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCreateGlyphSet: Glyphset at [%p].\n", (void *) pGly);
+ #endif
+
+ pForm = NULL;
+
+ if (pGly -> format != NULL)
+ {
+ pForm = nxagentMatchingFormats(pGly -> format);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+
+ pGly -> remoteID = XRenderCreateGlyphSet(nxagentDisplay, pForm);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet)
+{
+ if (glyphSet -> remoteID == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReferenceGlyphSet: Operation deferred because glyphset at [%p] is corrupted.\n",
+ (void *) glyphSet);
+ #endif
+
+ return;
+ }
+
+ XRenderReferenceGlyphSet (nxagentDisplay, glyphSet -> remoteID);
+}
+
+void nxagentFreeGlyphSet(GlyphSetPtr glyphSet)
+{
+ if (glyphSet -> remoteID == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentFreeGlyphs: Operation ignored because glyphset at [%p] is corrupted.\n",
+ (void *) glyphSet);
+ #endif
+
+ return;
+ }
+
+ XRenderFreeGlyphSet(nxagentDisplay, glyphSet -> remoteID);
+}
+
+void nxagentAddGlyphs(GlyphSetPtr glyphSet, Glyph *gids, xGlyphInfo *gi,
+ int nglyphs, CARD8 *images, int sizeImages)
+{
+ GlyphRefPtr gr;
+ Glyph *tempGids;
+
+ int i;
+
+ CARD8 *normalizedImages;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAddGlyphs: Glyphset at [%p]. Number of glyphs [%d].\n",
+ (void *) glyphSet, nglyphs);
+ #endif
+
+ if (glyphSet -> remoteID == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentAddGlyphs: Going to reconnect the glyhpset at [%p] before adding glyphs.\n",
+ (void *) glyphSet);
+ #endif
+
+ nxagentReconnectGlyphSet(glyphSet, (XID) 0, (void*) NULL);
+ }
+
+ /*
+ * By adding a glyph to a glyphset on
+ * remote X server we mark its reference
+ * as synchronized.
+ */
+
+ tempGids = gids;
+
+ for (i = 0; i < nglyphs; i++)
+ {
+ if ((gr = FindGlyphRef(&glyphSet -> hash, *tempGids, 0, 0)) &&
+ gr -> glyph != DeletedGlyph)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAddGlyphs: Added Glyph [%p][%ld] to glyphset [%p].\n",
+ (void *) gr -> glyph, *tempGids, (void *) glyphSet);
+ #endif
+
+ gr -> corruptedGlyph = 0;
+ }
+
+ tempGids++;
+ }
+
+ normalizedImages = NULL;
+
+ if (glyphDepths[glyphSet -> fdepth] == 1 &&
+ nxagentServerOrder() != BitmapBitOrder(nxagentDisplay))
+ {
+ normalizedImages = xalloc(sizeImages);
+
+ if (normalizedImages != NULL)
+ {
+ memcpy(normalizedImages, images, sizeImages);
+
+ BitOrderInvert ((unsigned char *) normalizedImages, sizeImages);
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentAddGlyphs: PANIC! Allocation of normalized glyph images failed.\n");
+ #endif
+ }
+ }
+
+ if (normalizedImages == NULL)
+ {
+ normalizedImages = images;
+ }
+
+ XRenderCleanGlyphs(gi, nglyphs, normalizedImages, glyphDepths[glyphSet -> fdepth], nxagentDisplay);
+
+ XRenderAddGlyphs(nxagentDisplay,
+ glyphSet -> remoteID,
+ gids,
+ (XGlyphInfo*)(gi),
+ nglyphs,
+ (char*) normalizedImages,
+ sizeImages);
+
+ if (normalizedImages != images)
+ {
+ xfree(normalizedImages);
+ }
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph)
+{
+ GlyphRefPtr gr;
+ CARD32 *tempGids;
+ Glyph gid;
+
+ int i;
+
+ if (glyphSet -> remoteID == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentFreeGlyphs: Operation ignored because glyphset at [%p] is corrupted.\n",
+ (void *) glyphSet);
+ #endif
+
+ return;
+ }
+
+ /*
+ * We loop across the list of glyphs id
+ * to establish if they have been added
+ * to glyphset on remote X server, so
+ * they can be freed.
+ */
+
+ tempGids = gids;
+
+ for (i = 0; i < nglyph; i++)
+ {
+ gid = (Glyph)*tempGids;
+
+ if ((gr = FindGlyphRef(&glyphSet -> hash, *tempGids, 0, 0)) &&
+ gr -> glyph != DeletedGlyph &&
+ gr -> corruptedGlyph == 0)
+ {
+ XRenderFreeGlyphs(nxagentDisplay, glyphSet -> remoteID, &gid, 1);
+ }
+
+ tempGids++;
+ }
+}
+
+void nxagentSetPictureTransform(PicturePtr pPicture, pointer transform)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetPictureTransform: Going to set transform [%p] to picture at [%p].\n",
+ (void *) transform, (void *) pPicture);
+ #endif
+
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ XRenderSetPictureTransform(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ (XTransform *) transform);
+ #endif
+}
+
+void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size,
+ pointer params, int nparams)
+{
+ char *szFilter = Xmalloc(name_size + 1);
+
+ if (szFilter == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSetPictureFilter: error allocating memory for filter name.\n");
+ #endif
+
+ return;
+ }
+
+ strncpy(szFilter, filter, name_size);
+
+ szFilter[name_size] = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetPictureFilter: Going to set filter [%s] to picture at [%p].\n",
+ szFilter, (void *) pPicture);
+ #endif
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ XRenderSetPictureFilter(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ szFilter,
+ (XFixed *) params,
+ nparams);
+ #endif
+
+ Xfree(szFilter);
+}
+
+
+Bool nxagentPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
+{
+ #ifdef RENDER
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPictureInit: Screen [%p].\n", (void *) pScreen);
+ #endif
+
+ nxagentQueryFormats();
+
+ if (fbPictureInit(pScreen, formats, nformats) == 0)
+ {
+ return FALSE;
+ }
+
+ nxagentPicturePrivateIndex = AllocatePicturePrivateIndex();
+
+ AllocatePicturePrivate(pScreen, nxagentPicturePrivateIndex, sizeof(nxagentPrivPictureRec));
+
+ #endif
+
+ return TRUE;
+}
+
+#ifdef DEBUG
+
+static void nxagentPrintFormat(XRenderPictFormat *pFormat)
+{
+ if (pFormat == NULL)
+ {
+ fprintf(stderr, "nxagentPrintFormat: WARNING! null pointer passed to function.\n");
+
+ return;
+ }
+
+ fprintf(stderr, "nxagentPrintFormat: Dumping information for format at [%p]:\n\
+ type=%d\n\
+ depth=%d\n\
+ red=%d\n\
+ redMask=%d\n\
+ green=%d\n\
+ greenMask=%d\n\
+ blue=%d\n\
+ blueMask=%d\n\
+ alpha=%d\n\
+ alphaMask=%d\n",
+ (void *) pFormat,
+ pFormat -> type,
+ pFormat -> depth,
+ pFormat -> direct.red,
+ pFormat -> direct.redMask,
+ pFormat -> direct.green,
+ pFormat -> direct.greenMask,
+ pFormat -> direct.blue,
+ pFormat -> direct.blueMask,
+ pFormat -> direct.alpha,
+ pFormat -> direct.alphaMask);
+}
+
+#endif
+
+Bool nxagentFillGlyphSet(GlyphSetPtr pGly)
+{
+ GlyphPtr glyph;
+
+ int i;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentFillGlyphSet: GlyphSet at [%p] Refcount [%ld] Glyphs [%ld] "
+ "Format [%p] FDepth [%d] RemoteID [%ld].\n", (void *) pGly, pGly -> refcnt,
+ pGly -> hash.hashSet -> size, (void *) pGly -> format, pGly -> fdepth, pGly -> remoteID);
+ #endif
+
+ /*
+ * The glyphs are synchronized when they
+ * are used in a composite text. During
+ * the reconnection we have only to mark
+ * corrupted the glyphs for each glyphset.
+ */
+
+ for (i = 0; i < pGly -> hash.hashSet -> size; i++)
+ {
+ glyph = pGly -> hash.table[i].glyph;
+
+ if (glyph && (glyph != DeletedGlyph))
+ {
+ pGly -> hash.table[i].corruptedGlyph = 1;
+ }
+ }
+
+ return TRUE;
+}
+
+void nxagentReconnectGlyphSet(void* p0, XID x1, void *p2)
+{
+ GlyphSetPtr pGly = (GlyphSetPtr) p0;
+
+ XRenderPictFormat *pForm = NULL;
+
+ int i;
+
+ if (nxagentReconnectTrap == 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentReconnectGlyphSet: GlyphSet at [%p].\n", (void *) pGly);
+ #endif
+
+ if (pGly -> format)
+ {
+ pForm = nxagentMatchingFormats(pGly -> format);
+ }
+
+ pGly -> remoteID = XRenderCreateGlyphSet(nxagentDisplay, pForm);
+
+ /*
+ * If we have deferred the operation, we
+ * have to check the number of references
+ * to the glyphset to update the X server.
+ */
+
+ if ((i = pGly -> refcnt) > 1)
+ {
+ while (i-- > 1)
+ {
+ nxagentReferenceGlyphSet(pGly);
+ }
+ }
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ nxagentFillGlyphSet(pGly);
+ }
+ else
+ {
+ pGly -> remoteID = 0;
+ }
+}
+
+Bool nxagentReconnectAllGlyphSet(void *p)
+{
+ Bool success = TRUE;
+ int i;
+
+ nxagentQueryFormats();
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentReconnectAllGlyphSet\n");
+ #endif
+
+ for (i = 0; (i < MAXCLIENTS) && (success); i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], GlyphSetType, nxagentReconnectGlyphSet, &success);
+ }
+ }
+
+ return success;
+}
+
+void nxagentReconnectPicture(pointer p0, XID x1, void *p2)
+{
+ PicturePtr pPicture = (PicturePtr) p0;
+ Bool *pBool = (Bool *) p2;
+ unsigned long mask = 0;
+
+ XRenderPictureAttributes attributes;
+ XRenderPictFormat *pForm;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectPicture: Called with bool [%d] and picture at [%p].\n",
+ *pBool, (void *) pPicture);
+
+ fprintf(stderr, "nxagentReconnectPicture: Virtual picture is [%ld].\n",
+ nxagentPicture(pPicture));
+ #endif
+
+ /*
+ * Check if a previous operation has failed
+ * and that the involved objects are valid.
+ */
+
+ if (*pBool == 0 || pPicture == NULL ||
+ nxagentPicture(pPicture) != 0)
+ {
+ return;
+ }
+
+ if (pPicture -> repeat)
+ {
+ mask |= CPRepeat;
+
+ attributes.repeat = (Bool) pPicture -> repeat;
+ }
+
+ if (pPicture -> alphaMap)
+ {
+ if (!nxagentPicture(pPicture -> alphaMap))
+ {
+ nxagentReconnectPicture(pPicture -> alphaMap, 0, pBool);
+
+ if (!*pBool || !nxagentPicture(pPicture -> alphaMap))
+ {
+ return;
+ }
+ }
+
+ attributes.alpha_map = nxagentPicture(pPicture -> alphaMap);
+ attributes.alpha_x_origin = pPicture -> alphaOrigin.x;
+ attributes.alpha_y_origin = pPicture -> alphaOrigin.y;
+
+ mask |= (CPAlphaMap | CPAlphaXOrigin | CPAlphaYOrigin);
+ }
+
+ if (pPicture -> graphicsExposures)
+ {
+ attributes.graphics_exposures = pPicture -> graphicsExposures;
+
+ mask |= CPGraphicsExposure;
+ }
+
+ attributes.subwindow_mode = pPicture -> subWindowMode;
+
+ mask |= CPSubwindowMode;
+
+ attributes.poly_edge = pPicture -> polyEdge;
+
+ mask |= CPPolyEdge;
+
+ attributes.poly_mode = pPicture -> polyMode;
+
+ mask |= CPPolyMode;
+
+ attributes.dither = pPicture -> dither;
+
+ mask |= CPDither;
+
+ attributes.component_alpha = pPicture -> componentAlpha;
+
+ mask |= CPComponentAlpha;
+
+ pForm = NULL;
+
+ if (pPicture -> pFormat)
+ {
+ pForm = nxagentMatchingFormats(pPicture -> pFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+ }
+
+ if (!pForm)
+ {
+ *pBool = False;
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectPicture: Creating picture at [%p] with drawable [%ld] at [%p].\n",
+ (void *) pPicture, nxagentDrawable(pPicture -> pDrawable), (void *) pPicture -> pDrawable);
+
+ fprintf(stderr, "nxagentReconnectPicture: Format is at [%p] mask is [%ld] attributes are at [%p].\n",
+ (void *) pForm, mask, (void *) &attributes);
+ #endif
+
+ nxagentPicture(pPicture) = XRenderCreatePicture(nxagentDisplay,
+ nxagentDrawable(pPicture -> pDrawable),
+ pForm,
+ mask,
+ &attributes);
+
+ #ifdef TEST
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectPicture: Reconnected picture at [%p] with value [%ld].\n",
+ (void *) pPicture, nxagentPicture(pPicture));
+ #endif
+
+ if (nxagentAlphaEnabled == 1 && pPicture -> pDrawable -> depth == 32 &&
+ pPicture -> pFormat -> direct.alpha != 0)
+ {
+ if (pPicture -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapPriv((PixmapPtr) pPicture -> pDrawable) -> pPicture = pPicture;
+ }
+ else if (pPicture -> pDrawable -> type == DRAWABLE_WINDOW)
+ {
+ nxagentWindowPriv((WindowPtr) pPicture -> pDrawable) -> pPicture = pPicture;
+ }
+ }
+}
+
+Bool nxagentReconnectAllPicture(void *p)
+{
+ int i;
+ Bool r;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectAllPicture: Going to recreate all pictures.\n");
+ #endif
+
+ for (i = 0, r = 1; i < MAXCLIENTS; i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], PictureType, nxagentReconnectPicture, &r);
+
+ #ifdef WARNING
+
+ if (r == False)
+ {
+ fprintf(stderr, "nxagentReconnectAllPicture: WARNING! Failed to recreate "
+ "picture for client [%d].\n", i);
+ }
+
+ #endif
+ }
+ }
+
+ return True;
+}
+
+void nxagentDisconnectPicture(pointer p0, XID x1, void* p2)
+{
+ PicturePtr pPicture = (PicturePtr) p0;
+ Bool *pBool = (Bool *) p2;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectPicture: Called with bool [%d] and picture at [%p].\n",
+ *pBool, (void *) pPicture);
+
+ fprintf(stderr, "nxagentDisconnectPicture: Virtual picture is [%ld].\n",
+ nxagentPicture(pPicture));
+ #endif
+
+ if (!*pBool || !pPicture)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDisconnectPicture: %p - XID %lx\n",
+ (void *) pPicture, nxagentPicture(pPicture));
+ #endif
+
+ nxagentPicture(pPicture) = None;
+}
+
+Bool nxagentDisconnectAllPicture()
+{
+ int i;
+ Bool r;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDisconnectAllPicture.\n");
+ #endif
+
+ for (i = 0, r = 1; i < MAXCLIENTS; i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], PictureType, nxagentDisconnectPicture, &r);
+
+ #ifdef WARNING
+
+ if (r == False)
+ {
+ fprintf(stderr, "nxagentDisconnectAllPicture: WARNING! Failed to disconnect "
+ "picture for client [%d].\n", i);
+ }
+
+ #endif
+ }
+ }
+
+ return True;
+}
+