From 1f5158676975b2b4c9c3be518b575b677a4fede3 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Thu, 15 Dec 2016 21:17:50 -0800 Subject: [PATCH] add libpainter for drawing when client does not have minimum orders --- common/xrdp_client_info.h | 2 + common/xrdp_constants.h | 34 +++ configure.ac | 5 + libxrdp/xrdp_caps.c | 20 ++ xrdp/Makefile.am | 6 + xrdp/xrdp_bitmap.c | 8 + xrdp/xrdp_painter.c | 555 +++++++++++++++++++++++++++++++++++++- xrdp/xrdp_types.h | 3 + xrdp/xrdp_wm.c | 53 +--- 9 files changed, 641 insertions(+), 45 deletions(-) diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index 254708f1..e71f8d71 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -148,6 +148,8 @@ struct xrdp_client_info int client_os_major; int client_os_minor; + + int no_orders_supported; }; #endif diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h index 7dcb3064..f4b97c3b 100644 --- a/common/xrdp_constants.h +++ b/common/xrdp_constants.h @@ -476,6 +476,40 @@ #define XR_ORDERFLAGS_EX_ALTSEC_FRAME_MARKER_SUPPORT 0x0004 #define XR_ORDERFLAGS_EX_OFFSCREEN_COMPOSITE_SUPPORT 0x0100 +/* orders negotiation indexes */ +#define TS_NEG_DSTBLT_INDEX 0x00 +#define TS_NEG_PATBLT_INDEX 0x01 +#define TS_NEG_SCRBLT_INDEX 0x02 +#define TS_NEG_MEMBLT_INDEX 0x03 +#define TS_NEG_MEM3BLT_INDEX 0x04 + /* 0x05 */ + /* 0x06 */ +#define TS_NEG_DRAWNINEGRID_INDEX 0x07 +#define TS_NEG_LINETO_INDEX 0x08 +#define TS_NEG_MULTI_DRAWNINEGRID_INDEX 0x09 + /* 0x0A */ +#define TS_NEG_SAVEBITMAP_INDEX 0x0B + /* 0x0C */ + /* 0x0D */ + /* 0x0E */ +#define TS_NEG_MULTIDSTBLT_INDEX 0x0F +#define TS_NEG_MULTIPATBLT_INDEX 0x10 +#define TS_NEG_MULTISCRBLT_INDEX 0x11 +#define TS_NEG_MULTIOPAQUERECT_INDEX 0x12 +#define TS_NEG_FAST_INDEX_INDEX 0x13 +#define TS_NEG_POLYGON_SC_INDEX 0x14 +#define TS_NEG_POLYGON_CB_INDEX 0x15 +#define TS_NEG_POLYLINE_INDEX 0x16 + /* 0x17 */ +#define TS_NEG_FAST_GLYPH_INDEX 0x18 +#define TS_NEG_ELLIPSE_SC_INDEX 0x19 +#define TS_NEG_ELLIPSE_CB_INDEX 0x1A +#define TS_NEG_INDEX_INDEX 0x1B + /* 0x1C */ + /* 0x1D */ + /* 0x1E */ + /* 0x1F */ + /* drawable types */ #define WND_TYPE_BITMAP 0 #define WND_TYPE_WND 1 diff --git a/configure.ac b/configure.ac index d8387114..302534bb 100644 --- a/configure.ac +++ b/configure.ac @@ -117,6 +117,11 @@ AC_ARG_ENABLE(pixman, AS_HELP_STRING([--enable-pixman], [Use pixman library (default: no)]), [], [enable_pixman=no]) AM_CONDITIONAL(XRDP_PIXMAN, [test x$enable_pixman = xyes]) +AM_CONDITIONAL(XRDP_PAINTER, [test x$enable_painter = xyes]) +AC_ARG_ENABLE(painter, AS_HELP_STRING([--enable-painter], + [Use painter library (default: no)]), + [], [enable_painter=no]) +AM_CONDITIONAL(XRDP_PAINTER, [test x$enable_painter = xyes]) # Check if -ldl is needed to use dlopen() DLOPEN_LIBS= diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index 8d5250d5..de76c550 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -159,6 +159,15 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, DEBUG(("desktop cache size %d", i)); in_uint8s(s, 4); /* Unknown */ in_uint8s(s, 4); /* Unknown */ + + /* check if libpainter should be used for drawing, instead of orders */ + if (!(order_caps[TS_NEG_DSTBLT_INDEX] && order_caps[TS_NEG_PATBLT_INDEX] && + order_caps[TS_NEG_SCRBLT_INDEX] && order_caps[TS_NEG_MEMBLT_INDEX])) + { + g_writeln("xrdp_caps_process_order: not enough orders supported by client, using painter."); + self->client_info.no_orders_supported = 1; + } + return 0; } @@ -667,6 +676,17 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) s->p = p + len + 4; } + if (self->client_info.no_orders_supported && + (self->client_info.offscreen_support_level != 0)) + { + g_writeln("xrdp_caps_process_confirm_active: not enough orders " + "supported by client, client wants off screen bitmap but " + "offscreen bitmaps disabled"); + self->client_info.offscreen_support_level = 0; + self->client_info.offscreen_cache_size = 0; + self->client_info.offscreen_cache_entries = 0; + } + DEBUG(("out xrdp_caps_process_confirm_active")); return 0; } diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index 400a4285..818a77a1 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -28,6 +28,12 @@ AM_CPPFLAGS += $(PIXMAN_CFLAGS) XRDP_EXTRA_LIBS += $(PIXMAN_LIBS) endif +if XRDP_PAINTER +AM_CPPFLAGS += -DXRDP_PAINTER +AM_CPPFLAGS += -I$(top_srcdir)/libpainter/include +XRDP_EXTRA_LIBS += $(top_srcdir)/libpainter/src/.libs/libpainter.a +endif + sbin_PROGRAMS = \ xrdp diff --git a/xrdp/xrdp_bitmap.c b/xrdp/xrdp_bitmap.c index 9ffc6284..1c759c3e 100644 --- a/xrdp/xrdp_bitmap.c +++ b/xrdp/xrdp_bitmap.c @@ -123,6 +123,14 @@ xrdp_bitmap_create(int width, int height, int bpp, self->data = (char *)g_malloc(width * height * Bpp, 0); } +#if defined(XRDP_PAINTER) + if (self->type == WND_TYPE_SCREEN) /* noorders */ + { + LLOGLN(0, ("xrdp_bitmap_create: noorders")); + self->data = (char *) g_malloc(width * height * Bpp, 0); + } +#endif + if (self->type != WND_TYPE_BITMAP) { self->child_list = list_create(); diff --git a/xrdp/xrdp_painter.c b/xrdp/xrdp_painter.c index f5605717..361a6a74 100644 --- a/xrdp/xrdp_painter.c +++ b/xrdp/xrdp_painter.c @@ -20,17 +20,152 @@ #include "xrdp.h" +#if defined(XRDP_PAINTER) +#include /* libpainter */ +#endif + +#define LLOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do \ + { \ + if (_level < LLOG_LEVEL) \ + { \ + g_write("xrdp:xrdp_painter [%10.10u]: ", g_time3()); \ + g_writeln _args ; \ + } \ + } \ + while (0) + +#if defined(XRDP_PAINTER) + +/*****************************************************************************/ +static int APP_CC +xrdp_painter_add_dirty_rect(struct xrdp_painter *self, int x, int y, + int cx, int cy, struct xrdp_rect *clip_rect) +{ + int x2; + int y2; + struct xrdp_rect rect; + + if (clip_rect != 0) + { + x2 = x + cx; + y2 = y + cy; + x = MAX(x, clip_rect->left); + y = MAX(y, clip_rect->top); + x2 = MIN(x2, clip_rect->right); + y2 = MIN(y2, clip_rect->bottom); + cx = x2 - x; + cy = y2 - y; + } + if (cx < 1 || cy < 1) + { + return 0; + } + rect.left = x; + rect.top = y; + rect.right = x + cx; + rect.bottom = y + cy; + xrdp_region_add_rect(self->dirty_region, &rect); + LLOGLN(10, ("xrdp_painter_add_dirty_rect: x %d y %d cx %d cy %d", + x, y, cx, cy)); + return 0; +} + +/*****************************************************************************/ +static int +xrdp_painter_send_dirty(struct xrdp_painter *self) +{ + int cx; + int cy; + int bpp; + int Bpp; + int index; + int jndex; + int error; + char *ldata; + char *src; + char *dst; + struct xrdp_rect rect; + + LLOGLN(10, ("xrdp_painter_send_dirty:")); + + bpp = self->wm->screen->bpp; + Bpp = (bpp + 7) / 8; + if (Bpp == 3) + { + Bpp = 4; + } + + jndex = 0; + error = xrdp_region_get_rect(self->dirty_region, jndex, &rect); + while (error == 0) + { + cx = rect.right - rect.left; + cy = rect.bottom - rect.top; + ldata = (char *)g_malloc(cx * cy * Bpp, 0); + if (ldata == 0) + { + return 1; + } + src = self->wm->screen->data; + src += self->wm->screen->line_size * rect.top; + src += rect.left * Bpp; + dst = ldata; + for (index = 0; index < cy; index++) + { + g_memcpy(dst, src, cx * Bpp); + src += self->wm->screen->line_size; + dst += cx * Bpp; + } + LLOGLN(10, ("xrdp_painter_send_dirty: x %d y %d cx %d cy %d", + rect.left, rect.top, cx, cy)); + libxrdp_send_bitmap(self->session, cx, cy, bpp, + ldata, rect.left, rect.top, cx, cy); + g_free(ldata); + + jndex++; + error = xrdp_region_get_rect(self->dirty_region, jndex, &rect); + } + + xrdp_region_delete(self->dirty_region); + self->dirty_region = xrdp_region_create(self->wm); + + return 0; +} + +#endif + /*****************************************************************************/ struct xrdp_painter *APP_CC xrdp_painter_create(struct xrdp_wm *wm, struct xrdp_session *session) { struct xrdp_painter *self; + LLOGLN(10, ("xrdp_painter_create:")); self = (struct xrdp_painter *)g_malloc(sizeof(struct xrdp_painter), 1); self->wm = wm; self->session = session; - self->rop = 0xcc; /* copy will use 0xcc*/ + self->rop = 0xcc; /* copy will use 0xcc */ self->clip_children = 1; + + + if (self->session->client_info->no_orders_supported) + { +#if defined(XRDP_PAINTER) + if (painter_create(&(self->painter)) != PT_ERROR_NONE) + { + self->painter = 0; + LLOGLN(0, ("xrdp_painter_create: painter_create failed")); + } + else + { + LLOGLN(10, ("xrdp_painter_create: painter_create success")); + } + self->dirty_region = xrdp_region_create(wm); +#endif + } + return self; } @@ -38,11 +173,17 @@ xrdp_painter_create(struct xrdp_wm *wm, struct xrdp_session *session) void APP_CC xrdp_painter_delete(struct xrdp_painter *self) { + LLOGLN(10, ("xrdp_painter_delete:")); if (self == 0) { return; } +#if defined(XRDP_PAINTER) + painter_delete(self->painter); + xrdp_region_delete(self->dirty_region); +#endif + g_free(self); } @@ -54,6 +195,13 @@ wm_painter_set_target(struct xrdp_painter *self) int index; struct list *del_list; + LLOGLN(10, ("wm_painter_set_target:")); + + if (self->painter != 0) + { + return 0; + } + if (self->wm->target_surface->type == WND_TYPE_SCREEN) { if (self->wm->current_surface_index != 0xffff) @@ -97,11 +245,19 @@ wm_painter_set_target(struct xrdp_painter *self) int APP_CC xrdp_painter_begin_update(struct xrdp_painter *self) { + LLOGLN(10, ("xrdp_painter_begin_update:")); if (self == 0) { return 0; } + self->begin_end_level++; + + if (self->painter != 0) + { + return 0; + } + libxrdp_orders_init(self->session); wm_painter_set_target(self); return 0; @@ -111,11 +267,25 @@ xrdp_painter_begin_update(struct xrdp_painter *self) int APP_CC xrdp_painter_end_update(struct xrdp_painter *self) { + LLOGLN(10, ("xrdp_painter_end_update:")); if (self == 0) { return 0; } + self->begin_end_level--; + + if (self->painter != 0) + { +#if defined(XRDP_PAINTER) + if (self->begin_end_level == 0) + { + xrdp_painter_send_dirty(self); + return 0; + } +#endif + } + libxrdp_orders_send(self->session); return 0; } @@ -270,6 +440,7 @@ xrdp_painter_text_width(struct xrdp_painter *self, const char *text) struct xrdp_font_char *font_item; twchar *wstr; + LLOGLN(10, ("xrdp_painter_text_width:")); xrdp_painter_font_needed(self); if (self->font == 0) @@ -307,6 +478,7 @@ xrdp_painter_text_height(struct xrdp_painter *self, const char *text) struct xrdp_font_char *font_item; twchar *wstr; + LLOGLN(10, ("xrdp_painter_text_height:")); xrdp_painter_font_needed(self); if (self->font == 0) @@ -342,6 +514,13 @@ xrdp_painter_setup_brush(struct xrdp_painter *self, { int cache_id; + LLOGLN(10, ("xrdp_painter_setup_brush:")); + + if (self->painter != 0) + { + return 0; + } + g_memcpy(out_brush, in_brush, sizeof(struct xrdp_brush)); if (in_brush->style == 3) @@ -358,6 +537,38 @@ xrdp_painter_setup_brush(struct xrdp_painter *self, return 0; } +#if defined(XRDP_PAINTER) + +/*****************************************************************************/ +static int APP_CC +get_pt_format(struct xrdp_painter *self) +{ + switch (self->wm->screen->bpp) + { + case 8: + return PT_FORMAT_r3g3b2; + case 15: + return PT_FORMAT_a1r5g5b5; + case 16: + return PT_FORMAT_r5g6b5; + } + return PT_FORMAT_a8r8g8b8; +} + +/*****************************************************************************/ +static int +get_rgb_from_rdp_color(struct xrdp_painter *self, int rdp_color) +{ + if (self->wm->screen->bpp < 24) + { + return rdp_color; + } + /* well, this is really BGR2RGB */ + return XR_RGB2BGR(rdp_color); +} + +#endif + /*****************************************************************************/ /* fill in an area of the screen with one color */ int APP_CC @@ -375,11 +586,120 @@ xrdp_painter_fill_rect(struct xrdp_painter *self, int dy; int rop; + LLOGLN(10, ("xrdp_painter_fill_rect:")); + if (self == 0) { return 0; } + dx = 0; + dy = 0; + + if (self->painter != 0) + { +#if defined(XRDP_PAINTER) + struct painter_bitmap dst_pb; + struct xrdp_bitmap *ldst; + struct painter_bitmap pat; + + LLOGLN(10, ("xrdp_painter_fill_rect: dst->type %d", dst->type)); + if (dst->type != WND_TYPE_OFFSCREEN) + { + LLOGLN(10, ("xrdp_painter_fill_rect: using painter")); + + ldst = self->wm->screen; + + g_memset(&dst_pb, 0, sizeof(dst_pb)); + dst_pb.format = get_pt_format(self); + dst_pb.width = ldst->width; + dst_pb.stride_bytes = ldst->line_size; + dst_pb.height = ldst->height; + dst_pb.data = ldst->data; + + LLOGLN(10, ("xrdp_painter_fill_rect: ldst->width %d ldst->height %d " + "dst->data %p self->fg_color %d", + ldst->width, ldst->height, ldst->data, self->fg_color)); + + xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); + region = xrdp_region_create(self->wm); + xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, region, + self->clip_children); + x += dx; + y += dy; + + rop = self->rop; + switch (self->rop) + { + case 0x5a: + rop = PT_ROP_DSx; + break; + case 0xf0: + rop = PT_ROP_S; + break; + case 0xfb: + rop = PT_ROP_D; + break; + case 0xc0: + rop = PT_ROP_DSa; + break; + } + painter_set_rop(self->painter, rop); + + if (self->mix_mode == 0) + { + painter_set_pattern_mode(self->painter, PT_PATTERN_MODE_OPAQUE); + painter_set_fgcolor(self->painter, get_rgb_from_rdp_color(self, self->fg_color)); + k = 0; + while (xrdp_region_get_rect(region, k, &rect) == 0) + { + if (rect_intersect(&rect, &clip_rect, &draw_rect)) + { + painter_set_clip(self->painter, + draw_rect.left, draw_rect.top, + draw_rect.right - draw_rect.left, + draw_rect.bottom - draw_rect.top); + painter_fill_rect(self->painter, &dst_pb, x, y, cx, cy); + xrdp_painter_add_dirty_rect(self, x, y, cx, cy, &draw_rect); + } + k++; + } + } + else + { + painter_set_pattern_mode(self->painter, PT_PATTERN_MODE_OPAQUE); + painter_set_fgcolor(self->painter, get_rgb_from_rdp_color(self, self->fg_color)); + painter_set_bgcolor(self->painter, get_rgb_from_rdp_color(self, self->bg_color)); + painter_set_pattern_origin(self->painter, self->brush.x_origin, self->brush.y_origin); + g_memset(&pat, 0, sizeof(pat)); + pat.format = PT_FORMAT_c1; + pat.width = 8; + pat.stride_bytes = 1; + pat.height = 8; + pat.data = self->brush.pattern; + k = 0; + while (xrdp_region_get_rect(region, k, &rect) == 0) + { + if (rect_intersect(&rect, &clip_rect, &draw_rect)) + { + painter_set_clip(self->painter, + draw_rect.left, draw_rect.top, + draw_rect.right - draw_rect.left, + draw_rect.bottom - draw_rect.top); + painter_fill_pattern(self->painter, &dst_pb, &pat, + x, y, x, y, cx, cy); + xrdp_painter_add_dirty_rect(self, x, y, cx, cy, &draw_rect); + } + k++; + } + } + painter_clear_clip(self->painter); + xrdp_region_delete(region); + } + return 0; +#endif + } + /* todo data */ if (dst->type == WND_TYPE_BITMAP) /* 0 */ @@ -508,11 +828,14 @@ xrdp_painter_draw_text(struct xrdp_painter *self, struct xrdp_font_char *font_item; twchar *wstr; + LLOGLN(10, ("xrdp_painter_draw_text:")); + if (self == 0) { return 0; } + len = g_mbstowcs(0, text, 0); if (len < 1) @@ -534,6 +857,88 @@ xrdp_painter_draw_text(struct xrdp_painter *self, return 0; } + if (self->painter != 0) + { +#if defined(XRDP_PAINTER) + struct painter_bitmap pat; + struct painter_bitmap dst_pb; + struct xrdp_bitmap *ldst; + + if (dst->type != WND_TYPE_OFFSCREEN) + { + ldst = self->wm->screen; + /* convert to wide char */ + wstr = (twchar *)g_malloc((len + 2) * sizeof(twchar), 0); + g_mbstowcs(wstr, text, len + 1); + font = self->font; + total_width = 0; + total_height = 0; + for (index = 0; index < len; index++) + { + font_item = font->font_items + wstr[index]; + k = font_item->incby; + total_width += k; + total_height = MAX(total_height, font_item->height); + } + xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); + region = xrdp_region_create(self->wm); + xrdp_wm_get_vis_region(self->wm, dst, x, y, + total_width, total_height, + region, self->clip_children); + x += dx; + y += dy; + g_memset(&dst_pb, 0, sizeof(dst_pb)); + dst_pb.format = get_pt_format(self); + dst_pb.width = ldst->width; + dst_pb.stride_bytes = ldst->line_size; + dst_pb.height = ldst->height; + dst_pb.data = ldst->data; + painter_set_rop(self->painter, PT_ROP_S); + painter_set_pattern_origin(self->painter, 0, 0); + painter_set_pattern_mode(self->painter, PT_PATTERN_MODE_NORMAL); + painter_set_fgcolor(self->painter, + get_rgb_from_rdp_color(self, self->fg_color)); + k = 0; + while (xrdp_region_get_rect(region, k, &rect) == 0) + { + if (rect_intersect(&rect, &clip_rect, &draw_rect)) + { + painter_set_clip(self->painter, + draw_rect.left, draw_rect.top, + draw_rect.right - draw_rect.left, + draw_rect.bottom - draw_rect.top); + for (index = 0; index < len; index++) + { + font_item = font->font_items + wstr[index]; + g_memset(&pat, 0, sizeof(pat)); + pat.format = PT_FORMAT_c1; + pat.width = font_item->width; + pat.stride_bytes = (font_item->width + 7) / 8; + pat.height = font_item->height; + pat.data = font_item->data; + x1 = x + font_item->offset; + y1 = y + (font_item->height + font_item->baseline); + painter_fill_pattern(self->painter, &dst_pb, &pat, + 0, 0, x1, y1, + font_item->width, + font_item->height); + xrdp_painter_add_dirty_rect(self, x, y, + font_item->width, + font_item->height, + &draw_rect); + x += font_item->incby; + } + } + k++; + } + painter_clear_clip(self->painter); + xrdp_region_delete(region); + g_free(wstr); + } + return 0; +#endif + } + /* convert to wide char */ wstr = (twchar *)g_malloc((len + 2) * sizeof(twchar), 0); g_mbstowcs(wstr, text, len + 1); @@ -616,11 +1021,18 @@ xrdp_painter_draw_text2(struct xrdp_painter *self, int dx; int dy; + LLOGLN(0, ("xrdp_painter_draw_text2:")); + if (self == 0) { return 0; } + if (self->painter != 0) + { + return 0; + } + /* todo data */ if (dst->type == WND_TYPE_BITMAP) @@ -711,11 +1123,76 @@ xrdp_painter_copy(struct xrdp_painter *self, int index; struct list *del_list; + LLOGLN(10, ("xrdp_painter_copy:")); + if (self == 0 || src == 0 || dst == 0) { return 0; } + if (self->painter != 0) + { +#if defined(XRDP_PAINTER) + struct painter_bitmap src_pb; + struct painter_bitmap dst_pb; + struct xrdp_bitmap *ldst; + + LLOGLN(10, ("xrdp_painter_copy: src->type %d dst->type %d", src->type, dst->type)); + LLOGLN(10, ("xrdp_painter_copy: self->rop 0x%2.2x", self->rop)); + + if (dst->type != WND_TYPE_OFFSCREEN) + { + LLOGLN(10, ("xrdp_painter_copy: using painter")); + ldst = self->wm->screen; + + g_memset(&dst_pb, 0, sizeof(dst_pb)); + dst_pb.format = get_pt_format(self); + dst_pb.width = ldst->width; + dst_pb.stride_bytes = ldst->line_size; + dst_pb.height = ldst->height; + dst_pb.data = ldst->data; + + g_memset(&src_pb, 0, sizeof(src_pb)); + src_pb.format = get_pt_format(self); + src_pb.width = src->width; + src_pb.stride_bytes = src->line_size; + src_pb.height = src->height; + src_pb.data = src->data; + + xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); + region = xrdp_region_create(self->wm); + xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, region, + self->clip_children); + x += dx; + y += dy; + k = 0; + + painter_set_rop(self->painter, self->rop); + while (xrdp_region_get_rect(region, k, &rect1) == 0) + { + if (rect_intersect(&rect1, &clip_rect, &draw_rect)) + { + painter_set_clip(self->painter, + draw_rect.left, draw_rect.top, + draw_rect.right - draw_rect.left, + draw_rect.bottom - draw_rect.top); + LLOGLN(10, (" x %d y %d cx %d cy %d srcx %d srcy %d", + x, y, cx, cy, srcx, srcy)); + painter_copy(self->painter, &dst_pb, x, y, cx, cy, + &src_pb, srcx, srcy); + xrdp_painter_add_dirty_rect(self, x, y, cx, cy, + &draw_rect); + } + k++; + } + painter_clear_clip(self->painter); + xrdp_region_delete(region); + } + + return 0; +#endif + } + /* todo data */ if (dst->type == WND_TYPE_BITMAP) @@ -848,7 +1325,7 @@ xrdp_painter_copy(struct xrdp_painter *self, while (i < (srcx + cx)) { w = MIN(64, ((srcx + cx) - i)); - h = MIN(63, ((srcy + cy) - j)); + h = MIN(64, ((srcy + cy) - j)); b = xrdp_bitmap_create(w, h, src->bpp, 0, self->wm); #if 1 xrdp_bitmap_copy_box_with_crc(src, b, i, j, w, h); @@ -883,7 +1360,7 @@ xrdp_painter_copy(struct xrdp_painter *self, i += 64; } - j += 63; + j += 64; } xrdp_region_delete(region); @@ -918,11 +1395,18 @@ xrdp_painter_composite(struct xrdp_painter* self, int cache_srcidx; int cache_mskidx; + LLOGLN(0, ("xrdp_painter_composite:")); + if (self == 0 || src == 0 || dst == 0) { return 0; } + if (self->painter != 0) + { + return 0; + } + /* todo data */ if (dst->type == WND_TYPE_BITMAP) @@ -985,10 +1469,75 @@ xrdp_painter_line(struct xrdp_painter *self, int dy; int rop; + LLOGLN(10, ("xrdp_painter_line:")); if (self == 0) { return 0; } + if (self->painter != 0) + { +#if defined(XRDP_PAINTER) + int x; + int y; + int cx; + int cy; + struct painter_bitmap dst_pb; + struct xrdp_bitmap *ldst; + + LLOGLN(10, ("xrdp_painter_line: dst->type %d", dst->type)); + LLOGLN(10, ("xrdp_painter_line: self->rop 0x%2.2x", self->rop)); + + if (dst->type != WND_TYPE_OFFSCREEN) + { + LLOGLN(10, ("xrdp_painter_line: using painter")); + ldst = self->wm->screen; + + g_memset(&dst_pb, 0, sizeof(dst_pb)); + dst_pb.format = get_pt_format(self); + dst_pb.width = ldst->width; + dst_pb.stride_bytes = ldst->line_size; + dst_pb.height = ldst->height; + dst_pb.data = ldst->data; + + xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); + region = xrdp_region_create(self->wm); + x = MIN(x1, x2); + y = MIN(y1, y2); + cx = g_abs(x1 - x2) + 1; + cy = g_abs(y1 - y2) + 1; + xrdp_wm_get_vis_region(self->wm, dst, x, y, cx, cy, + region, self->clip_children); + x1 += dx; + y1 += dy; + x2 += dx; + y2 += dy; + k = 0; + rop = self->rop; + + painter_set_rop(self->painter, rop); + painter_set_fgcolor(self->painter, self->pen.color); + while (xrdp_region_get_rect(region, k, &rect) == 0) + { + if (rect_intersect(&rect, &clip_rect, &draw_rect)) + { + painter_set_clip(self->painter, + draw_rect.left, draw_rect.top, + draw_rect.right - draw_rect.left, + draw_rect.bottom - draw_rect.top); + painter_line(self->painter, &dst_pb, x1, y1, x2, x2, + self->pen.width, 0); + xrdp_painter_add_dirty_rect(self, x, y, cx, cy, + &draw_rect); + } + k++; + } + painter_clear_clip(self->painter); + xrdp_region_delete(region); + } + + return 0; +#endif + } /* todo data */ diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 46a23ca1..cc0eaa3c 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -429,6 +429,9 @@ struct xrdp_painter struct xrdp_session* session; struct xrdp_wm* wm; /* owner */ struct xrdp_font* font; + void *painter; + struct xrdp_region *dirty_region; + int begin_end_level; }; /* window or bitmap */ diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index 4917c3aa..a8ae5033 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -834,44 +834,6 @@ xrdp_wm_xor_pat(struct xrdp_wm *self, int x, int y, int cx, int cy) return 0; } -/*****************************************************************************/ -/* this don't are about nothing, just copy the bits */ -/* no clipping rects, no windows in the way, nothing */ -static int APP_CC -xrdp_wm_bitblt(struct xrdp_wm *self, - struct xrdp_bitmap *dst, int dx, int dy, - struct xrdp_bitmap *src, int sx, int sy, - int sw, int sh, int rop) -{ - // int i; - // int line_size; - // int Bpp; - // char* s; - // char* d; - - // if (sw <= 0 || sh <= 0) - // return 0; - if (self->screen == dst && self->screen == src) - { - /* send a screen blt */ - // Bpp = (dst->bpp + 7) / 8; - // line_size = sw * Bpp; - // s = src->data + (sy * src->width + sx) * Bpp; - // d = dst->data + (dy * dst->width + dx) * Bpp; - // for (i = 0; i < sh; i++) - // { - // //g_memcpy(d, s, line_size); - // s += src->width * Bpp; - // d += dst->width * Bpp; - // } - libxrdp_orders_init(self->session); - libxrdp_orders_screen_blt(self->session, dx, dy, sw, sh, sx, sy, rop, 0); - libxrdp_orders_send(self->session); - } - - return 0; -} - /*****************************************************************************/ /* return true if rect is totally exposed going in reverse z order */ /* from wnd up */ @@ -935,6 +897,7 @@ xrdp_wm_move_window(struct xrdp_wm *self, struct xrdp_bitmap *wnd, MAKERECT(rect1, wnd->left, wnd->top, wnd->width, wnd->height); + self->painter->clip_children = 0; if (xrdp_wm_is_rect_vis(self, wnd, &rect1)) { rect2 = rect1; @@ -942,10 +905,13 @@ xrdp_wm_move_window(struct xrdp_wm *self, struct xrdp_bitmap *wnd, if (xrdp_wm_is_rect_vis(self, wnd, &rect2)) { - /* if both src and dst are unobscured, we can do a bitblt move */ - xrdp_wm_bitblt(self, self->screen, wnd->left + dx, wnd->top + dy, - self->screen, wnd->left, wnd->top, - wnd->width, wnd->height, 0xcc); + xrdp_painter_begin_update(self->painter); + xrdp_painter_copy(self->painter, self->screen, self->screen, + wnd->left + dx, wnd->top + dy, + wnd->width, wnd->height, + wnd->left, wnd->top); + xrdp_painter_end_update(self->painter); + wnd->left += dx; wnd->top += dy; r = xrdp_region_create(self); @@ -960,9 +926,11 @@ xrdp_wm_move_window(struct xrdp_wm *self, struct xrdp_bitmap *wnd, } xrdp_region_delete(r); + self->painter->clip_children = 1; return 0; } } + self->painter->clip_children = 1; wnd->left += dx; wnd->top += dy; @@ -971,6 +939,7 @@ xrdp_wm_move_window(struct xrdp_wm *self, struct xrdp_bitmap *wnd, return 0; } + /*****************************************************************************/ static int APP_CC xrdp_wm_undraw_dragging_box(struct xrdp_wm *self, int do_begin_end)