diff options
author | Jason Ekstrand <[email protected]> | 2015-01-12 14:43:34 -0800 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2015-01-22 10:35:43 -0800 |
commit | e24d17e08cb19bbecadb22ed43b25eeec26cde27 (patch) | |
tree | ca18a9a1129abe5f59169837d4ebc82e7cff7767 | |
parent | 333226522cd9ae541147b52e20f577aa19c50426 (diff) |
formats: Use a hash table for _mesa_format_from_array_format
Going through the for loop every time has noticable overhead. This fixes
things up so we only do that once ever and then just do a hash table lookup
which should be much cheaper.
v2 Jason Ekstrand <[email protected]>:
- Use once_flag and call_once from c11/threads.h instead of pthreads
Reviewed-by: Neil Roberts <[email protected]>
-rw-r--r-- | src/mesa/main/formats.c | 68 |
1 files changed, 56 insertions, 12 deletions
diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c index b6c51242f80..958d6f245ea 100644 --- a/src/mesa/main/formats.c +++ b/src/mesa/main/formats.c @@ -28,7 +28,8 @@ #include "formats.h" #include "macros.h" #include "glformats.h" - +#include "c11/threads.h" +#include "util/hash_table.h" /** * Information about texture formats. @@ -377,24 +378,67 @@ _mesa_format_to_array_format(mesa_format format) return _mesa_array_format_flip_channels(info->ArrayFormat); } +static struct hash_table *format_array_format_table; +static once_flag format_array_format_table_exists = ONCE_FLAG_INIT; + +static bool +array_formats_equal(const void *a, const void *b) +{ + return (intptr_t)a == (intptr_t)b; +} + +static void +format_array_format_table_init() +{ + const struct gl_format_info *info; + mesa_array_format array_format; + unsigned f; + + format_array_format_table = _mesa_hash_table_create(NULL, NULL, + array_formats_equal); + + for (f = 1; f < MESA_FORMAT_COUNT; ++f) { + info = _mesa_get_format_info(f); + if (!info->ArrayFormat) + continue; + + if (_mesa_little_endian()) { + array_format = info->ArrayFormat; + } else { + array_format = _mesa_array_format_flip_channels(info->ArrayFormat); + } + + /* This can happen and does for some of the BGR formats. Let's take + * the first one in the list. + */ + if (_mesa_hash_table_search_pre_hashed(format_array_format_table, + array_format, + (void *)(intptr_t)array_format)) + continue; + + _mesa_hash_table_insert_pre_hashed(format_array_format_table, + array_format, + (void *)(intptr_t)array_format, + (void *)(intptr_t)f); + } +} + mesa_format _mesa_format_from_array_format(uint32_t array_format) { - mesa_array_format af; - unsigned f; + struct hash_entry *entry; assert(_mesa_format_is_mesa_array_format(array_format)); - if (_mesa_little_endian()) - af = array_format; - else - af = _mesa_array_format_flip_channels(array_format); - - for (f = 1; f < MESA_FORMAT_COUNT; ++f) - if (_mesa_get_format_info(f)->ArrayFormat == af) - return f; + call_once(&format_array_format_table_exists, format_array_format_table_init); - return MESA_FORMAT_NONE; + entry = _mesa_hash_table_search_pre_hashed(format_array_format_table, + array_format, + (void *)(intptr_t)array_format); + if (entry) + return (intptr_t)entry->data; + else + return MESA_FORMAT_NONE; } /** Is the given format a compressed format? */ |