Implement deferred cache via memblt.

This commit is contained in:
Michael Jumper 2012-04-10 14:23:37 -07:00
parent 8d9a0211d3
commit 82c2594320
3 changed files with 53 additions and 21 deletions

View File

@ -61,6 +61,7 @@ typedef struct guac_rdp_bitmap {
} 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_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_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); void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap);

View File

@ -53,7 +53,7 @@
#include "client.h" #include "client.h"
#include "rdp_bitmap.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_client* client = ((rdp_freerdp_context*) context)->client;
guac_socket* socket = client->socket; 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 not cached, cache if necessary */
if (((guac_rdp_bitmap*) bitmap)->layer == NULL if (((guac_rdp_bitmap*) bitmap)->layer == NULL
&& ((guac_rdp_bitmap*) bitmap)->used >= 2) { && ((guac_rdp_bitmap*) bitmap)->used >= 1)
__guac_rdp_cache_bitmap(context, bitmap); guac_rdp_cache_bitmap(context, bitmap);
guac_client_log_info(client, "Deferred cache! bitmap used=%i", ((guac_rdp_bitmap*) bitmap)->used);
}
/* If cached, retrieve from cache */ /* If cached, retrieve from cache */
if (((guac_rdp_bitmap*) bitmap)->layer != NULL) if (((guac_rdp_bitmap*) bitmap)->layer != NULL)
@ -158,8 +154,6 @@ void guac_rdp_bitmap_paint(rdpContext* context, rdpBitmap* bitmap) {
/* Increment usage counter */ /* Increment usage counter */
((guac_rdp_bitmap*) bitmap)->used++; ((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) { 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 not available as a surface, make available. */
if (((guac_rdp_bitmap*) bitmap)->layer == NULL) 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 ((rdp_guac_client_data*) client->data)->current_surface
= ((guac_rdp_bitmap*) bitmap)->layer; = ((guac_rdp_bitmap*) bitmap)->layer;

View File

@ -159,9 +159,7 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
guac_socket* socket = client->socket; guac_socket* socket = client->socket;
guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap; guac_rdp_bitmap* bitmap = (guac_rdp_bitmap*) memblt->bitmap;
if (bitmap->layer != NULL) { switch (memblt->bRop) {
switch (memblt->bRop) {
/* If blackness, send black rectangle */ /* If blackness, send black rectangle */
case 0x00: case 0x00:
@ -180,12 +178,45 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
/* If operation is just SRC, simply copy */ /* If operation is just SRC, simply copy */
case 0xCC: case 0xCC:
guac_protocol_send_copy(socket,
bitmap->layer, /* If not cached, cache if necessary */
memblt->nXSrc, memblt->nYSrc, if (((guac_rdp_bitmap*) bitmap)->used >= 1)
memblt->nWidth, memblt->nHeight, guac_rdp_cache_bitmap(context, memblt->bitmap);
GUAC_COMP_OVER,
current_layer, memblt->nLeftRect, memblt->nTopRect); /* 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; break;
/* If whiteness, send white rectangle */ /* If whiteness, send white rectangle */
@ -201,6 +232,11 @@ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt) {
/* Otherwise, use transfer */ /* Otherwise, use transfer */
default: 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, guac_protocol_send_transfer(socket,
bitmap->layer, bitmap->layer,
memblt->nXSrc, memblt->nYSrc, 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), guac_rdp_rop3_transfer_function(client, memblt->bRop),
current_layer, memblt->nLeftRect, memblt->nTopRect); current_layer, memblt->nLeftRect, memblt->nTopRect);
} /* Increment usage counter */
((guac_rdp_bitmap*) bitmap)->used++;
} /* end if layer not NULL */ }
} }