|
|
|
/*
|
|
|
|
Copyright 2012-2013 Jay Sorg
|
|
|
|
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
the above copyright notice appear in all copies and that both that
|
|
|
|
copyright notice and this permission notice appear in supporting
|
|
|
|
documentation.
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "rdp.h"
|
|
|
|
#include "rdpdraw.h"
|
|
|
|
|
|
|
|
#define LDEBUG 0
|
|
|
|
|
|
|
|
#define LOG_LEVEL 1
|
|
|
|
#define LLOG(_level, _args) \
|
|
|
|
do { if (_level < LOG_LEVEL) { ErrorF _args ; } } while (0)
|
|
|
|
#define LLOGLN(_level, _args) \
|
|
|
|
do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0)
|
|
|
|
|
|
|
|
extern rdpScreenInfoRec g_rdpScreen; /* from rdpmain.c */
|
|
|
|
extern DevPrivateKeyRec g_rdpGCIndex; /* from rdpmain.c */
|
|
|
|
extern DevPrivateKeyRec g_rdpWindowIndex; /* from rdpmain.c */
|
|
|
|
extern DevPrivateKeyRec g_rdpPixmapIndex; /* from rdpmain.c */
|
|
|
|
extern int g_Bpp; /* from rdpmain.c */
|
|
|
|
extern ScreenPtr g_pScreen; /* from rdpmain.c */
|
|
|
|
extern Bool g_wrapPixmap; /* from rdpmain.c */
|
|
|
|
extern int g_can_do_pix_to_pix; /* from rdpmain.c */
|
|
|
|
extern int g_do_dirty_os; /* in rdpmain.c */
|
|
|
|
extern int g_do_dirty_ons; /* in rdpmain.c */
|
|
|
|
extern rdpPixmapRec g_screenPriv; /* in rdpmain.c */
|
|
|
|
extern int g_do_glyph_cache; /* in rdpmain.c */
|
|
|
|
extern int g_doing_font; /* in rdpmain.c */
|
|
|
|
extern int g_do_composite; /* in rdpmain.c */
|
|
|
|
|
|
|
|
extern GCOps g_rdpGCOps; /* from rdpdraw.c */
|
|
|
|
|
|
|
|
extern int g_con_number; /* in rdpup.c */
|
|
|
|
|
|
|
|
extern int g_crc_seed; /* in rdpmisc.c */
|
|
|
|
extern int g_crc_table[]; /* in rdpmisc.c */
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
int
|
|
|
|
rdpCreatePicture(PicturePtr pPicture)
|
|
|
|
{
|
|
|
|
PictureScreenPtr ps;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
LLOGLN(10, ("rdpCreatePicture:"));
|
|
|
|
ps = GetPictureScreen(g_pScreen);
|
|
|
|
ps->CreatePicture = g_rdpScreen.CreatePicture;
|
|
|
|
rv = ps->CreatePicture(pPicture);
|
|
|
|
ps->CreatePicture = rdpCreatePicture;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
void
|
|
|
|
rdpDestroyPicture(PicturePtr pPicture)
|
|
|
|
{
|
|
|
|
PictureScreenPtr ps;
|
|
|
|
|
|
|
|
LLOGLN(10, ("rdpDestroyPicture:"));
|
|
|
|
ps = GetPictureScreen(g_pScreen);
|
|
|
|
ps->DestroyPicture = g_rdpScreen.DestroyPicture;
|
|
|
|
ps->DestroyPicture(pPicture);
|
|
|
|
ps->DestroyPicture = rdpDestroyPicture;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static int
|
|
|
|
print_format(PictFormatShort format)
|
|
|
|
{
|
|
|
|
switch (format)
|
|
|
|
{
|
|
|
|
case PIXMAN_a2r10g10b10:
|
|
|
|
LLOGLN(0, (" PIXMAN_x2r10g10b10"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_x2r10g10b10:
|
|
|
|
LLOGLN(0, (" PIXMAN_x2r10g10b10"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_a2b10g10r10:
|
|
|
|
LLOGLN(0, (" PIXMAN_a2b10g10r10"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_x2b10g10r10:
|
|
|
|
LLOGLN(0, (" PIXMAN_x2b10g10r10"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIXMAN_a8r8g8b8:
|
|
|
|
LLOGLN(0, (" PIXMAN_a8r8g8b8"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_x8r8g8b8:
|
|
|
|
LLOGLN(0, (" PIXMAN_x8r8g8b8"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_a8b8g8r8:
|
|
|
|
LLOGLN(0, (" PIXMAN_a8b8g8r8"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_x8b8g8r8:
|
|
|
|
LLOGLN(0, (" PIXMAN_x8b8g8r8"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_b8g8r8a8:
|
|
|
|
LLOGLN(0, (" PIXMAN_b8g8r8a8"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_b8g8r8x8:
|
|
|
|
LLOGLN(0, (" PIXMAN_b8g8r8x8"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* 24bpp formats */
|
|
|
|
case PIXMAN_r8g8b8:
|
|
|
|
LLOGLN(0, (" PIXMAN_r8g8b8"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_b8g8r8:
|
|
|
|
LLOGLN(0, (" PIXMAN_b8g8r8"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* 16bpp formats */
|
|
|
|
case PIXMAN_r5g6b5:
|
|
|
|
LLOGLN(0, (" PIXMAN_r5g6b5"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_b5g6r5:
|
|
|
|
LLOGLN(0, (" PIXMAN_b5g6r5"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIXMAN_a1r5g5b5:
|
|
|
|
LLOGLN(0, (" PIXMAN_a1r5g5b5"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_x1r5g5b5:
|
|
|
|
LLOGLN(0, (" PIXMAN_x1r5g5b5"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_a1b5g5r5:
|
|
|
|
LLOGLN(0, (" PIXMAN_a1b5g5r5"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_x1b5g5r5:
|
|
|
|
LLOGLN(0, (" PIXMAN_x1b5g5r5"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_a4r4g4b4:
|
|
|
|
LLOGLN(0, (" PIXMAN_a4r4g4b4"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_x4r4g4b4:
|
|
|
|
LLOGLN(0, (" PIXMAN_x4r4g4b4"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_a4b4g4r4:
|
|
|
|
LLOGLN(0, (" PIXMAN_a4b4g4r4"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_x4b4g4r4:
|
|
|
|
LLOGLN(0, (" PIXMAN_x4b4g4r4"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* 8bpp formats */
|
|
|
|
case PIXMAN_a8:
|
|
|
|
LLOGLN(0, (" PIXMAN_a8"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_r3g3b2:
|
|
|
|
LLOGLN(0, (" PIXMAN_r3g3b2"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_b2g3r3:
|
|
|
|
LLOGLN(0, (" PIXMAN_b2g3r3"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_a2r2g2b2:
|
|
|
|
LLOGLN(0, (" PIXMAN_a2r2g2b2"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_a2b2g2r2:
|
|
|
|
LLOGLN(0, (" PIXMAN_a2b2g2r2"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIXMAN_c8:
|
|
|
|
LLOGLN(0, (" PIXMAN_c8"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_g8:
|
|
|
|
LLOGLN(0, (" PIXMAN_g8"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIXMAN_x4a4:
|
|
|
|
LLOGLN(0, (" PIXMAN_x4a4"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* 4bpp formats */
|
|
|
|
case PIXMAN_a4:
|
|
|
|
LLOGLN(0, (" PIXMAN_a4"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_r1g2b1:
|
|
|
|
LLOGLN(0, (" PIXMAN_r1g2b1"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_b1g2r1:
|
|
|
|
LLOGLN(0, (" PIXMAN_b1g2r1"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_a1r1g1b1:
|
|
|
|
LLOGLN(0, (" PIXMAN_a1r1g1b1"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_a1b1g1r1:
|
|
|
|
LLOGLN(0, (" PIXMAN_a1b1g1r1"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PIXMAN_c4:
|
|
|
|
LLOGLN(0, (" PIXMAN_c4"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_g4:
|
|
|
|
LLOGLN(0, (" PIXMAN_g4"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* 1bpp formats */
|
|
|
|
case PIXMAN_a1:
|
|
|
|
LLOGLN(0, (" PIXMAN_a1"));
|
|
|
|
break;
|
|
|
|
case PIXMAN_g1:
|
|
|
|
LLOGLN(0, (" PIXMAN_g1"));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static int
|
|
|
|
composite_print(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
|
|
|
|
INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
|
|
|
|
INT16 yDst, CARD16 width, CARD16 height)
|
|
|
|
{
|
|
|
|
PixmapPtr pSrcPixmap;
|
|
|
|
PixmapPtr pDstPixmap;
|
|
|
|
rdpPixmapRec* pSrcPriv;
|
|
|
|
rdpPixmapRec* pDstPriv;
|
|
|
|
|
|
|
|
LLOGLN(0, ("composite_print: op %d xSrc %d ySrc %d xDst %d yDst %d "
|
|
|
|
"width %d height %d",
|
|
|
|
op, xSrc, ySrc, xDst, yDst, width, height));
|
|
|
|
|
|
|
|
if (pSrc != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, (" src depth %d width %d height %d repeat %d repeatType %d "
|
|
|
|
"dither %d filter %d alphaMap %p componentAlpha %d", pSrc->pDrawable->depth,
|
|
|
|
pSrc->pDrawable->width, pSrc->pDrawable->height,
|
|
|
|
pSrc->repeat, pSrc->repeatType, pSrc->dither, pSrc->filter,
|
|
|
|
pSrc->alphaMap, pSrc->componentAlpha));
|
|
|
|
LLOGLN(0, (" transform %p", pSrc->transform));
|
|
|
|
LLOGLN(0, (" detail format red %d red mask %d green %d green mask %d "
|
|
|
|
"blue %d blue mask %d",
|
|
|
|
pSrc->pFormat->direct.red, pSrc->pFormat->direct.redMask,
|
|
|
|
pSrc->pFormat->direct.green, pSrc->pFormat->direct.greenMask,
|
|
|
|
pSrc->pFormat->direct.blue, pSrc->pFormat->direct.blueMask));
|
|
|
|
print_format(pSrc->format);
|
|
|
|
if (pSrc->pDrawable->type == DRAWABLE_PIXMAP)
|
|
|
|
{
|
|
|
|
pSrcPixmap = (PixmapPtr)(pSrc->pDrawable);
|
|
|
|
pSrcPriv = GETPIXPRIV(pSrcPixmap);
|
|
|
|
LLOGLN(0, (" DRAWABLE_PIXMAP pSrcPriv %p status %d", pSrcPriv, pSrcPriv->status));
|
|
|
|
}
|
|
|
|
else if (pSrc->pDrawable->type == DRAWABLE_WINDOW)
|
|
|
|
{
|
|
|
|
LLOGLN(0, (" DRAWABLE_WINDOW"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LLOGLN(0, (" OTHER"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pMask != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, (" msk depth %d width %d height %d repeat %d repeatType %d",
|
|
|
|
pMask->pDrawable->depth,
|
|
|
|
pMask->pDrawable->width,
|
|
|
|
pMask->pDrawable->height, pMask->repeat, pMask->repeatType));
|
|
|
|
print_format(pMask->format);
|
|
|
|
}
|
|
|
|
if (pDst != 0)
|
|
|
|
{
|
|
|
|
LLOGLN(0, (" dst depth %d width %d height %d repeat %d repeatType %d "
|
|
|
|
"dither %d filter %d alphaMap %p", pDst->pDrawable->depth,
|
|
|
|
pDst->pDrawable->width, pDst->pDrawable->height,
|
|
|
|
pDst->repeat, pDst->repeatType, pDst->dither, pDst->filter,
|
|
|
|
pDst->alphaMap));
|
|
|
|
LLOGLN(0, (" transform %p", pDst->transform));
|
|
|
|
print_format(pDst->format);
|
|
|
|
if (pDst->pDrawable->type == DRAWABLE_PIXMAP)
|
|
|
|
{
|
|
|
|
pDstPixmap = (PixmapPtr)(pDst->pDrawable);
|
|
|
|
pDstPriv = GETPIXPRIV(pDstPixmap);
|
|
|
|
LLOGLN(0, (" DRAWABLE_PIXMAP pDstPriv %p status %d", pDstPriv, pDstPriv->status));
|
|
|
|
}
|
|
|
|
else if (pDst->pDrawable->type == DRAWABLE_WINDOW)
|
|
|
|
{
|
|
|
|
LLOGLN(0, (" DRAWABLE_WINDOW"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LLOGLN(0, (" OTHER"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static int
|
|
|
|
src_alpha_needed(CARD8 op)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
rv = 0;
|
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
case 3: /* Over */
|
|
|
|
case 6: /* InReverse */
|
|
|
|
case 8: /* OutReverse */
|
|
|
|
case 9: /* Atop */
|
|
|
|
case 10: /* AtopReverse */
|
|
|
|
case 11: /* Xor */
|
|
|
|
case 13: /* Saturate */
|
|
|
|
case 17: /* DisjointOver */
|
|
|
|
case 18: /* DisjointOverReverse */
|
|
|
|
case 19: /* DisjointIn */
|
|
|
|
case 20: /* DisjointInReverse */
|
|
|
|
case 21: /* DisjointOut */
|
|
|
|
case 22: /* DisjointOutReverse */
|
|
|
|
case 23: /* DisjointAtop */
|
|
|
|
case 24: /* DisjointAtopReverse */
|
|
|
|
case 25: /* DisjointXor */
|
|
|
|
case 29: /* ConjointOver */
|
|
|
|
case 30: /* ConjointOverReverse */
|
|
|
|
case 31: /* ConjointIn */
|
|
|
|
case 32: /* ConjointInReverse */
|
|
|
|
case 33: /* ConjointOut */
|
|
|
|
case 34: /* ConjointOutReverse */
|
|
|
|
case 35: /* ConjointAtop */
|
|
|
|
case 36: /* ConjointAtopReverse */
|
|
|
|
case 37: /* ConjointXor */
|
|
|
|
rv = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static int
|
|
|
|
dst_alpha_needed(CARD8 op)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
rv = 0;
|
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
case 4: /* OverReverse */
|
|
|
|
case 5: /* In */
|
|
|
|
case 7: /* Out */
|
|
|
|
case 9: /* Atop */
|
|
|
|
case 10: /* AtopReverse */
|
|
|
|
case 11: /* Xor */
|
|
|
|
case 13: /* Saturate */
|
|
|
|
case 17: /* DisjointOver */
|
|
|
|
case 18: /* DisjointOverReverse */
|
|
|
|
case 19: /* DisjointIn */
|
|
|
|
case 20: /* DisjointInReverse */
|
|
|
|
case 21: /* DisjointOut */
|
|
|
|
case 22: /* DisjointOutReverse */
|
|
|
|
case 23: /* DisjointAtop */
|
|
|
|
case 24: /* DisjointAtopReverse */
|
|
|
|
case 25: /* DisjointXor */
|
|
|
|
case 29: /* ConjointOver */
|
|
|
|
case 30: /* ConjointOverReverse */
|
|
|
|
case 31: /* ConjointIn */
|
|
|
|
case 32: /* ConjointInReverse */
|
|
|
|
case 33: /* ConjointOut */
|
|
|
|
case 34: /* ConjointOutReverse */
|
|
|
|
case 35: /* ConjointAtop */
|
|
|
|
case 36: /* ConjointAtopReverse */
|
|
|
|
case 37: /* ConjointXor */
|
|
|
|
rv = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct msk_info
|
|
|
|
{
|
|
|
|
int flags;
|
|
|
|
int idx;
|
|
|
|
int format;
|
|
|
|
int width;
|
|
|
|
int repeat;
|
|
|
|
};
|
|
|
|
|
|
|
|
static char g_com_fail_strings[][128] =
|
|
|
|
{
|
|
|
|
"OK",
|
|
|
|
"src not remotable",
|
|
|
|
"dst not remotable",
|
|
|
|
"msk not remotable"
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* returns boolean */
|
|
|
|
static int
|
|
|
|
check_drawables(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
|
|
|
|
INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
|
|
|
|
INT16 yDst, CARD16 width, CARD16 height, struct msk_info* msk)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
int fail_reason;
|
|
|
|
PixmapPtr pSrcPixmap;
|
|
|
|
PixmapPtr pDstPixmap;
|
|
|
|
PixmapPtr pMskPixmap;
|
|
|
|
rdpPixmapRec* pSrcPriv;
|
|
|
|
rdpPixmapRec* pDstPriv;
|
|
|
|
rdpPixmapRec* pMskPriv;
|
|
|
|
|
|
|
|
fail_reason = 0;
|
|
|
|
pSrcPixmap = 0;
|
|
|
|
pDstPixmap = 0;
|
|
|
|
pMskPixmap = 0;
|
|
|
|
pSrcPriv = 0;
|
|
|
|
pDstPriv = 0;
|
|
|
|
pMskPriv = 0;
|
|
|
|
rv = 0;
|
|
|
|
if (pSrc != 0)
|
|
|
|
{
|
|
|
|
if (pSrc->pDrawable != 0)
|
|
|
|
{
|
|
|
|
if (pSrc->pDrawable->type == DRAWABLE_PIXMAP)
|
|
|
|
{
|
|
|
|
pSrcPixmap = (PixmapPtr)(pSrc->pDrawable);
|
|
|
|
pSrcPriv = GETPIXPRIV(pSrcPixmap);
|
|
|
|
if (xrdp_is_os(pSrcPixmap, pSrcPriv))
|
|
|
|
{
|
|
|
|
if (pDst != 0)
|
|
|
|
{
|
|
|
|
if (pDst->pDrawable != 0)
|
|
|
|
{
|
|
|
|
if (pDst->pDrawable->type == DRAWABLE_PIXMAP)
|
|
|
|
{
|
|
|
|
pDstPixmap = (PixmapPtr)(pDst->pDrawable);
|
|
|
|
pDstPriv = GETPIXPRIV(pDstPixmap);
|
|
|
|
if (xrdp_is_os(pDstPixmap, pDstPriv))
|
|
|
|
{
|
|
|
|
rv = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fail_reason = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fail_reason = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rv)
|
|
|
|
{
|
|
|
|
if (pMask != 0)
|
|
|
|
{
|
|
|
|
#if 1
|
|
|
|
rv = 0;
|
|
|
|
if (pMask->pDrawable != 0)
|
|
|
|
{
|
|
|
|
if (pMask->pDrawable->type == DRAWABLE_PIXMAP)
|
|
|
|
{
|
|
|
|
pMskPixmap = (PixmapPtr)(pMask->pDrawable);
|
|
|
|
pMskPriv = GETPIXPRIV(pMskPixmap);
|
|
|
|
if (xrdp_is_os(pMskPixmap, pMskPriv))
|
|
|
|
{
|
|
|
|
rv = 1;
|
|
|
|
msk->flags = 1;
|
|
|
|
msk->idx = pMskPriv->rdpindex;
|
|
|
|
msk->format = pMask->format;
|
|
|
|
msk->width = pMask->pDrawable->width;
|
|
|
|
msk->repeat = pMask->repeatType;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fail_reason = 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rv == 0)
|
|
|
|
{
|
|
|
|
LLOGLN(10, ("check_drawables: can not remote [%s]", g_com_fail_strings[fail_reason]));
|
|
|
|
#if 0
|
|
|
|
composite_print(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
|
|
|
|
xDst, yDst, width, height);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LLOGLN(10, ("check_drawables: can remote [%s]", g_com_fail_strings[fail_reason]));
|
|
|
|
#if 0
|
|
|
|
composite_print(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
|
|
|
|
xDst, yDst, width, height);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static int
|
|
|
|
rdpRemoteComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
|
|
|
|
INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
|
|
|
|
INT16 yDst, CARD16 width, CARD16 height)
|
|
|
|
{
|
|
|
|
int ok_to_remote;
|
|
|
|
PixmapPtr pSrcPixmap;
|
|
|
|
PixmapPtr pMskPixmap;
|
|
|
|
PixmapPtr pDstPixmap;
|
|
|
|
rdpPixmapRec* pSrcPriv;
|
|
|
|
rdpPixmapRec* pMskPriv;
|
|
|
|
rdpPixmapRec* pDstPriv;
|
|
|
|
BoxRec box;
|
|
|
|
RegionRec reg1;
|
|
|
|
RegionRec reg2;
|
|
|
|
DrawablePtr p;
|
|
|
|
int j;
|
|
|
|
int num_clips;
|
|
|
|
struct msk_info msk;
|
|
|
|
|
|
|
|
LLOGLN(10, ("rdpRemoteComposite:"));
|
|
|
|
|
|
|
|
memset(&msk, 0, sizeof(msk));
|
|
|
|
ok_to_remote = check_drawables(op, pSrc, pMask, pDst, xSrc, ySrc,
|
|
|
|
xMask, yMask, xDst, yDst, width, height,
|
|
|
|
&msk);
|
|
|
|
if (!ok_to_remote)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ValidatePicture(pSrc);
|
|
|
|
pSrcPixmap = (PixmapPtr)(pSrc->pDrawable);
|
|
|
|
pSrcPriv = GETPIXPRIV(pSrcPixmap);
|
|
|
|
rdpup_check_dirty(pSrcPixmap, pSrcPriv);
|
|
|
|
if (PIXMAN_FORMAT_A(pSrc->format) > 0)
|
|
|
|
{
|
|
|
|
if (src_alpha_needed(op))
|
|
|
|
{
|
|
|
|
rdpup_check_alpha_dirty(pSrcPixmap, pSrcPriv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ValidatePicture(pDst);
|
|
|
|
pDstPixmap = (PixmapPtr)(pDst->pDrawable);
|
|
|
|
pDstPriv = GETPIXPRIV(pDstPixmap);
|
|
|
|
rdpup_check_dirty(pDstPixmap, pDstPriv);
|
|
|
|
|
|
|
|
if (PIXMAN_FORMAT_A(pDst->format) > 0)
|
|
|
|
{
|
|
|
|
if (dst_alpha_needed(op))
|
|
|
|
{
|
|
|
|
rdpup_check_alpha_dirty(pDstPixmap, pDstPriv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pMask != 0)
|
|
|
|
{
|
|
|
|
ValidatePicture(pMask);
|
|
|
|
pMskPixmap = (PixmapPtr)(pMask->pDrawable);
|
|
|
|
pMskPriv = GETPIXPRIV(pMskPixmap);
|
|
|
|
rdpup_check_dirty(pMskPixmap, pMskPriv);
|
|
|
|
if (PIXMAN_FORMAT_A(msk.format) > 0)
|
|
|
|
{
|
|
|
|
rdpup_check_alpha_dirty(pMskPixmap, pMskPriv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
p = pDst->pDrawable;
|
|
|
|
rdpup_switch_os_surface(pDstPriv->rdpindex);
|
|
|
|
if (pDst->pCompositeClip != 0)
|
|
|
|
{
|
|
|
|
box.x1 = xDst;
|
|
|
|
box.y1 = yDst;
|
|
|
|
box.x2 = box.x1 + width;
|
|
|
|
box.y2 = box.y1 + height;
|
|
|
|
RegionInit(®1, &box, 0);
|
|
|
|
RegionInit(®2, NullBox, 0);
|
|
|
|
RegionCopy(®2, pDst->pCompositeClip);
|
|
|
|
RegionIntersect(®1, ®1, ®2);
|
|
|
|
RegionTranslate(®1, p->x, p->y);
|
|
|
|
num_clips = REGION_NUM_RECTS(®1);
|
|
|
|
if (num_clips > 0)
|
|
|
|
{
|
|
|
|
LLOGLN(10, ("num_clips %d", num_clips));
|
|
|
|
rdpup_begin_update();
|
|
|
|
for (j = num_clips - 1; j >= 0; j--)
|
|
|
|
{
|
|
|
|
box = REGION_RECTS(®1)[j];
|
|
|
|
rdpup_set_clip(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
|
|
|
|
LLOGLN(10, ("pSrc->format 0x%x 0x%x 0x%x %d %d %d %d %d %d %d %d",
|
|
|
|
pSrc->format, msk.format, pDst->format, xSrc, ySrc,
|
|
|
|
xMask, yMask, xDst, yDst, width, height));
|
|
|
|
rdpup_composite(pSrcPriv->rdpindex, pSrc->format,
|
|
|
|
pSrc->pDrawable->width, pSrc->repeatType,
|
|
|
|
pSrc->transform, msk.flags, msk.idx, msk.format,
|
|
|
|
msk.width, msk.repeat, op, xSrc, ySrc,
|
|
|
|
xMask, yMask, xDst, yDst, width, height, pDst->format);
|
|
|
|
}
|
|
|
|
rdpup_reset_clip();
|
|
|
|
rdpup_end_update();
|
|
|
|
}
|
|
|
|
RegionUninit(®1);
|
|
|
|
RegionUninit(®2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rdpup_begin_update();
|
|
|
|
rdpup_composite(pSrcPriv->rdpindex, pSrc->format,
|
|
|
|
pSrc->pDrawable->width, pSrc->repeatType,
|
|
|
|
pSrc->transform, msk.flags, msk.idx, msk.format,
|
|
|
|
msk.width, msk.repeat, op, xSrc, ySrc,
|
|
|
|
xMask, yMask, xDst, yDst, width, height, pDst->format);
|
|
|
|
rdpup_end_update();
|
|
|
|
}
|
|
|
|
rdpup_switch_os_surface(-1);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
static void
|
|
|
|
rdpCompositeOrg(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
|
|
|
|
INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
|
|
|
|
INT16 yDst, CARD16 width, CARD16 height)
|
|
|
|
{
|
|
|
|
PictureScreenPtr ps;
|
|
|
|
|
|
|
|
ps = GetPictureScreen(g_pScreen);
|
|
|
|
ps->Composite = g_rdpScreen.Composite;
|
|
|
|
ps->Composite(op, pSrc, pMask, pDst, xSrc, ySrc,
|
|
|
|
xMask, yMask, xDst, yDst, width, height);
|
|
|
|
ps->Composite = rdpComposite;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/* it looks like all the antialias draws go through here
|
|
|
|
op is one of the following
|
|
|
|
#define PictOpMinimum 0
|
|
|
|
#define PictOpClear 0
|
|
|
|
#define PictOpSrc 1
|
|
|
|
#define PictOpDst 2
|
|
|
|
#define PictOpOver 3
|
|
|
|
#define PictOpOverReverse 4
|
|
|
|
#define PictOpIn 5
|
|
|
|
#define PictOpInReverse 6
|
|
|
|
#define PictOpOut 7
|
|
|
|
#define PictOpOutReverse 8
|
|
|
|
#define PictOpAtop 9
|
|
|
|
#define PictOpAtopReverse 10
|
|
|
|
#define PictOpXor 11
|
|
|
|
#define PictOpAdd 12
|
|
|
|
#define PictOpSaturate 13
|
|
|
|
#define PictOpMaximum 13
|
|
|
|
|
|
|
|
see for porter duff
|
|
|
|
http://www.svgopen.org/2005/papers/abstractsvgopen/
|
|
|
|
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
rdpComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
|
|
|
|
INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
|
|
|
|
INT16 yDst, CARD16 width, CARD16 height)
|
|
|
|
{
|
|
|
|
BoxRec box;
|
|
|
|
RegionRec reg1;
|
|
|
|
RegionRec reg2;
|
|
|
|
DrawablePtr p;
|
|
|
|
int dirty_type;
|
|
|
|
int j;
|
|
|
|
int num_clips;
|
|
|
|
int post_process;
|
|
|
|
int reset_surface;
|
|
|
|
int got_id;
|
|
|
|
WindowPtr pDstWnd;
|
|
|
|
PixmapPtr pDstPixmap;
|
|
|
|
rdpPixmapRec* pDstPriv;
|
|
|
|
rdpPixmapRec* pDirtyPriv;
|
|
|
|
struct image_data id;
|
|
|
|
|
|
|
|
LLOGLN(10, ("rdpComposite:"));
|
|
|
|
|
|
|
|
if (g_doing_font == 2)
|
|
|
|
{
|
|
|
|
rdpCompositeOrg(op, pSrc, pMask, pDst, xSrc, ySrc,
|
|
|
|
xMask, yMask, xDst, yDst, width, height);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
if (g_do_glyph_cache && g_do_alpha_glyphs)
|
|
|
|
{
|
|
|
|
if (pSrc->pDrawable->width == 1 &&
|
|
|
|
pSrc->pDrawable->height == 1)
|
|
|
|
{
|
|
|
|
if (pMask != 0)
|
|
|
|
{
|
|
|
|
/* TODO: here we can try to send it as a glyph */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* try to remote the composite call */
|
|
|
|
if (g_do_composite &&
|
|
|
|
rdpRemoteComposite(op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
|
|
|
|
xDst, yDst, width, height) == 0)
|
|
|
|
{
|
|
|
|
rdpCompositeOrg(op, pSrc, pMask, pDst, xSrc, ySrc,
|
|
|
|
xMask, yMask, xDst, yDst, width, height);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rdpCompositeOrg(op, pSrc, pMask, pDst, xSrc, ySrc,
|
|
|
|
xMask, yMask, xDst, yDst, width, height);
|
|
|
|
|
|
|
|
LLOGLN(10, ("rdpComposite: op %d %p %p %p w %d h %d", op, pSrc, pMask, pDst, width, height));
|
|
|
|
|
|
|
|
p = pDst->pDrawable;
|
|
|
|
|
|
|
|
pDstPriv = 0;
|
|
|
|
dirty_type = 0;
|
|
|
|
pDirtyPriv = 0;
|
|
|
|
post_process = 0;
|
|
|
|
reset_surface = 0;
|
|
|
|
got_id = 0;
|
|
|
|
if (p->type == DRAWABLE_PIXMAP)
|
|
|
|
{
|
|
|
|
pDstPixmap = (PixmapPtr)p;
|
|
|
|
pDstPriv = GETPIXPRIV(pDstPixmap);
|
|
|
|
if (XRDP_IS_OS(pDstPriv))
|
|
|
|
{
|
|
|
|
post_process = 1;
|
|
|
|
if (g_do_dirty_os)
|
|
|
|
{
|
|
|
|
LLOGLN(10, ("rdpComposite: getting dirty"));
|
|
|
|
pDstPriv->is_dirty = 1;
|
|
|
|
dirty_type = g_doing_font ? RDI_IMGLL : RDI_IMGLY;
|
|
|
|
pDirtyPriv = pDstPriv;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rdpup_switch_os_surface(pDstPriv->rdpindex);
|
|
|
|
reset_surface = 1;
|
|
|
|
rdpup_get_pixmap_image_rect(pDstPixmap, &id);
|
|
|
|
got_id = 1;
|
|
|
|
LLOGLN(10, ("rdpComposite: offscreen"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (p->type == DRAWABLE_WINDOW)
|
|
|
|
{
|
|
|
|
pDstWnd = (WindowPtr)p;
|
|
|
|
if (pDstWnd->viewable)
|
|
|
|
{
|
|
|
|
post_process = 1;
|
|
|
|
if (g_do_dirty_ons)
|
|
|
|
{
|
|
|
|
LLOGLN(10, ("rdpComposite: getting dirty"));
|
|
|
|
g_screenPriv.is_dirty = 1;
|
|
|
|
pDirtyPriv = &g_screenPriv;
|
|
|
|
dirty_type = g_doing_font ? RDI_IMGLL : RDI_IMGLY;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rdpup_get_screen_image_rect(&id);
|
|
|
|
got_id = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!post_process)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pDst->pCompositeClip != 0)
|
|
|
|
{
|
|
|
|
box.x1 = p->x + xDst;
|
|
|
|
box.y1 = p->y + yDst;
|
|
|
|
box.x2 = box.x1 + width;
|
|
|
|
box.y2 = box.y1 + height;
|
|
|
|
RegionInit(®1, &box, 0);
|
|
|
|
RegionInit(®2, NullBox, 0);
|
|
|
|
RegionCopy(®2, pDst->pCompositeClip);
|
|
|
|
RegionIntersect(®1, ®1, ®2);
|
|
|
|
if (dirty_type != 0)
|
|
|
|
{
|
|
|
|
draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type, TAG_COMPOSITE);
|
|
|
|
}
|
|
|
|
else if (got_id)
|
|
|
|
{
|
|
|
|
num_clips = REGION_NUM_RECTS(®1);
|
|
|
|
if (num_clips > 0)
|
|
|
|
{
|
|
|
|
rdpup_begin_update();
|
|
|
|
for (j = num_clips - 1; j >= 0; j--)
|
|
|
|
{
|
|
|
|
box = REGION_RECTS(®1)[j];
|
|
|
|
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
|
|
|
|
}
|
|
|
|
rdpup_end_update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RegionUninit(®1);
|
|
|
|
RegionUninit(®2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
box.x1 = p->x + xDst;
|
|
|
|
box.y1 = p->y + yDst;
|
|
|
|
box.x2 = box.x1 + width;
|
|
|
|
box.y2 = box.y1 + height;
|
|
|
|
if (dirty_type != 0)
|
|
|
|
{
|
|
|
|
RegionInit(®1, &box, 0);
|
|
|
|
draw_item_add_img_region(pDirtyPriv, ®1, GXcopy, dirty_type, TAG_COMPOSITE);
|
|
|
|
RegionUninit(®1);
|
|
|
|
}
|
|
|
|
else if (got_id)
|
|
|
|
{
|
|
|
|
rdpup_begin_update();
|
|
|
|
rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
|
|
|
|
rdpup_end_update();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (reset_surface)
|
|
|
|
{
|
|
|
|
rdpup_switch_os_surface(-1);
|
|
|
|
}
|
|
|
|
}
|