20#include <freerdp/config.h>
25#include <winpr/assert.h>
26#include <winpr/stream.h>
28#include <freerdp/log.h>
33#define TAG FREERDP_TAG("cache.pointer")
36static const char* pointerType(
bool colorCache)
39 return colorCache ?
"ColorPointerCache" :
"PointerCache";
43static BOOL pointer_cache_put(rdpPointerCache* pointer_cache, UINT32 index, rdpPointer* pointer,
47static rdpPointer* pointer_cache_get(rdpPointerCache* pointer_cache, UINT32 index);
49static void pointer_clear(rdpPointer* pointer)
53 pointer->lengthAndMask = 0;
54 free(pointer->andMaskData);
55 pointer->andMaskData =
nullptr;
57 pointer->lengthXorMask = 0;
58 free(pointer->xorMaskData);
59 pointer->xorMaskData =
nullptr;
63static void pointer_free(rdpContext* context, rdpPointer* pointer)
67 IFCALL(pointer->Free, context, pointer);
68 pointer_clear(pointer);
74static BOOL update_pointer_position(rdpContext* context,
77 if (!context || !context->graphics || !context->graphics->Pointer_Prototype ||
85 const rdpPointer* pointer = context->graphics->Pointer_Prototype;
86 WINPR_ASSERT(pointer);
88 return IFCALLRESULT(TRUE, pointer->SetPosition, context, pointer_position->xPos,
89 pointer_position->yPos);
95 if (!context || !context->graphics || !context->graphics->Pointer_Prototype || !pointer_system)
98 rdpPointer* pointer = context->graphics->Pointer_Prototype;
100 switch (pointer_system->type)
103 return IFCALLRESULT(TRUE, pointer->SetNull, context);
106 return IFCALLRESULT(TRUE, pointer->SetDefault, context);
109 WLog_ERR(TAG,
"Unknown system pointer type (0x%08" PRIX32
")", pointer_system->type);
115static BOOL update_pointer_copy_andxor(rdpPointer* pointer,
const BYTE* andMaskData,
116 size_t lengthAndMask,
const BYTE* xorMaskData,
117 size_t lengthXorMask)
119 WINPR_ASSERT(pointer);
121 pointer_clear(pointer);
122 if (lengthAndMask && andMaskData)
124 if (lengthAndMask > UINT32_MAX)
126 pointer->lengthAndMask = (UINT32)lengthAndMask;
127 pointer->andMaskData = (BYTE*)malloc(lengthAndMask);
128 if (!pointer->andMaskData)
131 CopyMemory(pointer->andMaskData, andMaskData, lengthAndMask);
134 if (lengthXorMask && xorMaskData)
136 if (lengthXorMask > UINT32_MAX)
138 pointer->lengthXorMask = (UINT32)lengthXorMask;
139 pointer->xorMaskData = (BYTE*)malloc(lengthXorMask);
140 if (!pointer->xorMaskData)
143 CopyMemory(pointer->xorMaskData, xorMaskData, lengthXorMask);
152 WINPR_ASSERT(context);
153 WINPR_ASSERT(pointer_color);
155 rdpCache* cache = context->cache;
158 rdpPointer* pointer = Pointer_Alloc(context);
160 if (pointer ==
nullptr)
162 pointer->xorBpp = 24;
163 pointer->xPos = pointer_color->hotSpotX;
164 pointer->yPos = pointer_color->hotSpotY;
165 pointer->width = pointer_color->width;
166 pointer->height = pointer_color->height;
168 if (!update_pointer_copy_andxor(pointer, pointer_color->andMaskData,
169 pointer_color->lengthAndMask, pointer_color->xorMaskData,
170 pointer_color->lengthXorMask))
173 if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
176 if (!pointer_cache_put(cache->pointer, pointer_color->cacheIndex, pointer, TRUE))
179 return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
182 pointer_free(context, pointer);
189 WINPR_ASSERT(context);
190 WINPR_ASSERT(pointer_large);
192 rdpCache* cache = context->cache;
195 rdpPointer* pointer = Pointer_Alloc(context);
196 if (pointer ==
nullptr)
198 pointer->xorBpp = pointer_large->xorBpp;
199 pointer->xPos = pointer_large->hotSpotX;
200 pointer->yPos = pointer_large->hotSpotY;
201 pointer->width = pointer_large->width;
202 pointer->height = pointer_large->height;
204 if (!update_pointer_copy_andxor(pointer, pointer_large->andMaskData,
205 pointer_large->lengthAndMask, pointer_large->xorMaskData,
206 pointer_large->lengthXorMask))
209 if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
212 if (!pointer_cache_put(cache->pointer, pointer_large->cacheIndex, pointer, FALSE))
215 return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
218 pointer_free(context, pointer);
223static BOOL update_pointer_new(rdpContext* context,
const POINTER_NEW_UPDATE* pointer_new)
225 if (!context || !pointer_new)
228 rdpCache* cache = context->cache;
229 rdpPointer* pointer = Pointer_Alloc(context);
234 pointer->xorBpp = pointer_new->xorBpp;
235 pointer->xPos = pointer_new->colorPtrAttr.hotSpotX;
236 pointer->yPos = pointer_new->colorPtrAttr.hotSpotY;
237 pointer->width = pointer_new->colorPtrAttr.width;
238 pointer->height = pointer_new->colorPtrAttr.height;
239 if (!update_pointer_copy_andxor(
240 pointer, pointer_new->colorPtrAttr.andMaskData, pointer_new->colorPtrAttr.lengthAndMask,
241 pointer_new->colorPtrAttr.xorMaskData, pointer_new->colorPtrAttr.lengthXorMask))
244 if (!IFCALLRESULT(TRUE, pointer->New, context, pointer))
247 if (!pointer_cache_put(cache->pointer, pointer_new->colorPtrAttr.cacheIndex, pointer, FALSE))
250 return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
253 pointer_free(context, pointer);
260 WINPR_ASSERT(context);
261 WINPR_ASSERT(pointer_cached);
263 rdpCache* cache = context->cache;
266 rdpPointer* pointer = pointer_cache_get(cache->pointer, pointer_cached->cacheIndex);
268 if (pointer !=
nullptr)
269 return IFCALLRESULT(TRUE, pointer->Set, context, pointer);
274rdpPointer* pointer_cache_get(rdpPointerCache* pointer_cache, UINT32 index)
276 WINPR_ASSERT(pointer_cache);
278 if (index >= pointer_cache->cacheSize)
280 WLog_ERR(TAG,
"invalid pointer index:%" PRIu32
" [%" PRIu32
"]", index,
281 pointer_cache->cacheSize);
285 WINPR_ASSERT(pointer_cache->entries);
286 return pointer_cache->entries[index];
289BOOL pointer_cache_put(rdpPointerCache* pointer_cache, UINT32 index, rdpPointer* pointer,
292 const FreeRDP_Settings_Keys_UInt32
id =
293 colorCache ? FreeRDP_ColorPointerCacheSize : FreeRDP_PointerCacheSize;
295 WINPR_ASSERT(pointer_cache);
296 WINPR_ASSERT(pointer_cache->context);
299 WLog_DBG(TAG,
"[%s] pointer index:%" PRIu32
" [allocated %" PRIu32
", size %" PRIu32
"]",
300 pointerType(colorCache), index, pointer_cache->cacheSize, size);
301 if (index >= pointer_cache->cacheSize)
304 "[%s] invalid pointer index:%" PRIu32
" [allocated %" PRIu32
", size %" PRIu32
"]",
305 pointerType(colorCache), index, pointer_cache->cacheSize, size);
311 "[%s] suspicious pointer index:%" PRIu32
" [allocated %" PRIu32
", size %" PRIu32
313 pointerType(colorCache), index, pointer_cache->cacheSize, size);
316 WINPR_ASSERT(pointer_cache->entries);
317 rdpPointer* prevPointer = pointer_cache->entries[index];
318 pointer_free(pointer_cache->context, prevPointer);
319 pointer_cache->entries[index] = pointer;
323void pointer_cache_register_callbacks(rdpUpdate* update)
325 rdpPointerUpdate* pointer =
nullptr;
327 WINPR_ASSERT(update);
328 WINPR_ASSERT(update->context);
330 pointer = update->pointer;
331 WINPR_ASSERT(pointer);
335 pointer->PointerPosition = update_pointer_position;
336 pointer->PointerSystem = update_pointer_system;
337 pointer->PointerColor = update_pointer_color;
338 pointer->PointerLarge = update_pointer_large;
339 pointer->PointerNew = update_pointer_new;
340 pointer->PointerCached = update_pointer_cached;
344rdpPointerCache* pointer_cache_new(rdpContext* context)
346 WINPR_ASSERT(context);
348 rdpSettings* settings = context->settings;
349 WINPR_ASSERT(settings);
351 rdpPointerCache* pointer_cache = (rdpPointerCache*)calloc(1,
sizeof(rdpPointerCache));
356 pointer_cache->context = context;
362 pointer_cache->cacheSize = MAX(size, colorSize) + 1;
365 "setting cacheSize=%" PRIu32
"[ColorPointerCache=%" PRIu32
", PointerCache=%" PRIu32
367 pointer_cache->cacheSize, colorSize, size);
368 pointer_cache->entries = (rdpPointer**)calloc(pointer_cache->cacheSize,
sizeof(rdpPointer*));
370 if (!pointer_cache->entries)
376 return pointer_cache;
379void pointer_cache_free(rdpPointerCache* pointer_cache)
381 if (pointer_cache !=
nullptr)
385 if (pointer_cache->context && pointer_cache->context->graphics)
387 rdpPointer* pointer = pointer_cache->context->graphics->Pointer_Prototype;
388 if (pointer && pointer->SetDefault)
389 (void)pointer->SetDefault(pointer_cache->context);
392 if (pointer_cache->entries)
394 for (UINT32 i = 0; i < pointer_cache->cacheSize; i++)
396 rdpPointer* pointer = pointer_cache->entries[i];
397 pointer_free(pointer_cache->context, pointer);
401 free((
void*)pointer_cache->entries);
411 if (!dst || !pointer)
416 if (pointer->lengthAndMask > 0)
418 dst->andMaskData = calloc(pointer->lengthAndMask,
sizeof(BYTE));
420 if (!dst->andMaskData)
423 memcpy(dst->andMaskData, pointer->andMaskData, pointer->lengthAndMask);
426 if (pointer->lengthXorMask > 0)
428 dst->xorMaskData = calloc(pointer->lengthXorMask,
sizeof(BYTE));
430 if (!dst->xorMaskData)
433 memcpy(dst->xorMaskData, pointer->xorMaskData, pointer->lengthXorMask);
438 free_pointer_color_update(context, dst);
444 WINPR_UNUSED(context);
449 free(pointer->xorMaskData);
450 free(pointer->andMaskData);
459 if (!dst || !pointer)
464 if (pointer->lengthAndMask > 0)
466 dst->andMaskData = calloc(pointer->lengthAndMask,
sizeof(BYTE));
468 if (!dst->andMaskData)
471 memcpy(dst->andMaskData, pointer->andMaskData, pointer->lengthAndMask);
474 if (pointer->lengthXorMask > 0)
476 dst->xorMaskData = calloc(pointer->lengthXorMask,
sizeof(BYTE));
478 if (!dst->xorMaskData)
481 memcpy(dst->xorMaskData, pointer->xorMaskData, pointer->lengthXorMask);
486 free_pointer_large_update(context, dst);
492 WINPR_UNUSED(context);
496 free(pointer->xorMaskData);
497 free(pointer->andMaskData);
505 if (!dst || !pointer)
510 if (pointer->colorPtrAttr.lengthAndMask > 0)
512 dst->colorPtrAttr.andMaskData = calloc(pointer->colorPtrAttr.lengthAndMask,
sizeof(BYTE));
514 if (!dst->colorPtrAttr.andMaskData)
517 memcpy(dst->colorPtrAttr.andMaskData, pointer->colorPtrAttr.andMaskData,
518 pointer->colorPtrAttr.lengthAndMask);
521 if (pointer->colorPtrAttr.lengthXorMask > 0)
523 dst->colorPtrAttr.xorMaskData = calloc(pointer->colorPtrAttr.lengthXorMask,
sizeof(BYTE));
525 if (!dst->colorPtrAttr.xorMaskData)
528 memcpy(dst->colorPtrAttr.xorMaskData, pointer->colorPtrAttr.xorMaskData,
529 pointer->colorPtrAttr.lengthXorMask);
534 free_pointer_new_update(context, dst);
538void free_pointer_new_update(WINPR_ATTR_UNUSED rdpContext* context,
POINTER_NEW_UPDATE* pointer)
543 free(pointer->colorPtrAttr.xorMaskData);
544 free(pointer->colorPtrAttr.andMaskData);
559 free_pointer_cached_update(context, dst);
565 WINPR_UNUSED(context);
571 WINPR_UNUSED(context);
580 if (!dst || !pointer)
586 free_pointer_position_update(context, dst);
592 WINPR_UNUSED(context);
601 if (!dst || !pointer)
607 free_pointer_system_update(context, dst);
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.