diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index 9396d317a..4a52e09b3 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "xf_gdi.h" @@ -271,7 +272,7 @@ void xf_gdi_bitmap_update(rdpUpdate* update, BITMAP_UPDATE* bitmap) { bmp = &bitmap->bitmaps[i]; - data = freerdp_image_convert(bmp->data, NULL, bmp->width, bmp->height, bmp->bpp, xfi->bpp, xfi->clrconv); + data = freerdp_image_convert(bmp->dstData, NULL, bmp->width, bmp->height, bmp->bpp, xfi->bpp, xfi->clrconv); image = XCreateImage(xfi->display, xfi->visual, xfi->depth, ZPixmap, 0, (char*) data, bmp->width, bmp->height, xfi->scanline_pad, 0); @@ -895,6 +896,32 @@ void xf_gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_c } } +void xf_gdi_bitmap_decompress(rdpUpdate* update, BITMAP_DATA* bitmap_data) +{ + uint16 dstSize; + + dstSize = bitmap_data->width * bitmap_data->height * (bitmap_data->bpp / 8); + + if (bitmap_data->dstData == NULL) + bitmap_data->dstData = (uint8*) xmalloc(dstSize); + else + bitmap_data->dstData = (uint8*) xrealloc(bitmap_data->dstData, dstSize); + + if (bitmap_data->compressed) + { + bitmap_decompress(bitmap_data->srcData, bitmap_data->dstData, + bitmap_data->width, bitmap_data->height, bitmap_data->length, + bitmap_data->bpp, bitmap_data->bpp); + } + else + { + freerdp_image_invert(bitmap_data->srcData, bitmap_data->dstData, + bitmap_data->width, bitmap_data->height, bitmap_data->bpp); + } + + bitmap_data->compressed = False; +} + void xf_gdi_register_update_callbacks(rdpUpdate* update) { update->Bitmap = xf_gdi_bitmap_update; @@ -932,5 +959,7 @@ void xf_gdi_register_update_callbacks(rdpUpdate* update) update->CacheBrush = xf_gdi_cache_brush; update->SurfaceBits = xf_gdi_surface_bits; + + update->BitmapDecompress = xf_gdi_bitmap_decompress; } diff --git a/include/freerdp/update.h b/include/freerdp/update.h index 85d531da1..e0f6ece4d 100644 --- a/include/freerdp/update.h +++ b/include/freerdp/update.h @@ -66,12 +66,15 @@ struct _BITMAP_DATA uint16 bpp; uint16 flags; uint16 length; - uint8* data; + uint8* srcData; + uint8* dstData; + boolean compressed; }; typedef struct _BITMAP_DATA BITMAP_DATA; struct _BITMAP_UPDATE { + uint16 count; uint16 number; BITMAP_DATA* bitmaps; }; @@ -1104,6 +1107,8 @@ typedef void (*pcNonMonitoredDesktop)(rdpUpdate* update, WINDOW_ORDER_INFO* orde typedef void (*pcSurfaceBits)(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_command); typedef void (*pcSurfaceCommand)(rdpUpdate* update, STREAM* s); +typedef void (*pcBitmapDecompress)(rdpUpdate* update, BITMAP_DATA* bitmap_data); + struct rdp_update { void* rdp; @@ -1189,6 +1194,8 @@ struct rdp_update pcSurfaceBits SurfaceBits; pcSurfaceCommand SurfaceCommand; + pcBitmapDecompress BitmapDecompress; + void* state_start; BITMAP_UPDATE bitmap_update; diff --git a/libfreerdp-core/update.c b/libfreerdp-core/update.c index 751b734c1..3d2acef41 100644 --- a/libfreerdp-core/update.c +++ b/libfreerdp-core/update.c @@ -29,17 +29,6 @@ uint8 UPDATE_TYPE_STRINGS[][32] = "Synchronize" }; -void update_free_bitmap(BITMAP_UPDATE* bitmap_update) -{ - int i; - - for (i = 0; i < bitmap_update->number; i++) - { - xfree(bitmap_update->bitmaps[i].data); - } - xfree(bitmap_update->bitmaps); -} - void update_recv_orders(rdpUpdate* update, STREAM* s) { uint16 numberOrders; @@ -48,8 +37,6 @@ void update_recv_orders(rdpUpdate* update, STREAM* s) stream_read_uint16(s, numberOrders); /* numberOrders (2 bytes) */ stream_seek_uint16(s); /* pad2OctetsB (2 bytes) */ - printf("numberOrders:%d\n", numberOrders); - while (numberOrders > 0) { update_recv_order(update, s); @@ -59,9 +46,6 @@ void update_recv_orders(rdpUpdate* update, STREAM* s) void update_read_bitmap_data(STREAM* s, BITMAP_DATA* bitmap_data) { - uint8* srcData; - uint16 dstSize; - boolean status; uint16 bytesPerPixel; stream_read_uint16(s, bitmap_data->left); @@ -86,34 +70,17 @@ void update_read_bitmap_data(STREAM* s, BITMAP_DATA* bitmap_data) stream_seek_uint16(s); /* cbScanWidth (2 bytes) */ stream_read_uint16(s, cbUncompressedSize); /* cbUncompressedSize (2 bytes) */ - dstSize = cbUncompressedSize; bitmap_data->length = cbCompMainBodySize; - bitmap_data->data = (uint8*) xmalloc(dstSize); - stream_get_mark(s, srcData); + bitmap_data->compressed = True; + stream_get_mark(s, bitmap_data->srcData); stream_seek(s, bitmap_data->length); - - status = bitmap_decompress(srcData, bitmap_data->data, bitmap_data->width, bitmap_data->height, - bitmap_data->length, bitmap_data->bpp, bitmap_data->bpp); - - if (status != True) - printf("bitmap decompression failed, bpp:%d\n", bitmap_data->bpp); } else { - int y; - int offset; - int scanline; - stream_get_mark(s, srcData); - dstSize = bitmap_data->length; - bitmap_data->data = (uint8*) xzalloc(dstSize); - scanline = bitmap_data->width * (bitmap_data->bpp / 8); - - for (y = 0; y < bitmap_data->height; y++) - { - offset = (bitmap_data->height - y - 1) * scanline; - stream_read(s, &bitmap_data->data[offset], scanline); - } + bitmap_data->compressed = False; + stream_get_mark(s, bitmap_data->srcData); + stream_seek(s, bitmap_data->length); } } @@ -121,15 +88,28 @@ void update_read_bitmap(rdpUpdate* update, STREAM* s, BITMAP_UPDATE* bitmap_upda { int i; - update_free_bitmap(bitmap_update); stream_read_uint16(s, bitmap_update->number); /* numberRectangles (2 bytes) */ - bitmap_update->bitmaps = (BITMAP_DATA*) xzalloc(sizeof(BITMAP_DATA) * bitmap_update->number); + if (bitmap_update->number > bitmap_update->count) + { + uint16 count; + + count = bitmap_update->number * 2; + + bitmap_update->bitmaps = (BITMAP_DATA*) xrealloc(bitmap_update->bitmaps, + sizeof(BITMAP_DATA) * count); + + memset(&bitmap_update->bitmaps[bitmap_update->count], 0, + sizeof(BITMAP_DATA) * (count - bitmap_update->count)); + + bitmap_update->count = count; + } /* rectangles */ for (i = 0; i < bitmap_update->number; i++) { update_read_bitmap_data(s, &bitmap_update->bitmaps[i]); + IFCALL(update->BitmapDecompress, update, &bitmap_update->bitmaps[i]); } } @@ -325,6 +305,11 @@ void update_recv(rdpUpdate* update, STREAM* s) void update_reset_state(rdpUpdate* update) { int length; + uint16 bitmap_count; + BITMAP_DATA* bitmaps; + + bitmaps = update->bitmap_update.bitmaps; + bitmap_count = update->bitmap_update.count; length = &update->state_end - &update->state_start; @@ -332,6 +317,9 @@ void update_reset_state(rdpUpdate* update) update->order_info.orderType = ORDER_TYPE_PATBLT; update->switch_surface.bitmapId = SCREEN_BITMAP_SURFACE; IFCALL(update->SwitchSurface, update, &(update->switch_surface)); + + update->bitmap_update.bitmaps = bitmaps; + update->bitmap_update.count = bitmap_count; } static void update_begin_paint(rdpUpdate* update) @@ -408,6 +396,9 @@ rdpUpdate* update_new(rdpRdp* rdp) if (update != NULL) { update->rdp = (void*) rdp; + + update->bitmap_update.count = 64; + update->bitmap_update.bitmaps = (BITMAP_DATA*) xzalloc(sizeof(BITMAP_DATA) * update->bitmap_update.count); } return update; @@ -415,10 +406,21 @@ rdpUpdate* update_new(rdpRdp* rdp) void update_free(rdpUpdate* update) { - update_free_bitmap(&update->bitmap_update); - if (update != NULL) { + uint16 i; + BITMAP_DATA* bitmaps; + BITMAP_UPDATE* bitmap_update; + + bitmap_update = &update->bitmap_update; + bitmaps = update->bitmap_update.bitmaps; + + for (i = 0; i < bitmap_update->count; i++) + { + if (bitmaps[i].dstData != NULL) + xfree(bitmaps[i].dstData); + } + xfree(update); } } diff --git a/libfreerdp-gdi/gdi.c b/libfreerdp-gdi/gdi.c index 0cf48df3e..d11b7df93 100644 --- a/libfreerdp-gdi/gdi.c +++ b/libfreerdp-gdi/gdi.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -452,7 +453,7 @@ void gdi_bitmap_update(rdpUpdate* update, BITMAP_UPDATE* bitmap) { bmp = &bitmap->bitmaps[i]; - gdi_bmp = gdi_bitmap_new(gdi, bmp->width, bmp->height, gdi->dstBpp, bmp->data); + gdi_bmp = gdi_bitmap_new(gdi, bmp->width, bmp->height, gdi->dstBpp, bmp->dstData); gdi_BitBlt(gdi->primary->hdc, bmp->left, bmp->top, bmp->right - bmp->left + 1, @@ -944,6 +945,32 @@ void gdi_surface_bits(rdpUpdate* update, SURFACE_BITS_COMMAND* surface_bits_comm xfree(tile_bitmap); } +void gdi_bitmap_decompress(rdpUpdate* update, BITMAP_DATA* bitmap_data) +{ + uint16 dstSize; + + dstSize = bitmap_data->width * bitmap_data->height * (bitmap_data->bpp / 8); + + if (bitmap_data->dstData == NULL) + bitmap_data->dstData = (uint8*) xmalloc(dstSize); + else + bitmap_data->dstData = (uint8*) xrealloc(bitmap_data->dstData, dstSize); + + if (bitmap_data->compressed) + { + bitmap_decompress(bitmap_data->srcData, bitmap_data->dstData, + bitmap_data->width, bitmap_data->height, bitmap_data->length, + bitmap_data->bpp, bitmap_data->bpp); + } + else + { + freerdp_image_invert(bitmap_data->srcData, bitmap_data->dstData, + bitmap_data->width, bitmap_data->height, bitmap_data->bpp); + } + + bitmap_data->compressed = False; +} + /** * Register GDI callbacks with libfreerdp-core. * @param inst current instance @@ -987,6 +1014,7 @@ void gdi_register_update_callbacks(rdpUpdate* update) update->CacheBrush = gdi_cache_brush; update->SurfaceBits = gdi_surface_bits; + update->BitmapDecompress = gdi_bitmap_decompress; } void gdi_init_primary(GDI* gdi)