20 #include <freerdp/config.h>
24 #include <winpr/crt.h>
25 #include <winpr/assert.h>
26 #include <winpr/stream.h>
28 #include <freerdp/log.h>
33 #define TAG FREERDP_TAG("cache.pointer")
35 static BOOL pointer_cache_put(rdpPointerCache* pointer_cache, UINT32 index, rdpPointer* pointer,
37 static rdpPointer* pointer_cache_get(rdpPointerCache* pointer_cache, UINT32 index);
39 static void pointer_clear(rdpPointer* pointer)
43 pointer->lengthAndMask = 0;
44 free(pointer->andMaskData);
45 pointer->andMaskData = NULL;
47 pointer->lengthXorMask = 0;
48 free(pointer->xorMaskData);
49 pointer->xorMaskData = NULL;
53 static void pointer_free(rdpContext* context, rdpPointer* pointer)
57 IFCALL(pointer->Free, context, pointer);
58 pointer_clear(pointer);
63 static BOOL update_pointer_position(rdpContext* context,
66 if (!context || !context->graphics || !context->graphics->Pointer_Prototype ||
74 const rdpPointer* pointer = context->graphics->Pointer_Prototype;
75 WINPR_ASSERT(pointer);
77 return IFCALLRESULT(TRUE, pointer->SetPosition, context, pointer_position->xPos,
78 pointer_position->yPos);
83 rdpPointer* pointer = NULL;
85 if (!context || !context->graphics || !context->graphics->Pointer_Prototype || !pointer_system)
88 pointer = context->graphics->Pointer_Prototype;
90 switch (pointer_system->type)
93 return IFCALLRESULT(TRUE, pointer->SetNull, context);
96 return IFCALLRESULT(TRUE, pointer->SetDefault, context);
99 WLog_ERR(TAG,
"Unknown system pointer type (0x%08" PRIX32
")", pointer_system->type);
104 static BOOL upate_pointer_copy_andxor(rdpPointer* pointer,
const BYTE* andMaskData,
105 size_t lengthAndMask,
const BYTE* xorMaskData,
106 size_t lengthXorMask)
108 WINPR_ASSERT(pointer);
110 pointer_clear(pointer);
111 if (lengthAndMask && andMaskData)
113 if (lengthAndMask > UINT32_MAX)
115 pointer->lengthAndMask = (UINT32)lengthAndMask;
116 pointer->andMaskData = (BYTE*)malloc(lengthAndMask);
117 if (!pointer->andMaskData)
120 CopyMemory(pointer->andMaskData, andMaskData, lengthAndMask);
123 if (lengthXorMask && xorMaskData)
125 if (lengthXorMask > UINT32_MAX)
127 pointer->lengthXorMask = (UINT32)lengthXorMask;
128 pointer->xorMaskData = (BYTE*)malloc(lengthXorMask);
129 if (!pointer->xorMaskData)
132 CopyMemory(pointer->xorMaskData, xorMaskData, lengthXorMask);
138 static BOOL update_pointer_color(rdpContext* context,
const POINTER_COLOR_UPDATE* pointer_color)
140 rdpPointer* pointer = NULL;
141 rdpCache* cache = NULL;
143 WINPR_ASSERT(context);
144 WINPR_ASSERT(pointer_color);
146 cache = context->cache;
149 pointer = Pointer_Alloc(context);
153 pointer->xorBpp = 24;
154 pointer->xPos = pointer_color->hotSpotX;
155 pointer->yPos = pointer_color->hotSpotY;
156 pointer->width = pointer_color->width;
157 pointer->height = pointer_color->height;
159 if (!upate_pointer_copy_andxor(pointer, pointer_color->andMaskData,
160 pointer_color->lengthAndMask, pointer_color->xorMaskData,
161 pointer_color->lengthXorMask))
164 if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
167 if (!pointer_cache_put(cache->pointer, pointer_color->cacheIndex, pointer, TRUE))
170 return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
173 pointer_free(context, pointer);
177 static BOOL update_pointer_large(rdpContext* context,
const POINTER_LARGE_UPDATE* pointer_large)
179 rdpPointer* pointer = NULL;
180 rdpCache* cache = NULL;
182 WINPR_ASSERT(context);
183 WINPR_ASSERT(pointer_large);
185 cache = context->cache;
188 pointer = Pointer_Alloc(context);
191 pointer->xorBpp = pointer_large->xorBpp;
192 pointer->xPos = pointer_large->hotSpotX;
193 pointer->yPos = pointer_large->hotSpotY;
194 pointer->width = pointer_large->width;
195 pointer->height = pointer_large->height;
197 if (!upate_pointer_copy_andxor(pointer, pointer_large->andMaskData,
198 pointer_large->lengthAndMask, pointer_large->xorMaskData,
199 pointer_large->lengthXorMask))
202 if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
205 if (!pointer_cache_put(cache->pointer, pointer_large->cacheIndex, pointer, FALSE))
208 return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
211 pointer_free(context, pointer);
215 static BOOL update_pointer_new(rdpContext* context,
const POINTER_NEW_UPDATE* pointer_new)
217 if (!context || !pointer_new)
220 rdpCache* cache = context->cache;
221 rdpPointer* pointer = Pointer_Alloc(context);
226 pointer->xorBpp = pointer_new->xorBpp;
227 pointer->xPos = pointer_new->colorPtrAttr.hotSpotX;
228 pointer->yPos = pointer_new->colorPtrAttr.hotSpotY;
229 pointer->width = pointer_new->colorPtrAttr.width;
230 pointer->height = pointer_new->colorPtrAttr.height;
231 if (!upate_pointer_copy_andxor(
232 pointer, pointer_new->colorPtrAttr.andMaskData, pointer_new->colorPtrAttr.lengthAndMask,
233 pointer_new->colorPtrAttr.xorMaskData, pointer_new->colorPtrAttr.lengthXorMask))
236 if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
239 if (!pointer_cache_put(cache->pointer, pointer_new->colorPtrAttr.cacheIndex, pointer, FALSE))
242 return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
245 pointer_free(context, pointer);
251 rdpPointer* pointer = NULL;
252 rdpCache* cache = NULL;
254 WINPR_ASSERT(context);
255 WINPR_ASSERT(pointer_cached);
257 cache = context->cache;
260 pointer = pointer_cache_get(cache->pointer, pointer_cached->cacheIndex);
263 return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
268 rdpPointer* pointer_cache_get(rdpPointerCache* pointer_cache, UINT32 index)
270 rdpPointer* pointer = NULL;
272 WINPR_ASSERT(pointer_cache);
274 if (index >= pointer_cache->cacheSize)
276 WLog_ERR(TAG,
"invalid pointer index:%" PRIu32
" [%" PRIu32
"]", index,
277 pointer_cache->cacheSize);
281 WINPR_ASSERT(pointer_cache->entries);
282 pointer = pointer_cache->entries[index];
286 BOOL pointer_cache_put(rdpPointerCache* pointer_cache, UINT32 index, rdpPointer* pointer,
289 rdpPointer* prevPointer = NULL;
290 const FreeRDP_Settings_Keys_UInt32
id =
291 colorCache ? FreeRDP_ColorPointerCacheSize : FreeRDP_PointerCacheSize;
293 WINPR_ASSERT(pointer_cache);
294 WINPR_ASSERT(pointer_cache->context);
297 if (index >= pointer_cache->cacheSize)
300 "invalid pointer index:%" PRIu32
" [allocated %" PRIu32
", %s size %" PRIu32
"]",
301 index, pointer_cache->cacheSize,
302 colorCache ?
"color-pointer-cache" :
"pointer-cache", size);
308 "suspicious pointer index:%" PRIu32
" [allocated %" PRIu32
", %s size %" PRIu32
310 index, pointer_cache->cacheSize,
311 colorCache ?
"color-pointer-cache" :
"pointer-cache", size);
314 WINPR_ASSERT(pointer_cache->entries);
315 prevPointer = pointer_cache->entries[index];
316 pointer_free(pointer_cache->context, prevPointer);
317 pointer_cache->entries[index] = pointer;
321 void pointer_cache_register_callbacks(rdpUpdate* update)
323 rdpPointerUpdate* pointer = NULL;
325 WINPR_ASSERT(update);
326 WINPR_ASSERT(update->context);
328 pointer = update->pointer;
329 WINPR_ASSERT(pointer);
333 pointer->PointerPosition = update_pointer_position;
334 pointer->PointerSystem = update_pointer_system;
335 pointer->PointerColor = update_pointer_color;
336 pointer->PointerLarge = update_pointer_large;
337 pointer->PointerNew = update_pointer_new;
338 pointer->PointerCached = update_pointer_cached;
342 rdpPointerCache* pointer_cache_new(rdpContext* context)
344 rdpPointerCache* pointer_cache = NULL;
345 rdpSettings* settings = NULL;
347 WINPR_ASSERT(context);
349 settings = context->settings;
350 WINPR_ASSERT(settings);
352 pointer_cache = (rdpPointerCache*)calloc(1,
sizeof(rdpPointerCache));
357 pointer_cache->context = context;
363 pointer_cache->cacheSize = MAX(size, colorSize) + 1;
365 pointer_cache->entries = (rdpPointer**)calloc(pointer_cache->cacheSize,
sizeof(rdpPointer*));
367 if (!pointer_cache->entries)
373 return pointer_cache;
376 void pointer_cache_free(rdpPointerCache* pointer_cache)
378 if (pointer_cache != NULL)
380 if (pointer_cache->entries)
382 for (UINT32 i = 0; i < pointer_cache->cacheSize; i++)
384 rdpPointer* pointer = pointer_cache->entries[i];
385 pointer_free(pointer_cache->context, pointer);
389 free(pointer_cache->entries);
404 if (src->lengthAndMask > 0)
406 dst->andMaskData = calloc(src->lengthAndMask,
sizeof(BYTE));
408 if (!dst->andMaskData)
411 memcpy(dst->andMaskData, src->andMaskData, src->lengthAndMask);
414 if (src->lengthXorMask > 0)
416 dst->xorMaskData = calloc(src->lengthXorMask,
sizeof(BYTE));
418 if (!dst->xorMaskData)
421 memcpy(dst->xorMaskData, src->xorMaskData, src->lengthXorMask);
426 free_pointer_color_update(context, dst);
432 WINPR_UNUSED(context);
437 free(pointer->xorMaskData);
438 free(pointer->andMaskData);
452 if (src->lengthAndMask > 0)
454 dst->andMaskData = calloc(src->lengthAndMask,
sizeof(BYTE));
456 if (!dst->andMaskData)
459 memcpy(dst->andMaskData, src->andMaskData, src->lengthAndMask);
462 if (src->lengthXorMask > 0)
464 dst->xorMaskData = calloc(src->lengthXorMask,
sizeof(BYTE));
466 if (!dst->xorMaskData)
469 memcpy(dst->xorMaskData, src->xorMaskData, src->lengthXorMask);
474 free_pointer_large_update(context, dst);
480 WINPR_UNUSED(context);
484 free(pointer->xorMaskData);
485 free(pointer->andMaskData);
498 if (src->colorPtrAttr.lengthAndMask > 0)
500 dst->colorPtrAttr.andMaskData = calloc(src->colorPtrAttr.lengthAndMask,
sizeof(BYTE));
502 if (!dst->colorPtrAttr.andMaskData)
505 memcpy(dst->colorPtrAttr.andMaskData, src->colorPtrAttr.andMaskData,
506 src->colorPtrAttr.lengthAndMask);
509 if (src->colorPtrAttr.lengthXorMask > 0)
511 dst->colorPtrAttr.xorMaskData = calloc(src->colorPtrAttr.lengthXorMask,
sizeof(BYTE));
513 if (!dst->colorPtrAttr.xorMaskData)
516 memcpy(dst->colorPtrAttr.xorMaskData, src->colorPtrAttr.xorMaskData,
517 src->colorPtrAttr.lengthXorMask);
522 free_pointer_new_update(context, dst);
531 free(pointer->colorPtrAttr.xorMaskData);
532 free(pointer->colorPtrAttr.andMaskData);
547 free_pointer_cached_update(context, dst);
553 WINPR_UNUSED(context);
559 WINPR_UNUSED(context);
568 if (!dst || !pointer)
574 free_pointer_position_update(context, dst);
580 WINPR_UNUSED(context);
589 if (!dst || !pointer)
595 free_pointer_system_update(context, dst);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.