gl-renderer: Add extension flag parser

This new utility parses extension strings and fills a bitfield of
matched flags. This will be used to store EGL and GL extension flags.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2024-10-10 11:30:42 +02:00 committed by Daniel Stone
parent 39a199293e
commit 00f7bf91d8
2 changed files with 69 additions and 0 deletions

View file

@ -54,6 +54,8 @@
/* Max number of images per buffer. */
#define SHADER_INPUT_TEX_MAX 3
#define EXT(string, flag) { string, ARRAY_LENGTH(string) - 1, (uint64_t) flag }
/* Keep the following in sync with vertex.glsl. */
enum gl_shader_texcoord_input {
SHADER_TEXCOORD_INPUT_ATTRIB = 0,
@ -107,6 +109,12 @@ static_assert(TEX_UNIT_LAST < 8, "OpenGL ES 2.0 requires at least 8 texture "
"GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS check at display creation "
"to require more.");
struct gl_extension_table {
const char *str;
size_t len;
uint64_t flag;
};
/** GL shader requirements key
*
* This structure is used as a binary blob key for building and searching
@ -325,6 +333,11 @@ gl_version_minor(uint32_t ver)
return ver & 0xffff;
}
void
gl_extensions_add(const struct gl_extension_table *table,
const char *extensions,
uint64_t *flags_out);
static inline struct gl_renderer *
get_renderer(struct weston_compositor *ec)
{

View file

@ -424,6 +424,62 @@ struct yuv_format_descriptor yuv_formats[] = {
}
};
/* Add extension flags to the bitfield that 'flags_out' points to. 'table'
* stores extension names and flags to check for and 'extensions' is the list
* usually returned by the EGL or GL implementation. New flags are stored using
* a binary OR in order to keep flags set from a previous call. Caller must
* ensure the bitfield is set to 0 at first call.
*/
void
gl_extensions_add(const struct gl_extension_table *table,
const char *extensions,
uint64_t *flags_out)
{
struct { const char *str; size_t len; } *map;
size_t i = 0, n = 0;
uint64_t flags = 0;
char prev_char = ' ';
/* Get number of extensions. */
while (extensions[i]) {
if (prev_char == ' ' && extensions[i] != ' ')
n++;
prev_char = extensions[i++];
}
if (n == 0)
return;
/* Allocate data structure mapping each extension with their length. */
map = xmalloc(n * sizeof *map);
prev_char = ' ';
i = n = 0;
while (prev_char) {
if (extensions[i] != ' ' && extensions[i] != '\0') {
if (prev_char == ' ')
map[n].str = &extensions[i];
} else if (prev_char != ' ') {
map[n].len = &extensions[i] - map[n].str;
n++;
}
prev_char = extensions[i++];
}
/* Match extensions with table. */
for (; table->str; table++) {
for (i = 0; i < n; i++) {
if (table->len == map[i].len &&
!strncmp(table->str, map[i].str, table->len)) {
flags |= table->flag;
break;
}
}
}
*flags_out |= flags;
free(map);
}
static void
timeline_begin_render_query(struct gl_renderer *gr, GLuint query)
{