xfreerdp: started bitmap caching support
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 5 Oct 2011 01:29:01 +0000 (21:29 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Wed, 5 Oct 2011 01:29:01 +0000 (21:29 -0400)
12 files changed:
client/Windows/wf_gdi.c
client/X11/xf_gdi.c
client/X11/xfreerdp.c
cunit/test_orders.c
include/freerdp/cache/bitmap_v2.h
include/freerdp/codec/color.h
include/freerdp/update.h
libfreerdp-cache/bitmap_v2.c
libfreerdp-codec/color.c
libfreerdp-core/orders.c
libfreerdp-core/orders.h
libfreerdp-gdi/gdi.c

index cb8695a..5e5839c 100644 (file)
@@ -403,7 +403,7 @@ void wf_gdi_bitmap_decompress(rdpUpdate* update, BITMAP_DATA* bitmap_data)
        }
        else
        {
-               freerdp_image_invert(bitmap_data->srcData, bitmap_data->dstData,
+               freerdp_image_flip(bitmap_data->srcData, bitmap_data->dstData,
                                bitmap_data->width, bitmap_data->height, bitmap_data->bpp);
        }
 
index 4a52e09..fe67b9b 100644 (file)
@@ -205,7 +205,7 @@ Pixmap xf_bitmap_new(xfInfo* xfi, int width, int height, int bpp, uint8* data)
        cdata = freerdp_image_convert(data, NULL, width, height, bpp, xfi->bpp, xfi->clrconv);
 
        image = XCreateImage(xfi->display, xfi->visual, xfi->depth,
-                       ZPixmap, 0, (char *) cdata, width, height, xfi->scanline_pad, 0);
+                       ZPixmap, 0, (char*) cdata, width, height, xfi->scanline_pad, 0);
 
        XPutImage(xfi->display, bitmap, xfi->gc, image, 0, 0, 0, 0, width, height);
        XFree(image);
@@ -579,6 +579,34 @@ void xf_gdi_polyline(rdpUpdate* update, POLYLINE_ORDER* polyline)
        xfree(points);
 }
 
