diff --git a/include/twin.h b/include/twin.h index 5879652a..7b88653b 100644 --- a/include/twin.h +++ b/include/twin.h @@ -253,6 +253,10 @@ typedef struct _twin_pixmap { #endif twin_window_t *window; /**< Associated window (if any) */ + + /* Transform buffer cache for compositing operations */ + void *xform_cache; /**< Cached xform buffer */ + size_t xform_cache_size; /**< Cached xform buffer size in bytes */ } twin_pixmap_t; /** diff --git a/src/draw-builtin.c b/src/draw-builtin.c index 936602f0..9788b235 100644 --- a/src/draw-builtin.c +++ b/src/draw-builtin.c @@ -633,10 +633,22 @@ static twin_xform_t *twin_pixmap_init_xform(twin_pixmap_t *pixmap, if (fmt == TWIN_RGB16) fmt = TWIN_ARGB32; - twin_xform_t *xform = - calloc(1, sizeof(twin_xform_t) + width * twin_bytes_per_pixel(fmt)); - if (!xform) - return NULL; + size_t required_size = + sizeof(twin_xform_t) + (size_t) width * twin_bytes_per_pixel(fmt); + + /* Reuse cached xform buffer if large enough */ + twin_xform_t *xform; + if (pixmap->xform_cache && pixmap->xform_cache_size >= required_size) { + xform = (twin_xform_t *) pixmap->xform_cache; + } else { + /* Need larger cache - reallocate */ + void *new_cache = realloc(pixmap->xform_cache, required_size); + if (!new_cache) + return NULL; + pixmap->xform_cache = new_cache; + pixmap->xform_cache_size = required_size; + xform = (twin_xform_t *) new_cache; + } xform->span.v = (twin_argb32_t *) (char *) (xform + 1); xform->pixmap = pixmap; @@ -650,7 +662,9 @@ static twin_xform_t *twin_pixmap_init_xform(twin_pixmap_t *pixmap, static void twin_pixmap_free_xform(twin_xform_t *xform) { - free(xform); + /* Xform buffer is now cached in pixmap - don't free */ + /* This function is kept for API compatibility but does nothing */ + (void) xform; } #define FX(x) twin_int_to_fixed(x) diff --git a/src/pixmap.c b/src/pixmap.c index 14f196e8..e9bde3f4 100644 --- a/src/pixmap.c +++ b/src/pixmap.c @@ -52,6 +52,8 @@ twin_pixmap_t *twin_pixmap_create(twin_format_t format, pixmap->shadow = false; #endif pixmap->window = NULL; /* Initialize window field */ + pixmap->xform_cache = NULL; + pixmap->xform_cache_size = 0; pixmap->p.v = pixmap + 1; memset(pixmap->p.v, '\0', space); return pixmap; @@ -82,6 +84,8 @@ twin_pixmap_t *twin_pixmap_create_const(twin_format_t format, pixmap->stride = stride; pixmap->disable = 0; pixmap->window = NULL; /* Initialize window field */ + pixmap->xform_cache = NULL; + pixmap->xform_cache_size = 0; pixmap->p = pixels; return pixmap; } @@ -90,6 +94,7 @@ void twin_pixmap_destroy(twin_pixmap_t *pixmap) { if (pixmap->screen) twin_pixmap_hide(pixmap); + free(pixmap->xform_cache); /* Free xform buffer cache */ free(pixmap); }