fixes for bitmap update

This commit is contained in:
Jay Sorg 2016-12-15 00:39:13 -08:00
parent 42272c0f18
commit 519359a823
2 changed files with 139 additions and 29 deletions

View File

@ -27,6 +27,8 @@
#define LLOGLN(_level, _args) \ #define LLOGLN(_level, _args) \
do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0)
#define MAX_BITMAP_BUF_SIZE (16 * 1024) /* 16K */
/******************************************************************************/ /******************************************************************************/
struct xrdp_session *EXPORT_CC struct xrdp_session *EXPORT_CC
libxrdp_init(tbus id, struct trans *trans) libxrdp_init(tbus id, struct trans *trans)
@ -373,15 +375,15 @@ libxrdp_send_bell(struct xrdp_session *session)
return 0; return 0;
} }
/*****************************************************************************/ /*****************************************************************************/
int EXPORT_CC int EXPORT_CC
libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
int bpp, char *data, int x, int y, int cx, int cy) int bpp, char *data, int x, int y, int cx, int cy)
{ {
int line_size = 0; int line_bytes = 0;
int i = 0; int i = 0;
int j = 0; int j = 0;
int k;
int total_lines = 0; int total_lines = 0;
int lines_sending = 0; int lines_sending = 0;
int Bpp = 0; int Bpp = 0;
@ -389,27 +391,43 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
int bufsize = 0; int bufsize = 0;
int total_bufsize = 0; int total_bufsize = 0;
int num_updates = 0; int num_updates = 0;
int line_pad_bytes;
int server_line_bytes;
char *p_num_updates = (char *)NULL; char *p_num_updates = (char *)NULL;
char *p = (char *)NULL; char *p = (char *)NULL;
char *q = (char *)NULL; char *q = (char *)NULL;
struct stream *s = (struct stream *)NULL; struct stream *s = (struct stream *)NULL;
struct stream *temp_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; Bpp = (bpp + 7) / 8;
e = width % 4; e = (4 - width) & 3;
switch (bpp)
if (e != 0)
{ {
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); make_stream(s);
init_stream(s, 8192); init_stream(s, MAX_BITMAP_BUF_SIZE);
if (session->client_info->use_bitmap_comp) if (session->client_info->use_bitmap_comp)
{ {
LLOGLN(10, ("libxrdp_send_bitmap: compression"));
make_stream(temp_s); make_stream(temp_s);
init_stream(temp_s, 65536); init_stream(temp_s, 65536);
i = 0; i = 0;
@ -421,6 +439,8 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
while (i > 0) while (i > 0)
{ {
LLOGLN(10, ("libxrdp_send_bitmap: i %d", i));
total_bufsize = 0; total_bufsize = 0;
num_updates = 0; num_updates = 0;
xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); 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; p = s->p;
lines_sending = xrdp_bitmap_compress(data, width, height,
s, bpp, if (bpp > 24)
4096 - total_bufsize, {
i - 1, temp_s, e); 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) 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 */ out_uint16_le(s, bufsize); /* compressed size */
j = (width + e) * Bpp; j = (width + e) * Bpp;
j = j * lines_sending; j = j * lines_sending;
total_bufsize += 18;
} }
else else
{ {
@ -481,31 +518,42 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
out_uint16_le(s, j); /* line size */ out_uint16_le(s, j); /* line size */
j = j * lines_sending; j = j * lines_sending;
out_uint16_le(s, j); /* final size */ 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; 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[0] = num_updates;
p_num_updates[1] = num_updates >> 8; p_num_updates[1] = num_updates >> 8;
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
RDP_DATA_PDU_UPDATE); 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", LLOGLN(0, ("libxrdp_send_bitmap: error, total compressed "
total_bufsize); "size too big: %d bytes", total_bufsize));
} }
} }
@ -513,22 +561,30 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
} }
else else
{ {
LLOGLN(10, ("libxrdp_send_bitmap: no compression"));
total_lines = height; total_lines = height;
i = 0; i = 0;
p = data; p = data;
if (line_size > 0 && total_lines > 0) if (line_bytes > 0 && total_lines > 0)
{ {
while (i < total_lines) 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) if (i + lines_sending > total_lines)
{ {
lines_sending = total_lines - i; 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); xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s);
out_uint16_le(s, RDP_UPDATE_BITMAP); out_uint16_le(s, RDP_UPDATE_BITMAP);
out_uint16_le(s, 1); /* num updates */ 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, lines_sending);
out_uint16_le(s, bpp); /* bpp */ out_uint16_le(s, bpp); /* bpp */
out_uint16_le(s, 0); /* compress */ 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; q = p;
for (j = 0; j < lines_sending; j++) switch (bpp)
{ {
q = q - line_size; case 15:
out_uint8a(s, q, line_size); /* B_ENDIAN doesn't work here, todo */ case 16:
out_uint8s(s, e * Bpp); 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); s_mark_end(s);

View File

@ -80,6 +80,7 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s,
in_uint8s(s, 6); in_uint8s(s, 6);
in_uint16_le(s, extraFlags); /* extraFlags (2 bytes) */ 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' */ /* use_compact_packets is pretty much 'use rdp5' */
self->client_info.use_compact_packets = (extraFlags != 0); self->client_info.use_compact_packets = (extraFlags != 0);
/* op2 is a boolean to use compact bitmap headers in bitmap cache */ /* op2 is a boolean to use compact bitmap headers in bitmap cache */