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 <jason.ekstrand@intel.com>: - Use once_flag and call_once from c11/threads.h instead of pthreads Reviewed-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
@@ -28,7 +28,8 @@
|
|||||||
#include "formats.h"
|
#include "formats.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "glformats.h"
|
#include "glformats.h"
|
||||||
|
#include "c11/threads.h"
|
||||||
|
#include "util/hash_table.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about texture formats.
|
* Information about texture formats.
|
||||||
@@ -377,24 +378,67 @@ _mesa_format_to_array_format(mesa_format format)
|
|||||||
return _mesa_array_format_flip_channels(info->ArrayFormat);
|
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
|
||||||
_mesa_format_from_array_format(uint32_t array_format)
|
_mesa_format_from_array_format(uint32_t array_format)
|
||||||
{
|
{
|
||||||
mesa_array_format af;
|
struct hash_entry *entry;
|
||||||
unsigned f;
|
|
||||||
|
|
||||||
assert(_mesa_format_is_mesa_array_format(array_format));
|
assert(_mesa_format_is_mesa_array_format(array_format));
|
||||||
|
|
||||||
if (_mesa_little_endian())
|
call_once(&format_array_format_table_exists, format_array_format_table_init);
|
||||||
af = array_format;
|
|
||||||
|
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
|
else
|
||||||
af = _mesa_array_format_flip_channels(array_format);
|
return MESA_FORMAT_NONE;
|
||||||
|
|
||||||
for (f = 1; f < MESA_FORMAT_COUNT; ++f)
|
|
||||||
if (_mesa_get_format_info(f)->ArrayFormat == af)
|
|
||||||
return f;
|
|
||||||
|
|
||||||
return MESA_FORMAT_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Is the given format a compressed format? */
|
/** Is the given format a compressed format? */
|
||||||
|
Reference in New Issue
Block a user