2756 lines
78 KiB
C
2756 lines
78 KiB
C
/**************************************************************************/
|
|
/* */
|
|
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
|
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
|
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
|
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
|
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
|
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
|
/* */
|
|
/* NXAGENT, NX protocol compression and NX extensions to this software */
|
|
/* are copyright of the aforementioned persons and companies. */
|
|
/* */
|
|
/* Redistribution and use of the present software is allowed according */
|
|
/* to terms specified in the file LICENSE which comes in the source */
|
|
/* distribution. */
|
|
/* */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* NOTE: This software has received contributions from various other */
|
|
/* contributors, only the core maintainers and supporters are listed as */
|
|
/* copyright holders. Please contact us, if you feel you should be listed */
|
|
/* as copyright holder, as well. */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
#include "picturestr.h"
|
|
#include "glyphstr.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 "protocol-versions.h"
|
|
|
|
#include "Agent.h"
|
|
#include "Drawable.h"
|
|
#include "Trap.h"
|
|
#include "Args.h"
|
|
#include "Utils.h"
|
|
|
|
#define Atom XlibAtom
|
|
#define Pixmap XlibPixmap
|
|
#include "X11/include/Xrenderint_nxagent.h"
|
|
#undef Atom
|
|
#undef Pixmap
|
|
|
|
#include "region.h"
|
|
#include <X11/extensions/extutil.h>
|
|
|
|
#include "Display.h"
|
|
#include "Pixmaps.h"
|
|
#include "Cursor.h"
|
|
#include "Client.h"
|
|
#include "Image.h"
|
|
#include "Pixels.h"
|
|
#include "Handlers.h"
|
|
|
|
#include <nx/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
|
|
|
|
/*
|
|
* Margin added around the glyphs extent (in pixels).
|
|
*/
|
|
|
|
#define GLYPH_BOX_MARGIN 2
|
|
|
|
int nxagentRenderEnable = UNDEFINED;
|
|
int nxagentRenderVersionMajor;
|
|
int nxagentRenderVersionMinor;
|
|
|
|
int nxagentPicturePrivateIndex = 0;
|
|
|
|
static int nxagentNumFormats = 0;
|
|
|
|
static XRenderPictFormat nxagentArrayFormats[MAX_FORMATS];
|
|
|
|
XRenderPictFormat *nxagentMatchingFormats(PictFormatPtr pForm);
|
|
|
|
BoxPtr nxagentGlyphsExtents;
|
|
BoxPtr nxagentTrapezoidExtents;
|
|
|
|
static void nxagentPrintFormat(XRenderPictFormat *pFormat);
|
|
|
|
/*
|
|
* From NXglyph.c.
|
|
*/
|
|
|
|
extern const CARD8 glyphDepths[];
|
|
|
|
/*
|
|
* From BitmapUtils.c.
|
|
*/
|
|
|
|
extern void nxagentBitOrderInvert(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);
|
|
|
|
int nxagentChangePictureClip(PicturePtr pPicture, int clipType, int nRects,
|
|
xRectangle *rects, int xOrigin, int yOrigin);
|
|
|
|
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 nxagentChangePicture(PicturePtr pPicture, Mask mask);
|
|
|
|
void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet);
|
|
|
|
void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph);
|
|
|
|
void nxagentFreeGlyphSet(GlyphSetPtr glyphSet);
|
|
|
|
void nxagentSetPictureTransform(PicturePtr pPicture, void * transform);
|
|
|
|
void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size,
|
|
void * params, int nparams);
|
|
|
|
Bool nxagentReconnectAllGlyphSet(void *p);
|
|
|
|
Bool nxagentReconnectAllPicture(void *);
|
|
|
|
Bool nxagentDisconnectAllPicture(void);
|
|
|
|
#ifdef NXAGENT_RENDER_CLEANUP
|
|
|
|
#include <stdio.h>
|
|
|
|
#define ROUNDUP(nbits, pad) ((((nbits) + ((pad)-1)) / (pad)) * ((pad)>>3))
|
|
|
|
/* Clean the padding bytes of data section of request.*/
|
|
void
|
|
nxagentCleanGlyphs(xGlyphInfo *gi,
|
|
int nglyphs,
|
|
CARD8 *images,
|
|
int depth,
|
|
Display *dpy)
|
|
{
|
|
int widthInBits;
|
|
int bytesPerLine;
|
|
int bytesToClean;
|
|
int bitsToClean;
|
|
int widthInBytes;
|
|
int height = gi -> height;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: Found a Glyph with Depth %d, width %d, pad %d.\n",
|
|
depth, gi -> width, BitmapPad(dpy));
|
|
#endif
|
|
|
|
while (nglyphs > 0)
|
|
{
|
|
if (depth == 24)
|
|
{
|
|
widthInBits = gi -> width * 32;
|
|
|
|
bytesPerLine = ROUNDUP(widthInBits, BitmapPad(dpy));
|
|
|
|
bytesToClean = bytesPerLine * height;
|
|
|
|
#ifdef DUBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: Found glyph with depth 24, bytes to clean is %d"
|
|
"width in bits is %d bytes per line [%d] height [%d].\n", bytesToClean,
|
|
widthInBits, bytesPerLine, height);
|
|
#endif
|
|
|
|
if (ImageByteOrder(dpy) == LSBFirst)
|
|
{
|
|
for (int i = 3; i < bytesToClean; i += 4)
|
|
{
|
|
images[i] = 0x00;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < bytesToClean; i += 4)
|
|
{
|
|
images[i] = 0x00;
|
|
}
|
|
}
|
|
|
|
#ifdef DUMP
|
|
fprintf(stderr, "nxagentCleanGlyphs: depth %d, bytesToClean %d, scanline: ", depth, bytesToClean);
|
|
for (int i = 0; i < bytesPerLine; i++)
|
|
{
|
|
fprintf(stderr, "[%d]", images[i]);
|
|
}
|
|
fprintf(stderr,"\n");
|
|
#endif
|
|
|
|
images += bytesToClean;
|
|
|
|
gi++;
|
|
|
|
nglyphs--;
|
|
}
|
|
else if (depth == 1)
|
|
{
|
|
widthInBits = gi -> width;
|
|
|
|
bytesPerLine = ROUNDUP(widthInBits, BitmapPad(dpy));
|
|
|
|
bitsToClean = (bytesPerLine << 3) - (gi -> width);
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: Found glyph with depth 1, width [%d], height [%d], bitsToClean [%d],"
|
|
" bytesPerLine [%d].\n", gi -> width, height, bitsToClean, bytesPerLine);
|
|
#endif
|
|
|
|
bytesToClean = bitsToClean >> 3;
|
|
|
|
bitsToClean &= 7;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: bitsToClean &=7 is %d, bytesToCLean is %d."
|
|
" byte_order is %d, bitmap_bit_order is %d.\n", bitsToClean, bytesToClean,
|
|
ImageByteOrder(dpy), BitmapBitOrder(dpy));
|
|
#endif
|
|
|
|
for (int i = 1; i <= height; i++)
|
|
{
|
|
int j;
|
|
if (ImageByteOrder(dpy) == BitmapBitOrder(dpy))
|
|
{
|
|
for (j = 1; j <= bytesToClean; j++)
|
|
{
|
|
images[i * bytesPerLine - j] = 0x00;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: byte_order == bitmap_bit_order, cleaning %d, i=%d, j=%d.\n"
|
|
, (i * bytesPerLine - j), i, j);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (j = bytesToClean; j >= 1; j--)
|
|
{
|
|
images[i * bytesPerLine - j] = 0x00;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: byte_order %d, bitmap_bit_order %d, cleaning %d, i=%d, j=%d.\n"
|
|
, ImageByteOrder(dpy), BitmapBitOrder(dpy), (i * bytesPerLine - j), i, j);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
if (BitmapBitOrder(dpy) == MSBFirst)
|
|
{
|
|
images[i * bytesPerLine - j] &= 0xff << bitsToClean;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: byte_order MSBFirst, cleaning %d, i=%d, j=%d.\n"
|
|
, (i * bytesPerLine - j), i, j);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
images[i * bytesPerLine - j] &= 0xff >> bitsToClean;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: byte_order LSBFirst, cleaning %d, i=%d, j=%d.\n"
|
|
, (i * bytesPerLine - j), i, j);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef DUMP
|
|
fprintf(stderr, "nxagentCleanGlyphs: depth %d, bytesToClean %d, scanline: ", depth, bytesToClean);
|
|
for (int i = 0; i < bytesPerLine; i++)
|
|
{
|
|
fprintf(stderr, "[%d]", images[i]);
|
|
}
|
|
fprintf(stderr,"\n");
|
|
#endif
|
|
|
|
images += bytesPerLine * height;
|
|
|
|
gi++;
|
|
|
|
nglyphs--;
|
|
}
|
|
else if ((depth == 8) || (depth == 16) )
|
|
{
|
|
widthInBits = gi -> width * depth;
|
|
|
|
bytesPerLine = ROUNDUP(widthInBits, BitmapPad(dpy));
|
|
|
|
widthInBytes = (widthInBits >> 3);
|
|
|
|
bytesToClean = bytesPerLine - widthInBytes;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: nglyphs is %d, width of glyph in bits is %d, in bytes is %d.\n",
|
|
nglyphs, widthInBits, widthInBytes);
|
|
|
|
fprintf(stderr, "nxagentCleanGlyphs: bytesPerLine is %d bytes, there are %d scanlines.\n", bytesPerLine, height);
|
|
|
|
fprintf(stderr, "nxagentCleanGlyphs: Bytes to clean for each scanline are %d.\n", bytesToClean);
|
|
#endif
|
|
|
|
if (bytesToClean > 0)
|
|
{
|
|
for (; height > 0; height--)
|
|
{
|
|
for (int i = bytesToClean; i > 0; i--)
|
|
{
|
|
*(images + (bytesPerLine - i)) = 0;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: cleaned a byte.\n");
|
|
#endif
|
|
}
|
|
|
|
#ifdef DUMP
|
|
fprintf(stderr, "nxagentCleanGlyphs: depth %d, bytesToClean %d, scanline: ", depth, bytesToClean);
|
|
for (int i = 0; i < bytesPerLine; i++)
|
|
{
|
|
fprintf(stderr, "[%d]", images[i]);
|
|
}
|
|
fprintf(stderr,"\n");
|
|
#endif
|
|
|
|
images += bytesPerLine;
|
|
}
|
|
}
|
|
|
|
gi++;
|
|
|
|
nglyphs--;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: Breaking Out.\n");
|
|
#endif
|
|
}
|
|
else if (depth == 32)
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCleanGlyphs: Found glyph with depth 32.\n");
|
|
#endif
|
|
|
|
gi++;
|
|
|
|
nglyphs--;
|
|
}
|
|
else
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentCleanGlyphs: Unrecognized glyph, depth is not 8/16/24/32, it appears to be %d.\n",
|
|
depth);
|
|
#endif
|
|
|
|
gi++;
|
|
|
|
nglyphs--;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* #ifdef NXAGENT_RENDER_CLEANUP */
|
|
|
|
void nxagentRenderExtensionInit(void)
|
|
{
|
|
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
|
|
* reasons let's advertise to our clients the lowest between the
|
|
* two versions.
|
|
*/
|
|
|
|
if (major_version > SERVER_RENDER_MAJOR_VERSION ||
|
|
(major_version == SERVER_RENDER_MAJOR_VERSION &&
|
|
minor_version > SERVER_RENDER_MINOR_VERSION))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentRenderExtensionInit: Using render version [%d.%d] with "
|
|
"remote version [%d.%d].\n", SERVER_RENDER_MAJOR_VERSION, SERVER_RENDER_MINOR_VERSION,
|
|
major_version, minor_version);
|
|
#endif
|
|
|
|
nxagentRenderVersionMajor = SERVER_RENDER_MAJOR_VERSION;
|
|
nxagentRenderVersionMinor = SERVER_RENDER_MINOR_VERSION;
|
|
}
|
|
else if (major_version < SERVER_RENDER_MAJOR_VERSION ||
|
|
(major_version == SERVER_RENDER_MAJOR_VERSION &&
|
|
minor_version < SERVER_RENDER_MINOR_VERSION))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "Info: Local render version %d.%d is higher "
|
|
"than remote version %d.%d.\n", SERVER_RENDER_MAJOR_VERSION, SERVER_RENDER_MINOR_VERSION,
|
|
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", SERVER_RENDER_MAJOR_VERSION, SERVER_RENDER_MINOR_VERSION,
|
|
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] = malloc(sizeof(nxagentPrivCursor));
|
|
|
|
if (nxagentCursorPriv(pCursor, pScreen) == NULL)
|
|
{
|
|
FatalError("malloc 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;
|
|
}
|
|
|
|
void nxagentRenderRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
|
|
{
|
|
PicturePtr pPicture = nxagentCursorPicture(pCursor, pScreen);
|
|
|
|
pPicture -> refcnt++;
|
|
|
|
int x = nxagentCursorXOffset(pCursor, pScreen);
|
|
int y = nxagentCursorYOffset(pCursor, pScreen);
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: Forcing the synchronization of the cursor.\n", __func__);
|
|
#endif
|
|
|
|
nxagentMarkCorruptedRegion(pPicture -> pDrawable, NULL);
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
|
|
nxagentLosslessTrap = True;
|
|
|
|
nxagentSynchronizeDrawable(pPicture -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
|
|
|
|
nxagentLosslessTrap = False;
|
|
nxagentCursor(pCursor, pScreen) = XRenderCreateCursor(nxagentDisplay, nxagentPicture(pPicture), x, y);
|
|
}
|
|
|
|
int nxagentCreatePicture(PicturePtr pPicture, Mask mask)
|
|
{
|
|
XRenderPictureAttributes attributes;
|
|
unsigned long valuemask=0;
|
|
|
|
#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);
|
|
}
|
|
|
|
XRenderPictFormat *pForm = NULL;
|
|
|
|
if (pPicture -> pFormat != NULL)
|
|
{
|
|
pForm = nxagentMatchingFormats(pPicture -> pFormat);
|
|
nxagentPrintFormat(pForm);
|
|
}
|
|
|
|
if (pForm == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentCreatePicture: WARNING! The requested format was not found.\n");
|
|
return 0;
|
|
}
|
|
|
|
Picture 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 && 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)
|
|
{
|
|
for (int 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)
|
|
{
|
|
if (pPicture == NULL || nxagentPicturePriv(pPicture) -> picture == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentDestroyPicture: Going to destroy picture at [%p].\n",
|
|
(void *) pPicture);
|
|
#endif
|
|
|
|
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 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))
|
|
{
|
|
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))
|
|
{
|
|
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))
|
|
{
|
|
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))
|
|
{
|
|
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))
|
|
{
|
|
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))
|
|
{
|
|
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))
|
|
{
|
|
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))
|
|
{
|
|
valuemask |= CPSubwindowMode;
|
|
nxagentSetPictureRemoteValue(pPicture, subwindow_mode, attributes.subwindow_mode);
|
|
}
|
|
}
|
|
|
|
if (mask & CPClipMask)
|
|
{
|
|
/*
|
|
* 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.
|
|
*/
|
|
|
|
attributes.clip_mask = None;
|
|
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))
|
|
{
|
|
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))
|
|
{
|
|
valuemask |= CPPolyMode;
|
|
nxagentSetPictureRemoteValue(pPicture, poly_mode, attributes.poly_mode);
|
|
}
|
|
}
|
|
|
|
if (mask & CPDither)
|
|
{
|
|
attributes.dither = pPicture -> dither;
|
|
if (!nxagentCheckPictureRemoteValue(pPicture, dither, attributes.dither))
|
|
{
|
|
valuemask |= CPDither;
|
|
nxagentSetPictureRemoteValue(pPicture, dither, attributes.dither);
|
|
}
|
|
}
|
|
|
|
if (mask & CPComponentAlpha)
|
|
{
|
|
attributes.component_alpha = pPicture -> componentAlpha;
|
|
if (!nxagentCheckPictureRemoteValue(pPicture, component_alpha, attributes.component_alpha))
|
|
{
|
|
valuemask |= CPComponentAlpha;
|
|
nxagentSetPictureRemoteValue(pPicture, component_alpha, attributes.component_alpha);
|
|
}
|
|
}
|
|
|
|
#ifdef TEST
|
|
if (pPicture && pPicture->pDrawable && 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 /* SKIP_REALLY_ALL_LOUSY_RENDER_OPERATIONS */
|
|
|
|
#ifdef DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
#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)
|
|
{
|
|
if (pSrc == NULL || pDst == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (pSrc && pSrc -> pDrawable != NULL)
|
|
{
|
|
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);
|
|
}
|
|
|
|
if (pDst && pDst->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 && pMask->pDrawable)
|
|
{
|
|
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))
|
|
{
|
|
RegionPtr pDstRegion = nxagentCreateRegion(pDst -> pDrawable, NULL, xDst, yDst, width, height);
|
|
|
|
#ifdef TEST
|
|
if ((pDstRegion) && (pDst && pDst->pDrawable)) {
|
|
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(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.
|
|
*/
|
|
|
|
if (pSrc -> pDrawable != NULL)
|
|
{
|
|
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 != 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)
|
|
{
|
|
BoxRec glyphBox = {0};
|
|
|
|
XGlyphElt8 *elements;
|
|
|
|
if (pSrc == NULL || pDst == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef TEST
|
|
if ((pSrc && pSrc->pDrawable) && (pDst && pDst->pDrawable)) {
|
|
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
|
|
|
|
XRenderPictFormat *pForm = NULL;
|
|
|
|
if (maskFormat != NULL)
|
|
{
|
|
pForm = nxagentMatchingFormats(maskFormat);
|
|
nxagentPrintFormat(pForm);
|
|
|
|
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 = nxagentCreateRegion(pDst -> pDrawable, NULL, glyphBox.x1, glyphBox.y1,
|
|
glyphBox.x2 - glyphBox.x1, glyphBox.y2 - glyphBox.y1);
|
|
|
|
if (RegionNil(pRegion))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentGlyphs: WARNING! Glyphs prevented on hidden window at [%p].\n",
|
|
(void *) pDst -> pDrawable);
|
|
#endif
|
|
|
|
nxagentFreeRegion(pRegion);
|
|
|
|
return;
|
|
}
|
|
|
|
nxagentFreeRegion(pRegion);
|
|
}
|
|
|
|
/*
|
|
* Need to synchronize the pixmaps involved in the operation before
|
|
* rendering the glyphs on the real X server.
|
|
*/
|
|
|
|
if (pSrc -> pDrawable != NULL &&
|
|
nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
|
|
{
|
|
#ifdef TEST
|
|
if (pSrc && pSrc->pDrawable) {
|
|
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
|
|
if (pSrc && pSrc->pDrawable) {
|
|
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
|
|
if (pSrc && pSrc->pDrawable) {
|
|
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
|
|
if (pDst && pDst->pDrawable) {
|
|
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
|
|
if (pDst && pDst->pDrawable) {
|
|
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
|
|
if (pDst && pDst->pDrawable) {
|
|
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
|
|
if (pDst && pDst->pDrawable) {
|
|
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
|
|
GlyphPtr glyph;
|
|
|
|
/*
|
|
* 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)
|
|
{
|
|
int x;
|
|
int y;
|
|
|
|
for (int 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 (int 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 (int 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 (int 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 (int 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)
|
|
{
|
|
if (pDst == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef TEST
|
|
if (pDst && pDst->pDrawable) {
|
|
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)))
|
|
{
|
|
RegionPtr rectRegion = RegionFromRects(nRect, rects, CT_REGION);
|
|
|
|
if (pDst -> clientClipType != CT_NONE)
|
|
{
|
|
RegionRec tmpRegion;
|
|
|
|
RegionInit(&tmpRegion, NullBox, 1);
|
|
|
|
RegionCopy(&tmpRegion, (RegionPtr) pDst -> clientClip);
|
|
|
|
if (pDst -> clipOrigin.x != 0 || pDst -> clipOrigin.y != 0)
|
|
{
|
|
RegionTranslate(&tmpRegion, pDst -> clipOrigin.x, pDst -> clipOrigin.y);
|
|
}
|
|
|
|
RegionIntersect(rectRegion, rectRegion, &tmpRegion);
|
|
|
|
RegionUninit(&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);
|
|
|
|
RegionDestroy(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)
|
|
{
|
|
XTrapezoid *current = (XTrapezoid *) traps;
|
|
|
|
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;
|
|
}
|
|
|
|
XRenderPictFormat *pForm = NULL;
|
|
|
|
if (maskFormat != NULL)
|
|
{
|
|
pForm = nxagentMatchingFormats(maskFormat);
|
|
nxagentPrintFormat(pForm);
|
|
|
|
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
|
|
if (pSrc->pDrawable) {
|
|
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 &&
|
|
RegionContainsRect(nxagentCorruptedRegion(pDst -> pDrawable),
|
|
nxagentTrapezoidExtents) == rgnIN)
|
|
{
|
|
#ifdef TEST
|
|
if (pDst && pDst->pDrawable) {
|
|
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))
|
|
{
|
|
RegionPtr pDstRegion = nxagentCreateRegion(pDst -> pDrawable, NULL,
|
|
nxagentTrapezoidExtents -> x1,
|
|
nxagentTrapezoidExtents -> y1,
|
|
nxagentTrapezoidExtents -> x2 - nxagentTrapezoidExtents -> x1,
|
|
nxagentTrapezoidExtents -> y2 - nxagentTrapezoidExtents -> y1);
|
|
|
|
#ifdef TEST
|
|
if (pDst && pDst->pDrawable) {
|
|
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(pDstRegion);
|
|
|
|
if (pDst -> pDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
nxagentPixmapContainTrapezoids((PixmapPtr) pDst -> pDrawable) = 1;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (pSrc -> pDrawable != NULL &&
|
|
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);
|
|
}
|
|
|
|
XRenderCompositeTrapezoids(nxagentDisplay,
|
|
op,
|
|
nxagentPicturePriv(pSrc) -> picture,
|
|
nxagentPicturePriv(pDst) -> picture,
|
|
pForm,
|
|
xSrc,
|
|
ySrc,
|
|
(XTrapezoid *) current,remaining);
|
|
|
|
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
#endif
|
|
}
|
|
|
|
void nxagentQueryFormats(void)
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentQueryFormats.\n");
|
|
#endif
|
|
|
|
if (XRenderQueryFormats(nxagentDisplay))
|
|
{
|
|
int i;
|
|
|
|
#ifdef DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
#endif
|
|
|
|
XExtDisplayInfo *info = (XExtDisplayInfo *) XRenderFindDisplay(nxagentDisplay);
|
|
|
|
#ifdef DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
#endif
|
|
|
|
XRenderInfo *xri = (XRenderInfo *) info -> data;
|
|
|
|
XRenderPictFormat *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)
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCreateGlyphSet: Glyphset at [%p].\n", (void *) pGly);
|
|
#endif
|
|
|
|
XRenderPictFormat *pForm = NULL;
|
|
|
|
if (pGly -> format != NULL)
|
|
{
|
|
pForm = nxagentMatchingFormats(pGly -> format);
|
|
nxagentPrintFormat(pForm);
|
|
|
|
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)
|
|
{
|
|
#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.
|
|
*/
|
|
|
|
for (int i = 0; i < nglyphs; i++)
|
|
{
|
|
Glyph *tempGids = gids;
|
|
GlyphRefPtr gr = FindGlyphRef(&glyphSet -> hash, *tempGids, 0, 0);
|
|
|
|
if (gr && 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++;
|
|
}
|
|
|
|
CARD8 *normalizedImages = NULL;
|
|
|
|
if (sizeImages > 0)
|
|
{
|
|
normalizedImages = malloc(sizeImages);
|
|
|
|
if (normalizedImages != NULL)
|
|
{
|
|
memcpy(normalizedImages, images, sizeImages);
|
|
|
|
if (glyphDepths[glyphSet -> fdepth] == 1 &&
|
|
nxagentServerOrder() != BitmapBitOrder(nxagentDisplay))
|
|
{
|
|
nxagentBitOrderInvert ((unsigned char *) normalizedImages, sizeImages);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#ifdef PANIC
|
|
fprintf(stderr, "nxagentAddGlyphs: PANIC! Allocation of normalized glyph images failed.\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (normalizedImages == NULL)
|
|
{
|
|
normalizedImages = images;
|
|
}
|
|
|
|
#ifdef NXAGENT_RENDER_CLEANUP
|
|
nxagentCleanGlyphs(gi, nglyphs, normalizedImages, glyphDepths[glyphSet -> fdepth], nxagentDisplay);
|
|
#endif /* NXAGENT_RENDER_CLEANUP */
|
|
|
|
XRenderAddGlyphs(nxagentDisplay,
|
|
glyphSet -> remoteID,
|
|
gids,
|
|
(XGlyphInfo*)(gi),
|
|
nglyphs,
|
|
(char*) normalizedImages,
|
|
sizeImages);
|
|
|
|
if (normalizedImages != images)
|
|
{
|
|
SAFE_free(normalizedImages);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
#endif
|
|
}
|
|
|
|
void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph)
|
|
{
|
|
GlyphRefPtr gr;
|
|
Glyph gid;
|
|
|
|
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.
|
|
*/
|
|
|
|
CARD32 *tempGids = gids;
|
|
|
|
for (int 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, void * 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,
|
|
void * 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
|
|
|
|
SAFE_free(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;
|
|
}
|
|
|
|
static void nxagentPrintFormat(XRenderPictFormat *pFormat)
|
|
{
|
|
#ifdef DEBUG
|
|
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)
|
|
{
|
|
#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 (int i = 0; i < pGly -> hash.hashSet -> size; i++)
|
|
{
|
|
GlyphPtr 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;
|
|
|
|
if (!nxagentReconnectTrap)
|
|
{
|
|
int i;
|
|
XRenderPictFormat *pForm = NULL;
|
|
|
|
#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;
|
|
|
|
nxagentQueryFormats();
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentReconnectAllGlyphSet\n");
|
|
#endif
|
|
|
|
for (int i = 0; (i < MAXCLIENTS) && (success); i++)
|
|
{
|
|
if (clients[i])
|
|
{
|
|
FindClientResourcesByType(clients[i], GlyphSetType, nxagentReconnectGlyphSet, &success);
|
|
}
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
void nxagentReconnectPicture(void * p0, XID x1, void *p2)
|
|
{
|
|
PicturePtr pPicture = (PicturePtr) p0;
|
|
Bool *pBool = (Bool *) p2;
|
|
unsigned long mask = 0;
|
|
|
|
XRenderPictureAttributes attributes;
|
|
|
|
#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 || pPicture == NULL ||
|
|
nxagentPicture(pPicture) != 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (pPicture -> repeat)
|
|
{
|
|
attributes.repeat = (Bool) pPicture -> repeat;
|
|
mask |= CPRepeat;
|
|
}
|
|
|
|
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;
|
|
|
|
XRenderPictFormat *pForm = NULL;
|
|
|
|
if (pPicture -> pFormat)
|
|
{
|
|
pForm = nxagentMatchingFormats(pPicture -> pFormat);
|
|
nxagentPrintFormat(pForm);
|
|
}
|
|
|
|
if (!pForm && pPicture->pSourcePict)
|
|
{
|
|
/*possible we need to add support for other picture types, for example gradients...*/
|
|
switch(pPicture->pSourcePict->type)
|
|
{
|
|
case SourcePictTypeSolidFill:
|
|
nxagentPicturePriv(pPicture) -> picture = XRenderCreateSolidFill(nxagentDisplay,
|
|
(const XRenderColor*) &pPicture->pSourcePict->solidFill.fullColor);
|
|
break;
|
|
}
|
|
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 && 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)
|
|
{
|
|
Bool r = True;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentReconnectAllPicture: Going to recreate all pictures.\n");
|
|
#endif
|
|
|
|
for (int i = 0; i < MAXCLIENTS; i++)
|
|
{
|
|
if (clients[i])
|
|
{
|
|
FindClientResourcesByType(clients[i], PictureType, nxagentReconnectPicture, &r);
|
|
|
|
#ifdef WARNING
|
|
if (!r)
|
|
{
|
|
fprintf(stderr, "nxagentReconnectAllPicture: WARNING! Failed to recreate "
|
|
"picture for client [%d].\n", i);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
void nxagentDisconnectPicture(void * 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(void)
|
|
{
|
|
Bool r = True;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentDisconnectAllPicture.\n");
|
|
#endif
|
|
|
|
for (int i = 0; i < MAXCLIENTS; i++)
|
|
{
|
|
if (clients[i])
|
|
{
|
|
FindClientResourcesByType(clients[i], PictureType, nxagentDisconnectPicture, &r);
|
|
|
|
#ifdef WARNING
|
|
if (!r)
|
|
{
|
|
fprintf(stderr, "nxagentDisconnectAllPicture: WARNING! Failed to disconnect "
|
|
"picture for client [%d].\n", i);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
void nxagentRenderCreateSolidFill(PicturePtr pPicture, xRenderColor *color)
|
|
{
|
|
if (nxagentRenderEnable == False)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentRenderCreateSolidFill: Got called.\n");
|
|
|
|
if (pPicture == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateSolidFill: WARNING! pPicture pointer is NULL.\n");
|
|
}
|
|
|
|
if (color == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateSolidFill: WARNING! color pointer is NULL.\n");
|
|
}
|
|
#endif /* #ifdef DEBUG */
|
|
|
|
memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
|
|
sizeof(XRenderPictureAttributes_));
|
|
|
|
Picture id = XRenderCreateSolidFill(nxagentDisplay, (XRenderColor *) color);
|
|
|
|
#ifdef DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
#endif
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentRenderCreateSolidFill: Created solid fill xid [%lu].\n", id);
|
|
#endif
|
|
|
|
nxagentPicturePriv(pPicture) -> picture = id;
|
|
}
|
|
|
|
void nxagentRenderCreateLinearGradient(PicturePtr pPicture, xPointFixed *p1,
|
|
xPointFixed *p2, int nStops,
|
|
xFixed *stops,
|
|
xRenderColor *colors)
|
|
{
|
|
if (nxagentRenderEnable == False)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentRenderCreateLinearGradient: Got called.\n");
|
|
|
|
if (pPicture == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! pPicture pointer is NULL.\n");
|
|
}
|
|
|
|
if (p1 == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! p1 pointer is NULL.\n");
|
|
}
|
|
|
|
if (p2 == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! p2 pointer is NULL.\n");
|
|
}
|
|
|
|
if (stops == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! stops pointer is NULL.\n");
|
|
}
|
|
|
|
if (colors == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! colors pointer is NULL.\n");
|
|
}
|
|
#endif /* #ifdef DEBUG */
|
|
|
|
memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
|
|
sizeof(XRenderPictureAttributes_));
|
|
|
|
XLinearGradient linearGradient;
|
|
|
|
linearGradient.p1.x = (XFixed) p1 -> x;
|
|
linearGradient.p1.y = (XFixed) p1 -> y;
|
|
linearGradient.p2.x = (XFixed) p2 -> x;
|
|
linearGradient.p2.y = (XFixed) p2 -> y;
|
|
|
|
Picture id = XRenderCreateLinearGradient(nxagentDisplay, &linearGradient,
|
|
(XFixed *) stops,
|
|
(XRenderColor *) colors, nStops);
|
|
|
|
#ifdef DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
#endif
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentRenderCreateLinearGradient: Created linear gradient xid [%lu].\n", id);
|
|
#endif
|
|
|
|
nxagentPicturePriv(pPicture) -> picture = id;
|
|
}
|
|
|
|
void nxagentRenderCreateRadialGradient(PicturePtr pPicture, xPointFixed *inner,
|
|
xPointFixed *outer,
|
|
xFixed innerRadius,
|
|
xFixed outerRadius,
|
|
int nStops,
|
|
xFixed *stops,
|
|
xRenderColor *colors)
|
|
{
|
|
if (nxagentRenderEnable == False)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentRenderCreateRadialGradient: Got called.\n");
|
|
|
|
if (pPicture == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! pPicture pointer is NULL.\n");
|
|
}
|
|
|
|
if (inner == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! inner pointer is NULL.\n");
|
|
}
|
|
|
|
if (outer == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! outer pointer is NULL.\n");
|
|
}
|
|
|
|
if (stops == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! stops pointer is NULL.\n");
|
|
}
|
|
|
|
if (colors == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! colors pointer is NULL.\n");
|
|
}
|
|
#endif /* #ifdef DEBUG */
|
|
|
|
memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
|
|
sizeof(XRenderPictureAttributes_));
|
|
|
|
XRadialGradient radialGradient;
|
|
|
|
radialGradient.inner.x = (XFixed) inner -> x;
|
|
radialGradient.inner.y = (XFixed) inner -> y;
|
|
radialGradient.inner.radius = (XFixed) innerRadius;
|
|
radialGradient.outer.x = (XFixed) outer -> x;
|
|
radialGradient.outer.y = (XFixed) outer -> y;
|
|
radialGradient.outer.radius = (XFixed) outerRadius;
|
|
|
|
Picture id = XRenderCreateRadialGradient(nxagentDisplay, &radialGradient,
|
|
(XFixed *) stops,
|
|
(XRenderColor *) colors, nStops);
|
|
|
|
#ifdef DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
#endif
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentRenderCreateRadialGradient: Created radial gradient xid [%lu].\n", id);
|
|
#endif
|
|
|
|
nxagentPicturePriv(pPicture) -> picture = id;
|
|
}
|
|
|
|
void nxagentRenderCreateConicalGradient(PicturePtr pPicture,
|
|
xPointFixed *center,
|
|
xFixed angle, int nStops,
|
|
xFixed *stops,
|
|
xRenderColor *colors)
|
|
{
|
|
if (nxagentRenderEnable == False)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentRenderCreateConicalGradient: Got called.\n");
|
|
|
|
if (pPicture == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! pPicture pointer is NULL.\n");
|
|
}
|
|
|
|
if (center == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! center pointer is NULL.\n");
|
|
}
|
|
|
|
if (stops == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! stops pointer is NULL.\n");
|
|
}
|
|
|
|
if (colors == NULL)
|
|
{
|
|
fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! colors pointer is NULL.\n");
|
|
}
|
|
#endif /* #ifdef DEBUG */
|
|
|
|
memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
|
|
sizeof(XRenderPictureAttributes_));
|
|
|
|
XConicalGradient conicalGradient;
|
|
|
|
conicalGradient.center.x = (XFixed) center -> x;
|
|
conicalGradient.center.y = (XFixed) center -> y;
|
|
conicalGradient.angle = (XFixed) angle;
|
|
|
|
Picture id = XRenderCreateConicalGradient(nxagentDisplay, &conicalGradient,
|
|
(XFixed *) stops,
|
|
(XRenderColor *) colors, nStops);
|
|
|
|
#ifdef DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
#endif
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentRenderCreateConicalGradient: Created conical gradient xid [%lu].\n", id);
|
|
#endif
|
|
|
|
nxagentPicturePriv(pPicture) -> picture = id;
|
|
}
|