From 809338d21349478554cff98c153f3fd921ef2995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 5 Aug 2011 16:56:40 -0400 Subject: [PATCH] libfreerdp-cache: added bitmap_v2 cache --- client/DirectFB/dfreerdp.c | 9 +- client/test/CMakeLists.txt | 1 + client/test/freerdp.c | 292 +++++++++++++++++++++++++++++++- include/freerdp/settings.h | 17 ++ libfreerdp-cache/CMakeLists.txt | 2 + libfreerdp-cache/bitmap_v2.c | 127 ++++++++++++++ libfreerdp-cache/bitmap_v2.h | 53 ++++++ libfreerdp-cache/cache.c | 2 + libfreerdp-cache/cache.h | 2 + libfreerdp-core/capabilities.c | 18 +- libfreerdp-core/settings.c | 6 +- libfreerdp-core/update.c | 15 +- libfreerdp-gdi/gdi.c | 23 ++- 13 files changed, 537 insertions(+), 30 deletions(-) create mode 100644 libfreerdp-cache/bitmap_v2.c create mode 100644 libfreerdp-cache/bitmap_v2.h diff --git a/client/DirectFB/dfreerdp.c b/client/DirectFB/dfreerdp.c index 387e32905..16ef15efe 100644 --- a/client/DirectFB/dfreerdp.c +++ b/client/DirectFB/dfreerdp.c @@ -56,10 +56,17 @@ void df_end_paint(rdpUpdate* update) if (gdi->primary->hdc->hwnd->invalid->null) return; +#if 1 dfi->update_rect.x = gdi->primary->hdc->hwnd->invalid->x; dfi->update_rect.y = gdi->primary->hdc->hwnd->invalid->y; dfi->update_rect.w = gdi->primary->hdc->hwnd->invalid->w; dfi->update_rect.h = gdi->primary->hdc->hwnd->invalid->h; +#else + dfi->update_rect.x = 0; + dfi->update_rect.y = 0; + dfi->update_rect.w = gdi->width; + dfi->update_rect.h = gdi->height; +#endif dfi->primary->Blit(dfi->primary, dfi->surface, &(dfi->update_rect), dfi->update_rect.x, dfi->update_rect.y); } @@ -115,7 +122,7 @@ boolean df_pre_connect(freerdp* instance) settings->order_support[NEG_POLYLINE_INDEX] = True; settings->order_support[NEG_MEMBLT_INDEX] = True; settings->order_support[NEG_MEM3BLT_INDEX] = False; - settings->order_support[NEG_SAVEBITMAP_INDEX] = False; + settings->order_support[NEG_SAVEBITMAP_INDEX] = True; settings->order_support[NEG_GLYPH_INDEX_INDEX] = True; settings->order_support[NEG_FAST_INDEX_INDEX] = True; settings->order_support[NEG_FAST_GLYPH_INDEX] = True; diff --git a/client/test/CMakeLists.txt b/client/test/CMakeLists.txt index 208930f26..ec412b938 100644 --- a/client/test/CMakeLists.txt +++ b/client/test/CMakeLists.txt @@ -27,3 +27,4 @@ add_executable(freerdp-test target_link_libraries(freerdp-test freerdp-core) target_link_libraries(freerdp-test freerdp-gdi) target_link_libraries(freerdp-test freerdp-utils) +target_link_libraries(freerdp-test freerdp-chanman) diff --git a/client/test/freerdp.c b/client/test/freerdp.c index 32f817d1c..6f8a4b80d 100644 --- a/client/test/freerdp.c +++ b/client/test/freerdp.c @@ -2,7 +2,7 @@ * FreeRDP: A Remote Desktop Protocol Client * FreeRDP Test UI * - * Copyright 2010 Marc-Andre Moreau + * Copyright 2011 Marc-Andre Moreau * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,26 +18,302 @@ */ #include "gdi.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SET_TFI(_instance, _tfi) (_instance)->param1 = _tfi +#define GET_TFI(_instance) ((tfInfo*) ((_instance)->param1)) + +#define SET_CHANMAN(_instance, _chanman) (_instance)->param2 = _chanman +#define GET_CHANMAN(_instance) ((rdpChanMan*) ((_instance)->param2)) + +struct tf_info +{ + +}; +typedef struct tf_info tfInfo; + +freerdp_sem g_sem; +static int g_thread_count = 0; + +struct thread_data +{ + freerdp* instance; +}; #include #include -freerdp* instance; -rdpSettings* settings; - -int main(int argc, char* argv[]) +void tf_begin_paint(rdpUpdate* update) { - instance = freerdp_new(); + GDI* gdi = GET_GDI(update); + gdi->primary->hdc->hwnd->invalid->null = 1; +} + +void tf_end_paint(rdpUpdate* update) +{ + GDI* gdi; + tfInfo* tfi; + + gdi = GET_GDI(update); + tfi = GET_TFI(update); + + if (gdi->primary->hdc->hwnd->invalid->null) + return; +} + +int tf_receive_channel_data(freerdp* instance, int channelId, uint8* data, int size, int flags, int total_size) +{ + return freerdp_chanman_data(instance, channelId, data, size, flags, total_size); +} + +int tf_process_plugin_args(rdpSettings* settings, const char* name, FRDP_PLUGIN_DATA* plugin_data, void* user_data) +{ + rdpChanMan* chanman = (rdpChanMan*) user_data; + + printf("Load plugin %s\n", name); + freerdp_chanman_load_plugin(chanman, settings, name, plugin_data); + + return 1; +} + +void tf_process_cb_sync_event(rdpChanMan* chanman, freerdp* instance) +{ + FRDP_EVENT* event; + FRDP_CB_FORMAT_LIST_EVENT* format_list_event; + + event = freerdp_event_new(FRDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); + + format_list_event = (FRDP_CB_FORMAT_LIST_EVENT*)event; + format_list_event->num_formats = 0; + + freerdp_chanman_send_event(chanman, "cliprdr", event); +} + +void tf_process_channel_event(rdpChanMan* chanman, freerdp* instance) +{ + FRDP_EVENT* event; + + event = freerdp_chanman_pop_event(chanman); + if (event) + { + switch (event->event_type) + { + case FRDP_EVENT_TYPE_CB_SYNC: + tf_process_cb_sync_event(chanman, instance); + break; + default: + printf("tf_process_channel_event: unknown event type %d\n", event->event_type); + break; + } + freerdp_event_free(event); + } +} + +boolean tf_pre_connect(freerdp* instance) +{ + tfInfo* tfi; + rdpSettings* settings; + + tfi = (tfInfo*) xzalloc(sizeof(tfInfo)); + SET_TFI(instance, tfi); settings = instance->settings; - freerdp_parse_args(settings, argc, argv, NULL, NULL, NULL, NULL); + settings->order_support[NEG_DSTBLT_INDEX] = True; + settings->order_support[NEG_PATBLT_INDEX] = True; + settings->order_support[NEG_SCRBLT_INDEX] = True; + settings->order_support[NEG_OPAQUE_RECT_INDEX] = True; + settings->order_support[NEG_DRAWNINEGRID_INDEX] = True; + settings->order_support[NEG_MULTIDSTBLT_INDEX] = True; + settings->order_support[NEG_MULTIPATBLT_INDEX] = True; + settings->order_support[NEG_MULTISCRBLT_INDEX] = True; + settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = True; + settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = True; + settings->order_support[NEG_LINETO_INDEX] = True; + settings->order_support[NEG_POLYLINE_INDEX] = True; + settings->order_support[NEG_MEMBLT_INDEX] = True; + settings->order_support[NEG_MEM3BLT_INDEX] = True; + settings->order_support[NEG_SAVEBITMAP_INDEX] = True; + settings->order_support[NEG_GLYPH_INDEX_INDEX] = True; + settings->order_support[NEG_FAST_INDEX_INDEX] = True; + settings->order_support[NEG_FAST_GLYPH_INDEX] = True; + settings->order_support[NEG_POLYGON_SC_INDEX] = True; + settings->order_support[NEG_POLYGON_CB_INDEX] = True; + settings->order_support[NEG_ELLIPSE_SC_INDEX] = True; + settings->order_support[NEG_ELLIPSE_CB_INDEX] = True; - gdi_init(instance, 0); + freerdp_chanman_pre_connect(GET_CHANMAN(instance), instance); + + return True; +} + +boolean tf_post_connect(freerdp* instance) +{ + GDI* gdi; + tfInfo* tfi; + + tfi = GET_TFI(instance); + SET_TFI(instance->update, tfi); + + gdi_init(instance, CLRCONV_ALPHA | CLRBUF_16BPP | CLRBUF_32BPP); + gdi = GET_GDI(instance->update); + + instance->update->BeginPaint = tf_begin_paint; + instance->update->EndPaint = tf_end_paint; + + freerdp_chanman_post_connect(GET_CHANMAN(instance), instance); + + return True; +} + +int tfreerdp_run(freerdp* instance) +{ + int i; + int fds; + int max_fds; + int rcount; + int wcount; + void* rfds[32]; + void* wfds[32]; + fd_set rfds_set; + fd_set wfds_set; + rdpChanMan* chanman; + + memset(rfds, 0, sizeof(rfds)); + memset(wfds, 0, sizeof(wfds)); + + chanman = GET_CHANMAN(instance); instance->Connect(instance); + while (1) + { + rcount = 0; + wcount = 0; + + if (instance->GetFileDescriptor(instance, rfds, &rcount, wfds, &wcount) != True) + { + printf("Failed to get FreeRDP file descriptor\n"); + break; + } + if (freerdp_chanman_get_fds(chanman, instance, rfds, &rcount, wfds, &wcount) != True) + { + printf("Failed to get channel manager file descriptor\n"); + break; + } + + max_fds = 0; + FD_ZERO(&rfds_set); + + for (i = 0; i < rcount; i++) + { + fds = (int)(long)(rfds[i]); + + if (fds > max_fds) + max_fds = fds; + + FD_SET(fds, &rfds_set); + } + + if (max_fds == 0) + break; + + if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1) + { + /* these are not really errors */ + if (!((errno == EAGAIN) || + (errno == EWOULDBLOCK) || + (errno == EINPROGRESS) || + (errno == EINTR))) /* signal occurred */ + { + printf("tfreerdp_run: select failed\n"); + break; + } + } + + if (instance->CheckFileDescriptor(instance) != True) + { + printf("Failed to check FreeRDP file descriptor\n"); + break; + } + if (freerdp_chanman_check_fds(chanman, instance) != True) + { + printf("Failed to check channel manager file descriptor\n"); + break; + } + tf_process_channel_event(chanman, instance); + } + + freerdp_chanman_close(chanman, instance); + freerdp_chanman_free(chanman); freerdp_free(instance); return 0; } + +void* thread_func(void* param) +{ + struct thread_data* data; + data = (struct thread_data*) param; + + tfreerdp_run(data->instance); + + xfree(data); + + pthread_detach(pthread_self()); + + g_thread_count--; + + if (g_thread_count < 1) + freerdp_sem_signal(&g_sem); + + return NULL; +} + +int main(int argc, char* argv[]) +{ + pthread_t thread; + freerdp* instance; + struct thread_data* data; + rdpChanMan* chanman; + + freerdp_chanman_global_init(); + + g_sem = freerdp_sem_new(1); + + instance = freerdp_new(); + instance->PreConnect = tf_pre_connect; + instance->PostConnect = tf_post_connect; + instance->ReceiveChannelData = tf_receive_channel_data; + + chanman = freerdp_chanman_new(); + SET_CHANMAN(instance, chanman); + + freerdp_parse_args(instance->settings, argc, argv, tf_process_plugin_args, chanman, NULL, NULL); + + data = (struct thread_data*) xzalloc(sizeof(struct thread_data)); + data->instance = instance; + + g_thread_count++; + pthread_create(&thread, 0, thread_func, data); + + while (g_thread_count > 0) + { + freerdp_sem_wait(g_sem); + } + + freerdp_chanman_global_uninit(); + + return 0; +} diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index aaec93caf..b79e200d4 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -133,6 +133,20 @@ struct rdp_ext_set void * data; /* plugin data */ }; +struct _BITMAP_CACHE_CELL_INFO +{ + uint16 numEntries; + uint16 maxSize; +}; +typedef struct _BITMAP_CACHE_CELL_INFO BITMAP_CACHE_CELL_INFO; + +struct _BITMAP_CACHE_V2_CELL_INFO +{ + uint32 numEntries; + boolean persistent; +}; +typedef struct _BITMAP_CACHE_V2_CELL_INFO BITMAP_CACHE_V2_CELL_INFO; + struct rdp_monitor { int x; @@ -227,6 +241,9 @@ struct rdp_settings boolean bitmap_cache; boolean persistent_bitmap_cache; + uint8 bitmapCacheV2NumCells; + BITMAP_CACHE_V2_CELL_INFO bitmapCacheV2CellInfo[6]; + uint32 vc_chunk_size; boolean draw_nine_grid; diff --git a/libfreerdp-cache/CMakeLists.txt b/libfreerdp-cache/CMakeLists.txt index 99f324007..fac9e0a78 100644 --- a/libfreerdp-cache/CMakeLists.txt +++ b/libfreerdp-cache/CMakeLists.txt @@ -20,6 +20,8 @@ set(FREERDP_CACHE_SRCS brush.c brush.h + bitmap_v2.c + bitmap_v2.h offscreen.c offscreen.h color_table.c diff --git a/libfreerdp-cache/bitmap_v2.c b/libfreerdp-cache/bitmap_v2.c new file mode 100644 index 000000000..f931ef75f --- /dev/null +++ b/libfreerdp-cache/bitmap_v2.c @@ -0,0 +1,127 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Bitmap Cache V2 + * + * Copyright 2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "bitmap_v2.h" + +void* bitmap_v2_get(rdpBitmapV2* bitmap_v2, uint8 id, uint16 index) +{ + void* entry; + + if (index > bitmap_v2->maxCells) + { + printf("invalid bitmap_v2 cell id: %d\n", id); + return NULL; + } + + if (index > bitmap_v2->cells[id].number) + { + printf("invalid bitmap_v2 index %d in cell id: %d\n", index, id); + return NULL; + } + + entry = bitmap_v2->cells[id].entries[index].entry; + + if (entry == NULL) + { + printf("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) +{ + if (id > bitmap_v2->maxCells) + { + printf("invalid bitmap_v2 cell id: %d\n", id); + return; + } + + if (index > bitmap_v2->cells[id].number) + { + printf("invalid bitmap_v2 index %d in cell id: %d\n", index, id); + return; + } + + bitmap_v2->cells[id].entries[index].entry = entry; +} + +rdpBitmapV2* bitmap_v2_new(rdpSettings* settings) +{ + int i; + rdpBitmapV2* bitmap_v2; + + bitmap_v2 = (rdpBitmapV2*) xzalloc(sizeof(rdpBitmapV2)); + + if (bitmap_v2 != NULL) + { + bitmap_v2->settings = settings; + + bitmap_v2->maxCells = 5; + + settings->bitmap_cache = True; + settings->bitmapCacheV2NumCells = 5; + settings->bitmapCacheV2CellInfo[0].numEntries = 600; + settings->bitmapCacheV2CellInfo[0].persistent = False; + settings->bitmapCacheV2CellInfo[1].numEntries = 600; + settings->bitmapCacheV2CellInfo[1].persistent = False; + settings->bitmapCacheV2CellInfo[2].numEntries = 2048; + settings->bitmapCacheV2CellInfo[2].persistent = False; + settings->bitmapCacheV2CellInfo[3].numEntries = 4096; + settings->bitmapCacheV2CellInfo[3].persistent = False; + settings->bitmapCacheV2CellInfo[4].numEntries = 2048; + settings->bitmapCacheV2CellInfo[4].persistent = False; + + bitmap_v2->cells = (BITMAP_V2_CELL*) xzalloc(sizeof(BITMAP_V2_CELL) * bitmap_v2->maxCells); + + for (i = 0; i < bitmap_v2->maxCells; i++) + { + bitmap_v2->cells[i].number = settings->bitmapCacheV2CellInfo[i].numEntries; + bitmap_v2->cells[i].entries = (BITMAP_V2_ENTRY*) xzalloc(sizeof(BITMAP_V2_ENTRY) * bitmap_v2->cells[i].number); + } + } + + return bitmap_v2; +} + +void bitmap_v2_free(rdpBitmapV2* bitmap_v2) +{ + int i, j; + + if (bitmap_v2 != NULL) + { + for (i = 0; i < bitmap_v2->maxCells; i++) + { + for (j = 0; j < bitmap_v2->cells[i].number; j++) + { + if (bitmap_v2->cells[i].entries[j].entry != NULL) + xfree(bitmap_v2->cells[i].entries[j].entry); + } + + xfree(bitmap_v2->cells[i].entries); + } + + xfree(bitmap_v2->cells); + xfree(bitmap_v2); + } +} diff --git a/libfreerdp-cache/bitmap_v2.h b/libfreerdp-cache/bitmap_v2.h new file mode 100644 index 000000000..32c651478 --- /dev/null +++ b/libfreerdp-cache/bitmap_v2.h @@ -0,0 +1,53 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Bitmap Cache V2 + * + * Copyright 2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __BITMAP_V2_CACHE_H +#define __BITMAP_V2_CACHE_H + +#include +#include + +struct _BITMAP_V2_ENTRY +{ + void* entry; +}; +typedef struct _BITMAP_V2_ENTRY BITMAP_V2_ENTRY; + +struct _BITMAP_V2_CELL +{ + uint32 number; + BITMAP_V2_ENTRY* entries; +}; +typedef struct _BITMAP_V2_CELL BITMAP_V2_CELL; + +struct rdp_bitmap_v2 +{ + uint8 maxCells; + rdpSettings* settings; + BITMAP_V2_CELL* cells; +}; +typedef struct rdp_bitmap_v2 rdpBitmapV2; + +void* bitmap_v2_get(rdpBitmapV2* bitmap_v2, uint8 id, uint16 index); +void bitmap_v2_put(rdpBitmapV2* bitmap_v2, uint8 id, uint16 index, void* entry); + +rdpBitmapV2* bitmap_v2_new(rdpSettings* settings); +void bitmap_v2_free(rdpBitmapV2* bitmap_v2); + +#endif /* __BITMAP_V2_CACHE_H */ diff --git a/libfreerdp-cache/cache.c b/libfreerdp-cache/cache.c index dac83d1b0..ac2baab1d 100644 --- a/libfreerdp-cache/cache.c +++ b/libfreerdp-cache/cache.c @@ -32,6 +32,7 @@ rdpCache* cache_new(rdpSettings* settings) { cache->settings = settings; cache->brush = brush_new(settings); + cache->bitmap_v2 = bitmap_v2_new(settings); cache->offscreen = offscreen_new(settings); cache->color_table = color_table_new(settings); } @@ -44,6 +45,7 @@ void cache_free(rdpCache* cache) if (cache != NULL) { brush_free(cache->brush); + bitmap_v2_free(cache->bitmap_v2); offscreen_free(cache->offscreen); color_table_free(cache->color_table); xfree(cache); diff --git a/libfreerdp-cache/cache.h b/libfreerdp-cache/cache.h index 04f8ca953..403e9f578 100644 --- a/libfreerdp-cache/cache.h +++ b/libfreerdp-cache/cache.h @@ -21,6 +21,7 @@ #define __CACHE_H #include "brush.h" +#include "bitmap_v2.h" #include "offscreen.h" #include "color_table.h" @@ -34,6 +35,7 @@ struct rdp_cache rdpSettings* settings; rdpBrush* brush; + rdpBitmapV2* bitmap_v2; rdpOffscreen* offscreen; rdpColorTable* color_table; }; diff --git a/libfreerdp-core/capabilities.c b/libfreerdp-core/capabilities.c index c7ccb85cf..09379e270 100644 --- a/libfreerdp-core/capabilities.c +++ b/libfreerdp-core/capabilities.c @@ -202,7 +202,7 @@ void rdp_write_bitmap_capability_set(STREAM* s, rdpSettings* settings) header = rdp_capability_set_start(s); - drawingFlags = 0; + drawingFlags = 1; if (settings->rdp_version > 5) preferredBitsPerPixel = settings->color_depth; @@ -280,10 +280,9 @@ void rdp_write_order_capability_set(STREAM* s, rdpSettings* settings) header = rdp_capability_set_start(s); - orderFlags = NEGOTIATE_ORDER_SUPPORT | + orderFlags = NEGOTIATE_ORDER_SUPPORT | ZERO_BOUNDS_DELTA_SUPPORT | - COLOR_INDEX_SUPPORT | - ORDER_FLAGS_EXTRA_SUPPORT; + COLOR_INDEX_SUPPORT; orderSupportExFlags = 0; @@ -1384,7 +1383,7 @@ void rdp_read_demand_active(STREAM* s, rdpSettings* settings) uint16 lengthSourceDescriptor; uint16 lengthCombinedCapabilities; - printf("Demand Active PDU\n"); + //printf("Demand Active PDU\n"); stream_read_uint32(s, settings->share_id); /* shareId (4 bytes) */ stream_read_uint16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */ @@ -1399,7 +1398,7 @@ void rdp_read_demand_active(STREAM* s, rdpSettings* settings) stream_get_mark(s, bm); rdp_read_capability_set_header(s, &length, &type); - printf("%s Capability Set (0x%02X), length:%d\n", CAPSET_TYPE_STRINGS[type], type, length); + //printf("%s Capability Set (0x%02X), length:%d\n", CAPSET_TYPE_STRINGS[type], type, length); settings->received_caps[type] = True; em = bm + length; @@ -1562,7 +1561,12 @@ void rdp_write_confirm_active(STREAM* s, rdpSettings* settings) rdp_write_general_capability_set(s, settings); rdp_write_bitmap_capability_set(s, settings); rdp_write_order_capability_set(s, settings); - rdp_write_bitmap_cache_capability_set(s, settings); + + if (settings->rdp_version >= 5) + rdp_write_bitmap_cache_v2_capability_set(s, settings); + else + rdp_write_bitmap_cache_capability_set(s, settings); + rdp_write_pointer_capability_set(s, settings); rdp_write_input_capability_set(s, settings); rdp_write_brush_capability_set(s, settings); diff --git a/libfreerdp-core/settings.c b/libfreerdp-core/settings.c index 027659769..2caa3b093 100644 --- a/libfreerdp-core/settings.c +++ b/libfreerdp-core/settings.c @@ -97,9 +97,9 @@ rdpSettings* settings_new() settings->bitmap_cache = True; settings->persistent_bitmap_cache = False; - settings->offscreen_bitmap_cache = False; - settings->offscreen_bitmap_cache_size = 0; - settings->offscreen_bitmap_cache_entries = 0; + settings->offscreen_bitmap_cache = True; + settings->offscreen_bitmap_cache_size = 7680; + settings->offscreen_bitmap_cache_entries = 100; settings->draw_nine_grid_cache_size = 2560; settings->draw_nine_grid_cache_entries = 256; diff --git a/libfreerdp-core/update.c b/libfreerdp-core/update.c index 166a57a8c..cab83610e 100644 --- a/libfreerdp-core/update.c +++ b/libfreerdp-core/update.c @@ -90,11 +90,19 @@ void update_read_bitmap_data(STREAM* s, BITMAP_DATA* bitmap_data) } else { + int y; + int offset; + int scanline; stream_get_mark(s, srcData); dstSize = bitmap_data->length; - stream_seek(s, bitmap_data->length); bitmap_data->data = (uint8*) xzalloc(dstSize); - memcpy(bitmap_data->data, srcData, 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); + } } } @@ -154,8 +162,7 @@ void update_recv(rdpUpdate* update, STREAM* s) stream_read_uint16(s, updateType); /* updateType (2 bytes) */ - if (updateType != UPDATE_TYPE_BITMAP) - printf("%s Update Data PDU\n", UPDATE_TYPE_STRINGS[updateType]); + printf("%s Update Data PDU\n", UPDATE_TYPE_STRINGS[updateType]); IFCALL(update->BeginPaint, update); diff --git a/libfreerdp-gdi/gdi.c b/libfreerdp-gdi/gdi.c index 6768f6f45..c16d3a2f4 100644 --- a/libfreerdp-gdi/gdi.c +++ b/libfreerdp-gdi/gdi.c @@ -454,8 +454,13 @@ void gdi_bitmap_update(rdpUpdate* update, BITMAP_UPDATE* bitmap) for (i = 0; i < bitmap->number; i++) { bmp = &bitmap->bitmaps[i]; + gdi_bmp = gdi_bitmap_new(gdi, bmp->width, bmp->height, gdi->dstBpp, bmp->data); - gdi_BitBlt(gdi->primary->hdc, bmp->left, bmp->top, bmp->width, bmp->height, gdi_bmp->hdc, 0, 0, GDI_SRCCOPY); + + gdi_BitBlt(gdi->primary->hdc, + bmp->left, bmp->top, bmp->right - bmp->left + 1, + bmp->bottom - bmp->top + 1, gdi_bmp->hdc, 0, 0, GDI_SRCCOPY); + gdi_bitmap_free((GDI_IMAGE*) gdi_bmp); } } @@ -584,7 +589,7 @@ void gdi_multi_opaque_rect(rdpUpdate* update, MULTI_OPAQUE_RECT_ORDER* multi_opa DELTA_RECT* rectangle; GDI *gdi = GET_GDI(update); - for (i = 0; i < multi_opaque_rect->numRectangles; i++) + for (i = 1; i < multi_opaque_rect->numRectangles + 1; i++) { rectangle = &multi_opaque_rect->rectangles[i]; @@ -649,9 +654,6 @@ void gdi_create_offscreen_bitmap(rdpUpdate* update, CREATE_OFFSCREEN_BITMAP_ORDE GDI_IMAGE* gdi_bmp; GDI* gdi = GET_GDI(update); - printf("create_offscreen_bitmap: id:%d cx:%d cy:%d\n", - create_offscreen_bitmap->id, create_offscreen_bitmap->cx, create_offscreen_bitmap->cy); - gdi_bmp = gdi_bitmap_new(gdi, create_offscreen_bitmap->cx, create_offscreen_bitmap->cy, gdi->dstBpp, NULL); offscreen_put(gdi->cache->offscreen, create_offscreen_bitmap->id, (void*) gdi_bmp); @@ -662,8 +664,6 @@ void gdi_switch_surface(rdpUpdate* update, SWITCH_SURFACE_ORDER* switch_surface) GDI_IMAGE* gdi_bmp; GDI* gdi = GET_GDI(update); - printf("switch surface: 0x%04X\n", switch_surface->bitmapId); - if (switch_surface->bitmapId == SCREEN_BITMAP_SURFACE) { gdi->drawing = (GDI_IMAGE*) gdi->primary; @@ -675,6 +675,14 @@ 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* gdi = GET_GDI(update); + + bitmap_v2_put(gdi->cache->bitmap_v2, cache_bitmap_v2->cacheId, + cache_bitmap_v2->cacheIndex, cache_bitmap_v2->bitmapDataStream); +} + void gdi_cache_color_table(rdpUpdate* update, CACHE_COLOR_TABLE_ORDER* cache_color_table) { GDI* gdi = GET_GDI(update); @@ -723,6 +731,7 @@ void gdi_register_update_callbacks(rdpUpdate* update) update->CreateOffscreenBitmap = gdi_create_offscreen_bitmap; update->SwitchSurface = gdi_switch_surface; + update->CacheBitmapV2 = gdi_cache_bitmap_v2; update->CacheColorTable = gdi_cache_color_table; update->CacheBrush = gdi_cache_brush; }