+void xf_gdi_memblt(rdpUpdate* update, MEMBLT_ORDER* memblt)
+{
+       void* extra;
+       Pixmap bitmap;
+       xfInfo* xfi = GET_XFI(update);
+
+       //xf_set_rop3(xfi, gdi_rop3_code(memblt->bRop));
+       bitmap_v2_get(xfi->cache->bitmap_v2, memblt->cacheId, memblt->cacheIndex, (void**) &extra);
+
+       bitmap = (Pixmap) extra;
+
+#if 0
+       XCopyArea(xfi->display, xfi->primary, xfi->drawable, xfi->gc,
+                       memblt->nLeftRect, memblt->nTopRect, memblt->nWidth, memblt->nHeight,
+                       memblt->nLeftRect, memblt->nTopRect);
+#endif
+
+       if (xfi->drawing == xfi->primary)
+       {
+
+       }
+}
+
+void xf_gdi_mem3blt(rdpUpdate* update, MEM3BLT_ORDER* mem3blt)
+{
+
+}
+
 void xf_gdi_fast_index(rdpUpdate* update, FAST_INDEX_ORDER* fast_index)
 {
        int i, j;
@@ -736,10 +764,16 @@ void xf_gdi_switch_surface(rdpUpdate* update, SWITCH_SURFACE_ORDER* switch_surfa
 
 void xf_gdi_cache_bitmap_v2(rdpUpdate* update, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2)
 {
+       Pixmap bitmap;
+       BITMAP_DATA* bitmap_data;
        xfInfo* xfi = GET_XFI(update);
 
+       bitmap_data = cache_bitmap_v2->bitmap_data;
+
+       bitmap = xf_bitmap_new(xfi, bitmap_data->width, bitmap_data->height, bitmap_data->bpp, bitmap_data->dstData);
+
        bitmap_v2_put(xfi->cache->bitmap_v2, cache_bitmap_v2->cacheId,
-                       cache_bitmap_v2->cacheIndex, cache_bitmap_v2->data);
+               cache_bitmap_v2->cacheIndex, bitmap_data, (void*) bitmap);
 }
 
 void xf_gdi_cache_color_table(rdpUpdate* update, CACHE_COLOR_TABLE_ORDER* cache_color_table)
@@ -835,7 +869,7 @@ void xf_gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_c
                xfi->bmp_codec_nsc = (uint8*) xrealloc(xfi->bmp_codec_nsc,
                                surface_bits_command->width * surface_bits_command->height * 4);
 
-               freerdp_image_invert(ncontext->bmpdata, xfi->bmp_codec_nsc,
+               freerdp_image_flip(ncontext->bmpdata, xfi->bmp_codec_nsc,
                                surface_bits_command->width, surface_bits_command->height, 32);
 
                image = XCreateImage(xfi->display, xfi->visual, 24, ZPixmap, 0,
@@ -867,7 +901,7 @@ void xf_gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_c
                xfi->bmp_codec_none = (uint8*) xrealloc(xfi->bmp_codec_none,
                                surface_bits_command->width * surface_bits_command->height * 4);
 
-               freerdp_image_invert(surface_bits_command->bitmapData, xfi->bmp_codec_none,
+               freerdp_image_flip(surface_bits_command->bitmapData, xfi->bmp_codec_none,
                                surface_bits_command->width, surface_bits_command->height, 32);
 
                image = XCreateImage(xfi->display, xfi->visual, 24, ZPixmap, 0,
@@ -915,7 +949,7 @@ void xf_gdi_bitmap_decompress(rdpUpdate* update, BITMAP_DATA* bitmap_data)
        }
        else
        {
-               freerdp_image_invert(bitmap_data->srcData, bitmap_data->dstData,
+               freerdp_image_flip(bitmap_data->srcData, bitmap_data->dstData,
                                bitmap_data->width, bitmap_data->height, bitmap_data->bpp);
        }
 
@@ -939,8 +973,8 @@ void xf_gdi_register_update_callbacks(rdpUpdate* update)
        update->MultiDrawNineGrid = NULL;
        update->LineTo = xf_gdi_line_to;
        update->Polyline = NULL;
-       update->MemBlt = NULL;
-       update->Mem3Blt = NULL;
+       update->MemBlt = xf_gdi_memblt;
+       update->Mem3Blt = xf_gdi_mem3blt;
        update->SaveBitmap = NULL;
        update->GlyphIndex = NULL;
        update->FastIndex = xf_gdi_fast_index;
index c2c2764..e1bafc8 100644 (file)
@@ -451,6 +451,7 @@ boolean xf_get_pixmap_info(xfInfo* xfi)
 boolean xf_pre_connect(freerdp* instance)
 {
        xfInfo* xfi;
+       boolean bitmap_cache;
        rdpSettings* settings;
 
        xfi = (xfInfo*) xzalloc(sizeof(xfInfo));
@@ -459,6 +460,7 @@ boolean xf_pre_connect(freerdp* instance)
        xfi->instance = instance;
 
        settings = instance->settings;
+       bitmap_cache = settings->bitmap_cache;
 
        settings->order_support[NEG_DSTBLT_INDEX] = True;
        settings->order_support[NEG_PATBLT_INDEX] = True;
@@ -472,10 +474,10 @@ boolean xf_pre_connect(freerdp* instance)
        settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = False;
        settings->order_support[NEG_LINETO_INDEX] = True;
        settings->order_support[NEG_POLYLINE_INDEX] = True;
-       settings->order_support[NEG_MEMBLT_INDEX] = False;
-       settings->order_support[NEG_MEM3BLT_INDEX] = False;
-       settings->order_support[NEG_MEMBLT_V2_INDEX] = False;
-       settings->order_support[NEG_MEM3BLT_V2_INDEX] = False;
+       settings->order_support[NEG_MEMBLT_INDEX] = bitmap_cache;
+       settings->order_support[NEG_MEM3BLT_INDEX] = bitmap_cache;
+       settings->order_support[NEG_MEMBLT_V2_INDEX] = bitmap_cache;
+       settings->order_support[NEG_MEM3BLT_V2_INDEX] = bitmap_cache;
        settings->order_support[NEG_SAVEBITMAP_INDEX] = True;
        settings->order_support[NEG_GLYPH_INDEX_INDEX] = True;
        settings->order_support[NEG_FAST_INDEX_INDEX] = True;
index c05c08f..44566fc 100644 (file)
@@ -611,11 +611,11 @@ void test_read_cache_bitmap_v2_order(void)
        update_read_cache_bitmap_v2_order(s, &cache_bitmap_v2, True, extraFlags);
 
        CU_ASSERT(cache_bitmap_v2.cacheId == 1);
-       CU_ASSERT(cache_bitmap_v2.bitmapBpp == 16);
+       CU_ASSERT(cache_bitmap_v2.bitmap_data->bpp == 16);
        CU_ASSERT(cache_bitmap_v2.flags == 0x19);
-       CU_ASSERT(cache_bitmap_v2.bitmapWidth == 32);
-       CU_ASSERT(cache_bitmap_v2.bitmapHeight == 32);
-       CU_ASSERT(cache_bitmap_v2.bitmapLength == 220);
+       CU_ASSERT(cache_bitmap_v2.bitmap_data->width == 32);
+       CU_ASSERT(cache_bitmap_v2.bitmap_data->height == 32);
+       CU_ASSERT(cache_bitmap_v2.bitmap_data->length == 220);
        CU_ASSERT(cache_bitmap_v2.cacheIndex == 32767);
 
        CU_ASSERT(stream_get_length(s) == (sizeof(cache_bitmap_v2_order) - 1));
index 731af6b..e0b72ee 100644 (file)
@@ -27,6 +27,7 @@
 struct _BITMAP_V2_ENTRY
 {
        void* entry;
+       void* extra;
 };
 typedef struct _BITMAP_V2_ENTRY BITMAP_V2_ENTRY;
 
@@ -45,8 +46,8 @@ struct rdp_bitmap_v2
 };
 typedef struct rdp_bitmap_v2 rdpBitmapV2;
 
-FREERDP_API void* bitmap_v2_get(rdpBitmapV2* bitmap_v2, uint8 id, uint16 index);
-FREERDP_API void bitmap_v2_put(rdpBitmapV2* bitmap_v2, uint8 id, uint16 index, void* entry);
+FREERDP_API void* bitmap_v2_get(rdpBitmapV2* bitmap_v2, uint8 id, uint16 index, void** extra);
+FREERDP_API void bitmap_v2_put(rdpBitmapV2* bitmap_v2, uint8 id, uint16 index, void* entry, void* extra);
 
 FREERDP_API rdpBitmapV2* bitmap_v2_new(rdpSettings* settings);
 FREERDP_API void bitmap_v2_free(rdpBitmapV2* bitmap_v2);
index 9138d74..8dbfd8d 100644 (file)
@@ -240,7 +240,7 @@ typedef uint8* (*p_freerdp_image_convert)(uint8* srcData, uint8* dstData, int wi
 FREERDP_API uint32 freerdp_color_convert(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv);
 FREERDP_API uint8* freerdp_image_convert(uint8* srcData, uint8 *dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv);
 FREERDP_API uint8* freerdp_glyph_convert(int width, int height, uint8* data);
-FREERDP_API uint8* freerdp_image_invert(uint8* srcData, uint8* dstData, int width, int height, int bpp);
+FREERDP_API uint8* freerdp_image_flip(uint8* srcData, uint8* dstData, int width, int height, int bpp);
 FREERDP_API uint8* freerdp_icon_convert(uint8* srcData, uint8* dstData, uint8* mask, int width, int height, int bpp, HCLRCONV clrconv);
 FREERDP_API uint8* freerdp_mono_image_convert(uint8* srcData, int width, int height, int srcBpp, int dstBpp, uint32 bgcolor, uint32 fgcolor, HCLRCONV clrconv);
 FREERDP_API void freerdp_alpha_cursor_convert(uint8* alphaData, uint8* xorMask, uint8* andMask, int width, int height, int bpp, HCLRCONV clrconv);
index e0f6ece..c6aec9e 100644 (file)
@@ -65,7 +65,7 @@ struct _BITMAP_DATA
        uint16 height;
        uint16 bpp;
        uint16 flags;
-       uint16 length;
+       uint32 length;
        uint8* srcData;
        uint8* dstData;
        boolean compressed;
@@ -528,14 +528,9 @@ struct _CACHE_BITMAP_V2_ORDER
        uint16 flags;
        uint32 key1;
        uint32 key2;
-       uint8 bitmapBpp;
-       uint16 bitmapWidth;
-       uint16 bitmapHeight;
-       uint32 bitmapLength;
        uint16 cacheIndex;
        uint8 bitmapComprHdr[8];
-       uint8* bitmapDataStream;
-       uint8* data;
+       BITMAP_DATA* bitmap_data;
 };
 typedef struct _CACHE_BITMAP_V2_ORDER CACHE_BITMAP_V2_ORDER;
 
@@ -928,6 +923,12 @@ typedef struct _SURFACE_BITS_COMMAND SURFACE_BITS_COMMAND;
 #define STREAM_BITMAP_V2               0x04
 
 #define SCREEN_BITMAP_SURFACE          0xFFFF
+#define BITMAP_CACHE_WAITING_LIST_INDEX 0x7FFF
+
+#define CBR2_HEIGHT_SAME_AS_WIDTH      0x01
+#define CBR2_PERSISTENT_KEY_PRESENT    0x02
+#define CBR2_NO_BITMAP_COMPRESSION_HDR 0x08
+#define CBR2_DO_NOT_CACHE              0x10
 
 #define GLYPH_FRAGMENT_NOP             0x00
 #define GLYPH_FRAGMENT_USE             0xFE
index 667b8d3..481317e 100644 (file)
 
 #include <freerdp/cache/bitmap_v2.h>
 
-void* bitmap_v2_get(rdpBitmapV2* bitmap_v2, uint8 id, uint16 index)
+void* bitmap_v2_get(rdpBitmapV2* bitmap_v2, uint8 id, uint16 index, void** extra)
 {
        void* entry;
 
-       if (index > bitmap_v2->maxCells)
+       if (id > bitmap_v2->maxCells)
        {
-               printf("invalid bitmap_v2 cell id: %d\n", id);
+               printf("get invalid bitmap_v2 cell id: %d\n", id);
                return NULL;
        }
 
+       if (index == 0x7FFF)
+               index = bitmap_v2->cells[id].number - 1;
+
        if (index > bitmap_v2->cells[id].number)
        {
-               printf("invalid bitmap_v2 index %d in cell id: %d\n", index, id);
+               printf("get invalid bitmap_v2 index %d in cell id: %d\n", index, id);
                return NULL;
        }
 
        entry = bitmap_v2->cells[id].entries[index].entry;
 
+       if (extra != NULL)
+               *extra = bitmap_v2->cells[id].entries[index].extra;
+
        if (entry == NULL)
        {
-               printf("invalid bitmap_v2 at index %d in cell id: %d\n", index, id);
+               printf("get invalid bitmap_v2 at index %d in cell id: %d\n", index, id);
                return NULL;
        }
 
        return entry;
 }
 
-void bitmap_v2_put(rdpBitmapV2* bitmap_v2, uint8 id, uint16 index, void* entry)
+void bitmap_v2_put(rdpBitmapV2* bitmap_v2, uint8 id, uint16 index, void* entry, void* extra)
 {
        if (id > bitmap_v2->maxCells)
        {
-               printf("invalid bitmap_v2 cell id: %d\n", id);
+               printf("put invalid bitmap_v2 cell id: %d\n", id);
                return;
        }
 
+       if (index == 0x7FFF)
+               index = bitmap_v2->cells[id].number - 1;
+
        if (index > bitmap_v2->cells[id].number)
        {
-               printf("invalid bitmap_v2 index %d in cell id: %d\n", index, id);
+               printf("put invalid bitmap_v2 index %d in cell id: %d\n", index, id);
                return;
        }
 
        bitmap_v2->cells[id].entries[index].entry = entry;
+       bitmap_v2->cells[id].entries[index].extra = extra;
 }
 
 rdpBitmapV2* bitmap_v2_new(rdpSettings* settings)
index e07d29c..21b5054 100644 (file)
@@ -628,7 +628,7 @@ uint8* freerdp_image_convert(uint8* srcData, uint8* dstData, int width, int heig
                return 0;
 }
 
-uint8* freerdp_image_invert(uint8* srcData, uint8* dstData, int width, int height, int bpp)
+uint8* freerdp_image_flip(uint8* srcData, uint8* dstData, int width, int height, int bpp)
 {
        int y;
        uint8* srcp;
@@ -663,7 +663,7 @@ uint8* freerdp_icon_convert(uint8* srcData, uint8* dstData, uint8* mask, int wid
        uint32* icon;
 
        pixel = 0;
-       data = freerdp_image_invert(srcData, dstData, width, height, bpp);
+       data = freerdp_image_flip(srcData, dstData, width, height, bpp);
        dstData = freerdp_image_convert(data, NULL, width, height, bpp, 32, clrconv);
 
        free(data);
index a5681c8..c1ba4d2 100644 (file)
@@ -1395,16 +1395,17 @@ void update_read_cache_bitmap_order(STREAM* s, CACHE_BITMAP_ORDER* cache_bitmap_
 
 void update_read_cache_bitmap_v2_order(STREAM* s, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2_order, boolean compressed, uint16 flags)
 {
-       boolean status;
-       uint16 dstSize;
-       uint8* srcData;
        uint8 bitsPerPixelId;
+       BITMAP_DATA* bitmap_data;
+
+       bitmap_data = (BITMAP_DATA*) xzalloc(sizeof(BITMAP_DATA));
+       cache_bitmap_v2_order->bitmap_data = bitmap_data;
 
        cache_bitmap_v2_order->cacheId = flags & 0x0003;
        cache_bitmap_v2_order->flags = (flags & 0xFF80) >> 7;
 
        bitsPerPixelId = (flags & 0x0078) >> 3;
-       cache_bitmap_v2_order->bitmapBpp = CBR2_BPP[bitsPerPixelId];
+       bitmap_data->bpp = CBR2_BPP[bitsPerPixelId];
 
        if (cache_bitmap_v2_order->flags & CBR2_PERSISTENT_KEY_PRESENT)
        {
@@ -1414,54 +1415,36 @@ void update_read_cache_bitmap_v2_order(STREAM* s, CACHE_BITMAP_V2_ORDER* cache_b
 
        if (cache_bitmap_v2_order->flags & CBR2_HEIGHT_SAME_AS_WIDTH)
        {
-               update_read_2byte_unsigned(s, &cache_bitmap_v2_order->bitmapWidth); /* bitmapWidth */
-               cache_bitmap_v2_order->bitmapHeight = cache_bitmap_v2_order->bitmapWidth;
+               update_read_2byte_unsigned(s, &bitmap_data->width); /* bitmapWidth */
+               bitmap_data->height = bitmap_data->width;
        }
        else
        {
-               update_read_2byte_unsigned(s, &cache_bitmap_v2_order->bitmapWidth); /* bitmapWidth */
-               update_read_2byte_unsigned(s, &cache_bitmap_v2_order->bitmapHeight); /* bitmapHeight */
+               update_read_2byte_unsigned(s, &bitmap_data->width); /* bitmapWidth */
+               update_read_2byte_unsigned(s, &bitmap_data->height); /* bitmapHeight */
        }
 
-       update_read_4byte_unsigned(s, &cache_bitmap_v2_order->bitmapLength); /* bitmapLength */
+       update_read_4byte_unsigned(s, &bitmap_data->length); /* bitmapLength */
        update_read_2byte_unsigned(s, &cache_bitmap_v2_order->cacheIndex); /* cacheIndex */
 
        if (compressed)
        {
-               if (!(cache_bitmap_v2_order->flags & CBR2_NO_BITMAP_COMPRESSION_HDR))
+               if ((cache_bitmap_v2_order->flags & CBR2_NO_BITMAP_COMPRESSION_HDR) == 0)
                {
                        uint8* bitmapComprHdr = (uint8*) &(cache_bitmap_v2_order->bitmapComprHdr);
                        stream_read(s, bitmapComprHdr, 8); /* bitmapComprHdr (8 bytes) */
+                       bitmap_data->length -= 8;
                }
 
-               dstSize = cache_bitmap_v2_order->bitmapLength;
-               cache_bitmap_v2_order->data = (uint8*) xmalloc(dstSize);
-
-               stream_get_mark(s, srcData);
-               stream_seek(s, cache_bitmap_v2_order->bitmapLength);
-
-               status = bitmap_decompress(srcData, cache_bitmap_v2_order->data, cache_bitmap_v2_order->bitmapWidth,
-                               cache_bitmap_v2_order->bitmapHeight, cache_bitmap_v2_order->bitmapLength,
-                               cache_bitmap_v2_order->bitmapBpp, cache_bitmap_v2_order->bitmapBpp);
-
-               if (status != True)
-                       printf("bitmap decompression failed, bpp:%d\n", cache_bitmap_v2_order->bitmapBpp);
+               stream_get_mark(s, bitmap_data->srcData);
+               stream_seek(s, bitmap_data->length);
+               bitmap_data->compressed = True;
        }
        else
        {
-               int y;
-               int offset;
-               int scanline;
-               stream_get_mark(s, srcData);
-               dstSize = cache_bitmap_v2_order->bitmapLength;
-               cache_bitmap_v2_order->data = (uint8*) xmalloc(dstSize);
-               scanline = cache_bitmap_v2_order->bitmapWidth * (cache_bitmap_v2_order->bitmapBpp / 8);
-
-               for (y = 0; y < cache_bitmap_v2_order->bitmapHeight; y++)
-               {
-                       offset = (cache_bitmap_v2_order->bitmapHeight - y - 1) * scanline;
-                       stream_read(s, &cache_bitmap_v2_order->data[offset], scanline);
-               }
+               stream_get_mark(s, bitmap_data->srcData);
+               stream_seek(s, bitmap_data->length);
+               bitmap_data->compressed = False;
        }
 }
 
@@ -2039,11 +2022,13 @@ void update_recv_secondary_order(rdpUpdate* update, STREAM* s, uint8 flags)
 
                case ORDER_TYPE_BITMAP_UNCOMPRESSED_V2:
                        update_read_cache_bitmap_v2_order(s, &(update->cache_bitmap_v2_order), False, extraFlags);
+                       IFCALL(update->BitmapDecompress, update, update->cache_bitmap_v2_order.bitmap_data);
                        IFCALL(update->CacheBitmapV2, update, &(update->cache_bitmap_v2_order));
                        break;
 
                case ORDER_TYPE_BITMAP_COMPRESSED_V2:
                        update_read_cache_bitmap_v2_order(s, &(update->cache_bitmap_v2_order), True, extraFlags);
+                       IFCALL(update->BitmapDecompress, update, update->cache_bitmap_v2_order.bitmap_data);
                        IFCALL(update->CacheBitmapV2, update, &(update->cache_bitmap_v2_order));
                        break;
 
index 6da06cd..89ed2b3 100644 (file)
 #define CBR2_24BPP                     0x5
 #define CBR2_32BPP                     0x6
 
-#define CBR2_HEIGHT_SAME_AS_WIDTH      0x01
-#define CBR2_PERSISTENT_KEY_PRESENT    0x02
-#define CBR2_NO_BITMAP_COMPRESSION_HDR 0x08
-#define CBR2_DO_NOT_CACHE              0x10
-
 #define CBR23_8BPP                     0x3
 #define CBR23_16BPP                    0x4
 #define CBR23_24BPP                    0x5
index ba66fed..5b690ff 100644 (file)
@@ -312,7 +312,7 @@ INLINE uint32 gdi_rop3_code(uint8 code)
 
 INLINE uint8* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, int x, int y)
 {
-       uint8 * p;
+       uint8* p;
        HGDI_BITMAP hBmp = (HGDI_BITMAP) hdcBmp->selectedObject;
        
        if (x >= 0 && x < hBmp->width && y >= 0 && y < hBmp->height)
@@ -626,7 +626,7 @@ void gdi_polyline(rdpUpdate* update, POLYLINE_ORDER* polyline)
        uint32 color;
        HGDI_PEN hPen;
        DELTA_POINT* points;
-       GDI *gdi = GET_GDI(update);
+       GDIgdi = GET_GDI(update);
 
        color = freerdp_color_convert(polyline->penColor, gdi->srcBpp, 32, gdi->clrconv);
        hPen = gdi_CreatePen(0, 1, (GDI_COLOR) color);
@@ -645,6 +645,25 @@ void gdi_polyline(rdpUpdate* update, POLYLINE_ORDER* polyline)
        gdi_DeleteObject((HGDIOBJECT) hPen);
 }
 
+void gdi_memblt(rdpUpdate* update, MEMBLT_ORDER* memblt)
+{
+       void* extra;
+       GDI_IMAGE* gdi_bmp;
+       GDI* gdi = GET_GDI(update);
+
+       bitmap_v2_get(gdi->cache->bitmap_v2, memblt->cacheId, memblt->cacheIndex, (void**) &extra);
+       gdi_bmp = (GDI_IMAGE*) extra;
+
+       gdi_BitBlt(gdi->drawing->hdc, memblt->nLeftRect, memblt->nTopRect,
+                       memblt->nWidth, memblt->nHeight, gdi_bmp->hdc,
+                       memblt->nXSrc, memblt->nYSrc, gdi_rop3_code(memblt->bRop));
+}
+
+void gdi_mem3blt(rdpUpdate* update, MEM3BLT_ORDER* mem3blt)
+{
+
+}
+
 void gdi_fast_index(rdpUpdate* update, FAST_INDEX_ORDER* fast_index)
 {
        int i, j;
@@ -772,10 +791,15 @@ void gdi_switch_surface(rdpUpdate* update, SWITCH_SURFACE_ORDER* switch_surface)
 
 void gdi_cache_bitmap_v2(rdpUpdate* update, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2)
 {
+       GDI_IMAGE* bitmap;
+       BITMAP_DATA* bitmap_data;
        GDI* gdi = GET_GDI(update);
 
+       bitmap_data = cache_bitmap_v2->bitmap_data;
+       bitmap = gdi_bitmap_new(gdi, bitmap_data->width, bitmap_data->height, gdi->dstBpp, bitmap_data->dstData);
+
        bitmap_v2_put(gdi->cache->bitmap_v2, cache_bitmap_v2->cacheId,
-                       cache_bitmap_v2->cacheIndex, cache_bitmap_v2->bitmapDataStream);
+               cache_bitmap_v2->cacheIndex, bitmap_data, (void*) bitmap);
 }
 
 void gdi_cache_color_table(rdpUpdate* update, CACHE_COLOR_TABLE_ORDER* cache_color_table)
@@ -900,7 +924,7 @@ void gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_comm
                gdi->image->bitmap->bitsPerPixel = surface_bits_command->bpp;
                gdi->image->bitmap->bytesPerPixel = gdi->image->bitmap->bitsPerPixel / 8;
                gdi->image->bitmap->data = (uint8*) xrealloc(gdi->image->bitmap->data, gdi->image->bitmap->width * gdi->image->bitmap->height * 4);
-               freerdp_image_invert(ncontext->bmpdata, gdi->image->bitmap->data, gdi->image->bitmap->width, gdi->image->bitmap->height, 32);
+               freerdp_image_flip(ncontext->bmpdata, gdi->image->bitmap->data, gdi->image->bitmap->width, gdi->image->bitmap->height, 32);
                gdi_BitBlt(gdi->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, gdi->image->hdc, 0, 0, GDI_SRCCOPY);
                nsc_context_destroy(ncontext);
        } 
@@ -926,13 +950,13 @@ void gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_comm
                        surface_bits_command->bitmapData = gdi->image->bitmap->data;
 
                        temp_image = (uint8*) xmalloc(gdi->image->bitmap->width * gdi->image->bitmap->height * 4);
-                       freerdp_image_invert(gdi->image->bitmap->data, temp_image, gdi->image->bitmap->width, gdi->image->bitmap->height, 32);
+                       freerdp_image_flip(gdi->image->bitmap->data, temp_image, gdi->image->bitmap->width, gdi->image->bitmap->height, 32);
                        xfree(gdi->image->bitmap->data);
                        gdi->image->bitmap->data = temp_image;
                }
                else
                {
-                       freerdp_image_invert(surface_bits_command->bitmapData, gdi->image->bitmap->data,
+                       freerdp_image_flip(surface_bits_command->bitmapData, gdi->image->bitmap->data,
                                        gdi->image->bitmap->width, gdi->image->bitmap->height, 32);
                }
 
@@ -967,11 +991,12 @@ void gdi_bitmap_decompress(rdpUpdate* update, BITMAP_DATA* bitmap_data)
        }
        else
        {
-               freerdp_image_invert(bitmap_data->srcData, bitmap_data->dstData,
+               freerdp_image_flip(bitmap_data->srcData, bitmap_data->dstData,
                                bitmap_data->width, bitmap_data->height, bitmap_data->bpp);
        }
 
        bitmap_data->compressed = False;
+       bitmap_data->length = bitmap_data->width * bitmap_data->height * (bitmap_data->bpp / 8);
 }
 
 /**
@@ -997,8 +1022,8 @@ void gdi_register_update_callbacks(rdpUpdate* update)
        update->MultiDrawNineGrid = NULL;
        update->LineTo = gdi_line_to;
        update->Polyline = NULL;
-       update->MemBlt = NULL;
-       update->Mem3Blt = NULL;
+       update->MemBlt = gdi_memblt;
+       update->Mem3Blt = gdi_mem3blt;
        update->SaveBitmap = NULL;
        update->GlyphIndex = NULL;
        update->FastIndex = gdi_fast_index;