summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Sorg <jay.sorg@gmail.com>2016-12-15 00:39:13 -0800
committerJay Sorg <jay.sorg@gmail.com>2016-12-15 00:39:13 -0800
commit519359a8230df9a72e83ca53cd271c024004110a (patch)
tree9b7d30e4bf9d0fde0e290c840845bc17ac2617eb
parent42272c0f1891264af718e8f0a02ebc883f248ed8 (diff)
downloadxrdp-proprietary-519359a8230df9a72e83ca53cd271c024004110a.tar.gz
xrdp-proprietary-519359a8230df9a72e83ca53cd271c024004110a.zip
fixes for bitmap update
-rw-r--r--libxrdp/libxrdp.c167
-rw-r--r--libxrdp/xrdp_caps.c1
2 files changed, 139 insertions, 29 deletions
diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c
index c3763bf5..b03db073 100644
--- a/libxrdp/libxrdp.c
+++ b/libxrdp/libxrdp.c
@@ -27,6 +27,8 @@
#define LLOGLN(_level, _args) \
do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0)
+#define MAX_BITMAP_BUF_SIZE (16 * 1024) /* 16K */
+
/******************************************************************************/
struct xrdp_session *EXPORT_CC
libxrdp_init(tbus id, struct trans *trans)
@@ -373,15 +375,15 @@ libxrdp_send_bell(struct xrdp_session *session)
return 0;
}
-
/*****************************************************************************/
int EXPORT_CC
libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
int bpp, char *data, int x, int y, int cx, int cy)
{
- int line_size = 0;
+ int line_bytes = 0;
int i = 0;
int j = 0;
+ int k;
int total_lines = 0;
int lines_sending = 0;
int Bpp = 0;
@@ -389,27 +391,43 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
int bufsize = 0;
int total_bufsize = 0;
int num_updates = 0;
+ int line_pad_bytes;
+ int server_line_bytes;
char *p_num_updates = (char *)NULL;
char *p = (char *)NULL;
char *q = (char *)NULL;
struct stream *s = (struct stream *)NULL;
struct stream *temp_s = (struct stream *)NULL;
+ tui32 pixel;
- DEBUG(("libxrdp_send_bitmap sending bitmap"));
+ LLOGLN(10, ("libxrdp_send_bitmap: sending bitmap"));
Bpp = (bpp + 7) / 8;
- e = width % 4;
-
- if (e != 0)
+ e = (4 - width) & 3;
+ switch (bpp)
{
- e = 4 - e;
+ case 15:
+ case 16:
+ server_line_bytes = width * 2;
+ break;
+ case 24:
+ case 32:
+ server_line_bytes = width * 4;
+ break;
+ default: /* 8 bpp */
+ server_line_bytes = width;
+ break;
}
+ line_bytes = width * Bpp;
+ line_pad_bytes = line_bytes + e * Bpp;
- line_size = width * Bpp;
+ LLOGLN(10, ("libxrdp_send_bitmap: bpp %d Bpp %d line_bytes %d "
+ "server_line_bytes %d", bpp, Bpp, line_bytes, server_line_bytes));
make_stream(s);
- init_stream(s, 8192);
+ init_stream(s, MAX_BITMAP_BUF_SIZE);
if (session->client_info->use_bitmap_comp)
{
+ LLOGLN(10, ("libxrdp_send_bitmap: compression"));
make_stream(temp_s);
init_stream(temp_s, 65536);
i = 0;
@@ -421,6 +439,8 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
while (i > 0)
{
+ LLOGLN(10, ("libxrdp_send_bitmap: i %d", i));
+
total_bufsize = 0;
num_updates = 0;
xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s);
@@ -440,10 +460,26 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
}
p = s->p;
- lines_sending = xrdp_bitmap_compress(data, width, height,
- s, bpp,
- 4096 - total_bufsize,
- i - 1, temp_s, e);
+
+ if (bpp > 24)
+ {
+ LLOGLN(10, ("libxrdp_send_bitmap: 32 bpp"));
+ lines_sending = xrdp_bitmap32_compress(data, width, height,
+ s, 32,
+ (MAX_BITMAP_BUF_SIZE - 100) - total_bufsize,
+ i - 1, temp_s, e, 0x10);
+ LLOGLN(10, ("libxrdp_send_bitmap: i %d lines_sending %d",
+ i, lines_sending));
+ }
+ else
+ {
+ lines_sending = xrdp_bitmap_compress(data, width, height,
+ s, bpp,
+ (MAX_BITMAP_BUF_SIZE - 100) - total_bufsize,
+ i - 1, temp_s, e);
+ LLOGLN(10, ("libxrdp_send_bitmap: i %d lines_sending %d",
+ i, lines_sending));
+ }
if (lines_sending == 0)
{
@@ -470,6 +506,7 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
out_uint16_le(s, bufsize); /* compressed size */
j = (width + e) * Bpp;
j = j * lines_sending;
+ total_bufsize += 18;
}
else
{
@@ -481,31 +518,42 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
out_uint16_le(s, j); /* line size */
j = j * lines_sending;
out_uint16_le(s, j); /* final size */
+ total_bufsize += 26;
}
- if (j > 32768)
+ LLOGLN(10, ("libxrdp_send_bitmap: decompressed pixels %d "
+ "decompressed bytes %d compressed bytes %d",
+ lines_sending * (width + e),
+ line_pad_bytes * lines_sending, bufsize));
+
+ if (j > MAX_BITMAP_BUF_SIZE)
{
- g_writeln("error, decompressed size too big: %d bytes", j);
+ LLOGLN(0, ("libxrdp_send_bitmap: error, decompressed "
+ "size too big: %d bytes", j));
}
- if (bufsize > 8192)
+ if (bufsize > MAX_BITMAP_BUF_SIZE)
{
- g_writeln("error, compressed size too big: %d bytes", bufsize);
+ LLOGLN(0, ("libxrdp_send_bitmap: error, compressed size "
+ "too big: %d bytes", bufsize));
}
s->p = s->end;
}
- while (total_bufsize < 4096 && i > 0);
+ while (total_bufsize < MAX_BITMAP_BUF_SIZE && i > 0);
+
+ LLOGLN(10, ("libxrdp_send_bitmap: num_updates %d total_bufsize %d",
+ num_updates, total_bufsize));
p_num_updates[0] = num_updates;
p_num_updates[1] = num_updates >> 8;
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
RDP_DATA_PDU_UPDATE);
- if (total_bufsize > 8192)
+ if (total_bufsize > MAX_BITMAP_BUF_SIZE)
{
- g_writeln("error, total compressed size too big: %d bytes",
- total_bufsize);
+ LLOGLN(0, ("libxrdp_send_bitmap: error, total compressed "
+ "size too big: %d bytes", total_bufsize));
}
}
@@ -513,22 +561,30 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
}
else
{
+ LLOGLN(10, ("libxrdp_send_bitmap: no compression"));
total_lines = height;
i = 0;
p = data;
- if (line_size > 0 && total_lines > 0)
+ if (line_bytes > 0 && total_lines > 0)
{
while (i < total_lines)
{
- lines_sending = 4096 / (line_size + e * Bpp);
+
+ lines_sending = (MAX_BITMAP_BUF_SIZE - 100) / (line_pad_bytes);
if (i + lines_sending > total_lines)
{
lines_sending = total_lines - i;
}
- p = p + line_size * lines_sending;
+ if (lines_sending == 0)
+ {
+ LLOGLN(0, ("libxrdp_send_bitmap: error, lines_sending == zero"));
+ break;
+ }
+
+ p = p + server_line_bytes * lines_sending;
xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s);
out_uint16_le(s, RDP_UPDATE_BITMAP);
out_uint16_le(s, 1); /* num updates */
@@ -540,14 +596,67 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
out_uint16_le(s, lines_sending);
out_uint16_le(s, bpp); /* bpp */
out_uint16_le(s, 0); /* compress */
- out_uint16_le(s, (line_size + e * Bpp) * lines_sending); /* bufsize */
+ out_uint16_le(s, line_pad_bytes * lines_sending); /* bufsize */
q = p;
- for (j = 0; j < lines_sending; j++)
+ switch (bpp)
{
- q = q - line_size;
- out_uint8a(s, q, line_size); /* B_ENDIAN doesn't work here, todo */
- out_uint8s(s, e * Bpp);
+ case 15:
+ case 16:
+ for (j = 0; j < lines_sending; j++)
+ {
+ q = q - server_line_bytes;
+ for (k = 0; k < width; k++)
+ {
+ pixel = *((tui16*)(q + k * 2));
+ out_uint16_le(s, pixel);
+ }
+ for (k = 0; k < e; k++)
+ {
+ out_uint8s(s, 2);
+ }
+ }
+ break;
+ case 24:
+ for (j = 0; j < lines_sending; j++)
+ {
+ q = q - server_line_bytes;
+ for (k = 0; k < width; k++)
+ {
+ pixel = *((tui32*)(q + k * 4));
+ out_uint8(s, pixel);
+ out_uint8(s, pixel >> 8);
+ out_uint8(s, pixel >> 16);
+ }
+ for (k = 0; k < e; k++)
+ {
+ out_uint8s(s, 3);
+ }
+ }
+ break;
+ case 32:
+ for (j = 0; j < lines_sending; j++)
+ {
+ q = q - server_line_bytes;
+ for (k = 0; k < width; k++)
+ {
+ pixel = *((int*)(q + k * 4));
+ out_uint32_le(s, pixel);
+ }
+ for (k = 0; k < e; k++)
+ {
+ out_uint8s(s, 4);
+ }
+ }
+ break;
+ default: /* 8 bpp */
+ for (j = 0; j < lines_sending; j++)
+ {
+ q = q - line_bytes;
+ out_uint8a(s, q, line_bytes);
+ out_uint8s(s, e * Bpp);
+ }
+ break;
}
s_mark_end(s);
diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c
index 8d5250d5..35778b5b 100644
--- a/libxrdp/xrdp_caps.c
+++ b/libxrdp/xrdp_caps.c
@@ -80,6 +80,7 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s,
in_uint8s(s, 6);
in_uint16_le(s, extraFlags); /* extraFlags (2 bytes) */
+ self->client_info.op1 = extraFlags & NO_BITMAP_COMPRESSION_HDR;
/* use_compact_packets is pretty much 'use rdp5' */
self->client_info.use_compact_packets = (extraFlags != 0);
/* op2 is a boolean to use compact bitmap headers in bitmap cache */