diff --git a/protocols/rdp/include/rdp_bitmap.h b/protocols/rdp/include/rdp_bitmap.h index 39e51f4d..b4cdd1e0 100644 --- a/protocols/rdp/include/rdp_bitmap.h +++ b/protocols/rdp/include/rdp_bitmap.h @@ -61,6 +61,7 @@ typedef struct guac_rdp_bitmap { } guac_rdp_bitmap; +void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap); void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap); void guac_rdp_bitmap_decompress(rdpContext* context, rdpBitmap* bitmap, uint8* data, int width, int height, int bpp, int length, boolean compressed); void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap); diff --git a/protocols/rdp/src/rdp_bitmap.c b/protocols/rdp/src/rdp_bitmap.c index 405aa00e..2d674102 100644 --- a/protocols/rdp/src/rdp_bitmap.c +++ b/protocols/rdp/src/rdp_bitmap.c @@ -53,7 +53,7 @@ #include "client.h" #include "rdp_bitmap.h" -void __guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { +void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_socket* socket = client->socket; @@ -122,12 +122,8 @@ void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) { /* If not cached, cache if necessary */ if (((guac_rdp_bitmap*) bitmap)->layer == NULL - && ((guac_rdp_bitmap*) bitmap)->used >= 2) { - __guac_rdp_cache_bitmap(context, bitmap); - - guac_client_log_info(client, "Deferred cache! bitmap used=%i", ((guac_rdp_bitmap*) bitmap)->used); - - } + && ((guac_rdp_bitmap*) bitmap)->used >= 1) + guac_rdp_cache_bitmap(context, bitmap); /* If cached, retrieve from cache */ if (((guac_rdp_bitmap*) bitmap)->layer != NULL) @@ -158,8 +154,6 @@ void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) { /* Increment usage counter */ ((guac_rdp_bitmap*) bitmap)->used++; - guac_client_log_info(client, "Used bitmap... used=%i", ((guac_rdp_bitmap*) bitmap)->used); - } void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap) { @@ -182,7 +176,7 @@ void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, boolean /* If not available as a surface, make available. */ if (((guac_rdp_bitmap*) bitmap)->layer == NULL) - __guac_rdp_cache_bitmap(context, bitmap); + guac_rdp_cache_bitmap(context, bitmap); ((rdp_guac_client_data*) client->data)->current_surface = ((guac_rdp_bitmap*) bitmap)->layer; diff --git a/protocols/rdp/src/rdp_gdi.c b/protocols/rdp/src/rdp_gdi.c index 7153f4bb..a287e101 100644 --- a/protocols/rdp/src/rdp_gdi.c +++ b/protocols/rdp/src/rdp_gdi.c @@ -159,9 +159,7 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { guac_socket* socket = client->socket; guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap; - if (bitmap->layer != NULL) { - - switch (memblt->bRop) { + switch (memblt->bRop) { /* If blackness, send black rectangle */ case 0x00: @@ -180,12 +178,45 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { /* If operation is just SRC, simply copy */ case 0xCC: - guac_protocol_send_copy(socket, - bitmap->layer, - memblt->nXSrc, memblt->nYSrc, - memblt->nWidth, memblt->nHeight, - GUAC_COMP_OVER, - current_layer, memblt->nLeftRect, memblt->nTopRect); + + /* If not cached, cache if necessary */ + if (((guac_rdp_bitmap*) bitmap)->used >= 1) + guac_rdp_cache_bitmap(context, memblt->bitmap); + + /* If not cached, send as PNG */ + if (bitmap->layer == NULL) { + if (memblt->bitmap->data != NULL) { + + /* Create surface from image data */ + cairo_surface_t* surface = cairo_image_surface_create_for_data( + memblt->bitmap->data + 4*(memblt->nXSrc + memblt->nYSrc*memblt->bitmap->width), + CAIRO_FORMAT_RGB24, + memblt->nWidth, memblt->nHeight, + 4*memblt->bitmap->width); + + /* Send surface to buffer */ + guac_protocol_send_png(socket, + GUAC_COMP_OVER, current_layer, + memblt->nLeftRect, memblt->nTopRect, surface); + + /* Free surface */ + cairo_surface_destroy(surface); + + } + } + + /* Otherwise, copy */ + else + guac_protocol_send_copy(socket, + bitmap->layer, + memblt->nXSrc, memblt->nYSrc, + memblt->nWidth, memblt->nHeight, + GUAC_COMP_OVER, + current_layer, memblt->nLeftRect, memblt->nTopRect); + + /* Increment usage counter */ + ((guac_rdp_bitmap*) bitmap)->used++; + break; /* If whiteness, send white rectangle */ @@ -201,6 +232,11 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { /* Otherwise, use transfer */ default: + + /* If not available as a surface, make available. */ + if (bitmap->layer == NULL) + guac_rdp_cache_bitmap(context, memblt->bitmap); + guac_protocol_send_transfer(socket, bitmap->layer, memblt->nXSrc, memblt->nYSrc, @@ -208,9 +244,10 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { guac_rdp_rop3_transfer_function(client, memblt->bRop), current_layer, memblt->nLeftRect, memblt->nTopRect); - } + /* Increment usage counter */ + ((guac_rdp_bitmap*) bitmap)->used++; - } /* end if layer not NULL */ + } }