diff options
Diffstat (limited to 'nx-X11/programs/Xserver/hw/nxagent/GCOps.c')
-rw-r--r-- | nx-X11/programs/Xserver/hw/nxagent/GCOps.c | 1995 |
1 files changed, 1995 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/nxagent/GCOps.c b/nx-X11/programs/Xserver/hw/nxagent/GCOps.c new file mode 100644 index 000000000..7a6432a8e --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/GCOps.c @@ -0,0 +1,1995 @@ +/**************************************************************************/ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ + +/* + +Copyright 1993 by Davor Matic + +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. Davor Matic makes no representations about +the suitability of this software for any purpose. It is provided "as +is" without express or implied warranty. + +*/ + +#include "scrnintstr.h" +#include "resource.h" +#include "dixstruct.h" +#include "../../fb/fb.h" + +#include "Agent.h" +#include "Composite.h" +#include "Display.h" +#include "Visual.h" +#include "Drawable.h" +#include "Pixmaps.h" +#include "GCs.h" +#include "Image.h" +#include "Font.h" +#include "Events.h" +#include "Client.h" +#include "Trap.h" +#include "Holder.h" +#include "Args.h" +#include "Screen.h" + +#include "NXlib.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +#undef DUMP + +/* + * Temporarily set/reset the trap. + */ + +static int nxagentSaveGCTrap; + +#define SET_GC_TRAP() \ +{ \ + nxagentSaveGCTrap = nxagentGCTrap;\ +\ + nxagentGCTrap = 1; \ +} + +#define RESET_GC_TRAP() \ +{ \ + nxagentGCTrap = nxagentSaveGCTrap; \ +} + +/* + * This is currently unused. + */ + +RegionPtr nxagentBitBlitHelper(GC *pGC); + +/* + * The NX agent implementation of the + * X server's graphics functions. + */ + +void nxagentFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nSpans, + xPoint *pPoints, int *pWidths, int fSorted) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to FillSpans on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbFillSpans(nxagentVirtualDrawable(pDrawable), pGC, nSpans, pPoints, pWidths, fSorted); + } + else + { + fbFillSpans(pDrawable, pGC, nSpans, pPoints, pWidths, fSorted); + } +} + +void nxagentSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pSrc, + xPoint *pPoints, int *pWidths, int nSpans, int fSorted) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to SetSpans on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbSetSpans(nxagentVirtualDrawable(pDrawable), pGC, pSrc, pPoints, pWidths, nSpans, fSorted); + } + else + { + fbSetSpans(pDrawable, pGC, pSrc, pPoints, pWidths, nSpans, fSorted); + } +} + +void nxagentGetSpans(DrawablePtr pDrawable, int maxWidth, xPoint *pPoints, + int *pWidths, int nSpans, char *pBuffer) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: going to GetSpans on FB pixmap [%p].\n", + (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbGetSpans(nxagentVirtualDrawable(pDrawable), maxWidth, pPoints, pWidths, nSpans, pBuffer); + } + else + { + fbGetSpans(pDrawable, maxWidth, pPoints, pWidths, nSpans, pBuffer); + } +} + +void nxagentQueryBestSize(int class, unsigned short *pwidth, + unsigned short *pheight, ScreenPtr pScreen) +{ + unsigned width, test; + + switch(class) + { + case CursorShape: + if (*pwidth > pScreen->width) + *pwidth = pScreen->width; + if (*pheight > pScreen->height) + *pheight = pScreen->height; + break; + case TileShape: + case StippleShape: + width = *pwidth; + if (!width) break; + /* Return the closes power of two not less than what they gave me */ + test = 0x80000000; + /* Find the highest 1 bit in the width given */ + while(!(test & width)) + test >>= 1; + /* If their number is greater than that, bump up to the next + * power of two */ + if((test - 1) & width) + test <<= 1; + *pwidth = test; + /* We don't care what height they use */ + break; + } +} + +RegionPtr nxagentBitBlitHelper(GC *pGC) +{ + #ifdef TEST + fprintf(stderr, "nxagentBitBlitHelper: Called for GC at [%p].\n", (void *) pGC); + #endif + + /* + * Force NullRegion. We consider enough the graphics + * expose events generated internally by the nxagent + * server. + */ + + #ifdef TEST + fprintf(stderr, "nxagentBitBlitHelper: WARNING! Skipping check on exposures events.\n"); + #endif + + return NullRegion; +} + +/* + * The deferring of X_RenderCompositeTrapezoids caused + * an ugly effect on pulldown menu: as the background + * may be not synchronized, the text floats in an invi- + * sible window. To avoid such effects, we use a system + * to guess if the destination target of a copy area + * is a popup, by assuming that those kind of windows + * use the override redirect property. + */ + +int nxagentWindowIsPopup(DrawablePtr pDrawable) +{ + WindowPtr parent; + + int windowIsPopup; + int level; + + if (pDrawable -> type != DRAWABLE_WINDOW) + { + return 0; + } + + windowIsPopup = 0; + + if (((WindowPtr) pDrawable) -> overrideRedirect == 1) + { + windowIsPopup = 1; + } + else + { + parent = ((WindowPtr) pDrawable) -> parent; + + /* + * Go up on the tree until a parent + * exists or 4 windows has been che- + * cked. This seems a good limit to + * up children's popup. + */ + + level = 0; + + while (parent != NULL && ++level <= 4) + { + #ifdef DEBUG + fprintf(stderr, "nxagentWindowIsPopup: Window [%p] has parent [%p] in tree with OverrideRedirect [%d] " + " Level [%d].\n", (void *) pDrawable, (void *) parent, parent -> overrideRedirect, level); + #endif + + if (parent -> overrideRedirect == 1) + { + windowIsPopup = 1; + + break; + } + + parent = parent -> parent; + } + } + + #ifdef TEST + fprintf(stderr, "nxagentWindowIsPopup: Window [%p] %s to be a popup.\n", (void *) pDrawable, + windowIsPopup == 1 ? "seems" : "does not seem"); + #endif + + return windowIsPopup; +} + +/* + * This function returns 1 if the + * XCopyArea request must be skipped. + */ + +int nxagentDeferCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GCPtr pGC, int srcx, int srcy, int width, + int height, int dstx, int dsty) +{ + RegionPtr pSrcRegion; + RegionPtr pClipRegion, pCorruptedRegion; + RegionRec corruptedRegion, tmpRegion; + + /* + * If the destination drawable is a popup + * window, we try to synchronize the source + * drawable to show a nice menu. Anyway if + * this synchronization breaks, the copy area + * is handled in the normal way. + */ + +/* +FIXME: The popup could be synchronized with one + single put image, clipped to the corrup- + ted region. As an intermediate step, the + pixmap to synchronize could be copied on + a cleared scratch pixmap, in order to + have a solid color in the clipped regions. +*/ + + if (nxagentOption(DeferLevel) >= 2 && + pSrcDrawable -> type == DRAWABLE_PIXMAP && + nxagentPixmapContainTrapezoids((PixmapPtr) pSrcDrawable) == 1 && + nxagentWindowIsPopup(pDstDrawable) == 1) + { + pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Copying to a popup menu. Source region [%d,%d,%d,%d].\n", + pSrcRegion -> extents.x1, pSrcRegion -> extents.y1, + pSrcRegion -> extents.x2, pSrcRegion -> extents.y2); + #endif + + REGION_INIT(pSrcDrawable -> pScreen, &corruptedRegion, NullBox, 1); + + REGION_INTERSECT(pSrcDrawable -> pScreen, &corruptedRegion, + pSrcRegion, nxagentCorruptedRegion(pSrcDrawable)); + + if (REGION_NIL(&corruptedRegion) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentDeferCopyArea: Forcing the synchronization of source drawable at [%p].\n", + (void *) pSrcDrawable); + #endif + + nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion, EVENT_BREAK, NULL); + } + + REGION_UNINIT(pSrcDrawable -> pScreen, &corruptedRegion); + + nxagentFreeRegion(pSrcDrawable, pSrcRegion); + + if (nxagentDrawableStatus(pSrcDrawable) == Synchronized) + { + return 0; + } + } + + /* + * We are going to decide if the source drawable + * must be synchronized before using it, or if + * the copy will be clipped to the synchronized + * source region. + */ + + if ((pDstDrawable -> type == DRAWABLE_PIXMAP && + nxagentOption(DeferLevel) > 0) || nxagentOption(DeferLevel) >= 2) + { + pClipRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, + width, height); + + /* + * We called this variable pCorruptedRegion + * because in the worst case the corrupted + * region will be equal to the destination + * region. The GC's clip mask is used to + * narrow the destination. + */ + + pCorruptedRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, + width, height); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Copy area source region is [%d,%d,%d,%d].\n", + pClipRegion -> extents.x1, pClipRegion -> extents.y1, + pClipRegion -> extents.x2, pClipRegion -> extents.y2); + #endif + + REGION_SUBTRACT(pSrcDrawable -> pScreen, pClipRegion, pClipRegion, nxagentCorruptedRegion(pSrcDrawable)); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Usable copy area source region is [%d,%d,%d,%d].\n", + pClipRegion -> extents.x1, pClipRegion -> extents.y1, + pClipRegion -> extents.x2, pClipRegion -> extents.y2); + #endif + + if (pGC -> clientClip == NULL || pGC -> clientClipType != CT_REGION) + { + #ifdef WARNING + + if (pGC -> clientClipType != CT_NONE) + { + fprintf(stderr, "nxagentDeferCopyArea: WARNING! pGC [%p] has a clip type [%d].\n", + (void *) pGC, pGC -> clientClipType); + } + + #endif + + REGION_TRANSLATE(pSrcDrawable -> pScreen, pClipRegion, dstx - srcx, dsty - srcy); + } + else + { + REGION_INIT(pDstDrawable -> pScreen, &tmpRegion, NullBox, 1); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Going to modify the original GC [%p] with clip mask " + "[%d,%d,%d,%d] and origin [%d,%d].\n", + (void *) pGC, + ((RegionPtr) pGC -> clientClip) -> extents.x1, ((RegionPtr) pGC -> clientClip) -> extents.y1, + ((RegionPtr) pGC -> clientClip) -> extents.x2, ((RegionPtr) pGC -> clientClip) -> extents.y2, + pGC -> clipOrg.x, pGC -> clipOrg.y); + #endif + + REGION_COPY(pDstDrawable -> pScreen, &tmpRegion, (RegionPtr) pGC -> clientClip); + + if (pGC -> clipOrg.x != 0 || pGC -> clipOrg.y != 0) + { + REGION_TRANSLATE(pDstDrawable -> pScreen, &tmpRegion, pGC -> clipOrg.x, pGC -> clipOrg.y); + } + + REGION_TRANSLATE(pSrcDrawable -> pScreen, pClipRegion, dstx - srcx, dsty - srcy); + + REGION_INTERSECT(pSrcDrawable -> pScreen, pClipRegion, &tmpRegion, pClipRegion); + + REGION_UNINIT(pSrcDrawable -> pScreen, &tmpRegion); + } + + /* + * The corrupted region on the destination + * drawable is composed by the areas of the + * destination that we are not going to copy. + */ + + REGION_SUBTRACT(pSrcDrawable -> pScreen, pCorruptedRegion, pCorruptedRegion, pClipRegion); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Recomputed clip region is [%d,%d,%d,%d][%ld].\n", + pClipRegion -> extents.x1, pClipRegion -> extents.y1, + pClipRegion -> extents.x2, pClipRegion -> extents.y2, + REGION_NUM_RECTS(pClipRegion)); + + fprintf(stderr, "nxagentDeferCopyArea: Inherited corrupted region is [%d,%d,%d,%d][%ld].\n", + pCorruptedRegion -> extents.x1, pCorruptedRegion -> extents.y1, + pCorruptedRegion -> extents.x2, pCorruptedRegion -> extents.y2, + REGION_NUM_RECTS(pCorruptedRegion)); + #endif + + /* + * The destination drawable inherits both the + * synchronized and the corrupted region. + */ + + if (REGION_NIL(pClipRegion) == 0) + { + nxagentUnmarkCorruptedRegion(pDstDrawable, pClipRegion); + } + + if (REGION_NIL(pCorruptedRegion) == 0) + { + nxagentMarkCorruptedRegion(pDstDrawable, pCorruptedRegion); + } + + if (REGION_NIL(pClipRegion) == 0) + { + GCPtr targetGC; + + CARD32 targetAttributes[2]; + + /* + * As we want to copy only the synchronized + * areas of the source drawable, we create + * a new GC copying the original one and + * setting a new clip mask. + */ + + targetGC = GetScratchGC(pDstDrawable -> depth, pDstDrawable -> pScreen); + + ValidateGC(pDstDrawable, targetGC); + + CopyGC(pGC, targetGC, GCFunction | GCPlaneMask | GCSubwindowMode | + GCClipXOrigin | GCClipYOrigin | GCClipMask | GCForeground | + GCBackground | GCGraphicsExposures); + + if (REGION_NUM_RECTS(pClipRegion) == 1) + { + /* + * If the region to copy is formed by one + * rectangle, we change only the copy coor- + * dinates. + */ + + srcx = srcx + pClipRegion -> extents.x1 - dstx; + srcy = srcy + pClipRegion -> extents.y1 - dsty; + + dstx = pClipRegion -> extents.x1; + dsty = pClipRegion -> extents.y1; + + width = pClipRegion -> extents.x2 - pClipRegion -> extents.x1; + height = pClipRegion -> extents.y2 - pClipRegion -> extents.y1; + } + else + { + /* + * Setting the clip mask origin. This + * operation must precede the clip chan- + * ge, because the origin information is + * used in the XSetClipRectangles(). + */ + + targetAttributes[0] = 0; + targetAttributes[1] = 0; + + ChangeGC(targetGC, GCClipXOrigin | GCClipYOrigin, targetAttributes); + + /* + * Setting the new clip mask. + */ + + nxagentChangeClip(targetGC, CT_REGION, pClipRegion, 0); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Going to execute a copy area with clip mask " + "[%d,%d,%d,%d] and origin [%d,%d].\n", ((RegionPtr) targetGC -> clientClip) -> extents.x1, + ((RegionPtr) targetGC -> clientClip) -> extents.y1, + ((RegionPtr) targetGC -> clientClip) -> extents.x2, + ((RegionPtr) targetGC -> clientClip) -> extents.y2, + targetGC -> clipOrg.x, targetGC -> clipOrg.y); + #endif + } + + XCopyArea(nxagentDisplay, nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable), + nxagentGC(targetGC), srcx, srcy, width, height, dstx, dsty); + + nxagentChangeClip(targetGC, CT_NONE, NullRegion, 0); + + FreeScratchGC(targetGC); + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentDeferCopyArea: The clipped region is NIL. CopyArea skipped.\n"); + #endif + + /* + * The pClipRegion is destroyed calling nxagentChangeClip(), + * so we deallocate it explicitly only if we don't change + * the clip. + */ + + nxagentFreeRegion(pSrcDrawable, pClipRegion); + } + + nxagentFreeRegion(pSrcDrawable, pCorruptedRegion); + + return 1; + } + else + { + pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height); + + #ifdef DEBUG + fprintf(stderr, "nxagentDeferCopyArea: Source region [%d,%d,%d,%d].\n", + pSrcRegion -> extents.x1, pSrcRegion -> extents.y1, + pSrcRegion -> extents.x2, pSrcRegion -> extents.y2); + #endif + + REGION_INIT(pSrcDrawable -> pScreen, &corruptedRegion, NullBox, 1); + + REGION_INTERSECT(pSrcDrawable -> pScreen, &corruptedRegion, + pSrcRegion, nxagentCorruptedRegion(pSrcDrawable)); + + if (REGION_NIL(&corruptedRegion) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentDeferCopyArea: Forcing the synchronization of source drawable at [%p].\n", + (void *) pSrcDrawable); + #endif + + nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion /*pSrcRegion*/, NEVER_BREAK, NULL); + } + + REGION_UNINIT(pSrcDrawable -> pScreen, &corruptedRegion); + + nxagentFreeRegion(pSrcDrawable, pSrcRegion); + } + + return 0; +} + +RegionPtr nxagentCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GCPtr pGC, int srcx, int srcy, int width, + int height, int dstx, int dsty) +{ + int leftPad = 0; + unsigned int format; + unsigned long planeMask = 0xffffffff; + + RegionPtr pDstRegion; + + int skip = 0; + + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Image src [%s:%p], dst [%s:%p] (%d,%d) -> (%d,%d) size (%d,%d)\n", + (pSrcDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable, + (pDstDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", + (void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height); + #endif + + if (nxagentGCTrap == 1 || nxagentShmTrap == 1) + { + if (pSrcDrawable -> type == DRAWABLE_PIXMAP && + pDstDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), + nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty); + } + else if (pSrcDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); + } + else if (pDstDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyArea(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty); + } + else + { + return fbCopyArea(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); + } + + return NullRegion; + } + + /* + * Try to detect if the copy area is to a window + * that is unmapped or fully covered. Similarly + * to the check in Image.c, this is of little use. + */ + + if (nxagentOption(IgnoreVisibility) == 0 && pDstDrawable -> type == DRAWABLE_WINDOW && + (nxagentWindowIsVisible((WindowPtr) pDstDrawable) == 0 || + (nxagentDefaultWindowIsVisible() == 0 && nxagentCompositeEnable == 0))) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Prevented operation on fully obscured window at [%p].\n", + (void *) pDstDrawable); + #endif + + return NullRegion; + } + + /* + * If the pixmap is on shared memory, we can't + * know if the pixmap content is changed and + * so have to translate the operation in a put + * image operation. This can seriously affect + * the performance. + */ + + if (pSrcDrawable -> type == DRAWABLE_PIXMAP && + nxagentIsShmPixmap((PixmapPtr) pSrcDrawable)) + { + char *data; + int depth, length; + + depth = pSrcDrawable -> depth; + + format = (depth == 1) ? XYPixmap : ZPixmap; + + length = nxagentImageLength(width, height, format, leftPad, depth); + + if ((data = xalloc(length)) == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentCopyArea: WARNING! Failed to allocate memory for the operation.\n"); + #endif + + return NullRegion; + } + + fbGetImage(nxagentVirtualDrawable(pSrcDrawable), srcx, srcy, width, height, format, planeMask, data); + + /* + * If the source is a shared memory pixmap, + * put the image directly to the destination. + */ + + nxagentPutImage(pDstDrawable, pGC, depth, dstx, dsty, + width, height, leftPad, format, data); + + #ifdef TEST + fprintf(stderr,"nxagentCopyArea: Realize Pixmap %p virtual %p x %d y %d w %d h %d\n", + (void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pSrcDrawable), + srcx, srcy, width, height); + #endif + + xfree(data); + + /* + * If the source is a shared memory pixmap, the + * content of the framebuffer has been placed + * directly on the destination so we can skip + * the copy area operation. + */ + + skip = 1; + } + + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Image src [%s:%p], dst [%s:%p] sx %d sy %d dx %d dy %d size w %d h %d\n", + ((pSrcDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable, + ((pDstDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", + (void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height); + #endif + + if (skip == 0 && nxagentDrawableStatus(pSrcDrawable) == NotSynchronized) + { + skip = nxagentDeferCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, + width, height, dstx, dsty); + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentCopyArea: Source drawable at [%p] already synchronized.\n", + (void *) pSrcDrawable); + } + #endif + + if (skip == 0) + { + XCopyArea(nxagentDisplay, nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable), + nxagentGC(pGC), srcx, srcy, width, height, dstx, dsty); + + /* + * The copy area restored the synchroni- + * zation status of destination drawable. + */ + + if (nxagentDrawableStatus(pDstDrawable) == NotSynchronized) + { + pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height); + + nxagentUnmarkCorruptedRegion(pDstDrawable, pDstRegion); + + nxagentFreeRegion(pDstDrawable, pDstRegion); + } + } + + if (nxagentDrawableContainGlyphs(pSrcDrawable) == 1) + { + nxagentSetDrawableContainGlyphs(pDstDrawable, 1); + } + + if (pSrcDrawable -> type == DRAWABLE_PIXMAP) + { + nxagentIncreasePixmapUsageCounter((PixmapPtr) pSrcDrawable); + } + + if (pSrcDrawable -> type == DRAWABLE_PIXMAP && + pDstDrawable -> type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Going to copy area from virtual pixmap [%p] to [%p]\n", + (void *) nxagentVirtualDrawable(pSrcDrawable), + (void *) nxagentVirtualDrawable(pDstDrawable)); + #endif + + return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), + nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty); + } + else if (pSrcDrawable -> type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Going to copy area from virtual pixmap [%p] to window [%p]\n", + (void *) nxagentVirtualDrawable(pSrcDrawable), + (void *) pDstDrawable); + #endif + + return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); + } + else if (pDstDrawable -> type == DRAWABLE_PIXMAP) + { + /* + * If we are here the source drawable + * must be a window. + */ + + if (((WindowPtr) pSrcDrawable) -> viewable) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Going to copy area from window [%p] to virtual pixmap [%p]\n", + (void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pDstDrawable)); + #endif + + return fbCopyArea(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty); + } + } + else + { + /* + * If we are here the source drawable + * must be a window. + */ + + if (((WindowPtr) pSrcDrawable) -> viewable) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyArea: Going to copy area from window [%p] to window [%p]\n", + (void *) pSrcDrawable, (void *) pDstDrawable); + #endif + + return fbCopyArea(pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty); + } + } + + return miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty, 0); +} + +RegionPtr nxagentCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, + GCPtr pGC, int srcx, int srcy, int width, int height, + int dstx, int dsty, unsigned long plane) +{ + unsigned int format; + int leftPad = 0; + unsigned long planeMask = 0xffffffff; + + RegionPtr pSrcRegion, pDstRegion; + RegionRec corruptedRegion; + + int skip = 0; + + #ifdef TEST + fprintf(stderr, "nxagentCopyPlane: Image src [%s:%p], dst [%s:%p] (%d,%d) -> (%d,%d) size (%d,%d)\n", + ((pSrcDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable, + ((pDstDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", + (void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height); + #endif + + if (nxagentGCTrap == 1 || nxagentShmTrap == 1) + { + if (pSrcDrawable -> type == DRAWABLE_PIXMAP && + pDstDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), + nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty, plane); + } + else if (pSrcDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, plane); + } + else if (pDstDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyPlane(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty, plane); + } + else + { + return fbCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, + dstx, dsty, plane); + } + + return NullRegion; + } + + /* + * If the pixmap is on shared memory, we can't + * know if the pixmap content is changed and + * so have to translate the operation in a put + * image operation. This can seriously affect + * the performance. + */ + + if (pSrcDrawable -> type == DRAWABLE_PIXMAP && + nxagentIsShmPixmap((PixmapPtr) pSrcDrawable)) + { + char *data; + int depth, length; + + depth = pSrcDrawable -> depth; + + format = (depth == 1) ? XYPixmap : ZPixmap; + + length = nxagentImageLength(width, height, format, leftPad, depth); + + if ((data = xalloc(length)) == NULL) + { + #ifdef DEBUG + fprintf(stderr, "nxagentCopyPlane: WARNING! Failed to allocate memory for the operation.\n"); + #endif + + return 0; + } + + fbGetImage(nxagentVirtualDrawable(pSrcDrawable), srcx, srcy, width, height, format, planeMask, data); + + /* + * If the source is a shared memory pixmap, + * put the image directly to the destination. + */ + + nxagentPutImage(pDstDrawable, pGC, depth, dstx, dsty, + width, height, leftPad, format, data); + + #ifdef TEST + fprintf(stderr,"nxagentCopyPlane: Synchronize Pixmap %p virtual %p x %d y %d w %d h %d \n", + (void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pSrcDrawable), + srcx, srcy, width, height); + #endif + + xfree(data); + + /* + * If the source is a shared memory pixmap, the + * content of the framebuffer has been placed + * directly on the destination so we can skip + * the copy plane operation. + */ + + skip = 1; + } + + if (skip == 0 && nxagentDrawableStatus(pSrcDrawable) == NotSynchronized) + { + if (pDstDrawable -> type == DRAWABLE_PIXMAP && + nxagentOption(DeferLevel) > 0) + { + pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height); + + nxagentMarkCorruptedRegion(pDstDrawable, pDstRegion); + + nxagentFreeRegion(pDstDrawable, pDstRegion); + + skip = 1; + } + else + { + pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height); + + REGION_INIT(pSrcDrawable -> pScreen, &corruptedRegion, NullBox, 1); + + REGION_INTERSECT(pSrcDrawable -> pScreen, &corruptedRegion, + pSrcRegion, nxagentCorruptedRegion(pSrcDrawable)); + + if (REGION_NIL(&corruptedRegion) == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyPlane: Forcing the synchronization of source drawable at [%p].\n", + (void *) pSrcDrawable); + #endif + + nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion /*pSrcRegion*/, NEVER_BREAK, NULL); + + pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height); + + nxagentUnmarkCorruptedRegion(pDstDrawable, pDstRegion); + + nxagentFreeRegion(pDstDrawable, pDstRegion); + } + + REGION_UNINIT(pSrcDrawable -> pScreen, &corruptedRegion); + + nxagentFreeRegion(pSrcDrawable, pSrcRegion); + } + } + #ifdef TEST + else + { + fprintf(stderr, "nxagentCopyPlane: Source drawable at [%p] already synchronized.\n", + (void *) pSrcDrawable); + } + #endif + + if (skip == 0) + { + XCopyPlane(nxagentDisplay, + nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable), + nxagentGC(pGC), srcx, srcy, width, height, dstx, dsty, plane); + } + + if ((pSrcDrawable)->type == DRAWABLE_PIXMAP && + (pDstDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "nxagentCopyPlane: going to copy plane from FB pixmap [%p] to [%p].\n", + (void *) nxagentVirtualDrawable(pSrcDrawable), + (void *) nxagentVirtualDrawable(pDstDrawable)); + #endif + + return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), + nxagentVirtualDrawable(pDstDrawable), + pGC, srcx, srcy, width, height, dstx, dsty, plane); + } + else if (pSrcDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty, plane); + } + else if (pDstDrawable -> type == DRAWABLE_PIXMAP) + { + return fbCopyPlane(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable), pGC, + srcx, srcy, width, height, dstx, dsty, plane); + } + else + { + return fbCopyPlane(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty, plane); + } + + return miHandleExposures(pSrcDrawable, pDstDrawable, pGC, + srcx, srcy, width, height, dstx, dsty, plane); +} + +void nxagentPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, + int nPoints, xPoint *pPoints) +{ + #ifdef TEST + fprintf(stderr, "nxagentPolyPoint: Drawable at [%p] GC at [%p] Points [%d].\n", + (void *) pDrawable, (void *) pGC, nPoints); + #endif + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + fbPolyPoint(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints); + } + else + { + fbPolyPoint(pDrawable, pGC, mode, nPoints, pPoints); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly point on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly point enters with virtual pixmap [%p] parent is [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawPoints(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XPoint *) pPoints, nPoints, mode); + } + } + else + { + XDrawPoints(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, mode); + } + + fbPolyPoint(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints); + + return; + } + else + { + XDrawPoints(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, mode); + + fbPolyPoint(pDrawable, pGC, mode, nPoints, pPoints); + } +} + +void nxagentPolyLines(DrawablePtr pDrawable, GCPtr pGC, int mode, + int nPoints, xPoint *pPoints) +{ + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + fbPolyLine(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints); + } + else + { + fbPolyLine(pDrawable, pGC, mode, nPoints, pPoints); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly line on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly lines enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawLines(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XPoint *) pPoints, nPoints, mode); + } + } + else + { + XDrawLines(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, mode); + } + + fbPolyLine(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints); + + return; + } + else + { + XDrawLines(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, mode); + + fbPolyLine(pDrawable, pGC, mode, nPoints, pPoints); + } +} + +void nxagentPolySegment(DrawablePtr pDrawable, GCPtr pGC, + int nSegments, xSegment *pSegments) +{ + #ifdef TEST + + if (nSegments == 1) + { + fprintf(stderr, "nxagentPolySegment: Drawable at [%p] GC at [%p] Segment [%d,%d,%d,%d].\n", + (void *) pDrawable, (void *) pGC, + pSegments -> x1, pSegments -> y1, pSegments -> x2, pSegments -> y2); + } + else + { + fprintf(stderr, "nxagentPolySegment: Drawable at [%p] GC at [%p] Segments [%d].\n", + (void *) pDrawable, (void *) pGC, nSegments); + } + + #endif + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + fbPolySegment(nxagentVirtualDrawable(pDrawable), pGC, nSegments, pSegments); + } + else + { + fbPolySegment(pDrawable, pGC, nSegments, pSegments); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly segment on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly segment enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawSegments(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XSegment *) pSegments, nSegments); + } + } + else + { + XDrawSegments(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XSegment *) pSegments, nSegments); + } + + fbPolySegment(nxagentVirtualDrawable(pDrawable), pGC, nSegments, pSegments); + + return; + } + else + { + XDrawSegments(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XSegment *) pSegments, nSegments); + + fbPolySegment(pDrawable, pGC, nSegments, pSegments); + } +} + +void nxagentPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, + int nRectangles, xRectangle *pRectangles) +{ + #ifdef TEST + + if (nRectangles == 1) + { + fprintf(stderr, "nxagentPolyRectangle: Drawable at [%p] GC at [%p] Rectangle [%d,%d][%d,%d].\n", + (void *) pDrawable, (void *) pGC, + pRectangles -> x, pRectangles -> y, pRectangles -> width, pRectangles -> height); + } + else + { + fprintf(stderr, "nxagentPolyRectangle: Drawable at [%p] GC at [%p] Rectangles [%d].\n", + (void *) pDrawable, (void *) pGC, nRectangles); + } + + #endif + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miPolyRectangle(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles); + } + else + { + miPolyRectangle(pDrawable, pGC, nRectangles, pRectangles); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly rectangle on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly rectangle enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawRectangles(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XRectangle *) pRectangles, nRectangles); + } + } + else + { + XDrawRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XRectangle *) pRectangles, nRectangles); + } + + SET_GC_TRAP(); + + miPolyRectangle(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles); + + RESET_GC_TRAP(); + + return; + } + else + { + XDrawRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XRectangle *) pRectangles, nRectangles); + + SET_GC_TRAP(); + + miPolyRectangle(pDrawable, pGC, nRectangles, pRectangles); + + RESET_GC_TRAP(); + } +} + +void nxagentPolyArc(DrawablePtr pDrawable, GCPtr pGC, + int nArcs, xArc *pArcs) +{ + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + fbPolyArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs); + } + else + { + fbPolyArc(pDrawable, pGC, nArcs, pArcs); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly arc on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly arc enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawArcs(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XArc *) pArcs, nArcs); + } + } + else + { + XDrawArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XArc *) pArcs, nArcs); + } + + fbPolyArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs); + + return; + } + else + { + XDrawArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XArc *) pArcs, nArcs); + + fbPolyArc(pDrawable, pGC, nArcs, pArcs); + } +} + +void nxagentFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, + int mode, int nPoints, xPoint *pPoints) +{ + xPoint *newPoints = NULL; + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miFillPolygon(nxagentVirtualDrawable(pDrawable), pGC, shape, mode, nPoints, pPoints); + } + else + { + miFillPolygon(pDrawable, pGC, shape, mode, nPoints, pPoints); + } + + return; + } + + /* + * The coordinate-mode must be CoordModePrevious + * to make better use of differential encoding of + * X_FillPoly request by the side of proxy. + */ + + if (mode == CoordModeOrigin) + { + int i; + + mode = CoordModePrevious; + + newPoints = xalloc(nPoints * sizeof(xPoint)); + + /* + * The first point is always relative + * to the drawable's origin. + */ + + newPoints[0].x = pPoints[0].x; + newPoints[0].y = pPoints[0].y; + + /* + * If coordinate-mode is CoordModePrevious, + * the points following the first are rela- + * tive to the previous point. + */ + + for (i = 1; i < nPoints; i++) + { + newPoints[i].x = pPoints[i].x - pPoints[i-1].x; + newPoints[i].y = pPoints[i].y - pPoints[i-1].y; + } + + pPoints = newPoints; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to fill polygon on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: fill polygon enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XFillPolygon(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XPoint *) pPoints, nPoints, shape, mode); + } + } + else + { + XFillPolygon(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, shape, mode); + } + + SET_GC_TRAP(); + + miFillPolygon(nxagentVirtualDrawable(pDrawable), pGC, shape, mode, nPoints, pPoints); + + RESET_GC_TRAP(); + } + else + { + XFillPolygon(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XPoint *) pPoints, nPoints, shape, mode); + + SET_GC_TRAP(); + + miFillPolygon(pDrawable, pGC, shape, mode, nPoints, pPoints); + + RESET_GC_TRAP(); + } + + if (newPoints != NULL) + { + xfree(newPoints); + } +} + +void nxagentPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, + int nRectangles, xRectangle *pRectangles) +{ + RegionPtr rectRegion; + + int inheritCorruptedRegion; + + #ifdef TEST + + if (nRectangles == 1) + { + fprintf(stderr, "nxagentPolyFillRect: Drawable at [%p] GC at [%p] FillStyle [%d] Rectangle [%d,%d][%d,%d].\n", + (void *) pDrawable, (void *) pGC, pGC -> fillStyle, + pRectangles -> x, pRectangles -> y, pRectangles -> width, pRectangles -> height); + } + else + { + fprintf(stderr, "nxagentPolyFillRect: Drawable at [%p] GC at [%p] FillStyle [%d] Rectangles [%d].\n", + (void *) pDrawable, (void *) pGC, pGC -> fillStyle, nRectangles); + } + + #endif + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + fbPolyFillRect(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles); + } + else + { + fbPolyFillRect(pDrawable, pGC, nRectangles, pRectangles); + } + + return; + } + + /* + * The PolyFillRect acts in two ways: if the GC + * has a corrupted tile, the operation propagates + * the corrupted region on the destination. In + * other cases, because the PolyFillRect will + * cover the destination, any corrupted region + * intersecting the target will be cleared. + */ + + inheritCorruptedRegion = 0; + + if (pGC -> fillStyle == FillTiled && + pGC -> tileIsPixel == 0 && pGC -> tile.pixmap != NULL) + { + nxagentIncreasePixmapUsageCounter(pGC -> tile.pixmap); + + if (nxagentDrawableStatus((DrawablePtr) pGC -> tile.pixmap) == NotSynchronized) + { + #ifdef TEST + fprintf(stderr, "nxagentPolyFillRect: GC at [%p] uses corrupted tile pixmap at [%p]. Going to " + "corrupt the destination [%s][%p].\n", (void *) pGC, (void *) pGC -> tile.pixmap, + (pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), (void *) pDrawable); + + #endif + + inheritCorruptedRegion = 1; + } + } + + if (inheritCorruptedRegion == 1 || nxagentDrawableStatus(pDrawable) == NotSynchronized) + { + rectRegion = RECTS_TO_REGION(pDrawable -> pScreen, nRectangles, pRectangles, CT_REGION); + + if (pGC -> clientClip != NULL) + { + RegionRec tmpRegion; + + REGION_INIT(pDrawable -> pScreen, &tmpRegion, NullBox, 1); + + REGION_COPY(pDrawable -> pScreen, &tmpRegion, ((RegionPtr) pGC -> clientClip)); + + if (pGC -> clipOrg.x != 0 || pGC -> clipOrg.y != 0) + { + REGION_TRANSLATE(pDrawable -> pScreen, &tmpRegion, pGC -> clipOrg.x, pGC -> clipOrg.y); + } + + REGION_INTERSECT(pDrawable -> pScreen, rectRegion, rectRegion, &tmpRegion); + + REGION_UNINIT(pDrawable -> pScreen, &tmpRegion); + } + + if (inheritCorruptedRegion == 1) + { + /* + * The fill style should affect the cor- + * rupted region propagation: if the tile + * is not completely corrupted the region + * should be 'tiled' over the destination. + */ + + nxagentMarkCorruptedRegion(pDrawable, rectRegion); + } + else + { + if (pGC -> fillStyle != FillStippled && pGC -> fillStyle != FillOpaqueStippled) + { + nxagentUnmarkCorruptedRegion(pDrawable, rectRegion); + } + else + { + /* + * The stipple mask computation could cause + * an high fragmentation of the destination + * region. An analysis should be done to exa- + * mine the better solution (e.g.rdesktop + * uses stipples to draw texts). + */ + + #ifdef TEST + fprintf(stderr, "nxagentPolyFillRect: Synchronizing the region [%d,%d,%d,%d] before using " + "the stipple at [%p].\n", rectRegion -> extents.x1, rectRegion -> extents.y1, + rectRegion -> extents.x2, rectRegion -> extents.y2, (void *) pGC -> stipple); + #endif + + nxagentSynchronizeRegion(pDrawable, rectRegion, NEVER_BREAK, NULL); + } + } + + REGION_DESTROY(pDrawable -> pScreen, rectRegion); + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly fill rect on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly fill rect enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XFillRectangles(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XRectangle *) pRectangles, nRectangles); + } + } + else + { + XFillRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XRectangle *) pRectangles, nRectangles); + } + + fbPolyFillRect(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles); + + return; + } + else + { + XFillRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XRectangle *) pRectangles, nRectangles); + + fbPolyFillRect(pDrawable, pGC, nRectangles, pRectangles); + } +} + +void nxagentPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, + int nArcs, xArc *pArcs) +{ + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miPolyFillArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs); + } + else + { + miPolyFillArc(pDrawable, pGC, nArcs, pArcs); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly fillarc on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly fill arc enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XFillArcs(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), (XArc *) pArcs, nArcs); + } + } + else + { + XFillArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + (XArc *) pArcs, nArcs); + } + + SET_GC_TRAP(); + + miPolyFillArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs); + + RESET_GC_TRAP(); + + return; + } + else + { + XFillArcs(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), (XArc *) pArcs, nArcs); + + SET_GC_TRAP(); + + miPolyFillArc(pDrawable, pGC, nArcs, pArcs); + + RESET_GC_TRAP(); + } +} + +int nxagentPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, char *string) +{ + int width; + + /* + * While the session is suspended + * the font structure is NULL. + */ + + if (nxagentFontStruct(pGC -> font) == NULL) + { + return x; + } + + width = XTextWidth(nxagentFontStruct(pGC->font), string, count); + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miPolyText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + } + else + { + miPolyText8(pDrawable, pGC, x, y, count, string); + } + + return width + x; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly text8 on FB pixmap [%p] with string [%s].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly text8 enters with virtual pixmap [%p] parent is [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawString(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), x, y, string, count); + } + } + else + { + XDrawString(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, string, count); + } + + miPolyText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + + return width + x; + } + else + { + XDrawString(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC), + x, y, string, count); + + miPolyText8(pDrawable, pGC, x, y, count, string); + } + + return width + x; +} + +int nxagentPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, unsigned short *string) +{ + int width; + + /* + * While the session is suspended + * the font structure is NULL. + */ + + if (nxagentFontStruct(pGC -> font) == NULL) + { + return x; + } + + width = XTextWidth16(nxagentFontStruct(pGC->font), (XChar2b *)string, count); + + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miPolyText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + } + else + { + miPolyText16(pDrawable, pGC, x, y, count, string); + } + + return width + x; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to poly text16 on FB pixmap %p] with string [%s]\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly text16 enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawString16(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + } + } + else + { + XDrawString16(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + } + + miPolyText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + + return width + x; + } + else + { + XDrawString16(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + + miPolyText16(pDrawable, pGC, x, y, count, string); + } + + return width + x; +} + +void nxagentImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, char *string) +{ + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miImageText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + } + else + { + miImageText8(pDrawable, pGC, x, y, count, string); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to image text8 on FB pixmap [%p] with string [%s].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), string); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly image text8 enters with virtual pixmap [%p] parent is [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawImageString(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), x, y, string, count); + } + } + else + { + XDrawImageString(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, string, count); + } + + miImageText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + + return; + } + else + { + XDrawImageString(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, string, count); + + miImageText8(pDrawable, pGC, x, y, count, string); + } +} + +void nxagentImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, + int y, int count, unsigned short *string) +{ + if (nxagentGCTrap == 1) + { + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + miImageText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + } + else + { + miImageText16(pDrawable, pGC, x, y, count, string); + } + + return; + } + + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to image text16 on FB pixmap [%p] with string [%s].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string); + #endif + + if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) + { + #ifdef TEST + fprintf(stderr, "GCOps: poly image text16 enters with virtual pixmap = [%p] parent is = [%p]\n", + (void *) nxagentVirtualDrawable(pDrawable), + (void *) nxagentRealPixmap((PixmapPtr) pDrawable)); + #endif + + if (nxagentRealPixmap((PixmapPtr) pDrawable)) + { + XDrawImageString16(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + } + } + else + { + XDrawImageString16(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + } + + miImageText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string); + + return; + } + else + { + XDrawImageString16(nxagentDisplay, nxagentDrawable(pDrawable), + nxagentGC(pGC), x, y, (XChar2b *)string, count); + + miImageText16(pDrawable, pGC, x, y, count, string); + } +} + +void nxagentImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + unsigned int nGlyphs, CharInfoPtr *pCharInfo, + pointer pGlyphBase) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to imageGlyphBlt on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbImageGlyphBlt(nxagentVirtualDrawable(pDrawable), pGC, x, y, nGlyphs, pCharInfo, pGlyphBase); + } + else + { + fbImageGlyphBlt(pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase); + } +} + +void nxagentPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + unsigned int nGlyphs, CharInfoPtr *pCharInfo, + pointer pGlyphBase) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to PolyGlyphBlt on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbPolyGlyphBlt(nxagentVirtualDrawable(pDrawable), pGC, x, y, nGlyphs, pCharInfo, pGlyphBase); + } + else + { + fbPolyGlyphBlt(pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase); + } +} + +void nxagentPushPixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, + int width, int height, int x, int y) +{ + if ((pDrawable)->type == DRAWABLE_PIXMAP) + { + #ifdef TEST + fprintf(stderr, "GCOps: GC [%p] going to PushPixels on FB pixmap [%p].\n", + (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable)); + #endif + + fbPushPixels(pGC, nxagentVirtualPixmap(pBitmap), + (DrawablePtr) nxagentVirtualDrawable(pDrawable), + width, height, x, y); + } + else + { + fbPushPixels(pGC, nxagentVirtualPixmap(pBitmap), + (DrawablePtr) pDrawable, width, height, x, y); + } +} |