2 * FreeRDP: A Remote Desktop Protocol Client
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 #include <freerdp/freerdp.h>
21 #include <freerdp/utils/stream.h>
22 #include <freerdp/utils/memory.h>
24 #include <freerdp/cache/bitmap.h>
26 void update_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
29 rdpCache* cache = context->cache;
31 if (memblt->cacheId == 0xFF)
32 bitmap = offscreen_cache_get(cache->offscreen, memblt->cacheIndex);
34 bitmap = bitmap_cache_get(cache->bitmap, (uint8) memblt->cacheId, memblt->cacheIndex);
36 memblt->bitmap = bitmap;
37 IFCALL(cache->bitmap->MemBlt, context, memblt);
40 void update_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
43 rdpCache* cache = context->cache;
45 if (mem3blt->cacheId == 0xFF)
46 bitmap = offscreen_cache_get(cache->offscreen, mem3blt->cacheIndex);
48 bitmap = bitmap_cache_get(cache->bitmap, (uint8) mem3blt->cacheId, mem3blt->cacheIndex);
50 mem3blt->bitmap = bitmap;
51 IFCALL(cache->bitmap->Mem3Blt, context, mem3blt);
54 void update_gdi_cache_bitmap(rdpContext* context, CACHE_BITMAP_ORDER* cache_bitmap)
57 rdpBitmap* prevBitmap;
58 rdpCache* cache = context->cache;
60 bitmap = Bitmap_Alloc(context);
62 Bitmap_SetDimensions(context, bitmap, cache_bitmap->bitmapWidth, cache_bitmap->bitmapHeight);
64 bitmap->Decompress(context, bitmap,
65 cache_bitmap->bitmapDataStream, cache_bitmap->bitmapWidth, cache_bitmap->bitmapHeight,
66 cache_bitmap->bitmapBpp, cache_bitmap->bitmapLength, cache_bitmap->compressed);
68 bitmap->New(context, bitmap);
70 prevBitmap = bitmap_cache_get(cache->bitmap, cache_bitmap->cacheId, cache_bitmap->cacheIndex);
72 if (prevBitmap != NULL)
73 Bitmap_Free(context, prevBitmap);
75 bitmap_cache_put(cache->bitmap, cache_bitmap->cacheId, cache_bitmap->cacheIndex, bitmap);
78 void update_gdi_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2)
81 rdpBitmap* prevBitmap;
82 rdpCache* cache = context->cache;
84 bitmap = Bitmap_Alloc(context);
86 Bitmap_SetDimensions(context, bitmap, cache_bitmap_v2->bitmapWidth, cache_bitmap_v2->bitmapHeight);
88 if (cache_bitmap_v2->bitmapBpp == 0)
90 /* Workaround for Windows 8 bug where bitmapBpp is not set */
91 cache_bitmap_v2->bitmapBpp = context->instance->settings->color_depth;
94 bitmap->Decompress(context, bitmap,
95 cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapWidth, cache_bitmap_v2->bitmapHeight,
96 cache_bitmap_v2->bitmapBpp, cache_bitmap_v2->bitmapLength, cache_bitmap_v2->compressed);
98 bitmap->New(context, bitmap);
100 prevBitmap = bitmap_cache_get(cache->bitmap, cache_bitmap_v2->cacheId, cache_bitmap_v2->cacheIndex);
102 if (prevBitmap != NULL)
103 Bitmap_Free(context, prevBitmap);
105 bitmap_cache_put(cache->bitmap, cache_bitmap_v2->cacheId, cache_bitmap_v2->cacheIndex, bitmap);
108 void update_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap_update)
112 BITMAP_DATA* bitmap_data;
113 boolean reused = true;
114 rdpCache* cache = context->cache;
116 if (cache->bitmap->bitmap == NULL)
118 cache->bitmap->bitmap = Bitmap_Alloc(context);
119 cache->bitmap->bitmap->ephemeral = true;
123 bitmap = cache->bitmap->bitmap;
125 for (i = 0; i < (int) bitmap_update->number; i++)
127 bitmap_data = &bitmap_update->rectangles[i];
129 bitmap->bpp = bitmap_data->bitsPerPixel;
130 bitmap->length = bitmap_data->bitmapLength;
131 bitmap->compressed = bitmap_data->compressed;
133 Bitmap_SetRectangle(context, bitmap,
134 bitmap_data->destLeft, bitmap_data->destTop,
135 bitmap_data->destRight, bitmap_data->destBottom);
137 Bitmap_SetDimensions(context, bitmap, bitmap_data->width, bitmap_data->height);
139 bitmap->Decompress(context, bitmap,
140 bitmap_data->bitmapDataStream, bitmap_data->width, bitmap_data->height,
141 bitmap_data->bitsPerPixel, bitmap_data->bitmapLength, bitmap_data->compressed);
144 bitmap->Free(context, bitmap);
148 bitmap->New(context, bitmap);
150 bitmap->Paint(context, bitmap);
154 rdpBitmap* bitmap_cache_get(rdpBitmapCache* bitmap_cache, uint32 id, uint32 index)
158 if (id > bitmap_cache->maxCells)
160 printf("get invalid bitmap cell id: %d\n", id);
164 if (index == BITMAP_CACHE_WAITING_LIST_INDEX)
165 index = bitmap_cache->cells[id].number - 1;
167 if (index > bitmap_cache->cells[id].number)
169 printf("get invalid bitmap index %d in cell id: %d\n", index, id);
173 bitmap = bitmap_cache->cells[id].entries[index];
178 void bitmap_cache_put(rdpBitmapCache* bitmap_cache, uint32 id, uint32 index, rdpBitmap* bitmap)
180 if (id > bitmap_cache->maxCells)
182 printf("put invalid bitmap cell id: %d\n", id);
186 if (index == BITMAP_CACHE_WAITING_LIST_INDEX)
187 index = bitmap_cache->cells[id].number - 1;
189 if (index > bitmap_cache->cells[id].number)
191 printf("put invalid bitmap index %d in cell id: %d\n", index, id);
195 bitmap_cache->cells[id].entries[index] = bitmap;
198 void bitmap_cache_register_callbacks(rdpUpdate* update)
200 rdpCache* cache = update->context->cache;
202 cache->bitmap->MemBlt = update->primary->MemBlt;
203 cache->bitmap->Mem3Blt = update->primary->Mem3Blt;
205 update->primary->MemBlt = update_gdi_memblt;
206 update->primary->Mem3Blt = update_gdi_mem3blt;
208 update->secondary->CacheBitmap = update_gdi_cache_bitmap;
209 update->secondary->CacheBitmapV2 = update_gdi_cache_bitmap_v2;
211 update->BitmapUpdate = update_gdi_bitmap_update;
214 rdpBitmapCache* bitmap_cache_new(rdpSettings* settings)
217 rdpBitmapCache* bitmap_cache;
219 bitmap_cache = (rdpBitmapCache*) xzalloc(sizeof(rdpBitmapCache));
221 if (bitmap_cache != NULL)
223 bitmap_cache->settings = settings;
224 bitmap_cache->update = ((freerdp*) settings->instance)->update;
225 bitmap_cache->context = bitmap_cache->update->context;
227 bitmap_cache->maxCells = 5;
229 settings->bitmap_cache = false;
230 settings->bitmapCacheV2NumCells = 5;
231 settings->bitmapCacheV2CellInfo[0].numEntries = 600;
232 settings->bitmapCacheV2CellInfo[0].persistent = false;
233 settings->bitmapCacheV2CellInfo[1].numEntries = 600;
234 settings->bitmapCacheV2CellInfo[1].persistent = false;
235 settings->bitmapCacheV2CellInfo[2].numEntries = 2048;
236 settings->bitmapCacheV2CellInfo[2].persistent = false;
237 settings->bitmapCacheV2CellInfo[3].numEntries = 4096;
238 settings->bitmapCacheV2CellInfo[3].persistent = false;
239 settings->bitmapCacheV2CellInfo[4].numEntries = 2048;
240 settings->bitmapCacheV2CellInfo[4].persistent = false;
242 bitmap_cache->cells = (BITMAP_V2_CELL*) xzalloc(sizeof(BITMAP_V2_CELL) * bitmap_cache->maxCells);
244 for (i = 0; i < (int) bitmap_cache->maxCells; i++)
246 bitmap_cache->cells[i].number = settings->bitmapCacheV2CellInfo[i].numEntries;
247 bitmap_cache->cells[i].entries = (rdpBitmap**) xzalloc(sizeof(rdpBitmap*) * bitmap_cache->cells[i].number);
254 void bitmap_cache_free(rdpBitmapCache* bitmap_cache)
259 if (bitmap_cache != NULL)
261 for (i = 0; i < (int) bitmap_cache->maxCells; i++)
263 for (j = 0; j < (int) bitmap_cache->cells[i].number; j++)
265 bitmap = bitmap_cache->cells[i].entries[j];
269 Bitmap_Free(bitmap_cache->context, bitmap);
273 xfree(bitmap_cache->cells[i].entries);
276 if (bitmap_cache->bitmap != NULL)
277 Bitmap_Free(bitmap_cache->context, bitmap_cache->bitmap);
279 xfree(bitmap_cache->cells);