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;
 
   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);
 
   85static 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);
 
   95static 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;
 
  121static 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);
 
  144void* 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);
 
  186void 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;
 
  220void 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;
 
  243rdpBrushCache* 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
 
  276void 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.