Implement deferred cache via memblt.
authorMichael Jumper <zhangmaike@users.sourceforge.net>
Tue, 10 Apr 2012 21:23:37 +0000 (14:23 -0700)
committerMichael Jumper <zhangmaike@users.sourceforge.net>
Tue, 10 Apr 2012 21:23:37 +0000 (14:23 -0700)
include/rdp_bitmap.h
src/rdp_bitmap.c
src/rdp_gdi.c

index 39e51f4..b4cdd1e 100644 (file)
@@ -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);
index 405aa00..2d67410 100644 (file)
@@ -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;
index 7153f4b..a287e10 100644 (file)
@@ -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 */
+    }
 
 }