summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2015-01-12 14:43:34 -0800
committerJason Ekstrand <[email protected]>2015-01-22 10:35:43 -0800
commite24d17e08cb19bbecadb22ed43b25eeec26cde27 (patch)
treeca18a9a1129abe5f59169837d4ebc82e7cff7767
parent333226522cd9ae541147b52e20f577aa19c50426 (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.c68
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? */