diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index 3cea767a4..7a574bc3e 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -73,15 +73,15 @@ boolean xf_set_rop3(xfInfo* xfi, int rop3) function = GXclear; break; - case 0x000500A9: + case GDI_DPon: function = GXnor; break; - case 0x000A0329: + case GDI_DPna: function = GXandInverted; break; - case 0x000F0001: + case GDI_Pn: function = GXcopyInverted; break; @@ -101,7 +101,7 @@ boolean xf_set_rop3(xfInfo* xfi, int rop3) function = GXandReverse; break; - case 0x00500325: + case GDI_PDna: function = GXandReverse; break; @@ -113,7 +113,7 @@ boolean xf_set_rop3(xfInfo* xfi, int rop3) function = GXxor; break; - case 0x005F00E9: + case GDI_DPan: function = GXnand; break; @@ -121,7 +121,7 @@ boolean xf_set_rop3(xfInfo* xfi, int rop3) function = GXxor; break; - case 0x007700E6: + case GDI_DSan: function = GXnand; break; @@ -129,11 +129,11 @@ boolean xf_set_rop3(xfInfo* xfi, int rop3) function = GXand; break; - case 0x00990066: + case GDI_DSxn: function = GXequiv; break; - case 0x00A000C9: + case GDI_DPa: function = GXand; break; @@ -141,11 +141,11 @@ boolean xf_set_rop3(xfInfo* xfi, int rop3) function = GXequiv; break; - case 0x00AA0029: + case GDI_D: function = GXnoop; break; - case 0x00AF0229: + case GDI_DPno: function = GXorInverted; break; @@ -157,7 +157,7 @@ boolean xf_set_rop3(xfInfo* xfi, int rop3) function = GXcopy; break; - case 0x00DD0228: + case GDI_SDno: function = GXorReverse; break; @@ -169,11 +169,11 @@ boolean xf_set_rop3(xfInfo* xfi, int rop3) function = GXcopy; break; - case 0x00F50225: + case GDI_PDno: function = GXorReverse; break; - case 0x00FA0089: + case GDI_DPo: function = GXor; break; @@ -181,6 +181,10 @@ boolean xf_set_rop3(xfInfo* xfi, int rop3) function = GXset; break; + case GDI_PSDPxax: + function = GXand; + break; + default: break; } @@ -205,17 +209,19 @@ Pixmap xf_brush_new(xfInfo* xfi, int width, int height, int bpp, uint8* data) bitmap = XCreatePixmap(xfi->display, xfi->drawable, width, height, xfi->depth); - if(data != NULL) + if (data != NULL) { - GC gc; // FIXME, should cache + GC gc; cdata = freerdp_image_convert(data, NULL, width, height, bpp, xfi->bpp, xfi->clrconv); + image = XCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, 0, (char*) cdata, width, height, xfi->scanline_pad, 0); gc = XCreateGC(xfi->display, xfi->drawable, 0, NULL); XPutImage(xfi->display, bitmap, gc, image, 0, 0, 0, 0, width, height); XFree(image); + if (cdata != data) xfree(cdata); @@ -620,7 +626,74 @@ void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) { - printf("Mem3Blt\n"); + rdpBrush* brush; + xfBitmap* bitmap; + uint32 foreColor; + uint32 backColor; + Pixmap pattern = 0; + xfInfo* xfi = ((xfContext*) context)->xfi; + + brush = &mem3blt->brush; + bitmap = (xfBitmap*) mem3blt->bitmap; + xf_set_rop3(xfi, gdi_rop3_code(mem3blt->bRop)); + foreColor = freerdp_color_convert_rgb(mem3blt->foreColor, xfi->srcBpp, 32, xfi->clrconv); + backColor = freerdp_color_convert_rgb(mem3blt->backColor, xfi->srcBpp, 32, xfi->clrconv); + + if (brush->style == GDI_BS_PATTERN) + { + if (brush->bpp > 1) + { + pattern = xf_brush_new(xfi, 8, 8, brush->bpp, brush->data); + + XSetFillStyle(xfi->display, xfi->gc, FillTiled); + XSetTile(xfi->display, xfi->gc, pattern); + XSetTSOrigin(xfi->display, xfi->gc, brush->x, brush->y); + } + else + { + pattern = xf_mono_bitmap_new(xfi, 8, 8, brush->data); + + XSetForeground(xfi->display, xfi->gc, backColor); + XSetBackground(xfi->display, xfi->gc, foreColor); + XSetFillStyle(xfi->display, xfi->gc, FillOpaqueStippled); + XSetStipple(xfi->display, xfi->gc, pattern); + XSetTSOrigin(xfi->display, xfi->gc, brush->x, brush->y); + } + } + else if (brush->style == GDI_BS_SOLID) + { + XSetForeground(xfi->display, xfi->gc, backColor); + XSetBackground(xfi->display, xfi->gc, foreColor); + XSetFillStyle(xfi->display, xfi->gc, FillStippled); + } + else + { + printf("Mem3Blt unimplemented brush style:%d\n", brush->style); + } + + XCopyArea(xfi->display, bitmap->pixmap, xfi->drawing, xfi->gc, + mem3blt->nXSrc, mem3blt->nYSrc, mem3blt->nWidth, mem3blt->nHeight, + mem3blt->nLeftRect, mem3blt->nTopRect); + + if (xfi->drawing == xfi->primary) + { + if (xfi->remote_app != true) + { + XCopyArea(xfi->display, bitmap->pixmap, xfi->drawable, xfi->gc, + mem3blt->nXSrc, mem3blt->nYSrc, mem3blt->nWidth, mem3blt->nHeight, + mem3blt->nLeftRect, mem3blt->nTopRect); + } + + gdi_InvalidateRegion(xfi->hdc, mem3blt->nLeftRect, mem3blt->nTopRect, mem3blt->nWidth, mem3blt->nHeight); + } + + XSetFillStyle(xfi->display, xfi->gc, FillSolid); + XSetTSOrigin(xfi->display, xfi->gc, 0, 0); + + if (pattern != 0) + XFreePixmap(xfi->display, pattern); + + XSetFunction(xfi->display, xfi->gc, GXcopy); } void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc) @@ -630,8 +703,6 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc) uint32 brush_color; xfInfo* xfi = ((xfContext*) context)->xfi; - printf("PolygonSC\n"); - xf_set_rop2(xfi, polygon_sc->bRop2); brush_color = freerdp_color_convert_rgb(polygon_sc->brushColor, xfi->srcBpp, 32, xfi->clrconv); @@ -774,7 +845,7 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb) } else { - printf("unimplemented brush style:%d\n", brush->style); + printf("PolygonCB unimplemented brush style:%d\n", brush->style); } XSetFunction(xfi->display, xfi->gc, GXcopy); diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index 8f42438ec..db17a8eb7 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -495,7 +495,9 @@ boolean xf_pre_connect(freerdp* instance) settings->order_support[NEG_LINETO_INDEX] = true; settings->order_support[NEG_POLYLINE_INDEX] = true; settings->order_support[NEG_MEMBLT_INDEX] = bitmap_cache; - settings->order_support[NEG_MEM3BLT_INDEX] = false; + + settings->order_support[NEG_MEM3BLT_INDEX] = (settings->sw_gdi) ? false : true; + settings->order_support[NEG_MEMBLT_V2_INDEX] = bitmap_cache; settings->order_support[NEG_MEM3BLT_V2_INDEX] = false; settings->order_support[NEG_SAVEBITMAP_INDEX] = false; diff --git a/include/freerdp/gdi/gdi.h b/include/freerdp/gdi/gdi.h index d1b36cbf7..03acd9052 100644 --- a/include/freerdp/gdi/gdi.h +++ b/include/freerdp/gdi/gdi.h @@ -63,11 +63,26 @@ #define GDI_BLACKNESS 0x00000042 /* D = 0 */ #define GDI_WHITENESS 0x00FF0062 /* D = 1 */ #define GDI_DSPDxax 0x00E20746 /* D = (S & P) | (~S & D) */ +#define GDI_PSDPxax 0x00B8074A /* D = (S & D) | (~S & P) */ #define GDI_SPna 0x000C0324 /* D = S & ~P */ #define GDI_DSna 0x00220326 /* D = D & ~S */ #define GDI_DPa 0x00A000C9 /* D = D & P */ #define GDI_PDxn 0x00A50065 /* D = D ^ ~P */ +#define GDI_DPon 0x000500A9 +#define GDI_DPna 0x000A0329 +#define GDI_Pn 0x000F0001 +#define GDI_PDna 0x00500325 +#define GDI_DPan 0x005F00E9 +#define GDI_DSan 0x007700E6 +#define GDI_DSxn 0x00990066 +#define GDI_DPa 0x00A000C9 +#define GDI_D 0x00AA0029 +#define GDI_DPno 0x00AF0229 +#define GDI_SDno 0x00DD0228 +#define GDI_PDno 0x00F50225 +#define GDI_DPo 0x00FA0089 + /* Brush Styles */ #define GDI_BS_SOLID 0x00 #define GDI_BS_NULL 0x01 diff --git a/libfreerdp-cache/bitmap.c b/libfreerdp-cache/bitmap.c index 652a39189..99c100531 100644 --- a/libfreerdp-cache/bitmap.c +++ b/libfreerdp-cache/bitmap.c @@ -39,16 +39,27 @@ void update_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) void update_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) { + uint8 style; rdpBitmap* bitmap; rdpCache* cache = context->cache; + rdpBrush* brush = &mem3blt->brush; if (mem3blt->cacheId == 0xFF) bitmap = offscreen_cache_get(cache->offscreen, mem3blt->cacheIndex); else bitmap = bitmap_cache_get(cache->bitmap, (uint8) mem3blt->cacheId, mem3blt->cacheIndex); + style = brush->style; + + if (brush->style & CACHED_BRUSH) + { + brush->data = brush_cache_get(cache->brush, brush->index, &brush->bpp); + brush->style = 0x03; + } + mem3blt->bitmap = bitmap; IFCALL(cache->bitmap->Mem3Blt, context, mem3blt); + brush->style = style; } void update_gdi_cache_bitmap(rdpContext* context, CACHE_BITMAP_ORDER* cache_bitmap)