From 4896c8cdc8b1c1b9cac37557bad686685fb1b271 Mon Sep 17 00:00:00 2001 From: Ell Date: Mon, 18 May 2020 20:47:49 +0300 Subject: [PATCH] palette: delay sorted radius vectors construction until needed In babl-palette, when C11 atomic operations are available, don't construct the sorted radius vectors on palette setup, but rather when first converting from RGB to the palette format. This avoids the costly vector-construction step for palettes that are never used as the destination format of a conversion. --- babl/babl-palette.c | 70 +++++++++++++++++++++++++++++++++++++++------ meson.build | 1 + 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/babl/babl-palette.c b/babl/babl-palette.c index f0eecc5..c4d3068 100644 --- a/babl/babl-palette.c +++ b/babl/babl-palette.c @@ -27,6 +27,10 @@ #include "babl.h" #include "babl-memory.h" +#ifdef HAVE_STDATOMIC_H +#include +#endif + #define HASH_TABLE_SIZE 1111 @@ -110,7 +114,8 @@ babl_palette_radius_compare (const void *r1, } static void -babl_palette_init_radii (BablPalette *pal) +babl_palette_init_radii (BablPalette *pal, + BablPaletteRadius *radii) { int i, j; @@ -122,12 +127,12 @@ babl_palette_init_radii (BablPalette *pal) for (i = 0; i < pal->count; i++) { - BablPaletteRadius *radii1 = pal->radii + (pal->count - 1) * i; + BablPaletteRadius *radii1 = radii + (pal->count - 1) * i; const unsigned char *p1 = pal->data_u8 + 4 * i; for (j = i + 1; j < pal->count; j++) { - BablPaletteRadius *radii2 = pal->radii + (pal->count - 1) * j; + BablPaletteRadius *radii2 = radii + (pal->count - 1) * j; const unsigned char *p2 = pal->data_u8 + 4 * j; unsigned short diff; @@ -145,6 +150,53 @@ babl_palette_init_radii (BablPalette *pal) } } +static BablPaletteRadius * +babl_palette_create_radii (BablPalette *pal) +{ + BablPaletteRadius *radii; + + radii = babl_malloc (sizeof (BablPaletteRadius) * + (pal->count - 1) * + pal->count); + + babl_palette_init_radii (pal, radii); + + return radii; +} + +static const BablPaletteRadius * +babl_palette_get_radii (BablPalette *pal, + int entry) +{ + BablPaletteRadius *radii; + +#ifdef HAVE_STDATOMIC_H + radii = atomic_load_explicit (&pal->radii, memory_order_consume); + + if (! radii) + { + BablPaletteRadius *existing_radii; + + existing_radii = NULL; + radii = babl_palette_create_radii (pal); + + if (! atomic_compare_exchange_strong_explicit (&pal->radii, + &existing_radii, radii, + memory_order_acq_rel, + memory_order_consume)) + { + babl_free (radii); + + radii = existing_radii; + } + } +#else + radii = pal->radii; +#endif + + return radii + (pal->count - 1) * entry; +} + static void babl_palette_reset_hash (BablPalette *pal) { @@ -181,7 +233,7 @@ babl_palette_lookup (BablPalette *pal, } else { - const BablPaletteRadius *radii = pal->radii + (pal->count - 1) * best_idx; + const BablPaletteRadius *radii = babl_palette_get_radii (pal, best_idx); const unsigned char *q; int best_diff2; int best_diff; @@ -256,9 +308,7 @@ make_pal (const Babl *pal_space, pal->data = babl_malloc (bpp * count); pal->data_double = babl_malloc (4 * sizeof(double) * count); pal->data_u8 = babl_malloc (4 * sizeof(char) * count); - pal->radii = babl_malloc (sizeof (BablPaletteRadius) * - (pal->count - 1) * - pal->count); + pal->radii = NULL; memcpy (pal->data, data, bpp * count); @@ -267,7 +317,9 @@ make_pal (const Babl *pal_space, babl_process (babl_fish (format, babl_format_with_space ("R'G'B'A u8", pal_space)), data, pal->data_u8, count); - babl_palette_init_radii (pal); +#ifndef HAVE_STDATOMIC_H + pal->radii = babl_palette_create_radii (pal); +#endif babl_palette_reset_hash (pal); @@ -315,7 +367,7 @@ default_palette (void) babl_process (babl_fish (pal.format, babl_format ("RGBA double")), pal.data, pal.data_double, pal.count); - babl_palette_init_radii (&pal); + babl_palette_init_radii (&pal, pal.radii); babl_palette_reset_hash (&pal); diff --git a/meson.build b/meson.build index be9779c..1ededd1 100644 --- a/meson.build +++ b/meson.build @@ -260,6 +260,7 @@ endif # Check headers check_headers = [ + ['HAVE_STDATOMIC_H', 'stdatomic.h'] ] # Don't check for dynamic load on windows if not platform_win32 -- 2.30.2