add libpainter for drawing when client does not have minimum orders

master
Jay Sorg 8 years ago
parent 42272c0f18
commit 1f51586769

@ -148,6 +148,8 @@ struct xrdp_client_info
int client_os_major; int client_os_major;
int client_os_minor; int client_os_minor;
int no_orders_supported;
}; };
#endif #endif

@ -476,6 +476,40 @@
#define XR_ORDERFLAGS_EX_ALTSEC_FRAME_MARKER_SUPPORT 0x0004 #define XR_ORDERFLAGS_EX_ALTSEC_FRAME_MARKER_SUPPORT 0x0004
#define XR_ORDERFLAGS_EX_OFFSCREEN_COMPOSITE_SUPPORT 0x0100 #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 */ /* drawable types */
#define WND_TYPE_BITMAP 0 #define WND_TYPE_BITMAP 0
#define WND_TYPE_WND 1 #define WND_TYPE_WND 1

@ -117,6 +117,11 @@ AC_ARG_ENABLE(pixman, AS_HELP_STRING([--enable-pixman],
[Use pixman library (default: no)]), [Use pixman library (default: no)]),
[], [enable_pixman=no]) [], [enable_pixman=no])
AM_CONDITIONAL(XRDP_PIXMAN, [test x$enable_pixman = xyes]) 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() # Check if -ldl is needed to use dlopen()
DLOPEN_LIBS= DLOPEN_LIBS=

@ -159,6 +159,15 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
DEBUG(("desktop cache size %d", i)); DEBUG(("desktop cache size %d", i));
in_uint8s(s, 4); /* Unknown */ in_uint8s(s, 4); /* Unknown */
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; return 0;
} }
@ -667,6 +676,17 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
s->p = p + len + 4; 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")); DEBUG(("out xrdp_caps_process_confirm_active"));
return 0; return 0;
} }

@ -28,6 +28,12 @@ AM_CPPFLAGS += $(PIXMAN_CFLAGS)
XRDP_EXTRA_LIBS += $(PIXMAN_LIBS) XRDP_EXTRA_LIBS += $(PIXMAN_LIBS)
endif 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 = \ sbin_PROGRAMS = \
xrdp xrdp

