gl-renderer: Add swizzles to texture parameters utilities

OpenGL ES 3 adds support for texture swizzling parameters in order to
let graphics drivers efficiently swizzle R, G, B and A components at
texture look-up, with the nice feature of allowing 0 and 1 as
supported values.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2024-11-08 16:02:15 +01:00 committed by Daniel Stone
parent 5342945bb8
commit 891736793a
4 changed files with 60 additions and 14 deletions

View file

@ -302,8 +302,10 @@ static_assert(sizeof(struct gl_shader_requirements) ==
enum gl_texture_flag {
TEXTURE_FILTERS_DIRTY = 1 << 0,
TEXTURE_WRAP_MODES_DIRTY = 1 << 1,
TEXTURE_SWIZZLES_DIRTY = 1 << 2,
TEXTURE_ALL_DIRTY = (TEXTURE_FILTERS_DIRTY |
TEXTURE_WRAP_MODES_DIRTY),
TEXTURE_WRAP_MODES_DIRTY |
TEXTURE_SWIZZLES_DIRTY),
};
struct gl_texture_parameters {
@ -316,6 +318,10 @@ struct gl_texture_parameters {
struct { GLint s, t, r; };
GLint array[3];
} wrap_modes;
union {
struct { GLint r, g, b, a; };
GLint array[4];
} swizzles;
uint32_t flags;
};
@ -618,6 +624,7 @@ gl_texture_parameters_init(struct gl_renderer *gr,
GLenum target,
const GLint *filters,
const GLint *wrap_modes,
const GLint *swizzles,
bool flush);
void

View file

@ -1978,7 +1978,7 @@ update_wireframe_tex(struct gl_renderer *gr,
gl_texture_2d_init(gr, (int) log2(new_size) + 1, GL_R8, new_size, 1,
&gr->wireframe_tex);
gl_texture_parameters_init(gr, &params, GL_TEXTURE_2D, filters, NULL,
true);
NULL, true);
gr->wireframe_size = new_size;
/* Store mip chain with a wireframe thickness of 1.0. */
@ -2016,7 +2016,7 @@ update_borders_tex(struct gl_renderer *gr,
pending->height, &go->borders_tex[i]);
gl_texture_parameters_init(
gr, &go->borders_param[i],
GL_TEXTURE_2D, NULL, NULL, false);
GL_TEXTURE_2D, NULL, NULL, NULL, false);
}
}
@ -2744,7 +2744,7 @@ ensure_textures(struct gl_buffer_state *gb, GLenum target, int num_textures)
for (i = 0; i < num_textures; i++)
gl_texture_parameters_init(gb->gr, &gb->parameters[i], target,
NULL, NULL, false);
NULL, NULL, NULL, false);
}
static void
@ -2876,7 +2876,8 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer)
buffer->width / hsub, buffer->height / vsub,
&gb->textures[i]);
gl_texture_parameters_init(gr, &gb->parameters[i],
GL_TEXTURE_2D, NULL, NULL, false);
GL_TEXTURE_2D, NULL, NULL, NULL,
false);
}
}
@ -4035,7 +4036,7 @@ gl_renderer_resize_output(struct weston_output *output,
area->height, &go->shadow_fb,
&go->shadow_tex);
gl_texture_parameters_init(gr, &go->shadow_param, GL_TEXTURE_2D, NULL,
NULL, false);
NULL, NULL, false);
return ret;
}

View file

@ -204,7 +204,7 @@ gl_color_curve_lut_3x1d(struct gl_renderer *gr,
gl_texture_2d_store(gr, 0, 0, 0, lut_len, nr_rows, GL_RED, GL_FLOAT,
lut);
gl_texture_parameters_init(gr, &params, GL_TEXTURE_2D, filters, NULL,
true);
NULL, true);
free(lut);
@ -239,7 +239,7 @@ gl_3d_lut(struct gl_renderer *gr,
gl_texture_3d_store(gr, 0, 0, 0, 0, dim_size, dim_size, dim_size,
GL_RGB, GL_FLOAT, lut);
gl_texture_parameters_init(gr, &params, GL_TEXTURE_3D, filters, NULL,
true);
NULL, true);
glBindTexture(GL_TEXTURE_3D, 0);
gl_xform->mapping.type = SHADER_COLOR_MAPPING_3DLUT;

