From bcd04e0fade6ca7b9f8a366f5893030847f0c998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Molinari?= Date: Wed, 15 Feb 2023 14:38:32 +0100 Subject: [PATCH] gl-renderer: Derive texcoords from position in the vertex shader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let the graphics hardware handle the transformation from surface position to texture coordinates. Paint nodes now have a single vertex position attribute from which texture coordinates are derived. A new vertex shader variant handles the transformation. Signed-off-by: Loïc Molinari --- libweston/renderer-gl/gl-renderer-internal.h | 11 +++- libweston/renderer-gl/gl-renderer.c | 46 +++++++---------- libweston/renderer-gl/gl-shaders.c | 54 +++++++++++++++++--- libweston/renderer-gl/vertex.glsl | 11 ++++ 4 files changed, 87 insertions(+), 35 deletions(-) diff --git a/libweston/renderer-gl/gl-renderer-internal.h b/libweston/renderer-gl/gl-renderer-internal.h index 5b64b7bb..50320359 100644 --- a/libweston/renderer-gl/gl-renderer-internal.h +++ b/libweston/renderer-gl/gl-renderer-internal.h @@ -38,6 +38,12 @@ #include "shared/weston-egl-ext.h" /* for PFN* stuff */ #include "shared/helpers.h" +/* Keep the following in sync with vertex.glsl. */ +enum gl_shader_texcoord_input { + SHADER_TEXCOORD_INPUT_ATTRIB = 0, + SHADER_TEXCOORD_INPUT_SURFACE, +}; + enum gl_shader_texture_variant { SHADER_VARIANT_NONE = 0, /* Keep the following in sync with fragment.glsl. */ @@ -75,6 +81,8 @@ enum gl_shader_color_mapping { */ struct gl_shader_requirements { + unsigned texcoord_input:1; /* enum gl_shader_texcoord_input */ + unsigned variant:4; /* enum gl_shader_texture_variant */ bool input_is_premult:1; bool green_tint:1; @@ -86,7 +94,7 @@ struct gl_shader_requirements * The total size of all bitfields plus pad_bits_ must fill up exactly * how many bytes the compiler allocates for them together. */ - unsigned pad_bits_:22; + unsigned pad_bits_:21; }; static_assert(sizeof(struct gl_shader_requirements) == 4 /* total bitfield size in bytes */, @@ -100,6 +108,7 @@ struct gl_shader_config { struct gl_shader_requirements req; struct weston_matrix projection; + struct weston_matrix surface_to_buffer; float view_alpha; GLfloat unicolor[4]; GLint input_tex_filter; /* GL_NEAREST or GL_LINEAR */ diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 24092eeb..bc3e9d48 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -569,12 +569,10 @@ texture_region(struct weston_paint_node *pnode, pixman_region32_t *region, pixman_region32_t *surf_region) { - struct gl_surface_state *gs = get_surface_state(pnode->surface); - struct weston_buffer *buffer = gs->buffer_ref.buffer; struct weston_compositor *ec = pnode->surface->compositor; struct weston_view *ev = pnode->view; struct gl_renderer *gr = get_renderer(ec); - GLfloat *v, inv_width, inv_height; + GLfloat *v; unsigned int *vtxcnt, nvtx = 0; pixman_box32_t *rects, *surf_rects; pixman_box32_t *raw_rects; @@ -596,12 +594,9 @@ texture_region(struct weston_paint_node *pnode, /* worst case we can have 8 vertices per rect (ie. clipped into * an octagon): */ - v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 4 * sizeof *v); + v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 2 * sizeof *v); vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt); - inv_width = 1.0 / buffer->width; - inv_height = 1.0 / buffer->height; - for (i = 0; i < nrects; i++) { rect_to_quad(&rects[i], ev, &quad); for (j = 0; j < nsurf; j++) { @@ -627,23 +622,8 @@ texture_region(struct weston_paint_node *pnode, /* emit edge points: */ for (k = 0; k < n; k++) { - struct weston_coord_surface pos_s; - struct weston_coord_buffer pos_b; - - /* position: */ *(v++) = e[k].x; *(v++) = e[k].y; - - /* texcoord: */ - pos_s = weston_coord_surface(e[k].x, e[k].y, ev->surface); - pos_b = weston_coord_surface_to_buffer(ev->surface, pos_s); - - *(v++) = pos_b.c.x * inv_width; - if (buffer->buffer_origin == ORIGIN_TOP_LEFT) { - *(v++) = pos_b.c.y * inv_height; - } else { - *(v++) = (buffer->height - pos_b.c.y) * inv_height; - } } vtxcnt[nvtx++] = n; @@ -1065,9 +1045,7 @@ repaint_region(struct gl_renderer *gr, vtxcnt = gr->vtxcnt.data; /* position: */ - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]); - /* texcoord: */ - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[2]); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof *v, v); if (!gl_renderer_use_program(gr, sconf)) { gl_renderer_send_shader_error(pnode); @@ -1264,18 +1242,33 @@ gl_shader_config_init_for_paint_node(struct gl_shader_config *sconf, { struct gl_surface_state *gs = get_surface_state(pnode->surface); struct gl_output_state *go = get_output_state(pnode->output); + struct weston_buffer *buffer = gs->buffer_ref.buffer; if (!pnode->surf_xform_valid) return false; *sconf = (struct gl_shader_config) { + .req.texcoord_input = SHADER_TEXCOORD_INPUT_SURFACE, .projection = pnode->view->transform.matrix, + .surface_to_buffer = + pnode->view->surface->surface_to_buffer_matrix, .view_alpha = pnode->view->alpha, .input_tex_filter = filter, }; weston_matrix_multiply(&sconf->projection, &go->output_matrix); + if (buffer->buffer_origin == ORIGIN_TOP_LEFT) { + weston_matrix_scale(&sconf->surface_to_buffer, + 1.0f / buffer->width, + 1.0f / buffer->height, 1); + } else { + weston_matrix_scale(&sconf->surface_to_buffer, + 1.0f / buffer->width, + -1.0f / buffer->height, 1); + weston_matrix_translate(&sconf->surface_to_buffer, 0, 1, 0); + } + gl_shader_config_set_input_textures(sconf, gs); if (!gl_shader_config_set_color_transform(sconf, pnode->surf_xform.transform)) { @@ -1387,9 +1380,7 @@ repaint_views(struct weston_output *output, pixman_region32_t *damage) struct weston_paint_node *pnode; glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); wl_list_for_each_reverse(pnode, &output->paint_node_z_order_list, z_order_link) { @@ -1397,7 +1388,6 @@ repaint_views(struct weston_output *output, pixman_region32_t *damage) draw_paint_node(pnode, damage); } - glDisableVertexAttribArray(1); glDisableVertexAttribArray(0); } diff --git a/libweston/renderer-gl/gl-shaders.c b/libweston/renderer-gl/gl-shaders.c index 8effa18e..88e84fb6 100644 --- a/libweston/renderer-gl/gl-shaders.c +++ b/libweston/renderer-gl/gl-shaders.c @@ -56,6 +56,7 @@ struct gl_shader { GLuint program; GLuint vertex_shader, fragment_shader; GLint proj_uniform; + GLint surface_to_buffer_uniform; GLint tex_uniforms[3]; GLint view_alpha_uniform; GLint color_uniform; @@ -74,6 +75,19 @@ struct gl_shader { struct timespec last_used; }; +static const char * +gl_shader_texcoord_input_to_string(enum gl_shader_texcoord_input kind) +{ + switch (kind) { +#define CASERET(x) case x: return #x; + CASERET(SHADER_TEXCOORD_INPUT_SURFACE) + CASERET(SHADER_TEXCOORD_INPUT_ATTRIB) +#undef CASERET + } + + return "!?!?"; /* never reached */ +} + static const char * gl_shader_texture_variant_to_string(enum gl_shader_texture_variant v) { @@ -186,7 +200,8 @@ create_shader_description_string(const struct gl_shader_requirements *req) int size; char *str; - size = asprintf(&str, "%s %s %s %s %cinput_is_premult %cgreen", + size = asprintf(&str, "%s %s %s %s %s %cinput_is_premult %cgreen", + gl_shader_texcoord_input_to_string(req->variant), gl_shader_texture_variant_to_string(req->variant), gl_shader_color_curve_to_string(req->color_pre_curve), gl_shader_color_mapping_to_string(req->color_mapping), @@ -199,7 +214,21 @@ create_shader_description_string(const struct gl_shader_requirements *req) } static char * -create_shader_config_string(const struct gl_shader_requirements *req) +create_vertex_shader_config_string(const struct gl_shader_requirements *req) +{ + int size; + char *str; + + size = asprintf(&str, + "#define DEF_TEXCOORD_INPUT %s\n", + gl_shader_texcoord_input_to_string(req->texcoord_input)); + if (size < 0) + return NULL; + return str; +} + +static char * +create_fragment_shader_config_string(const struct gl_shader_requirements *req) { int size; char *str; @@ -252,12 +281,18 @@ gl_shader_create(struct gl_renderer *gr, free(desc); } - sources[0] = vertex_shader; - shader->vertex_shader = compile_shader(GL_VERTEX_SHADER, 1, sources); + conf = create_vertex_shader_config_string(&shader->key); + if (!conf) + goto error_vertex; + + sources[0] = conf; + sources[1] = vertex_shader; + shader->vertex_shader = compile_shader(GL_VERTEX_SHADER, 2, sources); if (shader->vertex_shader == GL_NONE) goto error_vertex; - conf = create_shader_config_string(&shader->key); + free(conf); + conf = create_fragment_shader_config_string(&shader->key); if (!conf) goto error_fragment; @@ -273,7 +308,8 @@ gl_shader_create(struct gl_renderer *gr, glAttachShader(shader->program, shader->vertex_shader); glAttachShader(shader->program, shader->fragment_shader); glBindAttribLocation(shader->program, 0, "position"); - glBindAttribLocation(shader->program, 1, "texcoord"); + if (requirements->texcoord_input == SHADER_TEXCOORD_INPUT_ATTRIB) + glBindAttribLocation(shader->program, 1, "texcoord"); glLinkProgram(shader->program); glGetProgramiv(shader->program, GL_LINK_STATUS, &status); @@ -287,6 +323,8 @@ gl_shader_create(struct gl_renderer *gr, glDeleteShader(shader->fragment_shader); shader->proj_uniform = glGetUniformLocation(shader->program, "proj"); + shader->surface_to_buffer_uniform = + glGetUniformLocation(shader->program, "surface_to_buffer"); shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex"); shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1"); shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2"); @@ -540,6 +578,10 @@ gl_shader_load_config(struct gl_shader *shader, glUniformMatrix4fv(shader->proj_uniform, 1, GL_FALSE, sconf->projection.d); + if (shader->surface_to_buffer_uniform != -1) + glUniformMatrix4fv(shader->surface_to_buffer_uniform, + 1, GL_FALSE, sconf->surface_to_buffer.d); + if (shader->color_uniform != -1) glUniform4fv(shader->color_uniform, 1, sconf->unicolor); diff --git a/libweston/renderer-gl/vertex.glsl b/libweston/renderer-gl/vertex.glsl index 8b8019c3..d798eced 100644 --- a/libweston/renderer-gl/vertex.glsl +++ b/libweston/renderer-gl/vertex.glsl @@ -25,6 +25,10 @@ * SOFTWARE. */ +/* enum gl_shader_texcoord_input */ +#define SHADER_TEXCOORD_INPUT_ATTRIB 0 +#define SHADER_TEXCOORD_INPUT_SURFACE 1 + /* Always use high-precision for vertex calculations */ precision highp float; @@ -35,6 +39,8 @@ precision highp float; #endif uniform mat4 proj; +uniform mat4 surface_to_buffer; + attribute vec2 position; attribute vec2 texcoord; @@ -44,5 +50,10 @@ varying FRAG_PRECISION vec2 v_texcoord; void main() { gl_Position = proj * vec4(position, 0.0, 1.0); + +#if DEF_TEXCOORD_INPUT == SHADER_TEXCOORD_INPUT_ATTRIB v_texcoord = texcoord; +#elif DEF_TEXCOORD_INPUT == SHADER_TEXCOORD_INPUT_SURFACE + v_texcoord = vec2(surface_to_buffer * vec4(position, 0.0, 1.0)); +#endif }