summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Sorg <jay.sorg@gmail.com>2016-12-15 21:17:50 -0800
committerJay Sorg <jay.sorg@gmail.com>2016-12-15 21:17:50 -0800
commit1f5158676975b2b4c9c3be518b575b677a4fede3 (patch)
tree5d8a9d61df74b216c132183cabe3593302e9b302
parent42272c0f1891264af718e8f0a02ebc883f248ed8 (diff)
downloadxrdp-proprietary-1f5158676975b2b4c9c3be518b575b677a4fede3.tar.gz
xrdp-proprietary-1f5158676975b2b4c9c3be518b575b677a4fede3.zip
add libpainter for drawing when client does not have minimum orders
-rw-r--r--common/xrdp_client_info.h2
-rw-r--r--common/xrdp_constants.h34
-rw-r--r--configure.ac5
-rw-r--r--libxrdp/xrdp_caps.c20
-rw-r--r--xrdp/Makefile.am6
-rw-r--r--xrdp/xrdp_bitmap.c8
-rw-r--r--xrdp/xrdp_painter.c555
-rw-r--r--xrdp/xrdp_types.h3
-rw-r--r--xrdp/xrdp_wm.c53
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 <painter.h> /* 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
@@ -835,44 +835,6 @@ xrdp_wm_xor_pat(struct xrdp_wm *self, int x, int y, int cx, int cy)
}
/*****************************************************************************/
-/* 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 */
static int APP_CC
@@ -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)