From 145d6f687701a2ba1e2d63209d2cc2812a47f4b7 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Wed, 13 Mar 2019 23:26:24 +0000 Subject: [PATCH 1/8] gl_common: add vertex shader Also use an attribute for the texture coordinates. Signed-off-by: Yuxuan Shui --- src/backend/gl/gl_common.c | 59 +++++++++++++++++++++++++++++--------- src/backend/gl/gl_common.h | 2 ++ 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index f7aa943e..45780654 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -259,7 +259,8 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, GLint vy[] = {vy1, vy1, vy2, vy2}; for (int i = 0; i < 4; i++) { - glTexCoord2f(texture_x[i], texture_y[i]); + glVertexAttrib2f(gd->win_shader.in_texcoord, texture_x[i], + texture_y[i]); glVertex3i(vx[i], vy[i], 0); } } @@ -386,7 +387,7 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur, GLint vy[] = {vy1, vy1, vy2, vy2}; for (int k = 0; k < 4; k++) { - glTexCoord2f(texture_x[k], texture_y[k]); + glVertexAttrib2f(p->in_texcoord, texture_x[k], texture_y[k]); glVertex3i(vx[k], vy[k], 0); } } @@ -418,6 +419,19 @@ static GLint glGetUniformLocationChecked(GLuint p, const char *name) { return ret; } +// clang-format off +const char *vertex_shader = GLSL(130, + uniform mat4 projection; + in vec2 in_texcoord; + out vec2 texcoord; + void main() { + gl_Position = projection * gl_Vertex; + texcoord = in_texcoord; + } + +); +// clang-format on + /** * Load a GLSL main program from shader strings. */ @@ -435,6 +449,7 @@ static int gl_win_shader_from_string(const char *vshader_str, const char *fshade ret->unifm_invert_color = glGetUniformLocationChecked(ret->prog, "invert_color"); ret->unifm_tex = glGetUniformLocationChecked(ret->prog, "tex"); ret->unifm_dim = glGetUniformLocationChecked(ret->prog, "dim"); + ret->in_texcoord = glGetAttribLocation(ret->prog, "in_texcoord"); gl_check_err(); @@ -446,15 +461,13 @@ static int gl_win_shader_from_string(const char *vshader_str, const char *fshade */ void gl_resize(struct gl_data *gd, int width, int height) { glViewport(0, 0, width, height); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, width, 0, height, -1000.0, 1000.0); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); gd->height = height; gd->width = width; + // Note: OpenGL matrices are column major + GLfloat projection_matrix[4][4] = { + {2.0 / width, 0, 0, 0}, {0, 2.0 / height, 0, 0}, {0, 0, 0, 0}, {-1, -1, 0, 1}}; + if (gd->npasses > 0) { // Resize the temporary textures used for blur glBindTexture(GL_TEXTURE_2D, gd->blur_texture[0]); @@ -465,7 +478,22 @@ void gl_resize(struct gl_data *gd, int width, int height) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, gd->width, gd->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); } + + // Update projection matrices in the blur shaders + for (int i = 0; i < gd->npasses; i++) { + assert(gd->blur_shader[i].prog); + glUseProgram(gd->blur_shader[i].prog); + int pml = glGetUniformLocationChecked(gd->blur_shader[i].prog, + "projection"); + glUniformMatrix4fv(pml, 1, false, projection_matrix[0]); + } } + // Update projection matrix in the win shader + glUseProgram(gd->win_shader.prog); + int pml = glGetUniformLocationChecked(gd->win_shader.prog, "projection"); + glUniformMatrix4fv(pml, 1, false, projection_matrix[0]); + + gl_check_err(); } void gl_fill(backend_t *base, double r, double g, double b, double a, const region_t *clip) { @@ -503,6 +531,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) { uniform float offset_y; uniform sampler2D tex_scr; uniform float opacity; + in vec2 texcoord; out vec4 out_color; void main() { vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); @@ -512,8 +541,8 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) { ); static const char *FRAG_SHADER_BLUR_ADD = QUOTE( sum += float(%.7g) * - texture2D(tex_scr, vec2(gl_TexCoord[0].x + offset_x * float(%d), - gl_TexCoord[0].y + offset_y * float(%d))); + texture2D(tex_scr, vec2(texcoord.x + offset_x * float(%d), + texcoord.y + offset_y * float(%d))); ); // clang-format on @@ -562,7 +591,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) { free(shader_body); // Build program - pass->prog = gl_create_program_from_str(NULL, shader_str); + pass->prog = gl_create_program_from_str(vertex_shader, shader_str); free(shader_str); if (!pass->prog) { log_error("Failed to create GLSL program."); @@ -576,6 +605,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) { pass->unifm_offset_y = glGetUniformLocationChecked(pass->prog, "offset_y"); pass->unifm_opacity = glGetUniformLocationChecked(pass->prog, "opacity"); + pass->in_texcoord = glGetAttribLocation(pass->prog, "in_texcoord"); } free(extension); @@ -611,14 +641,15 @@ err: } // clang-format off -const char *win_shader_glsl = GLSL(110, +const char *win_shader_glsl = GLSL(130, uniform float opacity; uniform float dim; uniform bool invert_color; + in vec2 texcoord; uniform sampler2D tex; void main() { - vec4 c = texture2D(tex, gl_TexCoord[0].xy); + vec4 c = texture2D(tex, texcoord.xy); if (invert_color) { c = vec4(c.aaa - c.rgb, c.a); } @@ -652,7 +683,7 @@ bool gl_init(struct gl_data *gd, session_t *ps) { glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); gd->npasses = 0; - gl_win_shader_from_string(NULL, win_shader_glsl, &gd->win_shader); + gl_win_shader_from_string(vertex_shader, win_shader_glsl, &gd->win_shader); if (!gl_init_blur(gd, ps->o.blur_kerns)) { return false; } diff --git a/src/backend/gl/gl_common.h b/src/backend/gl/gl_common.h index 2ada4dba..5f492d06 100644 --- a/src/backend/gl/gl_common.h +++ b/src/backend/gl/gl_common.h @@ -21,6 +21,7 @@ typedef struct { GLint unifm_invert_color; GLint unifm_tex; GLint unifm_dim; + GLint in_texcoord; } gl_win_shader_t; // Program and uniforms for blur shader @@ -29,6 +30,7 @@ typedef struct { GLint unifm_offset_x; GLint unifm_offset_y; GLint unifm_opacity; + GLint in_texcoord; } gl_blur_shader_t; /// @brief Wrapper of a binded GLX texture. From 874e123ef50ae48725b73e8a921a116bd8da6a88 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Wed, 27 Mar 2019 20:35:26 +0000 Subject: [PATCH 2/8] gl_common: remove some fixed function glEnable/Disable Signed-off-by: Yuxuan Shui --- src/backend/gl/gl_common.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index 45780654..5f0eb7ea 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -181,9 +181,6 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, bool dual_texture = false; - // It's required by legacy versions of OpenGL to enable texture target - // before specifying environment. Thanks to madsy for telling me. - glEnable(GL_TEXTURE_2D); if (gd->win_shader.prog) { glUseProgram(gd->win_shader.prog); if (gd->win_shader.unifm_opacity >= 0) { @@ -271,12 +268,10 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, glBindTexture(GL_TEXTURE_2D, 0); glColor4f(0.0f, 0.0f, 0.0f, 0.0f); glDisable(GL_COLOR_LOGIC_OP); - glDisable(GL_TEXTURE_2D); if (dual_texture) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); } @@ -306,7 +301,6 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur, int curr = 0; glReadBuffer(GL_BACK); - glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, gd->blur_texture[0]); // Copy the area to be blurred into tmp buffer glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, extent->x1, dst_y, width, height); @@ -402,7 +396,6 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur, end: glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); gl_check_err(); @@ -737,7 +730,6 @@ GLuint gl_new_texture(GLenum target) { return 0; } - glEnable(target); glBindTexture(target, texture); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); From efd717fb862e3530de73281aa0a043c544f44b68 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sun, 31 Mar 2019 18:15:14 +0100 Subject: [PATCH 3/8] gl_common: fix implicit conversion warnings Signed-off-by: Yuxuan Shui --- src/backend/gl/gl_common.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index 5f0eb7ea..71ee9a88 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -256,7 +256,7 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, GLint vy[] = {vy1, vy1, vy2, vy2}; for (int i = 0; i < 4; i++) { - glVertexAttrib2f(gd->win_shader.in_texcoord, texture_x[i], + glVertexAttrib2f((GLuint)gd->win_shader.in_texcoord, texture_x[i], texture_y[i]); glVertex3i(vx[i], vy[i], 0); } @@ -381,7 +381,8 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur, GLint vy[] = {vy1, vy1, vy2, vy2}; for (int k = 0; k < 4; k++) { - glVertexAttrib2f(p->in_texcoord, texture_x[k], texture_y[k]); + glVertexAttrib2f((GLuint)p->in_texcoord, texture_x[k], + texture_y[k]); glVertex3i(vx[k], vy[k], 0); } } @@ -458,8 +459,10 @@ void gl_resize(struct gl_data *gd, int width, int height) { gd->width = width; // Note: OpenGL matrices are column major - GLfloat projection_matrix[4][4] = { - {2.0 / width, 0, 0, 0}, {0, 2.0 / height, 0, 0}, {0, 0, 0, 0}, {-1, -1, 0, 1}}; + GLfloat projection_matrix[4][4] = {{2.0f / (GLfloat)width, 0, 0, 0}, + {0, 2.0f / (GLfloat)height, 0, 0}, + {0, 0, 0, 0}, + {-1, -1, 0, 1}}; if (gd->npasses > 0) { // Resize the temporary textures used for blur @@ -577,8 +580,8 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) { strlen(shader_body) + 10 /* sum */ + 1 /* null terminator */; char *shader_str = ccalloc(shader_len, char); - auto real_shader_len = snprintf( - shader_str, shader_len, FRAG_SHADER_BLUR, extension, shader_body, sum); + auto real_shader_len = snprintf(shader_str, shader_len, FRAG_SHADER_BLUR, + extension, shader_body, sum); CHECK(real_shader_len >= 0); CHECK((size_t)real_shader_len < shader_len); free(shader_body); From 0366151a91251e8c2b7c73bac5514fab61366703 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Mon, 1 Apr 2019 19:34:02 +0100 Subject: [PATCH 4/8] gl_common: update gl_fill to core profile Signed-off-by: Yuxuan Shui --- src/backend/gl/gl_common.c | 68 +++++++++++++++++++++++++++++++++----- src/backend/gl/gl_common.h | 7 ++++ 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index 71ee9a88..d7a6cd78 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -422,7 +422,6 @@ const char *vertex_shader = GLSL(130, gl_Position = projection * gl_Vertex; texcoord = in_texcoord; } - ); // clang-format on @@ -489,22 +488,71 @@ void gl_resize(struct gl_data *gd, int width, int height) { int pml = glGetUniformLocationChecked(gd->win_shader.prog, "projection"); glUniformMatrix4fv(pml, 1, false, projection_matrix[0]); + glUseProgram(gd->fill_shader.prog); + pml = glGetUniformLocationChecked(gd->fill_shader.prog, "projection"); + glUniformMatrix4fv(pml, 1, false, projection_matrix[0]); + gl_check_err(); } +// clang-format off +static const char fill_frag[] = GLSL(120, + uniform vec4 color; + void main() { + gl_FragColor = color; + } +); + +static const char fill_vert[] = GLSL(130, + in vec2 in_coord; + uniform mat4 projection; + void main() { + gl_Position = projection * vec4(in_coord, 0, 1); + } +); +// clang-format on + void gl_fill(backend_t *base, double r, double g, double b, double a, const region_t *clip) { int nrects; const rect_t *rect = pixman_region32_rectangles((region_t *)clip, &nrects); struct gl_data *gd = (void *)base; - glColor4d(r, g, b, a); - glBegin(GL_QUADS); + GLuint bo[2]; + glGenBuffers(2, bo); + glUseProgram(gd->fill_shader.prog); + glUniform4f(gd->fill_shader.color_loc, (GLfloat)r, (GLfloat)g, (GLfloat)b, + (GLfloat)a); + glEnableVertexAttribArray((GLuint)gd->fill_shader.in_coord_loc); + glBindBuffer(GL_ARRAY_BUFFER, bo[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[1]); + + auto coord = ccalloc(nrects * 8, GLint); + auto indices = ccalloc(nrects * 6, GLuint); for (int i = 0; i < nrects; i++) { - glVertex2i(rect[i].x1, gd->height - rect[i].y2); - glVertex2i(rect[i].x2, gd->height - rect[i].y2); - glVertex2i(rect[i].x2, gd->height - rect[i].y1); - glVertex2i(rect[i].x1, gd->height - rect[i].y1); + memcpy(&coord[i * 8], + (GLint[][2]){{rect[i].x1, gd->height - rect[i].y2}, + {rect[i].x2, gd->height - rect[i].y2}, + {rect[i].x2, gd->height - rect[i].y1}, + {rect[i].x1, gd->height - rect[i].y1}}, + sizeof(GLint[2]) * 4); + indices[i * 6 + 0] = (GLuint)i * 4 + 0; + indices[i * 6 + 1] = (GLuint)i * 4 + 1; + indices[i * 6 + 2] = (GLuint)i * 4 + 2; + indices[i * 6 + 3] = (GLuint)i * 4 + 2; + indices[i * 6 + 4] = (GLuint)i * 4 + 3; + indices[i * 6 + 5] = (GLuint)i * 4 + 0; } - glEnd(); + glBufferData(GL_ARRAY_BUFFER, nrects * 8 * (long)sizeof(*coord), coord, GL_STREAM_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, nrects * 6 * (long)sizeof(*indices), + indices, GL_STREAM_DRAW); + + glVertexAttribPointer((GLuint)gd->fill_shader.in_coord_loc, 2, GL_INT, GL_FALSE, + sizeof(*coord) * 2, (void *)0); + glDrawElements(GL_TRIANGLES, nrects * 6, GL_UNSIGNED_INT, NULL); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glDisableVertexAttribArray((GLuint)gd->fill_shader.in_coord_loc); + + glDeleteBuffers(2, bo); } /** @@ -683,6 +731,10 @@ bool gl_init(struct gl_data *gd, session_t *ps) { if (!gl_init_blur(gd, ps->o.blur_kerns)) { return false; } + gd->fill_shader.prog = gl_create_program_from_str(fill_vert, fill_frag); + gd->fill_shader.in_coord_loc = + glGetAttribLocation(gd->fill_shader.prog, "in_coord"); + gd->fill_shader.color_loc = glGetUniformLocation(gd->fill_shader.prog, "color"); // Set up the size of the viewport. We do this last because it expects the blur // textures are already set up. diff --git a/src/backend/gl/gl_common.h b/src/backend/gl/gl_common.h index 5f492d06..252a1412 100644 --- a/src/backend/gl/gl_common.h +++ b/src/backend/gl/gl_common.h @@ -33,6 +33,12 @@ typedef struct { GLint in_texcoord; } gl_blur_shader_t; +typedef struct { + GLuint prog; + GLint in_coord_loc; + GLint color_loc; +} gl_fill_shader_t; + /// @brief Wrapper of a binded GLX texture. typedef struct gl_texture { double opacity; @@ -55,6 +61,7 @@ struct gl_data { int height, width; int npasses; gl_win_shader_t win_shader; + gl_fill_shader_t fill_shader; gl_blur_shader_t blur_shader[MAX_BLUR_PASS]; // Temporary textures used for blurring. They are always the same size as the From acd64ebbbbb3e24b818a4d3180f31e058a586bdb Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Mon, 1 Apr 2019 19:43:24 +0100 Subject: [PATCH 5/8] gl_common: update gl_blur to core profile Signed-off-by: Yuxuan Shui --- src/backend/gl/gl_common.c | 146 +++++++++++++++++++++++-------------- src/backend/gl/gl_common.h | 2 + 2 files changed, 95 insertions(+), 53 deletions(-) diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index d7a6cd78..e5f7c0cf 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -299,6 +299,66 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur, // these should be arguments bool ret = false; + int nrects; + const rect_t *rect = pixman_region32_rectangles((region_t *)reg_blur, &nrects); + if (!nrects) { + return true; + } + + auto coord = ccalloc(nrects * 16, GLfloat); + auto indices = ccalloc(nrects * 6, GLuint); + for (int i = 0; i < nrects; i++) { + rect_t crect = rect[i]; + // flip y axis, because the regions are in Xorg's coordinates, + // which is y-flipped from OpenGL's. + crect.y1 = gd->height - crect.y1; + crect.y2 = gd->height - crect.y2; + + // Texture coordinates + auto texture_x1 = (GLfloat)(crect.x1 - extent->x1); + auto texture_y1 = (GLfloat)(crect.y2 - dst_y); + auto texture_x2 = texture_x1 + (GLfloat)(crect.x2 - crect.x1); + auto texture_y2 = texture_y1 + (GLfloat)(crect.y1 - crect.y2); + + texture_x1 /= (GLfloat)gd->width; + texture_x2 /= (GLfloat)gd->width; + texture_y1 /= (GLfloat)gd->height; + texture_y2 /= (GLfloat)gd->height; + + // Vertex coordinates + // For passes before the last one, we are drawing into a buffer, + // so (dx, dy) from source maps to (0, 0) + auto vx1 = (GLfloat)(crect.x1 - extent->x1); + auto vy1 = (GLfloat)(crect.y2 - dst_y); + auto vx2 = vx1 + (GLfloat)(crect.x2 - crect.x1); + auto vy2 = vy1 + (GLfloat)(crect.y1 - crect.y2); + + memcpy(&coord[i * 16], + (GLfloat[][2]){ + {vx1, vy1}, + {texture_x1, texture_y1}, + {vx2, vy1}, + {texture_x2, texture_y1}, + {vx2, vy2}, + {texture_x2, texture_y2}, + {vx1, vy2}, + {texture_x1, texture_y2}, + }, + sizeof(GLfloat[2]) * 8); + + GLuint u = (GLuint)(i * 4); + memcpy(&indices[i * 6], (GLuint[]){u + 0, u + 1, u + 2, u + 2, u + 3, u + 0}, + sizeof(GLuint) * 6); + } + + GLuint bo[2]; + glGenBuffers(2, bo); + glBindBuffer(GL_ARRAY_BUFFER, bo[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[1]); + glBufferData(GL_ARRAY_BUFFER, (long)sizeof(*coord) * nrects * 16, coord, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, (long)sizeof(*indices) * nrects * 6, + indices, GL_STATIC_DRAW); + int curr = 0; glReadBuffer(GL_BACK); glBindTexture(GL_TEXTURE_2D, gd->blur_texture[0]); @@ -332,63 +392,30 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur, glDrawBuffer(GL_BACK); glUniform1f(p->unifm_opacity, (float)opacity); } + if (i == gd->npasses - 1) { + // For last pass, we are drawing back to source, so we need to + // translate the render region + glUniform2f(p->orig_loc, (GLfloat)extent->x1, (GLfloat)dst_y); + } else { + glUniform2f(p->orig_loc, 0, 0); + } glUniform1f(p->unifm_offset_x, 1.0f / (GLfloat)gd->width); glUniform1f(p->unifm_offset_y, 1.0f / (GLfloat)gd->height); + glEnableVertexAttribArray((GLuint)p->coord_loc); + glEnableVertexAttribArray((GLuint)p->in_texcoord); + glVertexAttribPointer((GLuint)p->coord_loc, 2, GL_FLOAT, GL_FALSE, + sizeof(GLfloat) * 4, NULL); + glVertexAttribPointer((GLuint)p->in_texcoord, 2, GL_FLOAT, GL_FALSE, + sizeof(GLfloat) * 4, (void *)(sizeof(GLfloat) * 2)); + glDrawElements(GL_TRIANGLES, nrects * 6, GL_UNSIGNED_INT, NULL); + glDisableVertexAttribArray((GLuint)p->coord_loc); + glDisableVertexAttribArray((GLuint)p->in_texcoord); + // XXX use multiple draw calls is probably going to be slow than // just simply blur the whole area. - int nrects; - const rect_t *rect = - pixman_region32_rectangles((region_t *)reg_blur, &nrects); - glBegin(GL_QUADS); - for (int j = 0; j < nrects; j++) { - rect_t crect = rect[j]; - // flip y axis, because the regions are in Xorg's coordinates, - // which is y-flipped from OpenGL's. - crect.y1 = gd->height - crect.y1; - crect.y2 = gd->height - crect.y2; - - // Texture coordinates - auto texture_x1 = (GLfloat)(crect.x1 - extent->x1); - auto texture_y1 = (GLfloat)(crect.y2 - dst_y); - auto texture_x2 = texture_x1 + (GLfloat)(crect.x2 - crect.x1); - auto texture_y2 = texture_y1 + (GLfloat)(crect.y1 - crect.y2); - - texture_x1 /= (GLfloat)gd->width; - texture_x2 /= (GLfloat)gd->width; - texture_y1 /= (GLfloat)gd->height; - texture_y2 /= (GLfloat)gd->height; - - // Vertex coordinates - // For passes before the last one, we are drawing into a buffer, - // so (dx, dy) from source maps to (0, 0) - GLint vx1 = crect.x1 - extent->x1; - GLint vy1 = crect.y2 - dst_y; - if (i == gd->npasses - 1) { - // For last pass, we are drawing back to source, so we - // don't need to map - vx1 = crect.x1; - vy1 = crect.y2; - } - GLint vx2 = vx1 + (crect.x2 - crect.x1); - GLint vy2 = vy1 + (crect.y1 - crect.y2); - - GLfloat texture_x[] = {texture_x1, texture_x2, texture_x2, texture_x1}; - GLfloat texture_y[] = {texture_y1, texture_y1, texture_y2, texture_y2}; - GLint vx[] = {vx1, vx2, vx2, vx1}; - GLint vy[] = {vy1, vy1, vy2, vy2}; - - for (int k = 0; k < 4; k++) { - glVertexAttrib2f((GLuint)p->in_texcoord, texture_x[k], - texture_y[k]); - glVertex3i(vx[k], vy[k], 0); - } - } - glEnd(); - - glUseProgram(0); curr = !curr; } @@ -397,6 +424,12 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur, end: glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glDeleteBuffers(2, bo); + + free(indices); + free(coord); gl_check_err(); @@ -416,10 +449,12 @@ static GLint glGetUniformLocationChecked(GLuint p, const char *name) { // clang-format off const char *vertex_shader = GLSL(130, uniform mat4 projection; + uniform vec2 orig; + in vec2 coord; in vec2 in_texcoord; out vec2 texcoord; void main() { - gl_Position = projection * gl_Vertex; + gl_Position = projection * vec4(coord + orig, 0, 1); texcoord = in_texcoord; } ); @@ -444,6 +479,10 @@ static int gl_win_shader_from_string(const char *vshader_str, const char *fshade ret->unifm_dim = glGetUniformLocationChecked(ret->prog, "dim"); ret->in_texcoord = glGetAttribLocation(ret->prog, "in_texcoord"); + glUseProgram(ret->prog); + int orig_loc = glGetUniformLocation(ret->prog, "orig"); + glUniform2f(orig_loc, 0, 0); + gl_check_err(); return true; @@ -519,8 +558,7 @@ void gl_fill(backend_t *base, double r, double g, double b, double a, const regi GLuint bo[2]; glGenBuffers(2, bo); glUseProgram(gd->fill_shader.prog); - glUniform4f(gd->fill_shader.color_loc, (GLfloat)r, (GLfloat)g, (GLfloat)b, - (GLfloat)a); + glUniform4f(gd->fill_shader.color_loc, (GLfloat)r, (GLfloat)g, (GLfloat)b, (GLfloat)a); glEnableVertexAttribArray((GLuint)gd->fill_shader.in_coord_loc); glBindBuffer(GL_ARRAY_BUFFER, bo[0]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[1]); @@ -649,7 +687,9 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) { pass->unifm_offset_y = glGetUniformLocationChecked(pass->prog, "offset_y"); pass->unifm_opacity = glGetUniformLocationChecked(pass->prog, "opacity"); + pass->orig_loc = glGetUniformLocationChecked(pass->prog, "orig"); pass->in_texcoord = glGetAttribLocation(pass->prog, "in_texcoord"); + pass->coord_loc = glGetAttribLocation(pass->prog, "coord"); } free(extension); diff --git a/src/backend/gl/gl_common.h b/src/backend/gl/gl_common.h index 252a1412..f0598fff 100644 --- a/src/backend/gl/gl_common.h +++ b/src/backend/gl/gl_common.h @@ -30,6 +30,8 @@ typedef struct { GLint unifm_offset_x; GLint unifm_offset_y; GLint unifm_opacity; + GLint orig_loc; + GLint coord_loc; GLint in_texcoord; } gl_blur_shader_t; From 7698f9c6426e157cc564d8f47f7fe1def13da449 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Mon, 1 Apr 2019 19:55:11 +0100 Subject: [PATCH 6/8] gl_common: update gl_compose to core profile Signed-off-by: Yuxuan Shui --- src/backend/gl/gl_common.c | 108 +++++++++++++++++++++++-------------- src/backend/gl/gl_common.h | 1 + 2 files changed, 70 insertions(+), 39 deletions(-) diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index e5f7c0cf..35b868b1 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -174,6 +174,15 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, return; } + // Painting + int nrects; + const rect_t *rects; + rects = pixman_region32_rectangles((region_t *)reg_tgt, &nrects); + if (!nrects) { + // Nothing to paint + return; + } + // dst_y is the top coordinate, in OpenGL, it is the upper bound of the y // coordinate. dst_y = gd->height - dst_y; @@ -181,20 +190,19 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, bool dual_texture = false; - if (gd->win_shader.prog) { - glUseProgram(gd->win_shader.prog); - if (gd->win_shader.unifm_opacity >= 0) { - glUniform1f(gd->win_shader.unifm_opacity, (float)ptex->opacity); - } - if (gd->win_shader.unifm_invert_color >= 0) { - glUniform1i(gd->win_shader.unifm_invert_color, ptex->color_inverted); - } - if (gd->win_shader.unifm_tex >= 0) { - glUniform1i(gd->win_shader.unifm_tex, 0); - } - if (gd->win_shader.unifm_dim >= 0) { - glUniform1f(gd->win_shader.unifm_dim, (float)ptex->dim); - } + assert(gd->win_shader.prog); + glUseProgram(gd->win_shader.prog); + if (gd->win_shader.unifm_opacity >= 0) { + glUniform1f(gd->win_shader.unifm_opacity, (float)ptex->opacity); + } + if (gd->win_shader.unifm_invert_color >= 0) { + glUniform1i(gd->win_shader.unifm_invert_color, ptex->color_inverted); + } + if (gd->win_shader.unifm_tex >= 0) { + glUniform1i(gd->win_shader.unifm_tex, 0); + } + if (gd->win_shader.unifm_dim >= 0) { + glUniform1f(gd->win_shader.unifm_dim, (float)ptex->dim); } // log_trace("Draw: %d, %d, %d, %d -> %d, %d (%d, %d) z %d\n", @@ -207,17 +215,12 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, glBindTexture(GL_TEXTURE_2D, ptex->texture); glActiveTexture(GL_TEXTURE0); } + auto coord = ccalloc(nrects * 16, GLfloat); + auto indices = ccalloc(nrects * 6, GLuint); - // Painting - int nrects; - - const rect_t *rects; - rects = pixman_region32_rectangles((region_t *)reg_tgt, &nrects); - - glBegin(GL_QUADS); - for (int ri = 0; ri < nrects; ++ri) { + for (int i = 0; i < nrects; ++i) { // Y-flip. Note after this, crect.y1 > crect.y2 - rect_t crect = rects[ri]; + rect_t crect = rects[i]; crect.y1 = gd->height - crect.y1; crect.y2 = gd->height - crect.y2; @@ -242,32 +245,52 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, texture_y2 /= (GLfloat)ptex->height; // Vertex coordinates - GLint vx1 = crect.x1; - GLint vy1 = crect.y2; - GLint vx2 = crect.x2; - GLint vy2 = crect.y1; + auto vx1 = (GLfloat)crect.x1; + auto vy1 = (GLfloat)crect.y2; + auto vx2 = (GLfloat)crect.x2; + auto vy2 = (GLfloat)crect.y1; // log_trace("Rect %d: %f, %f, %f, %f -> %d, %d, %d, %d", // ri, rx, ry, rxe, rye, rdx, rdy, rdxe, rdye); - GLfloat texture_x[] = {texture_x1, texture_x2, texture_x2, texture_x1}; - GLfloat texture_y[] = {texture_y1, texture_y1, texture_y2, texture_y2}; - GLint vx[] = {vx1, vx2, vx2, vx1}; - GLint vy[] = {vy1, vy1, vy2, vy2}; + memcpy(&coord[i * 16], + (GLfloat[][2]){ + {vx1, vy1}, + {texture_x1, texture_y1}, + {vx2, vy1}, + {texture_x2, texture_y1}, + {vx2, vy2}, + {texture_x2, texture_y2}, + {vx1, vy2}, + {texture_x1, texture_y2}, + }, + sizeof(GLfloat[2]) * 8); - for (int i = 0; i < 4; i++) { - glVertexAttrib2f((GLuint)gd->win_shader.in_texcoord, texture_x[i], - texture_y[i]); - glVertex3i(vx[i], vy[i], 0); - } + GLuint u = (GLuint)(i * 4); + memcpy(&indices[i * 6], (GLuint[]){u + 0, u + 1, u + 2, u + 2, u + 3, u + 0}, + sizeof(GLuint) * 6); } - glEnd(); + GLuint bo[2]; + glGenBuffers(2, bo); + glBindBuffer(GL_ARRAY_BUFFER, bo[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[1]); + glBufferData(GL_ARRAY_BUFFER, (long)sizeof(*coord) * nrects * 16, coord, GL_STATIC_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, (long)sizeof(*indices) * nrects * 6, + indices, GL_STATIC_DRAW); + + glEnableVertexAttribArray((GLuint)gd->win_shader.coord_loc); + glEnableVertexAttribArray((GLuint)gd->win_shader.in_texcoord); + glVertexAttribPointer((GLuint)gd->win_shader.coord_loc, 2, GL_FLOAT, GL_FALSE, + sizeof(GLfloat) * 4, NULL); + glVertexAttribPointer((GLuint)gd->win_shader.in_texcoord, 2, GL_FLOAT, GL_FALSE, + sizeof(GLfloat) * 4, (void *)(sizeof(GLfloat) * 2)); + glDrawElements(GL_TRIANGLES, nrects * 6, GL_UNSIGNED_INT, NULL); + glDisableVertexAttribArray((GLuint)gd->win_shader.coord_loc); + glDisableVertexAttribArray((GLuint)gd->win_shader.in_texcoord); // Cleanup glBindTexture(GL_TEXTURE_2D, 0); - glColor4f(0.0f, 0.0f, 0.0f, 0.0f); - glDisable(GL_COLOR_LOGIC_OP); if (dual_texture) { glActiveTexture(GL_TEXTURE1); @@ -275,6 +298,13 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, glActiveTexture(GL_TEXTURE0); } + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glDeleteBuffers(2, bo); + + free(indices); + free(coord); + glUseProgram(0); gl_check_err(); diff --git a/src/backend/gl/gl_common.h b/src/backend/gl/gl_common.h index f0598fff..993b6691 100644 --- a/src/backend/gl/gl_common.h +++ b/src/backend/gl/gl_common.h @@ -22,6 +22,7 @@ typedef struct { GLint unifm_tex; GLint unifm_dim; GLint in_texcoord; + GLint coord_loc; } gl_win_shader_t; // Program and uniforms for blur shader From 23e2ac16b39fd7283035be1401e0e81baeb0e2b5 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Mon, 1 Apr 2019 19:57:49 +0100 Subject: [PATCH 7/8] gl_common: use vao Signed-off-by: Yuxuan Shui --- src/backend/gl/gl_common.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index 35b868b1..75ef99c0 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -271,6 +271,10 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, sizeof(GLuint) * 6); } + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + GLuint bo[2]; glGenBuffers(2, bo); glBindBuffer(GL_ARRAY_BUFFER, bo[0]); @@ -288,6 +292,8 @@ void gl_compose(backend_t *base, void *image_data, int dst_x, int dst_y, glDrawElements(GL_TRIANGLES, nrects * 6, GL_UNSIGNED_INT, NULL); glDisableVertexAttribArray((GLuint)gd->win_shader.coord_loc); glDisableVertexAttribArray((GLuint)gd->win_shader.in_texcoord); + glBindVertexArray(0); + glDeleteVertexArrays(1, &vao); // Cleanup glBindTexture(GL_TEXTURE_2D, 0); @@ -381,6 +387,10 @@ bool gl_blur(backend_t *base, double opacity, const region_t *reg_blur, sizeof(GLuint) * 6); } + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + GLuint bo[2]; glGenBuffers(2, bo); glBindBuffer(GL_ARRAY_BUFFER, bo[0]); @@ -457,6 +467,8 @@ end: glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDeleteBuffers(2, bo); + glBindVertexArray(0); + glDeleteVertexArrays(1, &vao); free(indices); free(coord); @@ -585,6 +597,11 @@ void gl_fill(backend_t *base, double r, double g, double b, double a, const regi int nrects; const rect_t *rect = pixman_region32_rectangles((region_t *)clip, &nrects); struct gl_data *gd = (void *)base; + + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + GLuint bo[2]; glGenBuffers(2, bo); glUseProgram(gd->fill_shader.prog); @@ -619,6 +636,8 @@ void gl_fill(backend_t *base, double r, double g, double b, double a, const regi glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDisableVertexAttribArray((GLuint)gd->fill_shader.in_coord_loc); + glBindVertexArray(0); + glDeleteVertexArrays(1, &vao); glDeleteBuffers(2, bo); } From b066156cda124259a86baf9fb3e61dd655b93508 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Mon, 1 Apr 2019 19:59:54 +0100 Subject: [PATCH 8/8] gl_common: bump GL to 3.30 Signed-off-by: Yuxuan Shui --- src/backend/gl/gl_common.c | 10 +++++----- src/backend/gl/glx.c | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index 75ef99c0..2d0acf48 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -489,7 +489,7 @@ static GLint glGetUniformLocationChecked(GLuint p, const char *name) { } // clang-format off -const char *vertex_shader = GLSL(130, +const char *vertex_shader = GLSL(330, uniform mat4 projection; uniform vec2 orig; in vec2 coord; @@ -577,14 +577,14 @@ void gl_resize(struct gl_data *gd, int width, int height) { } // clang-format off -static const char fill_frag[] = GLSL(120, +static const char fill_frag[] = GLSL(330, uniform vec4 color; void main() { gl_FragColor = color; } ); -static const char fill_vert[] = GLSL(130, +static const char fill_vert[] = GLSL(330, in vec2 in_coord; uniform mat4 projection; void main() { @@ -656,7 +656,7 @@ static bool gl_init_blur(struct gl_data *gd, conv *const *const kernels) { setlocale(LC_NUMERIC, "C"); // clang-format off - static const char *FRAG_SHADER_BLUR = GLSL(130, + static const char *FRAG_SHADER_BLUR = GLSL(330, %s\n // other extension pragmas uniform float offset_x; uniform float offset_y; @@ -774,7 +774,7 @@ err: } // clang-format off -const char *win_shader_glsl = GLSL(130, +const char *win_shader_glsl = GLSL(330, uniform float opacity; uniform float dim; uniform bool invert_color; diff --git a/src/backend/gl/glx.c b/src/backend/gl/glx.c index ebcc73ca..0c1d2dde 100644 --- a/src/backend/gl/glx.c +++ b/src/backend/gl/glx.c @@ -290,7 +290,9 @@ static backend_t *glx_init(session_t *ps) { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, - 0, + 3, + GLX_CONTEXT_PROFILE_MASK_ARB, + GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 0, }); free(cfg);