diff --git a/libweston/renderer-gl/gl-renderer-internal.h b/libweston/renderer-gl/gl-renderer-internal.h index b1659cdf1..57a141f46 100644 --- a/libweston/renderer-gl/gl-renderer-internal.h +++ b/libweston/renderer-gl/gl-renderer-internal.h @@ -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 diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 5d8584db4..227c587ab 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -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, ¶ms, 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; } diff --git a/libweston/renderer-gl/gl-shader-config-color-transformation.c b/libweston/renderer-gl/gl-shader-config-color-transformation.c index a578033bd..941993e70 100644 --- a/libweston/renderer-gl/gl-shader-config-color-transformation.c +++ b/libweston/renderer-gl/gl-shader-config-color-transformation.c @@ -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, ¶ms, 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, ¶ms, GL_TEXTURE_3D, filters, NULL, - true); + NULL, true); glBindTexture(GL_TEXTURE_3D, 0); gl_xform->mapping.type = SHADER_COLOR_MAPPING_3DLUT; diff --git a/libweston/renderer-gl/gl-utils.c b/libweston/renderer-gl/gl-utils.c index 8c08f4584..6f1752e54 100644 --- a/libweston/renderer-gl/gl-utils.c +++ b/libweston/renderer-gl/gl-utils.c @@ -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(¶meters->wrap_modes, wrap_modes ? wrap_modes : default_wrap_modes, sizeof default_wrap_modes); + memcpy(¶meters->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; }