From f8ac59798fd244ef9b8575ab778d24a7066cdf62 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 30 Apr 2014 11:44:06 -0700 Subject: [PATCH] GUAC-656: Migrate RDP to guac_common_surface. --- src/protocols/rdp/client.c | 10 +-- src/protocols/rdp/client.h | 12 ++- src/protocols/rdp/guac_handlers.c | 2 + src/protocols/rdp/rdp_bitmap.c | 66 ++++++++------- src/protocols/rdp/rdp_bitmap.h | 10 ++- src/protocols/rdp/rdp_gdi.c | 133 +++++++----------------------- src/protocols/rdp/rdp_glyph.c | 9 +- 7 files changed, 95 insertions(+), 147 deletions(-) diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index a1199865..8b3c0cb3 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -650,7 +650,6 @@ int guac_client_init(guac_client* client, int argc, char** argv) { guac_client_data->rdp_inst = rdp_inst; guac_client_data->bounded = FALSE; guac_client_data->mouse_button_mask = 0; - guac_client_data->current_surface = GUAC_DEFAULT_LAYER; guac_client_data->clipboard = guac_common_clipboard_alloc(GUAC_RDP_CLIPBOARD_MAX_LENGTH); guac_client_data->requested_clipboard_format = CB_FORMAT_TEXT; guac_client_data->audio = NULL; @@ -707,10 +706,6 @@ int guac_client_init(guac_client* client, int argc, char** argv) { /* Send connection name */ guac_protocol_send_name(client->socket, settings->hostname); - /* Send size */ - guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER, - settings->width, settings->height); - /* Create glyph surfaces */ guac_client_data->opaque_glyph_surface = cairo_image_surface_create( CAIRO_FORMAT_RGB24, settings->width, settings->height); @@ -718,6 +713,11 @@ int guac_client_init(guac_client* client, int argc, char** argv) { guac_client_data->trans_glyph_surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, settings->width, settings->height); + /* Create default surface */ + guac_client_data->default_surface = guac_common_surface_alloc(client->socket, GUAC_DEFAULT_LAYER, + settings->width, settings->height); + guac_client_data->current_surface = guac_client_data->default_surface; + /* Set default pointer */ guac_common_set_pointer_cursor(client); diff --git a/src/protocols/rdp/client.h b/src/protocols/rdp/client.h index 4ffc0515..266ca9f0 100644 --- a/src/protocols/rdp/client.h +++ b/src/protocols/rdp/client.h @@ -28,6 +28,7 @@ #include "guac_clipboard.h" #include "guac_list.h" +#include "guac_surface.h" #include "rdp_fs.h" #include "rdp_keymap.h" #include "rdp_settings.h" @@ -120,10 +121,15 @@ typedef struct rdp_guac_client_data { cairo_t* glyph_cairo; /** - * The Guacamole layer that GDI operations should draw to. RDP messages - * exist which change this surface to allow drawing to occur off-screen. + * The display. */ - const guac_layer* current_surface; + guac_common_surface* default_surface; + + /** + * The surface that GDI operations should draw to. RDP messages exist which + * change this surface to allow drawing to occur off-screen. + */ + guac_common_surface* current_surface; /** * Whether graphical operations are restricted to a specific bounding diff --git a/src/protocols/rdp/guac_handlers.c b/src/protocols/rdp/guac_handlers.c index 27d84084..33e8ece9 100644 --- a/src/protocols/rdp/guac_handlers.c +++ b/src/protocols/rdp/guac_handlers.c @@ -25,6 +25,7 @@ #include "client.h" #include "guac_handlers.h" #include "guac_list.h" +#include "guac_surface.h" #include "rdp_cliprdr.h" #include "rdp_keymap.h" #include "rdp_rail.h" @@ -92,6 +93,7 @@ int rdp_guac_client_free_handler(guac_client* client) { /* Free client data */ guac_common_clipboard_free(guac_client_data->clipboard); + guac_common_surface_free(guac_client_data->default_surface); cairo_surface_destroy(guac_client_data->opaque_glyph_surface); cairo_surface_destroy(guac_client_data->trans_glyph_surface); free(guac_client_data); diff --git a/src/protocols/rdp/rdp_bitmap.c b/src/protocols/rdp/rdp_bitmap.c index df394604..28fa6346 100644 --- a/src/protocols/rdp/rdp_bitmap.c +++ b/src/protocols/rdp/rdp_bitmap.c @@ -23,6 +23,7 @@ #include "config.h" #include "client.h" +#include "guac_surface.h" #include "rdp_bitmap.h" #include @@ -48,28 +49,29 @@ void guac_rdp_cache_bitmap(rdpContext* context, rdpBitmap* bitmap) { guac_client* client = ((rdp_freerdp_context*) context)->client; guac_socket* socket = client->socket; - /* Allocate buffer */ + /* Allocate surface */ guac_layer* buffer = guac_client_alloc_buffer(client); + guac_common_surface* surface = guac_common_surface_alloc(socket, buffer, bitmap->width, bitmap->height); /* Cache image data if present */ if (bitmap->data != NULL) { /* Create surface from image data */ - cairo_surface_t* surface = cairo_image_surface_create_for_data( + cairo_surface_t* image = cairo_image_surface_create_for_data( bitmap->data, CAIRO_FORMAT_RGB24, bitmap->width, bitmap->height, 4*bitmap->width); /* Send surface to buffer */ - guac_protocol_send_png(socket, - GUAC_COMP_SRC, buffer, 0, 0, surface); + guac_common_surface_draw(surface, 0, 0, image); /* Free surface */ - cairo_surface_destroy(surface); + cairo_surface_destroy(image); } /* Store buffer reference in bitmap */ - ((guac_rdp_bitmap*) bitmap)->layer = buffer; + ((guac_rdp_bitmap*) bitmap)->buffer = buffer; + ((guac_rdp_bitmap*) bitmap)->surface = surface; } @@ -97,8 +99,9 @@ void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { } - /* No corresponding layer yet - caching is deferred. */ - ((guac_rdp_bitmap*) bitmap)->layer = NULL; + /* No corresponding surface yet - caching is deferred. */ + ((guac_rdp_bitmap*) bitmap)->buffer = NULL; + ((guac_rdp_bitmap*) bitmap)->surface = NULL; /* Start at zero usage */ ((guac_rdp_bitmap*) bitmap)->used = 0; @@ -108,39 +111,35 @@ void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) { guac_client* client = ((rdp_freerdp_context*) context)->client; - guac_socket* socket = client->socket; + rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data; + + guac_common_surface* surface = ((guac_rdp_bitmap*) bitmap)->surface; int width = bitmap->right - bitmap->left + 1; int height = bitmap->bottom - bitmap->top + 1; /* If not cached, cache if necessary */ - if (((guac_rdp_bitmap*) bitmap)->layer == NULL - && ((guac_rdp_bitmap*) bitmap)->used >= 1) + if (surface == NULL && ((guac_rdp_bitmap*) bitmap)->used >= 1) guac_rdp_cache_bitmap(context, bitmap); /* If cached, retrieve from cache */ - if (((guac_rdp_bitmap*) bitmap)->layer != NULL) - guac_protocol_send_copy(socket, - ((guac_rdp_bitmap*) bitmap)->layer, - 0, 0, width, height, - GUAC_COMP_OVER, - GUAC_DEFAULT_LAYER, bitmap->left, bitmap->top); + if (surface != NULL) + guac_common_surface_copy(surface, 0, 0, width, height, + client_data->default_surface, bitmap->left, bitmap->top); /* Otherwise, draw with stored image data */ else if (bitmap->data != NULL) { /* Create surface from image data */ - cairo_surface_t* surface = cairo_image_surface_create_for_data( + cairo_surface_t* image = cairo_image_surface_create_for_data( bitmap->data, CAIRO_FORMAT_RGB24, width, height, 4*bitmap->width); - /* Send surface to buffer */ - guac_protocol_send_png(socket, - GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, - bitmap->left, bitmap->top, surface); + /* Draw image on default surface */ + guac_common_surface_draw(client_data->default_surface, bitmap->left, bitmap->top, image); /* Free surface */ - cairo_surface_destroy(surface); + cairo_surface_destroy(image); } @@ -150,20 +149,28 @@ void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) { } void guac_rdp_bitmap_free(rdpContext* context, rdpBitmap* bitmap) { + guac_client* client = ((rdp_freerdp_context*) context)->client; + guac_layer* buffer = ((guac_rdp_bitmap*) bitmap)->buffer; + guac_common_surface* surface = ((guac_rdp_bitmap*) bitmap)->surface; /* If cached, free buffer */ - if (((guac_rdp_bitmap*) bitmap)->layer != NULL) - guac_client_free_buffer(client, ((guac_rdp_bitmap*) bitmap)->layer); + if (buffer != NULL) + guac_client_free_buffer(client, buffer); + + /* If cached, free surface */ + if (surface != NULL) + guac_common_surface_free(surface); } void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL primary) { + guac_client* client = ((rdp_freerdp_context*) context)->client; + rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data; if (primary) - ((rdp_guac_client_data*) client->data)->current_surface - = GUAC_DEFAULT_LAYER; + client_data->current_surface = client_data->default_surface; else { @@ -174,11 +181,10 @@ void guac_rdp_bitmap_setsurface(rdpContext* context, rdpBitmap* bitmap, BOOL pri } /* If not available as a surface, make available. */ - if (((guac_rdp_bitmap*) bitmap)->layer == NULL) + if (((guac_rdp_bitmap*) bitmap)->surface == NULL) guac_rdp_cache_bitmap(context, bitmap); - ((rdp_guac_client_data*) client->data)->current_surface - = ((guac_rdp_bitmap*) bitmap)->layer; + client_data->current_surface = ((guac_rdp_bitmap*) bitmap)->surface; } diff --git a/src/protocols/rdp/rdp_bitmap.h b/src/protocols/rdp/rdp_bitmap.h index da29f8ce..95ae90cc 100644 --- a/src/protocols/rdp/rdp_bitmap.h +++ b/src/protocols/rdp/rdp_bitmap.h @@ -25,6 +25,7 @@ #define _GUAC_RDP_RDP_BITMAP_H #include "config.h" +#include "guac_surface.h" #include #include @@ -43,9 +44,14 @@ typedef struct guac_rdp_bitmap { rdpBitmap bitmap; /** - * Guacamole layer containing cached image data. + * The allocated buffer which backs this bitmap. */ - guac_layer* layer; + guac_layer* buffer; + + /** + * Surface containing cached image data. + */ + guac_common_surface* surface; /** * The number of times a bitmap has been used. diff --git a/src/protocols/rdp/rdp_gdi.c b/src/protocols/rdp/rdp_gdi.c index 04af4e02..ba6caaeb 100644 --- a/src/protocols/rdp/rdp_gdi.c +++ b/src/protocols/rdp/rdp_gdi.c @@ -23,6 +23,7 @@ #include "config.h" #include "client.h" +#include "guac_surface.h" #include "rdp_bitmap.h" #include @@ -96,7 +97,7 @@ guac_transfer_function guac_rdp_rop3_transfer_function(guac_client* client, void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) { guac_client* client = ((rdp_freerdp_context*) context)->client; - const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface; + guac_common_surface* current_surface = ((rdp_guac_client_data*) client->data)->current_surface; int x = dstblt->nLeftRect; int y = dstblt->nTopRect; @@ -114,23 +115,13 @@ void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) { case 0: /* Send black rectangle */ - guac_protocol_send_rect(client->socket, current_layer, x, y, w, h); - - guac_protocol_send_cfill(client->socket, - GUAC_COMP_OVER, current_layer, - 0, 0, 0, 255); - + guac_common_surface_rect(current_surface, x, y, w, h, 0, 0, 0); break; /* DSTINVERT */ case 0x55: - - /* Invert */ - guac_protocol_send_transfer(client->socket, - current_layer, x, y, w, h, - GUAC_TRANSFER_BINARY_NDEST, - current_layer, x, y); - + guac_common_surface_transfer(current_surface, x, y, w, h, + GUAC_TRANSFER_BINARY_NDEST, current_surface, x, y); break; /* NOP */ @@ -139,11 +130,7 @@ void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt) { /* Whiteness */ case 0xFF: - guac_protocol_send_rect(client->socket, current_layer, x, y, w, h); - - guac_protocol_send_cfill(client->socket, - GUAC_COMP_OVER, current_layer, - 0xFF, 0xFF, 0xFF, 0xFF); + guac_common_surface_rect(current_surface, x, y, w, h, 0xFF, 0xFF, 0xFF); break; /* Unsupported ROP3 */ @@ -170,7 +157,7 @@ void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { /* Get client and current layer */ guac_client* client = ((rdp_freerdp_context*) context)->client; - const guac_layer* current_layer = + guac_common_surface* current_surface = ((rdp_guac_client_data*) client->data)->current_surface; int x = patblt->nLeftRect; @@ -180,9 +167,6 @@ void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { rdp_guac_client_data* data = (rdp_guac_client_data*) client->data; - /* Layer for actual transfer */ - guac_layer* buffer; - /* * Warn that rendering is a fallback, as the server should not be sending * this order. @@ -199,11 +183,7 @@ void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { /* If blackness, send black rectangle */ case 0x00: - guac_protocol_send_rect(client->socket, current_layer, x, y, w, h); - - guac_protocol_send_cfill(client->socket, - GUAC_COMP_OVER, current_layer, - 0x00, 0x00, 0x00, 0xFF); + guac_common_surface_rect(current_surface, x, y, w, h, 0, 0, 0); break; /* If NOP, do nothing */ @@ -213,53 +193,21 @@ void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { /* If operation is just a copy, send foreground only */ case 0xCC: case 0xF0: - guac_protocol_send_rect(client->socket, current_layer, x, y, w, h); - - guac_protocol_send_cfill(client->socket, - GUAC_COMP_OVER, current_layer, + guac_common_surface_rect(current_surface, x, y, w, h, (patblt->foreColor >> 16) & 0xFF, (patblt->foreColor >> 8 ) & 0xFF, - (patblt->foreColor ) & 0xFF, - 0xFF); + (patblt->foreColor ) & 0xFF); break; /* If whiteness, send white rectangle */ case 0xFF: - guac_protocol_send_rect(client->socket, current_layer, x, y, w, h); - - guac_protocol_send_cfill(client->socket, - GUAC_COMP_OVER, current_layer, - 0xFF, 0xFF, 0xFF, 0xFF); + guac_common_surface_rect(current_surface, x, y, w, h, 0xFF, 0xFF, 0xFF); break; /* Otherwise, invert entire rect */ default: - - /* Allocate buffer for transfer */ - buffer = guac_client_alloc_buffer(client); - - /* Send rectangle stroke */ - guac_protocol_send_rect(client->socket, buffer, - 0, 0, w, h); - - /* Fill rectangle with fore color only */ - guac_protocol_send_cfill(client->socket, GUAC_COMP_OVER, buffer, - 0xFF, 0xFF, 0xFF, 0xFF); - - /* Transfer */ - guac_protocol_send_transfer(client->socket, - - /* ... from buffer */ - buffer, 0, 0, w, h, - - /* ... inverting */ - GUAC_TRANSFER_BINARY_XOR, - - /* ... to current layer */ - current_layer, x, y); - - /* Done with buffer */ - guac_client_free_buffer(client, buffer); + guac_common_surface_transfer(current_surface, x, y, w, h, + GUAC_TRANSFER_BINARY_NDEST, current_surface, x, y); } @@ -268,7 +216,7 @@ void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) { void guac_rdp_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) { guac_client* client = ((rdp_freerdp_context*) context)->client; - const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface; + guac_common_surface* current_surface = ((rdp_guac_client_data*) client->data)->current_surface; int x = scrblt->nLeftRect; int y = scrblt->nTopRect; @@ -288,17 +236,15 @@ void guac_rdp_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt) { y_src += y - scrblt->nTopRect; /* Copy screen rect to current surface */ - guac_protocol_send_copy(client->socket, - GUAC_DEFAULT_LAYER, x_src, y_src, w, h, - GUAC_COMP_OVER, current_layer, x, y); + guac_common_surface_copy(data->default_surface, x_src, y_src, w, h, + current_surface, x, y); } void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { guac_client* client = ((rdp_freerdp_context*) context)->client; - const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface; - guac_socket* socket = client->socket; + guac_common_surface* current_surface = ((rdp_guac_client_data*) client->data)->current_surface; guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap; int x = memblt->nLeftRect; @@ -329,11 +275,7 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { /* If blackness, send black rectangle */ case 0x00: - guac_protocol_send_rect(client->socket, current_layer, x, y, w, h); - - guac_protocol_send_cfill(client->socket, - GUAC_COMP_OVER, current_layer, - 0x00, 0x00, 0x00, 0xFF); + guac_common_surface_rect(current_surface, x, y, w, h, 0, 0, 0); break; /* If NOP, do nothing */ @@ -344,12 +286,11 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { case 0xCC: /* If not cached, cache if necessary */ - if (((guac_rdp_bitmap*) bitmap)->layer == NULL - && ((guac_rdp_bitmap*) bitmap)->used >= 1) + if (bitmap->surface == NULL && bitmap->used >= 1) guac_rdp_cache_bitmap(context, memblt->bitmap); /* If not cached, send as PNG */ - if (bitmap->layer == NULL) { + if (bitmap->surface == NULL) { if (memblt->bitmap->data != NULL) { /* Create surface from image data */ @@ -358,9 +299,7 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { CAIRO_FORMAT_RGB24, w, h, 4*memblt->bitmap->width); /* Send surface to buffer */ - guac_protocol_send_png(socket, - GUAC_COMP_OVER, current_layer, - x, y, surface); + guac_common_surface_draw(current_surface, x, y, surface); /* Free surface */ cairo_surface_destroy(surface); @@ -370,9 +309,8 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { /* Otherwise, copy */ else - guac_protocol_send_copy(socket, - bitmap->layer, x_src, y_src, w, h, - GUAC_COMP_OVER, current_layer, x, y); + guac_common_surface_copy(bitmap->surface, x_src, y_src, w, h, + current_surface, x, y); /* Increment usage counter */ ((guac_rdp_bitmap*) bitmap)->used++; @@ -381,24 +319,19 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) { /* If whiteness, send white rectangle */ case 0xFF: - guac_protocol_send_rect(client->socket, current_layer, x, y, w, h); - - guac_protocol_send_cfill(client->socket, - GUAC_COMP_OVER, current_layer, - 0xFF, 0xFF, 0xFF, 0xFF); + guac_common_surface_rect(current_surface, x, y, w, h, 0xFF, 0xFF, 0xFF); break; /* Otherwise, use transfer */ default: /* If not available as a surface, make available. */ - if (bitmap->layer == NULL) + if (bitmap->surface == NULL) guac_rdp_cache_bitmap(context, memblt->bitmap); - guac_protocol_send_transfer(socket, - bitmap->layer, x_src, y_src, w, h, - guac_rdp_rop3_transfer_function(client, memblt->bRop), - current_layer, x, y); + guac_common_surface_transfer(bitmap->surface, x_src, y_src, w, h, + guac_rdp_rop3_transfer_function(client, memblt->bRop), + current_surface, x, y); /* Increment usage counter */ ((guac_rdp_bitmap*) bitmap)->used++; @@ -417,7 +350,7 @@ void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect client_data->settings.color_depth, 32, ((rdp_freerdp_context*) context)->clrconv); - const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface; + guac_common_surface* current_surface = ((rdp_guac_client_data*) client->data)->current_surface; rdp_guac_client_data* data = (rdp_guac_client_data*) client->data; @@ -430,14 +363,10 @@ void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect if (guac_rdp_clip_rect(data, &x, &y, &w, &h)) return; - guac_protocol_send_rect(client->socket, current_layer, x, y, w, h); - - guac_protocol_send_cfill(client->socket, - GUAC_COMP_OVER, current_layer, + guac_common_surface_rect(current_surface, x, y, w, h, (color >> 16) & 0xFF, (color >> 8 ) & 0xFF, - (color ) & 0xFF, - 255); + (color ) & 0xFF); } diff --git a/src/protocols/rdp/rdp_glyph.c b/src/protocols/rdp/rdp_glyph.c index 26f54533..44865aac 100644 --- a/src/protocols/rdp/rdp_glyph.c +++ b/src/protocols/rdp/rdp_glyph.c @@ -23,6 +23,7 @@ #include "config.h" #include "client.h" +#include "guac_surface.h" #include "rdp_glyph.h" #include @@ -199,7 +200,7 @@ void guac_rdp_glyph_enddraw(rdpContext* context, guac_client* client = ((rdp_freerdp_context*) context)->client; rdp_guac_client_data* guac_client_data = (rdp_guac_client_data*) client->data; - const guac_layer* current_layer = ((rdp_guac_client_data*) client->data)->current_surface; + guac_common_surface* current_surface = ((rdp_guac_client_data*) client->data)->current_surface; /* Use glyph surface to provide image data for glyph rectangle */ cairo_surface_t* glyph_surface = guac_client_data->glyph_surface; @@ -225,10 +226,8 @@ void guac_rdp_glyph_enddraw(rdpContext* context, cairo_image_surface_get_format(glyph_surface), width, height, stride); - /* Send surface with all glyphs to layer */ - guac_protocol_send_png(client->socket, - GUAC_COMP_OVER, current_layer, x, y, - surface); + /* Send surface with all glyphs to current surface */ + guac_common_surface_draw(current_surface, x, y, surface); /* Destroy surface */ cairo_surface_destroy(surface);