gl-renderer: Derive texcoords from position in the vertex shader
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 <loic.molinari@gmail.com>
This commit is contained in:
parent
a4d31fa8bd
commit
bcd04e0fad
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user