Merge pull request #550 from jsorg71/bitmap_update

fixes for bitmap update
This commit is contained in:
metalefty 2016-12-20 17:01:32 +09:00 committed by GitHub
commit 1753f6317c
2 changed files with 130 additions and 29 deletions

View File

@ -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;
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,
4096 - total_bufsize,
(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; /* bytes since pop layer */
}
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; /* bytes since pop layer */
}
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 += 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,58 @@ 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;
switch (bpp)
{
case 8:
for (j = 0; j < lines_sending; j++)
{
q = q - line_size;
out_uint8a(s, q, line_size); /* B_ENDIAN doesn't work here, todo */
out_uint8s(s, e * Bpp);
q = q - line_bytes;
out_uint8a(s, q, line_bytes);
out_uint8s(s, e);
}
break;
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);
}
out_uint8s(s, e * 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);
}
out_uint8s(s, e * 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);
}
out_uint8s(s, e * 4);
}
break;
}
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_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 */