From 6d539b8e2211eabb33ea8dd6a289a5588c85b00d Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Mon, 23 Jul 2012 11:12:39 -0700 Subject: [PATCH] user rfx for cache v3 if client supports --- common/xrdp_client_info.h | 2 +- common/xrdp_constants.h | 4 ++ libxrdp/xrdp_orders.c | 83 +++++++++++++++++++++++++++++++++++++++ libxrdp/xrdp_rdp.c | 36 ++++++++++++----- xrdp/xrdp_cache.c | 42 ++++++++++++-------- 5 files changed, 140 insertions(+), 27 deletions(-) diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index e1879cef..d7c20783 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -40,7 +40,7 @@ struct xrdp_client_info int cache3_entries; int cache3_size; int bitmap_cache_persist_enable; /* 0 or 2 */ - int bitmap_cache_version; /* 0 = original version, 2 = v2, 3 = v3 */ + int bitmap_cache_version; /* ored 1 = original version, 2 = v2, 4 = v3 */ /* pointer info */ int pointer_cache_entries; /* other */ diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h index 7d31326e..1aa18eb5 100644 --- a/common/xrdp_constants.h +++ b/common/xrdp_constants.h @@ -516,6 +516,10 @@ #define XR_CODEC_GUID_REMOTEFX \ "\x12\x2F\x77\x76\x72\xBD\x63\x44\xAF\xB3\xB7\x3C\x9C\x6F\x78\x86" +/* CODEC_GUID_JPEG 0x430C9EED1BAF4CE6869ACB8B37B66237*/ +#define XR_CODEC_GUID_JPEG \ + "\xE6\x4C\xAF\x1B\xED\x9E\x0C\x43\x86\x9A\xCB\x8B\x37\xB6\x62\x37" + #define RDP_CAPSET_SURFCMDS 0x1c #define RDP_CAPLEN_SURFCMDS 0x0c #define RDP_CAPSET_BMPCODECS 0x1d diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 77fdbf23..35666492 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -1946,6 +1946,26 @@ height(%d)", lines_sending, height); return 0; } +#if defined(XRDP_FREERDP1) +/*****************************************************************************/ +/* secondary drawing order (bitmap v3) using remotefx compression */ +static int APP_CC +xrdp_orders_send_in_rfx(struct xrdp_orders* self, + int width, int height, int bpp, + int hints) +{ + if (bpp != 24) + { + return 0; + } + if (self->rdp_layer->client_info.rfx_codec_id == 0) + { + return 0; + } + return 1; +} +#endif + /*****************************************************************************/ /* secondary drawing order (bitmap v3) using remotefx compression */ int APP_CC @@ -1953,6 +1973,69 @@ xrdp_orders_send_bitmap3(struct xrdp_orders* self, int width, int height, int bpp, char* data, int cache_id, int cache_idx, int hints) { +#if defined(XRDP_FREERDP1) + int bufsize; + int Bpp; + int order_flags; + int len; + int i; + STREAM* fr_s; /* FreeRDP stream */ + struct stream* xr_s; /* xrdp stream */ + RFX_CONTEXT* context = (RFX_CONTEXT*)(self->rdp_layer->rfx_enc); + RFX_RECT rect; + + if (width > 64) + { + g_writeln("error, width > 64"); + return 1; + } + if (height > 64) + { + g_writeln("error, height > 64"); + return 1; + } + if (!xrdp_orders_send_in_rfx(self, width, height, bpp, hints)) + { + return 2; + } + make_stream(xr_s); + init_stream(xr_s, 16384); + fr_s = stream_new(0); + stream_attach(fr_s, xr_s->data, 16384); + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + rfx_compose_message(context, fr_s, &rect, 1, data, width, height, width * 4); + bufsize = stream_get_length(fr_s); + Bpp = (bpp + 7) / 8; + xrdp_orders_check(self, bufsize + 30); + self->order_count++; + order_flags = RDP_ORDER_STANDARD | RDP_ORDER_SECONDARY; + out_uint8(self->out_s, order_flags); + len = (bufsize + 22) - 7; /* length after type minus 7 */ + out_uint16_le(self->out_s, len); + i = (((Bpp + 2) << 3) & 0x38) | (cache_id & 7); + out_uint16_le(self->out_s, i); /* flags */ + out_uint8(self->out_s, RDP_ORDER_BMPCACHE3); /* type */ + /* cache index */ + out_uint16_le(self->out_s, cache_idx); + /* persistant cache key 1/2 */ + out_uint32_le(self->out_s, 0); + out_uint32_le(self->out_s, 0); + /* bitmap data */ + out_uint8(self->out_s, bpp); + out_uint8(self->out_s, 0); /* reserved */ + out_uint8(self->out_s, 0); /* reserved */ + out_uint8(self->out_s, self->rdp_layer->client_info.rfx_codec_id); + out_uint16_le(self->out_s, width); + out_uint16_le(self->out_s, height); + out_uint32_le(self->out_s, bufsize); + out_uint8a(self->out_s, fr_s->data, bufsize); + stream_detach(fr_s); + stream_free(fr_s); + free_stream(xr_s); +#endif return 0; } diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index f25108f0..1c381274 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -684,18 +684,25 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self) /* Output bmpcodecs capability set */ caps_count++; out_uint16_le(s, RDP_CAPSET_BMPCODECS); - out_uint16_le(s, 302); /* cap len */ - out_uint8(s, 2); /* bitmapCodecCount */ + out_uint16_le(s, 5 + 22 + 275 + 20); /* cap len */ + out_uint8(s, 3); /* bitmapCodecCount */ + /* nscodec */ out_uint8a(s, XR_CODEC_GUID_NSCODEC, 16); out_uint8(s, 1); /* codec id */ out_uint16_le(s, 3); out_uint8(s, 0x01); /* fAllowDynamicFidelity */ out_uint8(s, 0x01); /* fAllowSubsampling */ out_uint8(s, 0x03); /* colorLossLevel */ + /* remotefx */ out_uint8a(s, XR_CODEC_GUID_REMOTEFX, 16); out_uint8(s, 0); /* codec id */ out_uint16_le(s, 256); out_uint8s(s, 256); + /* jpeg */ + out_uint8a(s, XR_CODEC_GUID_JPEG, 16); + out_uint8(s, 2); /* codec id */ + out_uint16_le(s, 1); /* ext length */ + out_uint8(s, 75); /* Output color cache capability set */ caps_count++; @@ -818,10 +825,7 @@ xrdp_process_capset_order(struct xrdp_rdp* self, struct stream* s, { g_writeln("RDP_CAPSET_BMPCACHE3"); DEBUG(("RDP_CAPSET_BMPCACHE3")); - if (self->client_info.bitmap_cache_version < 3) - { - self->client_info.bitmap_cache_version = 3; - } + self->client_info.bitmap_cache_version |= 4; } in_uint8s(s, 4); /* Pad */ @@ -839,6 +843,7 @@ static int APP_CC xrdp_process_capset_bmpcache(struct xrdp_rdp* self, struct stream* s, int len) { + self->client_info.bitmap_cache_version |= 1; in_uint8s(s, 24); in_uint16_le(s, self->client_info.cache1_entries); in_uint16_le(s, self->client_info.cache1_size); @@ -864,10 +869,7 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp* self, struct stream* s, int Bpp = 0; int i = 0; - if (self->client_info.bitmap_cache_version < 2) - { - self->client_info.bitmap_cache_version = 2; - } + self->client_info.bitmap_cache_version |= 2; Bpp = (self->client_info.bpp + 7) / 8; in_uint16_le(s, i); /* cache flags */ #if defined(XRDP_JPEG) @@ -1036,8 +1038,22 @@ xrdp_process_capset_codecs(struct xrdp_rdp* self, struct stream* s, int len) g_memcpy(self->client_info.rfx_prop, s->p, i1); self->client_info.rfx_prop_len = i1; } + else if (g_memcmp(codec_guid, XR_CODEC_GUID_JPEG, 16) == 0) + { + g_writeln("xrdp_process_capset_codecs: jpeg codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.jpeg_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.jpeg_prop, s->p, i1); + self->client_info.jpeg_prop_len = i1; + } + else + { + g_writeln("xrdp_process_capset_codecs: unknown codec id %d", codec_id); + } s->p = next_guid; } + return 0; } /*****************************************************************************/ diff --git a/xrdp/xrdp_cache.c b/xrdp/xrdp_cache.c index 9c708313..17316633 100644 --- a/xrdp/xrdp_cache.c +++ b/xrdp/xrdp_cache.c @@ -261,36 +261,46 @@ xrdp_cache_add_bitmap(struct xrdp_cache* self, struct xrdp_bitmap* bitmap, xrdp_bitmap_delete(self->bitmap_items[cache_id][cache_idx].bitmap); self->bitmap_items[cache_id][cache_idx].bitmap = bitmap; self->bitmap_items[cache_id][cache_idx].stamp = self->bitmap_stamp; - if (self->bitmap_cache_version == 0) /* orginal version */ + if (self->use_bitmap_comp) { - if (self->use_bitmap_comp) + if (self->bitmap_cache_version & 4) { - libxrdp_orders_send_bitmap(self->session, bitmap->width, - bitmap->height, bitmap->bpp, - bitmap->data, cache_id, cache_idx); - } - else - { - libxrdp_orders_send_raw_bitmap(self->session, bitmap->width, - bitmap->height, bitmap->bpp, - bitmap->data, cache_id, cache_idx); + if (libxrdp_orders_send_bitmap3(self->session, bitmap->width, + bitmap->height, bitmap->bpp, + bitmap->data, cache_id, cache_idx, + hints) == 0) + { + return MAKELONG(cache_idx, cache_id); + } } - } - else - { - if (self->use_bitmap_comp) + if (self->bitmap_cache_version & 2) { libxrdp_orders_send_bitmap2(self->session, bitmap->width, bitmap->height, bitmap->bpp, bitmap->data, cache_id, cache_idx, hints); } - else + else if (self->bitmap_cache_version & 1) + { + libxrdp_orders_send_bitmap(self->session, bitmap->width, + bitmap->height, bitmap->bpp, + bitmap->data, cache_id, cache_idx); + } + } + else + { + if (self->bitmap_cache_version & 2) { libxrdp_orders_send_raw_bitmap2(self->session, bitmap->width, bitmap->height, bitmap->bpp, bitmap->data, cache_id, cache_idx); } + else if (self->bitmap_cache_version & 1) + { + libxrdp_orders_send_raw_bitmap(self->session, bitmap->width, + bitmap->height, bitmap->bpp, + bitmap->data, cache_id, cache_idx); + } } return MAKELONG(cache_idx, cache_id); }