@ -123,6 +123,14 @@ xrdp_bitmap_create(int width, int height, int bpp,
self->data = (char *)g_malloc(width * height * Bpp, 0); 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) if (self->type != WND_TYPE_BITMAP)
{ {
self->child_list = list_create(); self->child_list = list_create();

@ -20,17 +20,152 @@
#include "xrdp.h" #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 struct xrdp_painter *APP_CC
xrdp_painter_create(struct xrdp_wm *wm, struct xrdp_session *session) xrdp_painter_create(struct xrdp_wm *wm, struct xrdp_session *session)
{ {
struct xrdp_painter *self; struct xrdp_painter *self;
LLOGLN(10, ("xrdp_painter_create:"));
self = (struct xrdp_painter *)g_malloc(sizeof(struct xrdp_painter), 1); self = (struct xrdp_painter *)g_malloc(sizeof(struct xrdp_painter), 1);
self->wm = wm; self->wm = wm;
self->session = session; self->session = session;
self->rop = 0xcc; /* copy will use 0xcc*/ self->rop = 0xcc; /* copy will use 0xcc */
self->clip_children = 1; 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; return self;
} }
@ -38,11 +173,17 @@ xrdp_painter_create(struct xrdp_wm *wm, struct xrdp_session *session)
void APP_CC void APP_CC
xrdp_painter_delete(struct xrdp_painter *self) xrdp_painter_delete(struct xrdp_painter *self)
{ {
LLOGLN(10, ("xrdp_painter_delete:"));
if (self == 0) if (self == 0)
{ {
return; return;
} }
#if defined(XRDP_PAINTER)
painter_delete(self->painter);
xrdp_region_delete(self->dirty_region);
#endif
g_free(self); g_free(self);
} }
@ -54,6 +195,13 @@ wm_painter_set_target(struct xrdp_painter *self)
int index; int index;
struct list *del_list; 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->target_surface->type == WND_TYPE_SCREEN)
{ {
if (self->wm->current_surface_index != 0xffff) if (self->wm->current_surface_index != 0xffff)
@ -97,11 +245,19 @@ wm_painter_set_target(struct xrdp_painter *self)
int APP_CC int APP_CC
xrdp_painter_begin_update(struct xrdp_painter *self) xrdp_painter_begin_update(struct xrdp_painter *self)
{ {
LLOGLN(10, ("xrdp_painter_begin_update:"));
if (self == 0) if (self == 0)
{ {
return 0; return 0;
} }
self->begin_end_level++;
if (self->painter != 0)
{
return 0;
}
libxrdp_orders_init(self->session); libxrdp_orders_init(self->session);
wm_painter_set_target(self); wm_painter_set_target(self);
return 0; return 0;
@ -111,11 +267,25 @@ xrdp_painter_begin_update(struct xrdp_painter *self)
int APP_CC int APP_CC
xrdp_painter_end_update(struct xrdp_painter *self) xrdp_painter_end_update(struct xrdp_painter *self)
{ {
LLOGLN(10, ("xrdp_painter_end_update:"));
if (self == 0) if (self == 0)
{ {
return 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); libxrdp_orders_send(self->session);
return 0; return 0;
} }
@ -270,6 +440,7 @@ xrdp_painter_text_width(struct xrdp_painter *self, const char *text)
struct xrdp_font_char *font_item; struct xrdp_font_char *font_item;
twchar *wstr; twchar *wstr;
LLOGLN(10, ("xrdp_painter_text_width:"));
xrdp_painter_font_needed(self); xrdp_painter_font_needed(self);
if (self->font == 0) 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; struct xrdp_font_char *font_item;
twchar *wstr; twchar *wstr;
LLOGLN(10, ("xrdp_painter_text_height:"));
xrdp_painter_font_needed(self); xrdp_painter_font_needed(self);
if (self->font == 0) if (self->font == 0)
@ -342,6 +514,13 @@ xrdp_painter_setup_brush(struct xrdp_painter *self,
{ {
int cache_id; 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)); g_memcpy(out_brush, in_brush, sizeof(struct xrdp_brush));
if (in_brush->style == 3) if (in_brush->style == 3)
@ -358,6 +537,38 @@ xrdp_painter_setup_brush(struct xrdp_painter *self,
return 0; 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 */ /* fill in an area of the screen with one color */
int APP_CC int APP_CC
@ -375,11 +586,120 @@ xrdp_painter_fill_rect(struct xrdp_painter *self,
int dy; int dy;
int rop; int rop;
LLOGLN(10, ("xrdp_painter_fill_rect:"));
if (self == 0) if (self == 0)
{ {
return 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 */ /* todo data */
if (dst->type == WND_TYPE_BITMAP) /* 0 */ 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; struct xrdp_font_char *font_item;
twchar *wstr; twchar *wstr;
LLOGLN(10, ("xrdp_painter_draw_text:"));
if (self == 0) if (self == 0)
{ {
return 0; return 0;
} }
len = g_mbstowcs(0, text, 0); len = g_mbstowcs(0, text, 0);
if (len < 1) if (len < 1)
@ -534,6 +857,88 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
return 0; 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 */ /* convert to wide char */
wstr = (twchar *)g_malloc((len + 2) * sizeof(twchar), 0); wstr = (twchar *)g_malloc((len + 2) * sizeof(twchar), 0);
g_mbstowcs(wstr, text, len + 1); g_mbstowcs(wstr, text, len + 1);
@ -616,11 +1021,18 @@ xrdp_painter_draw_text2(struct xrdp_painter *self,
int dx; int dx;
int dy; int dy;
LLOGLN(0, ("xrdp_painter_draw_text2:"));
if (self == 0) if (self == 0)
{ {
return 0; return 0;
} }
if (self->painter != 0)
{
return 0;
}
/* todo data */ /* todo data */
if (dst->type == WND_TYPE_BITMAP) if (dst->type == WND_TYPE_BITMAP)
@ -711,11 +1123,76 @@ xrdp_painter_copy(struct xrdp_painter *self,
int index; int index;
struct list *del_list; struct list *del_list;
LLOGLN(10, ("xrdp_painter_copy:"));
if (self == 0 || src == 0 || dst == 0) if (self == 0 || src == 0 || dst == 0)
{ {
return 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 */ /* todo data */
if (dst->type == WND_TYPE_BITMAP) if (dst->type == WND_TYPE_BITMAP)
@ -848,7 +1325,7 @@ xrdp_painter_copy(struct xrdp_painter *self,
while (i < (srcx + cx)) while (i < (srcx + cx))
{ {
w = MIN(64, ((srcx + cx) - i)); 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); b = xrdp_bitmap_create(w, h, src->bpp, 0, self->wm);
#if 1 #if 1
xrdp_bitmap_copy_box_with_crc(src, b, i, j, w, h); 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; i += 64;
} }
j += 63; j += 64;
} }
xrdp_region_delete(region); xrdp_region_delete(region);
@ -918,11 +1395,18 @@ xrdp_painter_composite(struct xrdp_painter* self,
int cache_srcidx; int cache_srcidx;
int cache_mskidx; int cache_mskidx;
LLOGLN(0, ("xrdp_painter_composite:"));
if (self == 0 || src == 0 || dst == 0) if (self == 0 || src == 0 || dst == 0)
{ {
return 0; return 0;
} }
if (self->painter != 0)
{
return 0;
}
/* todo data */ /* todo data */
if (dst->type == WND_TYPE_BITMAP) if (dst->type == WND_TYPE_BITMAP)
@ -985,10 +1469,75 @@ xrdp_painter_line(struct xrdp_painter *self,
int dy; int dy;
int rop; int rop;
LLOGLN(10, ("xrdp_painter_line:"));
if (self == 0) if (self == 0)
{ {
return 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 */ /* todo data */

@ -429,6 +429,9 @@ struct xrdp_painter
struct xrdp_session* session; struct xrdp_session* session;
struct xrdp_wm* wm; /* owner */ struct xrdp_wm* wm; /* owner */
struct xrdp_font* font; struct xrdp_font* font;
void *painter;
struct xrdp_region *dirty_region;
int begin_end_level;
}; };
/* window or bitmap */ /* window or bitmap */

@ -834,44 +834,6 @@ xrdp_wm_xor_pat(struct xrdp_wm *self, int x, int y, int cx, int cy)
return 0; 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 */ /* return true if rect is totally exposed going in reverse z order */
/* from wnd up */ /* 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); MAKERECT(rect1, wnd->left, wnd->top, wnd->width, wnd->height);
self->painter->clip_children = 0;
if (xrdp_wm_is_rect_vis(self, wnd, &rect1)) if (xrdp_wm_is_rect_vis(self, wnd, &rect1))
{ {
rect2 = 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 (xrdp_wm_is_rect_vis(self, wnd, &rect2))
{ {
/* if both src and dst are unobscured, we can do a bitblt move */ xrdp_painter_begin_update(self->painter);
xrdp_wm_bitblt(self, self->screen, wnd->left + dx, wnd->top + dy, xrdp_painter_copy(self->painter, self->screen, self->screen,
self->screen, wnd->left, wnd->top, wnd->left + dx, wnd->top + dy,
wnd->width, wnd->height, 0xcc); wnd->width, wnd->height,
wnd->left, wnd->top);
xrdp_painter_end_update(self->painter);
wnd->left += dx; wnd->left += dx;
wnd->top += dy; wnd->top += dy;
r = xrdp_region_create(self); 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); xrdp_region_delete(r);
self->painter->clip_children = 1;
return 0; return 0;
} }
} }
self->painter->clip_children = 1;
wnd->left += dx; wnd->left += dx;
wnd->top += dy; wnd->top += dy;
@ -971,6 +939,7 @@ xrdp_wm_move_window(struct xrdp_wm *self, struct xrdp_bitmap *wnd,
return 0; return 0;
} }
/*****************************************************************************/ /*****************************************************************************/
static int APP_CC static int APP_CC
xrdp_wm_undraw_dragging_box(struct xrdp_wm *self, int do_begin_end) xrdp_wm_undraw_dragging_box(struct xrdp_wm *self, int do_begin_end)

Loading…
Cancel
Save