20#include <freerdp/config.h>
24#include <winpr/assert.h>
26#include <freerdp/log.h>
27#include <freerdp/update.h>
28#include <freerdp/freerdp.h>
29#include <winpr/stream.h>
34#define TAG FREERDP_TAG("cache.brush")
45 pCacheBrush CacheBrush;
48 UINT32 paddingA[16 - 4];
51 UINT32 maxMonoEntries;
53 BRUSH_ENTRY* monoEntries;
54 UINT32 paddingB[32 - 20];
59static BOOL update_gdi_patblt(rdpContext* context,
PATBLT_ORDER* patblt)
63 WINPR_ASSERT(context);
66 const rdpCache* cache = context->cache;
69 rdpBrush* brush = &patblt->brush;
70 WINPR_ASSERT(brush->style <= UINT8_MAX);
71 const BYTE style = (BYTE)brush->style;
72 BYTE* data = brush->data;
74 if (brush->style & CACHED_BRUSH)
76 brush->data = brush_cache_get(cache->brush, brush->index, &brush->bpp);
80 WINPR_ASSERT(cache->brush);
81 IFCALLRET(cache->brush->PatBlt, ret, context, patblt);
87static BOOL update_gdi_polygon_sc(rdpContext* context,
const POLYGON_SC_ORDER* polygon_sc)
89 rdpCache* cache =
nullptr;
90 WINPR_ASSERT(context);
91 cache = context->cache;
93 WINPR_ASSERT(cache->brush);
94 return IFCALLRESULT(TRUE, cache->brush->PolygonSC, context, polygon_sc);
97static BOOL update_gdi_polygon_cb(rdpContext* context,
POLYGON_CB_ORDER* polygon_cb)
101 WINPR_ASSERT(context);
102 WINPR_ASSERT(polygon_cb);
104 rdpCache* cache = context->cache;
107 rdpBrush* brush = &polygon_cb->brush;
108 WINPR_ASSERT(brush->style <= UINT8_MAX);
109 const BYTE style = (UINT8)brush->style;
110 BYTE* data = brush->data;
112 if (brush->style & CACHED_BRUSH)
114 brush->data = brush_cache_get(cache->brush, brush->index, &brush->bpp);
118 WINPR_ASSERT(cache->brush);
119 IFCALLRET(cache->brush->PolygonCB, ret, context, polygon_cb);
120 brush->style = style;
125static BOOL update_gdi_cache_brush(rdpContext* context,
const CACHE_BRUSH_ORDER* cacheBrush)
128 void* data =
nullptr;
129 rdpCache* cache =
nullptr;
131 WINPR_ASSERT(context);
132 WINPR_ASSERT(cacheBrush);
134 cache = context->cache;
137 length = cacheBrush->bpp * 64 / 8;
138 data = malloc(length);
143 CopyMemory(data, cacheBrush->data, length);
144 brush_cache_put(cache->brush, cacheBrush->index, data, cacheBrush->bpp);
148void* brush_cache_get(rdpBrushCache* brushCache, UINT32 index, UINT32* bpp)
150 void* entry =
nullptr;
160 if (index >= brushCache->maxMonoEntries)
162 WLog_ERR(TAG,
"invalid brush (%" PRIu32
" bpp) index: 0x%08" PRIX32
"", *bpp, index);
166 *bpp = brushCache->monoEntries[index].bpp;
167 entry = brushCache->monoEntries[index].entry;
171 if (index >= brushCache->maxEntries)
173 WLog_ERR(TAG,
"invalid brush (%" PRIu32
" bpp) index: 0x%08" PRIX32
"", *bpp, index);
177 *bpp = brushCache->entries[index].bpp;
178 entry = brushCache->entries[index].entry;
181 if (entry ==
nullptr)
183 WLog_ERR(TAG,
"invalid brush (%" PRIu32
" bpp) at index: 0x%08" PRIX32
"", *bpp, index);
190void brush_cache_put(rdpBrushCache* brushCache, UINT32 index,
void* entry, UINT32 bpp)
192 WINPR_ASSERT(brushCache);
196 if (index >= brushCache->maxMonoEntries)
198 WLog_ERR(TAG,
"invalid brush (%" PRIu32
" bpp) index: 0x%08" PRIX32
"", bpp, index);
203 WINPR_ASSERT(brushCache->monoEntries);
204 free(brushCache->monoEntries[index].entry);
205 brushCache->monoEntries[index].bpp = bpp;
206 brushCache->monoEntries[index].entry = entry;
210 if (index >= brushCache->maxEntries)
212 WLog_ERR(TAG,
"invalid brush (%" PRIu32
" bpp) index: 0x%08" PRIX32
"", bpp, index);
217 WINPR_ASSERT(brushCache->entries);
218 free(brushCache->entries[index].entry);
219 brushCache->entries[index].bpp = bpp;
220 brushCache->entries[index].entry = entry;
224void brush_cache_register_callbacks(rdpUpdate* update)
226 WINPR_ASSERT(update);
227 WINPR_ASSERT(update->context);
228 WINPR_ASSERT(update->primary);
229 WINPR_ASSERT(update->secondary);
233 rdpCache* cache = update->context->cache;
235 WINPR_ASSERT(cache->brush);
237 cache->brush->PatBlt = update->primary->PatBlt;
238 cache->brush->PolygonSC = update->primary->PolygonSC;
239 cache->brush->PolygonCB = update->primary->PolygonCB;
240 update->primary->PatBlt = update_gdi_patblt;
241 update->primary->PolygonSC = update_gdi_polygon_sc;
242 update->primary->PolygonCB = update_gdi_polygon_cb;
243 update->secondary->CacheBrush = update_gdi_cache_brush;
247rdpBrushCache* brush_cache_new(rdpContext* context)
249 rdpBrushCache* brushCache =
nullptr;
251 WINPR_ASSERT(context);
253 brushCache = (rdpBrushCache*)calloc(1,
sizeof(rdpBrushCache));
258 brushCache->context = context;
259 brushCache->maxEntries = 64;
260 brushCache->maxMonoEntries = 64;
261 brushCache->entries = (BRUSH_ENTRY*)calloc(brushCache->maxEntries,
sizeof(BRUSH_ENTRY));
263 if (!brushCache->entries)
266 brushCache->monoEntries = (BRUSH_ENTRY*)calloc(brushCache->maxMonoEntries,
sizeof(BRUSH_ENTRY));
268 if (!brushCache->monoEntries)
273 WINPR_PRAGMA_DIAG_PUSH
274 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
275 brush_cache_free(brushCache);
276 WINPR_PRAGMA_DIAG_POP
280void brush_cache_free(rdpBrushCache* brushCache)
284 if (brushCache->entries)
286 for (
size_t i = 0; i < brushCache->maxEntries; i++)
287 free(brushCache->entries[i].entry);
289 free(brushCache->entries);
292 if (brushCache->monoEntries)
294 for (
size_t i = 0; i < brushCache->maxMonoEntries; i++)
295 free(brushCache->monoEntries[i].entry);
297 free(brushCache->monoEntries);
306 WINPR_UNUSED(context);
314 WINPR_ASSERT(context);
324 free_cache_brush_order(context, dst);
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.