20 #include <freerdp/config.h>
23 #include <winpr/crt.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")
42 struct rdp_brush_cache
45 pCacheBrush CacheBrush;
48 UINT32 paddingA[16 - 4];
51 UINT32 maxMonoEntries;
53 BRUSH_ENTRY* monoEntries;
54 UINT32 paddingB[32 - 20];
59 static 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;
73 if (brush->style & CACHED_BRUSH)
75 brush->data = brush_cache_get(cache->brush, brush->index, &brush->bpp);
79 WINPR_ASSERT(cache->brush);
80 IFCALLRET(cache->brush->PatBlt, ret, context, patblt);
85 static BOOL update_gdi_polygon_sc(rdpContext* context,
const POLYGON_SC_ORDER* polygon_sc)
87 rdpCache* cache = NULL;
88 WINPR_ASSERT(context);
89 cache = context->cache;
91 WINPR_ASSERT(cache->brush);
92 return IFCALLRESULT(TRUE, cache->brush->PolygonSC, context, polygon_sc);
95 static BOOL update_gdi_polygon_cb(rdpContext* context,
POLYGON_CB_ORDER* polygon_cb)
99 WINPR_ASSERT(context);
100 WINPR_ASSERT(polygon_cb);
102 rdpCache* cache = context->cache;
105 rdpBrush* brush = &polygon_cb->brush;
106 WINPR_ASSERT(brush->style <= UINT8_MAX);
107 const BYTE style = (UINT8)brush->style;
109 if (brush->style & CACHED_BRUSH)
111 brush->data = brush_cache_get(cache->brush, brush->index, &brush->bpp);
115 WINPR_ASSERT(cache->brush);
116 IFCALLRET(cache->brush->PolygonCB, ret, context, polygon_cb);
117 brush->style = style;
121 static BOOL update_gdi_cache_brush(rdpContext* context,
const CACHE_BRUSH_ORDER* cacheBrush)
125 rdpCache* cache = NULL;
127 WINPR_ASSERT(context);
128 WINPR_ASSERT(cacheBrush);
130 cache = context->cache;
133 length = cacheBrush->bpp * 64 / 8;
134 data = malloc(length);
139 CopyMemory(data, cacheBrush->data, length);
140 brush_cache_put(cache->brush, cacheBrush->index, data, cacheBrush->bpp);
144 void* brush_cache_get(rdpBrushCache* brushCache, UINT32 index, UINT32* bpp)
156 if (index >= brushCache->maxMonoEntries)
158 WLog_ERR(TAG,
"invalid brush (%" PRIu32
" bpp) index: 0x%08" PRIX32
"", *bpp, index);
162 *bpp = brushCache->monoEntries[index].bpp;
163 entry = brushCache->monoEntries[index].entry;
167 if (index >= brushCache->maxEntries)
169 WLog_ERR(TAG,
"invalid brush (%" PRIu32
" bpp) index: 0x%08" PRIX32
"", *bpp, index);
173 *bpp = brushCache->entries[index].bpp;
174 entry = brushCache->entries[index].entry;
179 WLog_ERR(TAG,
"invalid brush (%" PRIu32
" bpp) at index: 0x%08" PRIX32
"", *bpp, index);
186 void brush_cache_put(rdpBrushCache* brushCache, UINT32 index,
void* entry, UINT32 bpp)
188 WINPR_ASSERT(brushCache);
192 if (index >= brushCache->maxMonoEntries)
194 WLog_ERR(TAG,
"invalid brush (%" PRIu32
" bpp) index: 0x%08" PRIX32
"", bpp, index);
199 WINPR_ASSERT(brushCache->monoEntries);
200 free(brushCache->monoEntries[index].entry);
201 brushCache->monoEntries[index].bpp = bpp;
202 brushCache->monoEntries[index].entry = entry;
206 if (index >= brushCache->maxEntries)
208 WLog_ERR(TAG,
"invalid brush (%" PRIu32
" bpp) index: 0x%08" PRIX32
"", bpp, index);
213 WINPR_ASSERT(brushCache->entries);
214 free(brushCache->entries[index].entry);
215 brushCache->entries[index].bpp = bpp;
216 brushCache->entries[index].entry = entry;
220 void brush_cache_register_callbacks(rdpUpdate* update)
222 WINPR_ASSERT(update);
223 WINPR_ASSERT(update->context);
224 WINPR_ASSERT(update->primary);
225 WINPR_ASSERT(update->secondary);
229 rdpCache* cache = update->context->cache;
231 WINPR_ASSERT(cache->brush);
233 cache->brush->PatBlt = update->primary->PatBlt;
234 cache->brush->PolygonSC = update->primary->PolygonSC;
235 cache->brush->PolygonCB = update->primary->PolygonCB;
236 update->primary->PatBlt = update_gdi_patblt;
237 update->primary->PolygonSC = update_gdi_polygon_sc;
238 update->primary->PolygonCB = update_gdi_polygon_cb;
239 update->secondary->CacheBrush = update_gdi_cache_brush;
243 rdpBrushCache* brush_cache_new(rdpContext* context)
245 rdpBrushCache* brushCache = NULL;
247 WINPR_ASSERT(context);
249 brushCache = (rdpBrushCache*)calloc(1,
sizeof(rdpBrushCache));
254 brushCache->context = context;
255 brushCache->maxEntries = 64;
256 brushCache->maxMonoEntries = 64;
257 brushCache->entries = (BRUSH_ENTRY*)calloc(brushCache->maxEntries,
sizeof(BRUSH_ENTRY));
259 if (!brushCache->entries)
262 brushCache->monoEntries = (BRUSH_ENTRY*)calloc(brushCache->maxMonoEntries,
sizeof(BRUSH_ENTRY));
264 if (!brushCache->monoEntries)
269 WINPR_PRAGMA_DIAG_PUSH
270 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
271 brush_cache_free(brushCache);
272 WINPR_PRAGMA_DIAG_POP
276 void brush_cache_free(rdpBrushCache* brushCache)
280 if (brushCache->entries)
282 for (
size_t i = 0; i < brushCache->maxEntries; i++)
283 free(brushCache->entries[i].entry);
285 free(brushCache->entries);
288 if (brushCache->monoEntries)
290 for (
size_t i = 0; i < brushCache->maxMonoEntries; i++)
291 free(brushCache->monoEntries[i].entry);
293 free(brushCache->monoEntries);
302 WINPR_UNUSED(context);
310 WINPR_ASSERT(context);
320 free_cache_brush_order(context, dst);
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.