diff --git a/src/backend/gl/blur.c b/src/backend/gl/blur.c index b61eaa45..c9d85fa0 100644 --- a/src/backend/gl/blur.c +++ b/src/backend/gl/blur.c @@ -344,18 +344,18 @@ bool gl_blur(struct backend_base *base, ivec2 origin, image_handle target_, } // Original region for the final compositing step from blur result to target. - auto coord = ccalloc(nrects * 16, GLint); + auto coord = ccalloc(nrects * 16, GLfloat); auto indices = ccalloc(nrects * 6, GLuint); - gl_mask_rects_to_coords(origin, nrects, rects, coord, indices); + gl_mask_rects_to_coords(origin, nrects, rects, SCALE_IDENTITY, coord, indices); if (!target->y_inverted) { gl_y_flip_target(nrects, coord, target->height); } // Resize region for sampling from source texture, and for blur passes - auto coord_resized = ccalloc(nrects_resized * 16, GLint); + auto coord_resized = ccalloc(nrects_resized * 16, GLfloat); auto indices_resized = ccalloc(nrects_resized * 6, GLuint); - gl_mask_rects_to_coords(origin, nrects_resized, rects_resized, coord_resized, - indices_resized); + gl_mask_rects_to_coords(origin, nrects_resized, rects_resized, SCALE_IDENTITY, + coord_resized, indices_resized); pixman_region32_fini(®_blur_resized); // FIXME(yshui) In theory we should handle blurring a non-y-inverted source, but // we never actually use that capability anywhere. @@ -375,9 +375,9 @@ bool gl_blur(struct backend_base *base, ivec2 origin, image_handle target_, indices, GL_STREAM_DRAW); glEnableVertexAttribArray(vert_coord_loc); glEnableVertexAttribArray(vert_in_texcoord_loc); - glVertexAttribPointer(vert_coord_loc, 2, GL_INT, GL_FALSE, sizeof(GLint) * 4, NULL); - glVertexAttribPointer(vert_in_texcoord_loc, 2, GL_INT, GL_FALSE, - sizeof(GLint) * 4, (void *)(sizeof(GLint) * 2)); + glVertexAttribPointer(vert_coord_loc, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, NULL); + glVertexAttribPointer(vert_in_texcoord_loc, 2, GL_FLOAT, GL_FALSE, + sizeof(GLfloat) * 4, (void *)(sizeof(GLfloat) * 2)); glBindVertexArray(vao[1]); glBindBuffer(GL_ARRAY_BUFFER, bo[2]); @@ -389,9 +389,9 @@ bool gl_blur(struct backend_base *base, ivec2 origin, image_handle target_, GL_STREAM_DRAW); glEnableVertexAttribArray(vert_coord_loc); glEnableVertexAttribArray(vert_in_texcoord_loc); - glVertexAttribPointer(vert_coord_loc, 2, GL_INT, GL_FALSE, sizeof(GLint) * 4, NULL); - glVertexAttribPointer(vert_in_texcoord_loc, 2, GL_INT, GL_FALSE, - sizeof(GLint) * 4, (void *)(sizeof(GLint) * 2)); + glVertexAttribPointer(vert_coord_loc, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, NULL); + glVertexAttribPointer(vert_in_texcoord_loc, 2, GL_FLOAT, GL_FALSE, + sizeof(GLfloat) * 4, (void *)(sizeof(GLfloat) * 2)); int vao_nelems[2] = {nrects * 6, nrects_resized * 6}; diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index 7d543561..e9ab9f3c 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -366,10 +366,10 @@ struct gl_vertex_attribs_definition { }; static const struct gl_vertex_attribs_definition gl_blit_vertex_attribs = { - .stride = sizeof(GLint) * 4, + .stride = sizeof(GLfloat) * 4, .count = 2, - .attribs = {{GL_INT, vert_coord_loc, NULL}, - {GL_INT, vert_in_texcoord_loc, ((GLint *)NULL) + 2}}, + .attribs = {{GL_FLOAT, vert_coord_loc, NULL}, + {GL_FLOAT, vert_in_texcoord_loc, ((GLfloat *)NULL) + 2}}, }; /** @@ -384,7 +384,7 @@ static const struct gl_vertex_attribs_definition gl_blit_vertex_attribs = { * @param nuniforms number of uniforms for `shader` * @param uniforms uniforms for `shader` */ -static void gl_blit_inner(GLuint target_fbo, int nrects, GLint *coord, GLuint *indices, +static void gl_blit_inner(GLuint target_fbo, int nrects, GLfloat *coord, GLuint *indices, const struct gl_vertex_attribs_definition *vert_attribs, const struct gl_shader *shader, int nuniforms, struct gl_uniform_value *uniforms) { @@ -475,26 +475,29 @@ static void gl_blit_inner(GLuint target_fbo, int nrects, GLint *coord, GLuint *i gl_check_err(); } -void gl_mask_rects_to_coords(ivec2 origin, int nrects, const rect_t *rects, GLint *coord, - GLuint *indices) { +void gl_mask_rects_to_coords(ivec2 origin, int nrects, const rect_t *rects, vec2 scale, + GLfloat *coord, GLuint *indices) { for (ptrdiff_t i = 0; i < nrects; i++) { // Rectangle in source image coordinates rect_t rect_src = region_translate_rect(rects[i], ivec2_neg(origin)); // Rectangle in target image coordinates rect_t rect_dst = rects[i]; + // clang-format off memcpy(&coord[i * 16], - ((GLint[][2]){ - {rect_dst.x1, rect_dst.y1}, // Vertex, bottom-left - {rect_src.x1, rect_src.y1}, // Texture - {rect_dst.x2, rect_dst.y1}, // Vertex, bottom-right - {rect_src.x2, rect_src.y1}, // Texture - {rect_dst.x2, rect_dst.y2}, // Vertex, top-right - {rect_src.x2, rect_src.y2}, // Texture - {rect_dst.x1, rect_dst.y2}, // Vertex, top-left - {rect_src.x1, rect_src.y2}, // Texture + ((GLfloat[][2]){ + // Interleaved vertex and texture coordinates, starting with vertex. + {(GLfloat)rect_dst.x1, (GLfloat)rect_dst.y1}, // bottom-left + {(GLfloat)(rect_src.x1 / scale.x), (GLfloat)(rect_src.y1 / scale.y)}, + {(GLfloat)rect_dst.x2, (GLfloat)rect_dst.y1}, // bottom-right + {(GLfloat)(rect_src.x2 / scale.x), (GLfloat)(rect_src.y1 / scale.y)}, + {(GLfloat)rect_dst.x2, (GLfloat)rect_dst.y2}, // top-right + {(GLfloat)(rect_src.x2 / scale.x), (GLfloat)(rect_src.y2 / scale.y)}, + {(GLfloat)rect_dst.x1, (GLfloat)rect_dst.y2}, // top-left + {(GLfloat)(rect_src.x1 / scale.x), (GLfloat)(rect_src.y2 / scale.y)}, }), sizeof(GLint[2]) * 8); + // clang-format on GLuint u = (GLuint)(i * 4); memcpy(&indices[i * 6], @@ -509,13 +512,13 @@ void gl_mask_rects_to_coords(ivec2 origin, int nrects, const rect_t *rects, GLin /// @param[in] nrects number of rectangles /// @param[in] coord OpenGL vertex coordinates /// @param[in] texture_height height of the source image -static inline void gl_y_flip_texture(int nrects, GLint *coord, GLint texture_height) { +static inline void gl_y_flip_texture(int nrects, GLfloat *coord, GLint texture_height) { for (ptrdiff_t i = 0; i < nrects; i++) { auto current_rect = &coord[i * 16]; // 16 numbers per rectangle for (ptrdiff_t j = 0; j < 4; j++) { // 4 numbers per vertex, texture coordinates are the last two auto current_vertex = ¤t_rect[j * 4 + 2]; - current_vertex[1] = texture_height - current_vertex[1]; + current_vertex[1] = (GLfloat)texture_height - current_vertex[1]; } } } @@ -524,7 +527,7 @@ static inline void gl_y_flip_texture(int nrects, GLint *coord, GLint texture_hei /// shader, and uniforms. static int gl_lower_blit_args(struct gl_data *gd, ivec2 origin, const struct backend_blit_args *args, - GLint **coord, GLuint **indices, struct gl_shader **shader, + GLfloat **coord, GLuint **indices, struct gl_shader **shader, struct gl_uniform_value *uniforms) { auto img = (struct gl_texture *)args->source_image; int nrects; @@ -534,9 +537,9 @@ gl_lower_blit_args(struct gl_data *gd, ivec2 origin, const struct backend_blit_a // Nothing to paint return 0; } - *coord = ccalloc(nrects * 16, GLint); + *coord = ccalloc(nrects * 16, GLfloat); *indices = ccalloc(nrects * 6, GLuint); - gl_mask_rects_to_coords(origin, nrects, rects, *coord, *indices); + gl_mask_rects_to_coords(origin, nrects, rects, args->scale, *coord, *indices); if (!img->y_inverted) { gl_y_flip_texture(nrects, *coord, img->height); } @@ -558,11 +561,13 @@ gl_lower_blit_args(struct gl_data *gd, ivec2 origin, const struct backend_blit_a border_width = 0; } // clang-format off + auto tex_sampler = vec2_eq(args->scale, SCALE_IDENTITY) ? + gd->samplers[GL_SAMPLER_REPEAT] : gd->samplers[GL_SAMPLER_REPEAT_SCALE]; struct gl_uniform_value from_uniforms[] = { [UNIFORM_OPACITY_LOC] = {.type = GL_FLOAT, .f = (float)args->opacity}, [UNIFORM_INVERT_COLOR_LOC] = {.type = GL_INT, .i = args->color_inverted}, [UNIFORM_TEX_LOC] = {.type = GL_TEXTURE_2D, - .tu = {img->texture, gd->samplers[GL_SAMPLER_REPEAT]}}, + .tu = {img->texture, tex_sampler}}, [UNIFORM_EFFECTIVE_SIZE_LOC] = {.type = GL_FLOAT_VEC2, .f2 = {(float)args->effective_size.width, (float)args->effective_size.height}}, @@ -613,7 +618,7 @@ bool gl_blit(backend_t *base, ivec2 origin, image_handle target_, return false; } - GLint *coord; + GLfloat *coord; GLuint *indices; struct gl_shader *shader; struct gl_uniform_value uniforms[NUMBER_OF_UNIFORMS] = {}; @@ -678,9 +683,9 @@ static bool gl_copy_area_draw(struct gl_data *gd, ivec2 origin, return true; } - auto coord = ccalloc(16 * nrects, GLint); + auto coord = ccalloc(16 * nrects, GLfloat); auto indices = ccalloc(6 * nrects, GLuint); - gl_mask_rects_to_coords(origin, nrects, rects, coord, indices); + gl_mask_rects_to_coords(origin, nrects, rects, SCALE_IDENTITY, coord, indices); if (!target->y_inverted) { gl_y_flip_target(nrects, coord, target->height); } @@ -856,6 +861,17 @@ uint64_t gl_get_shader_attributes(backend_t *backend_data attr_unused, void *sha return ret; } +static const struct { + GLint filter; + GLint wrap; +} gl_sampler_params[] = { + [GL_SAMPLER_REPEAT] = {GL_NEAREST, GL_REPEAT}, + [GL_SAMPLER_REPEAT_SCALE] = {GL_LINEAR, GL_REPEAT}, + [GL_SAMPLER_BLUR] = {GL_LINEAR, GL_CLAMP_TO_EDGE}, + [GL_SAMPLER_EDGE] = {GL_NEAREST, GL_CLAMP_TO_EDGE}, + [GL_SAMPLER_BORDER] = {GL_NEAREST, GL_CLAMP_TO_BORDER}, +}; + bool gl_init(struct gl_data *gd, session_t *ps) { if (!epoxy_has_gl_extension("GL_ARB_explicit_uniform_location")) { log_error("GL_ARB_explicit_uniform_location support is required but " @@ -965,20 +981,16 @@ bool gl_init(struct gl_data *gd, session_t *ps) { gd->back_image.height = ps->root_height; glGenSamplers(GL_MAX_SAMPLERS, gd->samplers); - for (int i = 0; i < GL_MAX_SAMPLERS; i++) { - glSamplerParameteri(gd->samplers[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glSamplerParameteri(gd->samplers[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); + for (size_t i = 0; i < ARR_SIZE(gl_sampler_params); i++) { + glSamplerParameteri(gd->samplers[i], GL_TEXTURE_MIN_FILTER, + gl_sampler_params[i].filter); + glSamplerParameteri(gd->samplers[i], GL_TEXTURE_MAG_FILTER, + gl_sampler_params[i].filter); + glSamplerParameteri(gd->samplers[i], GL_TEXTURE_WRAP_S, + gl_sampler_params[i].wrap); + glSamplerParameteri(gd->samplers[i], GL_TEXTURE_WRAP_T, + gl_sampler_params[i].wrap); } - glSamplerParameterf(gd->samplers[GL_SAMPLER_EDGE], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameterf(gd->samplers[GL_SAMPLER_EDGE], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glSamplerParameterf(gd->samplers[GL_SAMPLER_BLUR], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glSamplerParameterf(gd->samplers[GL_SAMPLER_BLUR], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glSamplerParameterf(gd->samplers[GL_SAMPLER_BLUR], GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glSamplerParameterf(gd->samplers[GL_SAMPLER_BLUR], GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glSamplerParameterf(gd->samplers[GL_SAMPLER_BORDER], GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_BORDER); - glSamplerParameterf(gd->samplers[GL_SAMPLER_BORDER], GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_BORDER); gd->logger = gl_string_marker_logger_new(); if (gd->logger) { @@ -1100,9 +1112,9 @@ image_handle gl_new_image(backend_t *backend_data attr_unused, bool gl_apply_alpha(backend_t *base, image_handle target, double alpha, const region_t *reg_op) { auto gd = (struct gl_data *)base; static const struct gl_vertex_attribs_definition vertex_attribs = { - .stride = sizeof(GLint) * 4, + .stride = sizeof(GLfloat) * 4, .count = 1, - .attribs = {{GL_INT, vert_coord_loc, NULL}}, + .attribs = {{GL_FLOAT, vert_coord_loc, NULL}}, }; if (alpha == 1.0 || !pixman_region32_not_empty(reg_op)) { return true; @@ -1115,7 +1127,7 @@ bool gl_apply_alpha(backend_t *base, image_handle target, double alpha, const re int nrects; const rect_t *rect = pixman_region32_rectangles(reg_op, &nrects); - auto coord = ccalloc(nrects * 16, GLint); + auto coord = ccalloc(nrects * 16, GLfloat); auto indices = ccalloc(nrects * 6, GLuint); struct gl_uniform_value uniforms[] = { diff --git a/src/backend/gl/gl_common.h b/src/backend/gl/gl_common.h index 3a679c75..6e388834 100644 --- a/src/backend/gl/gl_common.h +++ b/src/backend/gl/gl_common.h @@ -66,7 +66,10 @@ struct gl_texture { }; enum gl_sampler { + /// A sampler that repeats the texture, with nearest filtering. GL_SAMPLER_REPEAT = 0, + /// A sampler that repeats the texture, with linear filtering. + GL_SAMPLER_REPEAT_SCALE, /// Clamp to edge GL_SAMPLER_EDGE, /// Clamp to border, border color will be (0, 0, 0, 0) @@ -126,13 +129,13 @@ void gl_prepare(backend_t *base, const region_t *reg); /// @param[in] rects mask rectangles, in mask coordinates /// @param[out] coord OpenGL vertex coordinates, suitable for creating VAO/VBO /// @param[out] indices OpenGL vertex indices, suitable for creating VAO/VBO -void gl_mask_rects_to_coords(ivec2 origin, int nrects, const rect_t *rects, GLint *coord, - GLuint *indices); -/// Like `gl_mask_rects_to_coords`, but with `origin` and `mask_origin` set to 0. i.e. all -/// coordinates are in the same space. +void gl_mask_rects_to_coords(ivec2 origin, int nrects, const rect_t *rects, vec2 scale, + GLfloat *coord, GLuint *indices); +/// Like `gl_mask_rects_to_coords`, but with `origin` is (0, 0). static inline void gl_mask_rects_to_coords_simple(int nrects, const rect_t *rects, - GLint *coord, GLuint *indices) { - return gl_mask_rects_to_coords((ivec2){0, 0}, nrects, rects, coord, indices); + GLfloat *coord, GLuint *indices) { + return gl_mask_rects_to_coords((ivec2){0, 0}, nrects, rects, SCALE_IDENTITY, + coord, indices); } GLuint gl_create_shader(GLenum shader_type, const char *shader_str); @@ -210,13 +213,13 @@ static inline GLuint gl_bind_image_to_fbo(struct gl_data *gd, image_handle image /// @param[in] nrects number of rectangles /// @param[in] coord OpenGL vertex coordinates /// @param[in] target_height height of the target image -static inline void gl_y_flip_target(int nrects, GLint *coord, GLint target_height) { +static inline void gl_y_flip_target(int nrects, GLfloat *coord, GLint target_height) { for (ptrdiff_t i = 0; i < nrects; i++) { auto current_rect = &coord[i * 16]; // 16 numbers per rectangle for (ptrdiff_t j = 0; j < 4; j++) { // 4 numbers per vertex, target coordinates are the first two auto current_vertex = ¤t_rect[j * 4]; - current_vertex[1] = target_height - current_vertex[1]; + current_vertex[1] = (GLfloat)target_height - current_vertex[1]; } } } diff --git a/src/types.h b/src/types.h index 4050f806..dd88ff6d 100644 --- a/src/types.h +++ b/src/types.h @@ -88,5 +88,9 @@ static inline ivec2 vec2_as(vec2 a) { }; } +static inline bool vec2_eq(vec2 a, vec2 b) { + return a.x == b.x && a.y == b.y; +} + #define MARGIN_INIT \ { 0, 0, 0, 0 }