gl-renderer: Add OpenGL ES 2 support to texture swizzles

Fallback to shader based swizzling when OpenGL ES 3 isn't available.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2024-11-11 12:44:21 +01:00 committed by Daniel Stone
parent a990e8ceda
commit be5c662bae
3 changed files with 113 additions and 17 deletions

View file

@ -131,6 +131,9 @@ uniform sampler2D tex_wireframe;
uniform float view_alpha;
uniform vec4 unicolor;
uniform vec4 tint;
uniform ivec4 swizzle_idx[3];
uniform vec4 swizzle_mask[3];
uniform vec4 swizzle_sub[3];
#define MAX_CURVE_PARAMS 10
#define MAX_CURVESET_PARAMS (MAX_CURVE_PARAMS * 3)
@ -151,6 +154,39 @@ uniform HIGHPRECISION vec2 color_mapping_lut_scale_offset;
#endif
uniform HIGHPRECISION mat3 color_mapping_matrix;
/*
* 2D texture sampler abstracting away the lack of swizzles on OpenGL ES 2. This
* should only be used by code relying on swizzling. 'unit' is the texture unit
* used to index the swizzling uniforms, which must appropriately be set prior
* to draw call.
*/
vec4
texture2D_swizzle(sampler2D sampler, int unit, vec2 coord)
{
#if GLES_API_MAJOR_VERSION == 3
return texture2D(sampler, coord);
#else
vec4 color = texture2D(sampler, coord);
/* Swizzle components. */
color = vec4(color[swizzle_idx[unit].x],
color[swizzle_idx[unit].y],
color[swizzle_idx[unit].z],
color[swizzle_idx[unit].w]);
/* Substitute with 0 or 1. */
return color * swizzle_mask[unit] + swizzle_sub[unit];
#endif
}
#if DEF_VARIANT == SHADER_VARIANT_EXTERNAL
vec4
texture2D_swizzle(samplerExternalOES sampler, int unit, vec2 coord)
{
return texture2D(sampler, coord);
}
#endif
vec4
sample_input_texture()
{
@ -162,11 +198,11 @@ sample_input_texture()
return unicolor;
if (c_variant == SHADER_VARIANT_EXTERNAL)
return texture2D(tex, v_texcoord);
return texture2D_swizzle(tex, 0, v_texcoord);
if (c_variant == SHADER_VARIANT_RGBA ||
c_variant == SHADER_VARIANT_RGBX) {
vec4 color = texture2D(tex, v_texcoord);
vec4 color = texture2D_swizzle(tex, 0, v_texcoord);
if (c_variant == SHADER_VARIANT_RGBX)
color.a = 1.0;
@ -177,20 +213,20 @@ sample_input_texture()
/* Requires conversion to RGBA */
if (c_variant == SHADER_VARIANT_Y_U_V) {
yuva.x = texture2D(tex, v_texcoord).x;
yuva.y = texture2D(tex1, v_texcoord).x;
yuva.z = texture2D(tex2, v_texcoord).x;
yuva.x = texture2D_swizzle(tex, 0, v_texcoord).x;
yuva.y = texture2D_swizzle(tex1, 1, v_texcoord).x;
yuva.z = texture2D_swizzle(tex2, 2, v_texcoord).x;
} else if (c_variant == SHADER_VARIANT_Y_UV) {
yuva.x = texture2D(tex, v_texcoord).x;
yuva.yz = texture2D(tex1, v_texcoord).rg;
yuva.x = texture2D_swizzle(tex, 0, v_texcoord).x;
yuva.yz = texture2D_swizzle(tex1, 1, v_texcoord).rg;
} else if (c_variant == SHADER_VARIANT_Y_XUXV) {
yuva.x = texture2D(tex, v_texcoord).x;
yuva.yz = texture2D(tex1, v_texcoord).ga;
yuva.x = texture2D_swizzle(tex, 0, v_texcoord).x;
yuva.yz = texture2D_swizzle(tex1, 1, v_texcoord).ga;
} else if (c_variant == SHADER_VARIANT_XYUV) {
yuva.xyz = texture2D(tex, v_texcoord).bgr;
yuva.xyz = texture2D_swizzle(tex, 0, v_texcoord).bgr;
} else {
/* Never reached, bad variant value. */

View file

@ -2262,6 +2262,7 @@ blit_shadow_to_output(struct weston_output *output,
pixman_region32_t *output_damage)
{
struct gl_output_state *go = get_output_state(output);
struct gl_renderer *gr = get_renderer(output->compositor);
struct gl_shader_config sconf = {
.req = {
.variant = SHADER_VARIANT_RGBA,
@ -2282,7 +2283,6 @@ blit_shadow_to_output(struct weston_output *output,
.input_param = &go->shadow_param,
.input_num = 1,
};
struct gl_renderer *gr = get_renderer(output->compositor);
double width = go->area.width;
double height = go->area.height;
struct weston_color_transform *ctransf;
@ -2805,14 +2805,24 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer)
num_planes = yuv->output_planes;
for (out = 0; out < num_planes; out++) {
const GLint swizzles_rg[] = {
GL_RED, GL_ALPHA, GL_ZERO, GL_ONE
};
const struct pixel_format_info *info;
info = pixel_format_get_info(yuv->plane[out].format);
assert(info);
texture_format[out] = info->gl;
assert(yuv->plane[out].plane_index < (int) shm_plane_count);
/* Emulate red-green texture behaviour when
* gl_texture_2d_init() implicitly falls back to a
* luminance-alpha texture format. */
if (!gl_features_has(gr, FEATURE_TEXTURE_RG) &&
texture_format[out].internal == GL_RG8)
ARRAY_COPY(texture_format[out].swizzles.array,
swizzles_rg);
assert(yuv->plane[out].plane_index < (int) shm_plane_count);
offset[out] = shm_offset[yuv->plane[out].plane_index];
}
} else {

View file

@ -60,6 +60,9 @@ struct gl_shader {
GLint proj_uniform;
GLint surface_to_buffer_uniform;
GLint tex_uniforms[3];
GLint swizzle_idx[3];
GLint swizzle_mask[3];
GLint swizzle_sub[3];
GLint tex_uniform_wireframe;
GLint view_alpha_uniform;
GLint color_uniform;
@ -282,7 +285,7 @@ gl_shader_create(struct gl_renderer *gr,
{
bool verbose = weston_log_scope_is_enabled(gr->shader_scope);
struct gl_shader *shader = NULL;
char msg[512];
char buffer[512];
GLint status;
const char *sources[3];
char *conf = NULL;
@ -321,7 +324,12 @@ gl_shader_create(struct gl_renderer *gr,
if (!conf)
goto error_fragment;
sources[0] = "#version 100\n";
sprintf(buffer,
"#version 100\n"
"#define GLES_API_MAJOR_VERSION %d\n",
gr->gl_version >= gl_version(3, 0) ? 3 : 2);
sources[0] = buffer;
sources[1] = conf;
sources[2] = fragment_shader;
shader->fragment_shader = compile_shader(GL_FRAGMENT_SHADER,
@ -346,8 +354,9 @@ gl_shader_create(struct gl_renderer *gr,
glLinkProgram(shader->program);
glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
if (!status) {
glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
weston_log("link info: %s\n", msg);
glGetProgramInfoLog(shader->program, sizeof buffer, NULL,
buffer);
weston_log("link info: %s\n", buffer);
goto error_link;
}
@ -363,6 +372,17 @@ gl_shader_create(struct gl_renderer *gr,
if (requirements->wireframe)
shader->tex_uniform_wireframe =
glGetUniformLocation(shader->program, "tex_wireframe");
if (gr->gl_version < gl_version(3, 0)) {
shader->swizzle_idx[0] = glGetUniformLocation(shader->program, "swizzle_idx[0]");
shader->swizzle_idx[1] = glGetUniformLocation(shader->program, "swizzle_idx[1]");
shader->swizzle_idx[2] = glGetUniformLocation(shader->program, "swizzle_idx[2]");
shader->swizzle_mask[0] = glGetUniformLocation(shader->program, "swizzle_mask[0]");
shader->swizzle_mask[1] = glGetUniformLocation(shader->program, "swizzle_mask[1]");
shader->swizzle_mask[2] = glGetUniformLocation(shader->program, "swizzle_mask[2]");
shader->swizzle_sub[0] = glGetUniformLocation(shader->program, "swizzle_sub[0]");
shader->swizzle_sub[1] = glGetUniformLocation(shader->program, "swizzle_sub[1]");
shader->swizzle_sub[2] = glGetUniformLocation(shader->program, "swizzle_sub[2]");
}
shader->view_alpha_uniform = glGetUniformLocation(shader->program, "view_alpha");
if (requirements->variant == SHADER_VARIANT_SOLID) {
shader->color_uniform = glGetUniformLocation(shader->program,
@ -639,8 +659,12 @@ gl_shader_load_config(struct gl_renderer *gr,
struct gl_shader *shader,
const struct gl_shader_config *sconf)
{
GLint *swizzles;
int swizzle_idx[4];
float swizzle_mask[4];
float swizzle_sub[4];
GLsizei n_params;
int i;
int i, j;
glUniformMatrix4fv(shader->proj_uniform,
1, GL_FALSE, sconf->projection.d);
@ -659,6 +683,32 @@ gl_shader_load_config(struct gl_renderer *gr,
assert(sconf->input_num <= SHADER_INPUT_TEX_MAX);
for (i = 0; i < sconf->input_num; i++) {
assert(shader->tex_uniforms[i] != -1);
/* If the OpenGL ES implementation lacks swizzles as texture
* parameters (OpenGL ES 2), the fragment shader loads swizzling
* info from uniforms. */
if (gr->gl_version < gl_version(3, 0)) {
swizzles = sconf->input_param[i].swizzles.array;
for (j = 0; j < 4; j++) {
swizzle_idx[j] = swizzles[j] - GL_RED;
if (swizzle_idx[j] >= 0) {
/* Swizzle is GL_RED, GL_GREEN, GL_BLUE
* or GL_ALPHA. */
swizzle_mask[j] = 1.0f;
swizzle_sub[j] = 0.0f;
} else {
/* Swizzle is GL_ZERO (0) or GL_ONE
* (1). */
swizzle_idx[j] = 0;
swizzle_mask[j] = 0.0f;
swizzle_sub[j] = (float) swizzles[j];
}
}
glUniform4iv(shader->swizzle_idx[i], 1, swizzle_idx);
glUniform4fv(shader->swizzle_mask[i], 1, swizzle_mask);
glUniform4fv(shader->swizzle_sub[i], 1, swizzle_sub);
}
glUniform1i(shader->tex_uniforms[i], TEX_UNIT_IMAGES + i);
glActiveTexture(GL_TEXTURE0 + TEX_UNIT_IMAGES + i);
glBindTexture(sconf->input_param[i].target,