From 43bcfb4a3ccc5dcc7d1a21e2d84d1aa5843b5466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 26 Aug 2011 14:48:51 -0400 Subject: [PATCH] xfreerdp: start using X11-GDI implementation --- client/X11/xf_gdi.c | 152 ++++++++++++++++++++++++++++++++++++- client/X11/xfreerdp.c | 17 ++++- client/X11/xfreerdp.h | 5 ++ include/freerdp/settings.h | 1 + libfreerdp-utils/args.c | 22 ++++++ 5 files changed, 195 insertions(+), 2 deletions(-) diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index 1c93a4a78..70d024d78 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -17,6 +17,8 @@ * limitations under the License. */ +#include + #include "xf_gdi.h" static const uint8 xf_rop2_table[] = @@ -186,14 +188,55 @@ boolean xf_set_rop3(xfInfo* xfi, int rop3) return True; } -void xf_bitmap_new(xfInfo* xfi, int width, int height, int bpp, uint8* data) +Pixmap xf_bitmap_new(xfInfo* xfi, int width, int height, int bpp, uint8* data) { + Pixmap bitmap; + uint8* cdata; + XImage* image; + bitmap = XCreatePixmap(xfi->display, xfi->window->handle, width, height, xfi->depth); + + cdata = gdi_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); + + XPutImage(xfi->display, bitmap, xfi->gc, image, 0, 0, 0, 0, width, height); + XFree(image); + + if (cdata != data) + xfree(cdata); + + return bitmap; } void xf_gdi_bitmap_update(rdpUpdate* update, BITMAP_UPDATE* bitmap) { + int i; + int x, y; + int w, h; + uint8* data; + XImage* image; + BITMAP_DATA* bmp; + xfInfo* xfi = GET_XFI(update); + for (i = 0; i < bitmap->number; i++) + { + bmp = &bitmap->bitmaps[i]; + + data = gdi_image_convert(bmp->data, NULL, bmp->width, bmp->height, bmp->bpp, xfi->bpp, xfi->clrconv); + + image = XCreateImage(xfi->display, xfi->visual, xfi->depth, + ZPixmap, 0, (char*) data, bmp->width, bmp->height, xfi->scanline_pad, 0); + + x = bmp->left; + y = bmp->top; + w = bmp->right - bmp->left + 1; + h = bmp->bottom - bmp->top + 1; + + XPutImage(xfi->display, xfi->primary, xfi->gc, image, 0, 0, x, y, w, h); + XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, x, y, w, h, x, y); + } } void xf_gdi_palette_update(rdpUpdate* update, PALETTE_UPDATE* palette) @@ -203,12 +246,40 @@ void xf_gdi_palette_update(rdpUpdate* update, PALETTE_UPDATE* palette) void xf_gdi_set_bounds(rdpUpdate* update, BOUNDS* bounds) { + XRectangle clip; + xfInfo* xfi = GET_XFI(update); + if (bounds != NULL) + { + clip.x = bounds->left; + clip.y = bounds->top; + clip.width = bounds->right - bounds->left + 1; + clip.height = bounds->bottom - bounds->top + 1; + XSetClipRectangles(xfi->display, xfi->gc, 0, 0, &clip, 1, YXBanded); + } + else + { + XSetClipMask(xfi->display, xfi->gc, None); + } } void xf_gdi_dstblt(rdpUpdate* update, DSTBLT_ORDER* dstblt) { + xfInfo* xfi = GET_XFI(update); + xf_set_rop3(xfi, gdi_rop3_code(dstblt->bRop)); + + XSetFillStyle(xfi->display, xfi->gc, FillSolid); + XFillRectangle(xfi->display, xfi->drawing, xfi->gc, + dstblt->nLeftRect, dstblt->nTopRect, + dstblt->nWidth, dstblt->nHeight); + + if (xfi->drawing == xfi->primary) + { + XFillRectangle(xfi->display, xfi->window->handle, xfi->gc, + dstblt->nLeftRect, dstblt->nTopRect, + dstblt->nWidth, dstblt->nHeight); + } } void xf_gdi_patblt(rdpUpdate* update, PATBLT_ORDER* patblt) @@ -218,17 +289,80 @@ void xf_gdi_patblt(rdpUpdate* update, PATBLT_ORDER* patblt) void xf_gdi_scrblt(rdpUpdate* update, SCRBLT_ORDER* scrblt) { + xfInfo* xfi = GET_XFI(update); + xf_set_rop3(xfi, gdi_rop3_code(scrblt->bRop)); + XCopyArea(xfi->display, xfi->primary, xfi->drawing, xfi->gc, scrblt->nXSrc, scrblt->nYSrc, + scrblt->nWidth, scrblt->nHeight, scrblt->nLeftRect, scrblt->nTopRect); + + if (xfi->drawing == xfi->primary) + { + if (xfi->unobscured) + { + XCopyArea(xfi->display, xfi->window->handle, xfi->window->handle, xfi->gc, + scrblt->nXSrc, scrblt->nYSrc, scrblt->nWidth, scrblt->nHeight, + scrblt->nLeftRect, scrblt->nTopRect); + } + else + { + XSetFunction(xfi->display, xfi->gc, GXcopy); + XCopyArea(xfi->display, xfi->primary, xfi->window->handle, xfi->gc, + scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight, + scrblt->nLeftRect, scrblt->nTopRect); + } + } } void xf_gdi_opaque_rect(rdpUpdate* update, OPAQUE_RECT_ORDER* opaque_rect) { + uint32 color; + xfInfo* xfi = GET_XFI(update); + color = gdi_color_convert(opaque_rect->color, xfi->srcBpp, xfi->bpp, xfi->clrconv); + + XSetFunction(xfi->display, xfi->gc, GXcopy); + XSetFillStyle(xfi->display, xfi->gc, FillSolid); + XSetForeground(xfi->display, xfi->gc, color); + XFillRectangle(xfi->display, xfi->drawing, xfi->gc, + opaque_rect->nLeftRect, opaque_rect->nTopRect, + opaque_rect->nWidth, opaque_rect->nHeight); + + if (xfi->drawing == xfi->primary) + { + XFillRectangle(xfi->display, xfi->window->handle, xfi->gc, + opaque_rect->nLeftRect, opaque_rect->nTopRect, + opaque_rect->nWidth, opaque_rect->nHeight); + } } void xf_gdi_multi_opaque_rect(rdpUpdate* update, MULTI_OPAQUE_RECT_ORDER* multi_opaque_rect) { + int i; + uint32 color; + DELTA_RECT* rectangle; + xfInfo* xfi = GET_XFI(update); + color = gdi_color_convert(multi_opaque_rect->color, xfi->srcBpp, xfi->bpp, xfi->clrconv); + + XSetFunction(xfi->display, xfi->gc, GXcopy); + XSetFillStyle(xfi->display, xfi->gc, FillSolid); + XSetForeground(xfi->display, xfi->gc, color); + + for (i = 1; i < multi_opaque_rect->numRectangles + 1; i++) + { + rectangle = &multi_opaque_rect->rectangles[i]; + + XFillRectangle(xfi->display, xfi->drawing, xfi->gc, + rectangle->left, rectangle->top, + rectangle->width, rectangle->height); + + if (xfi->drawing == xfi->primary) + { + XFillRectangle(xfi->display, xfi->window->handle, xfi->gc, + rectangle->left, rectangle->top, + rectangle->width, rectangle->height); + } + } } void xf_gdi_line_to(rdpUpdate* update, LINE_TO_ORDER* line_to) @@ -248,12 +382,28 @@ void xf_gdi_fast_index(rdpUpdate* update, FAST_INDEX_ORDER* fast_index) void xf_gdi_create_offscreen_bitmap(rdpUpdate* update, CREATE_OFFSCREEN_BITMAP_ORDER* create_offscreen_bitmap) { + Pixmap surface; + xfInfo* xfi = GET_XFI(update); + surface = xf_bitmap_new(xfi, create_offscreen_bitmap->cx, create_offscreen_bitmap->cy, xfi->bpp, NULL); + + offscreen_put(xfi->cache->offscreen, create_offscreen_bitmap->id, (void*) surface); } void xf_gdi_switch_surface(rdpUpdate* update, SWITCH_SURFACE_ORDER* switch_surface) { + Pixmap surface; + xfInfo* xfi = GET_XFI(update); + if (switch_surface->bitmapId == SCREEN_BITMAP_SURFACE) + { + xfi->drawing = xfi->primary; + } + else + { + surface = (Pixmap) offscreen_get(xfi->cache->offscreen, switch_surface->bitmapId); + xfi->drawing = surface; + } } void xf_gdi_cache_bitmap_v2(rdpUpdate* update, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2) diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index 3a078850c..e17f91b51 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -296,6 +296,14 @@ boolean xf_pre_connect(freerdp* instance) xf_kbd_init(xfi); + xfi->clrconv = (HCLRCONV) malloc(sizeof(CLRCONV)); + xfi->clrconv->palette = NULL; + xfi->clrconv->alpha = 1; + xfi->clrconv->invert = 0; + xfi->clrconv->rgb555 = 0; + + xfi->cache = cache_new(instance->settings); + xfi->xfds = ConnectionNumber(xfi->display); xfi->screen_number = DefaultScreen(xfi->display); xfi->screen = ScreenOfDisplay(xfi->display, xfi->screen_number); @@ -385,7 +393,11 @@ boolean xf_post_connect(freerdp* instance) gdi_init(instance, CLRCONV_ALPHA | CLRBUF_32BPP); gdi = GET_GDI(instance->update); - //xf_gdi_register_update_callbacks(instance->update); + if (instance->settings->sw_gdi != True) + { + xfi->srcBpp = instance->settings->color_depth; + xf_gdi_register_update_callbacks(instance->update); + } if (xfi->fullscreen) xfi->decoration = False; @@ -427,6 +439,7 @@ boolean xf_post_connect(freerdp* instance) xfi->gc = XCreateGC(xfi->display, DefaultRootWindow(xfi->display), GCGraphicsExposures, &gcv); xfi->primary = XCreatePixmap(xfi->display, DefaultRootWindow(xfi->display), xfi->width, xfi->height, xfi->depth); + xfi->drawing = xfi->primary; XSetForeground(xfi->display, xfi->gc, BlackPixelOfScreen(xfi->screen)); XFillRectangle(xfi->display, xfi->primary, xfi->gc, 0, 0, xfi->width, xfi->height); @@ -705,6 +718,8 @@ int main(int argc, char* argv[]) chanman = freerdp_chanman_new(); SET_CHANMAN(instance, chanman); + instance->settings->sw_gdi = False; + if (freerdp_parse_args(instance->settings, argc, argv, xf_process_plugin_args, chanman, xf_process_ui_args, NULL) < 0) return 1; diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 3c3bb02ac..38a9792cd 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -26,6 +26,7 @@ #include #include #include +#include typedef struct xf_info xfInfo; @@ -54,9 +55,11 @@ struct xf_info int depth; int width; int height; + int srcBpp; Screen* screen; XImage* image; Pixmap primary; + Pixmap drawing; Visual* visual; Display* display; Colormap colormap; @@ -71,7 +74,9 @@ struct xf_info xfWorkArea workArea; int current_desktop; boolean remote_app; + HCLRCONV clrconv; rdpRail* rail; + rdpCache* cache; boolean focused; boolean mouse_active; diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 8af844120..861620fc6 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -176,6 +176,7 @@ struct rdp_settings { uint16 width; uint16 height; + boolean sw_gdi; boolean workarea; boolean fullscreen; boolean decorations; diff --git a/libfreerdp-utils/args.c b/libfreerdp-utils/args.c index 32d392c0f..c260c2d28 100644 --- a/libfreerdp-utils/args.c +++ b/libfreerdp-utils/args.c @@ -211,6 +211,28 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, settings->fastpath_input = False; settings->fastpath_output = False; } + else if (strcmp("--gdi", argv[index]) == 0) + { + index++; + if (index == argc) + { + printf("missing GDI backend\n"); + return -1; + } + if (strncmp("sw", argv[index], 1) == 0) /* software */ + { + settings->sw_gdi = True; + } + else if (strncmp("hw", argv[index], 1) == 0) /* hardware */ + { + settings->sw_gdi = False; + } + else + { + printf("unknown GDI backend\n"); + return -1; + } + } else if (strcmp("--rfx", argv[index]) == 0) { settings->rfx_codec = True;