PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/jni/FreeRDP/libfreerdp/cache/bitmap.c

https://bitbucket.org/starup/android-rdp
C | 330 lines | 234 code | 75 blank | 21 comment | 40 complexity | 2eacee6d39d175c3c4853f1927707b16 MD5 | raw file
  1. /**
  2. * FreeRDP: A Remote Desktop Protocol Implementation
  3. * Bitmap Cache V2
  4. *
  5. * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
  6. *
  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
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  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.
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include "config.h"
  21. #endif
  22. #include <stdio.h>
  23. #include <winpr/crt.h>
  24. #include <freerdp/freerdp.h>
  25. #include <freerdp/constants.h>
  26. #include <freerdp/utils/stream.h>
  27. #include <freerdp/cache/bitmap.h>
  28. void update_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
  29. {
  30. rdpBitmap* bitmap;
  31. rdpCache* cache = context->cache;
  32. if (memblt->cacheId == 0xFF)
  33. bitmap = offscreen_cache_get(cache->offscreen, memblt->cacheIndex);
  34. else
  35. bitmap = bitmap_cache_get(cache->bitmap, (BYTE) memblt->cacheId, memblt->cacheIndex);
  36. memblt->bitmap = bitmap;
  37. IFCALL(cache->bitmap->MemBlt, context, memblt);
  38. }
  39. void update_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
  40. {
  41. BYTE style;
  42. rdpBitmap* bitmap;
  43. rdpCache* cache = context->cache;
  44. rdpBrush* brush = &mem3blt->brush;
  45. if (mem3blt->cacheId == 0xFF)
  46. bitmap = offscreen_cache_get(cache->offscreen, mem3blt->cacheIndex);
  47. else
  48. bitmap = bitmap_cache_get(cache->bitmap, (BYTE) mem3blt->cacheId, mem3blt->cacheIndex);
  49. style = brush->style;
  50. if (brush->style & CACHED_BRUSH)
  51. {
  52. brush->data = brush_cache_get(cache->brush, brush->index, &brush->bpp);
  53. brush->style = 0x03;
  54. }
  55. mem3blt->bitmap = bitmap;
  56. IFCALL(cache->bitmap->Mem3Blt, context, mem3blt);
  57. brush->style = style;
  58. }
  59. void update_gdi_cache_bitmap(rdpContext* context, CACHE_BITMAP_ORDER* cache_bitmap)
  60. {
  61. rdpBitmap* bitmap;
  62. rdpBitmap* prevBitmap;
  63. rdpCache* cache = context->cache;
  64. bitmap = Bitmap_Alloc(context);
  65. Bitmap_SetDimensions(context, bitmap, cache_bitmap->bitmapWidth, cache_bitmap->bitmapHeight);
  66. bitmap->Decompress(context, bitmap,
  67. cache_bitmap->bitmapDataStream, cache_bitmap->bitmapWidth, cache_bitmap->bitmapHeight,
  68. cache_bitmap->bitmapBpp, cache_bitmap->bitmapLength,
  69. cache_bitmap->compressed, CODEC_ID_NONE);
  70. bitmap->New(context, bitmap);
  71. prevBitmap = bitmap_cache_get(cache->bitmap, cache_bitmap->cacheId, cache_bitmap->cacheIndex);
  72. if (prevBitmap != NULL)
  73. Bitmap_Free(context, prevBitmap);
  74. bitmap_cache_put(cache->bitmap, cache_bitmap->cacheId, cache_bitmap->cacheIndex, bitmap);
  75. }
  76. void update_gdi_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cache_bitmap_v2)
  77. {
  78. rdpBitmap* bitmap;
  79. rdpBitmap* prevBitmap;
  80. rdpCache* cache = context->cache;
  81. UINT32 codecID = CODEC_ID_NONE;
  82. bitmap = Bitmap_Alloc(context);
  83. Bitmap_SetDimensions(context, bitmap, cache_bitmap_v2->bitmapWidth, cache_bitmap_v2->bitmapHeight);
  84. if (cache_bitmap_v2->bitmapBpp == 0)
  85. {
  86. /* Workaround for Windows 8 bug where bitmapBpp is not set */
  87. cache_bitmap_v2->bitmapBpp = context->instance->settings->ColorDepth;
  88. }
  89. bitmap->Decompress(context, bitmap,
  90. cache_bitmap_v2->bitmapDataStream, cache_bitmap_v2->bitmapWidth, cache_bitmap_v2->bitmapHeight,
  91. cache_bitmap_v2->bitmapBpp, cache_bitmap_v2->bitmapLength,
  92. cache_bitmap_v2->compressed, codecID);
  93. bitmap->New(context, bitmap);
  94. prevBitmap = bitmap_cache_get(cache->bitmap, cache_bitmap_v2->cacheId, cache_bitmap_v2->cacheIndex);
  95. if (prevBitmap != NULL)
  96. Bitmap_Free(context, prevBitmap);
  97. bitmap_cache_put(cache->bitmap, cache_bitmap_v2->cacheId, cache_bitmap_v2->cacheIndex, bitmap);
  98. }
  99. void update_gdi_cache_bitmap_v3(rdpContext* context, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3)
  100. {
  101. rdpBitmap* bitmap;
  102. rdpBitmap* prevBitmap;
  103. rdpCache* cache = context->cache;
  104. BITMAP_DATA_EX* bitmapData = &cache_bitmap_v3->bitmapData;
  105. bitmap = Bitmap_Alloc(context);
  106. Bitmap_SetDimensions(context, bitmap, bitmapData->width, bitmapData->height);
  107. if (cache_bitmap_v3->bitmapData.bpp == 0)
  108. {
  109. /* Workaround for Windows 8 bug where bitmapBpp is not set */
  110. cache_bitmap_v3->bitmapData.bpp = context->instance->settings->ColorDepth;
  111. }
  112. bitmap->Decompress(context, bitmap,
  113. bitmapData->data, bitmap->width, bitmap->height,
  114. bitmapData->bpp, bitmapData->length, FALSE,
  115. bitmapData->codecID);
  116. bitmap->New(context, bitmap);
  117. prevBitmap = bitmap_cache_get(cache->bitmap, cache_bitmap_v3->cacheId, cache_bitmap_v3->cacheIndex);
  118. if (prevBitmap != NULL)
  119. Bitmap_Free(context, prevBitmap);
  120. bitmap_cache_put(cache->bitmap, cache_bitmap_v3->cacheId, cache_bitmap_v3->cacheIndex, bitmap);
  121. }
  122. void update_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap_update)
  123. {
  124. int i;
  125. rdpBitmap* bitmap;
  126. BITMAP_DATA* bitmap_data;
  127. BOOL reused = TRUE;
  128. rdpCache* cache = context->cache;
  129. if (cache->bitmap->bitmap == NULL)
  130. {
  131. cache->bitmap->bitmap = Bitmap_Alloc(context);
  132. cache->bitmap->bitmap->ephemeral = TRUE;
  133. reused = FALSE;
  134. }
  135. bitmap = cache->bitmap->bitmap;
  136. for (i = 0; i < (int) bitmap_update->number; i++)
  137. {
  138. bitmap_data = &bitmap_update->rectangles[i];
  139. bitmap->bpp = bitmap_data->bitsPerPixel;
  140. bitmap->length = bitmap_data->bitmapLength;
  141. bitmap->compressed = bitmap_data->compressed;
  142. Bitmap_SetRectangle(context, bitmap,
  143. bitmap_data->destLeft, bitmap_data->destTop,
  144. bitmap_data->destRight, bitmap_data->destBottom);
  145. Bitmap_SetDimensions(context, bitmap, bitmap_data->width, bitmap_data->height);
  146. bitmap->Decompress(context, bitmap,
  147. bitmap_data->bitmapDataStream, bitmap_data->width, bitmap_data->height,
  148. bitmap_data->bitsPerPixel, bitmap_data->bitmapLength,
  149. bitmap_data->compressed, CODEC_ID_NONE);
  150. if (reused)
  151. bitmap->Free(context, bitmap);
  152. else
  153. reused = TRUE;
  154. bitmap->New(context, bitmap);
  155. bitmap->Paint(context, bitmap);
  156. }
  157. }
  158. rdpBitmap* bitmap_cache_get(rdpBitmapCache* bitmap_cache, UINT32 id, UINT32 index)
  159. {
  160. rdpBitmap* bitmap;
  161. if (id > bitmap_cache->maxCells)
  162. {
  163. printf("get invalid bitmap cell id: %d\n", id);
  164. return NULL;
  165. }
  166. if (index == BITMAP_CACHE_WAITING_LIST_INDEX)
  167. {
  168. index = bitmap_cache->cells[id].number;
  169. }
  170. else if (index > bitmap_cache->cells[id].number)
  171. {
  172. printf("get invalid bitmap index %d in cell id: %d\n", index, id);
  173. return NULL;
  174. }
  175. bitmap = bitmap_cache->cells[id].entries[index];
  176. return bitmap;
  177. }
  178. void bitmap_cache_put(rdpBitmapCache* bitmap_cache, UINT32 id, UINT32 index, rdpBitmap* bitmap)
  179. {
  180. if (id > bitmap_cache->maxCells)
  181. {
  182. printf("put invalid bitmap cell id: %d\n", id);
  183. return;
  184. }
  185. if (index == BITMAP_CACHE_WAITING_LIST_INDEX)
  186. {
  187. index = bitmap_cache->cells[id].number;
  188. }
  189. else if (index > bitmap_cache->cells[id].number)
  190. {
  191. printf("put invalid bitmap index %d in cell id: %d\n", index, id);
  192. return;
  193. }
  194. bitmap_cache->cells[id].entries[index] = bitmap;
  195. }
  196. void bitmap_cache_register_callbacks(rdpUpdate* update)
  197. {
  198. rdpCache* cache = update->context->cache;
  199. cache->bitmap->MemBlt = update->primary->MemBlt;
  200. cache->bitmap->Mem3Blt = update->primary->Mem3Blt;
  201. update->primary->MemBlt = update_gdi_memblt;
  202. update->primary->Mem3Blt = update_gdi_mem3blt;
  203. update->secondary->CacheBitmap = update_gdi_cache_bitmap;
  204. update->secondary->CacheBitmapV2 = update_gdi_cache_bitmap_v2;
  205. update->secondary->CacheBitmapV3 = update_gdi_cache_bitmap_v3;
  206. update->BitmapUpdate = update_gdi_bitmap_update;
  207. }
  208. rdpBitmapCache* bitmap_cache_new(rdpSettings* settings)
  209. {
  210. int i;
  211. rdpBitmapCache* bitmap_cache;
  212. bitmap_cache = (rdpBitmapCache*) malloc(sizeof(rdpBitmapCache));
  213. ZeroMemory(bitmap_cache, sizeof(rdpBitmapCache));
  214. if (bitmap_cache != NULL)
  215. {
  216. bitmap_cache->settings = settings;
  217. bitmap_cache->update = ((freerdp*) settings->instance)->update;
  218. bitmap_cache->context = bitmap_cache->update->context;
  219. bitmap_cache->maxCells = settings->BitmapCacheV2NumCells;
  220. bitmap_cache->cells = (BITMAP_V2_CELL*) malloc(sizeof(BITMAP_V2_CELL) * bitmap_cache->maxCells);
  221. ZeroMemory(bitmap_cache->cells, sizeof(BITMAP_V2_CELL) * bitmap_cache->maxCells);
  222. for (i = 0; i < (int) bitmap_cache->maxCells; i++)
  223. {
  224. bitmap_cache->cells[i].number = settings->BitmapCacheV2CellInfo[i].numEntries;
  225. /* allocate an extra entry for BITMAP_CACHE_WAITING_LIST_INDEX */
  226. bitmap_cache->cells[i].entries = (rdpBitmap**) malloc(sizeof(rdpBitmap*) * (bitmap_cache->cells[i].number + 1));
  227. ZeroMemory(bitmap_cache->cells[i].entries, sizeof(rdpBitmap*) * (bitmap_cache->cells[i].number + 1));
  228. }
  229. }
  230. return bitmap_cache;
  231. }
  232. void bitmap_cache_free(rdpBitmapCache* bitmap_cache)
  233. {
  234. int i, j;
  235. rdpBitmap* bitmap;
  236. if (bitmap_cache != NULL)
  237. {
  238. for (i = 0; i < (int) bitmap_cache->maxCells; i++)
  239. {
  240. for (j = 0; j < (int) bitmap_cache->cells[i].number + 1; j++)
  241. {
  242. bitmap = bitmap_cache->cells[i].entries[j];
  243. if (bitmap != NULL)
  244. {
  245. Bitmap_Free(bitmap_cache->context, bitmap);
  246. }
  247. }
  248. free(bitmap_cache->cells[i].entries);
  249. }
  250. if (bitmap_cache->bitmap != NULL)
  251. Bitmap_Free(bitmap_cache->context, bitmap_cache->bitmap);
  252. free(bitmap_cache->cells);
  253. free(bitmap_cache);
  254. }
  255. }