View file

@ -633,6 +633,24 @@ are_valid_texture_parameters(struct gl_renderer *gr,
};
}
/* Swizzles. */
if (parameters->target != GL_TEXTURE_EXTERNAL_OES) {
for (i = 0; i < 4; i++) {
switch (parameters->swizzles.array[i]) {
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_ZERO:
case GL_ONE:
break;
default:
return false;
};
}
}
return true;
}
@ -1274,13 +1292,16 @@ gl_texture_fini(GLuint *tex)
/* Initialise texture parameters. 'target' is either a 2D, a 3D or an external
* texture target. 'filters' points to an array of 2 values for respectively the
* texture minification and magnification filters. 'wrap_modes' points to an
* array of 3 values for the S, T and R texture wrap modes. The texture object
* bound to the given texture target (of the active texture) is updated if
* 'flush' is true, make sure it's properly bound in that case. The parameters
* and the flags bitfield can then directly be set and flushed when needed.
* array of 3 values for the S, T and R texture wrap modes. 'swizzles' points to
* an array of 4 values for the R, G, B and A texture swizzles. The texture
* object bound to the given texture target (of the active texture) is updated
* if 'flush' is true, make sure it's properly bound in that case. The
* parameters and the flags bitfield can then directly be set and flushed when
* needed.
*
* filters are set to GL_NEAREST if 'filters' is NULL and wrap modes are set to
* GL_CLAMP_TO_EDGE if 'wrap_modes' is NULL.
* filters are set to GL_NEAREST if 'filters' is NULL, wrap modes are set to
* GL_CLAMP_TO_EDGE if 'wrap_modes' is NULL and swizzles are set to their
* default components if 'swizzles' is NULL.
*
* See gl_texture_parameters_flush().
*/
@ -1290,11 +1311,13 @@ gl_texture_parameters_init(struct gl_renderer *gr,
GLenum target,
const GLint *filters,
const GLint *wrap_modes,
const GLint *swizzles,
bool flush)
{
GLint default_filters[] = { GL_NEAREST, GL_NEAREST };
GLint default_wrap_modes[] = { GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE,
GL_CLAMP_TO_EDGE };
GLint default_swizzles[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA };
assert(target == GL_TEXTURE_2D ||
target == GL_TEXTURE_3D ||
@ -1309,6 +1332,8 @@ gl_texture_parameters_init(struct gl_renderer *gr,
sizeof default_filters);
memcpy(&parameters->wrap_modes, wrap_modes ? wrap_modes :
default_wrap_modes, sizeof default_wrap_modes);
memcpy(&parameters->swizzles, swizzles ? swizzles : default_swizzles,
sizeof default_swizzles);
parameters->flags = TEXTURE_ALL_DIRTY;
if (flush)
@ -1343,6 +1368,19 @@ gl_texture_parameters_flush(struct gl_renderer *gr,
parameters->wrap_modes.r);
}
if (parameters->flags & TEXTURE_SWIZZLES_DIRTY &&
parameters->target != GL_TEXTURE_EXTERNAL_OES &&
gr->gl_version >= gl_version(3, 0)) {
glTexParameteri(parameters->target, GL_TEXTURE_SWIZZLE_R,
parameters->swizzles.r);
glTexParameteri(parameters->target, GL_TEXTURE_SWIZZLE_G,
parameters->swizzles.g);
glTexParameteri(parameters->target, GL_TEXTURE_SWIZZLE_B,
parameters->swizzles.b);
glTexParameteri(parameters->target, GL_TEXTURE_SWIZZLE_A,
parameters->swizzles.a);
}
parameters->flags = 0;
}