diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-09-07 21:27:09 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-09-07 21:27:09 +0000 |
commit | bab7092a69a42fe05c97a6bfb9a829a818623953 (patch) | |
tree | 51b6a08c861e932b91e88d655bb961f233059310 /gsk | |
parent | fe429ffc4581554ea4f015f647b2742251951bbe (diff) | |
parent | 3b6941b04bd4de4c7aa47ee140d347e8b9e8e6df (diff) | |
download | gtk+-bab7092a69a42fe05c97a6bfb9a829a818623953.tar.gz |
Merge branch 'gl-linear' into 'master'
Gl: use linear interpolation
See merge request GNOME/gtk!2523
Diffstat (limited to 'gsk')
-rw-r--r-- | gsk/gl/gskgldriver.c | 4 | ||||
-rw-r--r-- | gsk/gl/gskgldriverprivate.h | 2 | ||||
-rw-r--r-- | gsk/gl/gskglrenderer.c | 106 | ||||
-rw-r--r-- | gsk/gsktransform.c | 25 | ||||
-rw-r--r-- | gsk/gsktransformprivate.h | 4 |
5 files changed, 103 insertions, 38 deletions
diff --git a/gsk/gl/gskgldriver.c b/gsk/gl/gskgldriver.c index 8cd32d72ab..08e19a980f 100644 --- a/gsk/gl/gskgldriver.c +++ b/gsk/gl/gskgldriver.c @@ -594,6 +594,8 @@ void gsk_gl_driver_create_render_target (GskGLDriver *self, int width, int height, + int min_filter, + int mag_filter, int *out_texture_id, int *out_render_target_id) { @@ -604,7 +606,7 @@ gsk_gl_driver_create_render_target (GskGLDriver *self, texture = create_texture (self, width, height); gsk_gl_driver_bind_source_texture (self, texture->texture_id); - gsk_gl_driver_init_texture_empty (self, texture->texture_id, GL_NEAREST, GL_NEAREST); + gsk_gl_driver_init_texture_empty (self, texture->texture_id, min_filter, mag_filter); glGenFramebuffers (1, &fbo_id); glBindFramebuffer (GL_FRAMEBUFFER, fbo_id); diff --git a/gsk/gl/gskgldriverprivate.h b/gsk/gl/gskgldriverprivate.h index 83d0c46af9..22c5ef8cb3 100644 --- a/gsk/gl/gskgldriverprivate.h +++ b/gsk/gl/gskgldriverprivate.h @@ -45,6 +45,8 @@ int gsk_gl_driver_create_texture (GskGLDriver *driver void gsk_gl_driver_create_render_target (GskGLDriver *driver, int width, int height, + int min_filter, + int mag_filter, int *out_texture_id, int *out_render_target_id); void gsk_gl_driver_mark_texture_permanent (GskGLDriver *self, diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 5078aeef65..27d1c48cbd 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -71,6 +71,7 @@ typedef enum RESET_OPACITY = 1 << 2, DUMP_FRAMEBUFFER = 1 << 3, NO_CACHE_PLZ = 1 << 5, + LINEAR_FILTER = 1 << 6, } OffscreenFlags; static inline void @@ -1000,6 +1001,38 @@ render_texture_node (GskGLRenderer *self, } } +/* Returns TRUE is applying transform to bounds + * yields an axis-aligned rectangle + */ +static gboolean +result_is_axis_aligned (GskTransform *transform, + const graphene_rect_t *bounds) +{ + graphene_matrix_t m; + graphene_quad_t q; + graphene_rect_t b; + graphene_point_t b1, b2; + const graphene_point_t *p; + int i; + + gsk_transform_to_matrix (transform, &m); + gsk_matrix_transform_rect (&m, bounds, &q); + graphene_quad_bounds (&q, &b); + graphene_rect_get_top_left (&b, &b1); + graphene_rect_get_bottom_right (&b, &b2); + + for (i = 0; i < 4; i++) + { + p = graphene_quad_get_point (&q, i); + if (fabs (p->x - b1.x) > FLT_EPSILON && fabs (p->x - b2.x) > FLT_EPSILON) + return FALSE; + if (fabs (p->y - b1.y) > FLT_EPSILON && fabs (p->y - b2.y) > FLT_EPSILON) + return FALSE; + } + + return TRUE; +} + static inline void render_transform_node (GskGLRenderer *self, GskRenderNode *node, @@ -1035,11 +1068,10 @@ render_transform_node (GskGLRenderer *self, } break; - case GSK_TRANSFORM_CATEGORY_UNKNOWN: - case GSK_TRANSFORM_CATEGORY_ANY: - case GSK_TRANSFORM_CATEGORY_3D: case GSK_TRANSFORM_CATEGORY_2D: - default: + case GSK_TRANSFORM_CATEGORY_3D: + case GSK_TRANSFORM_CATEGORY_ANY: + case GSK_TRANSFORM_CATEGORY_UNKNOWN: { TextureRegion region; gboolean is_offscreen; @@ -1050,29 +1082,42 @@ render_transform_node (GskGLRenderer *self, gsk_gl_renderer_add_render_ops (self, child, builder); ops_pop_modelview (builder); } - else if (add_offscreen_ops (self, builder, + else + { + int filter_flag = 0; + + if (!result_is_axis_aligned (node_transform, &child->bounds)) + filter_flag = LINEAR_FILTER; + + if (add_offscreen_ops (self, builder, &child->bounds, child, ®ion, &is_offscreen, - RESET_CLIP | RESET_OPACITY)) - { - /* For non-trivial transforms, we draw everything on a texture and then - * draw the texture transformed. */ - /* TODO: We should compute a modelview containing only the "non-trivial" - * part (e.g. the rotation) and use that. We want to keep the scale - * for the texture. - */ - ops_push_modelview (builder, node_transform); - ops_set_texture (builder, region.texture_id); - ops_set_program (builder, &self->programs->blit_program); - - load_vertex_data_with_region (ops_draw (builder, NULL), - child, builder, - ®ion, - is_offscreen); - ops_pop_modelview (builder); + RESET_CLIP | RESET_OPACITY | filter_flag)) + { + /* For non-trivial transforms, we draw everything on a texture and then + * draw the texture transformed. */ + /* TODO: We should compute a modelview containing only the "non-trivial" + * part (e.g. the rotation) and use that. We want to keep the scale + * for the texture. + */ + ops_push_modelview (builder, node_transform); + ops_set_texture (builder, region.texture_id); + ops_set_program (builder, &self->programs->blit_program); + + load_vertex_data_with_region (ops_draw (builder, NULL), + child, builder, + ®ion, + is_offscreen); + ops_pop_modelview (builder); + } } } + break; + + default: + g_assert_not_reached (); + break; } } @@ -1451,10 +1496,12 @@ blur_texture (GskGLRenderer *self, gsk_gl_driver_create_render_target (self->gl_driver, texture_to_blur_width, texture_to_blur_height, + GL_NEAREST, GL_NEAREST, &pass1_texture_id, &pass1_render_target); gsk_gl_driver_create_render_target (self->gl_driver, texture_to_blur_width, texture_to_blur_height, + GL_NEAREST, GL_NEAREST, &pass2_texture_id, &pass2_render_target); graphene_matrix_init_ortho (&item_proj, @@ -1696,6 +1743,7 @@ render_inset_shadow_node (GskGLRenderer *self, gsk_gl_driver_create_render_target (self->gl_driver, texture_width, texture_height, + GL_NEAREST, GL_NEAREST, &texture_id, &render_target); graphene_matrix_init_ortho (&item_proj, @@ -1869,7 +1917,9 @@ render_outset_shadow_node (GskGLRenderer *self, graphene_rect_t prev_viewport; graphene_matrix_t item_proj; - gsk_gl_driver_create_render_target (self->gl_driver, texture_width, texture_height, + gsk_gl_driver_create_render_target (self->gl_driver, + texture_width, texture_height, + GL_NEAREST, GL_NEAREST, &texture_id, &render_target); if (gdk_gl_context_has_debug (self->gl_context)) { @@ -3349,6 +3399,7 @@ add_offscreen_ops (GskGLRenderer *self, float prev_opacity = 1.0; int texture_id = 0; int max_texture_size; + int filter; if (node_is_invisible (child_node)) { @@ -3401,7 +3452,14 @@ add_offscreen_ops (GskGLRenderer *self, width = ceilf (width * scale); height = ceilf (height * scale); - gsk_gl_driver_create_render_target (self->gl_driver, width, height, &texture_id, &render_target); + if (flags & LINEAR_FILTER) + filter = GL_LINEAR; + else + filter = GL_NEAREST; + gsk_gl_driver_create_render_target (self->gl_driver, + width, height, + filter, filter, + &texture_id, &render_target); if (gdk_gl_context_has_debug (self->gl_context)) { gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, texture_id, diff --git a/gsk/gsktransform.c b/gsk/gsktransform.c index 337a27ed12..2bd1bdc920 100644 --- a/gsk/gsktransform.c +++ b/gsk/gsktransform.c @@ -2204,13 +2204,11 @@ gsk_matrix_transform_point3d (const graphene_matrix_t *m, } void -gsk_matrix_transform_bounds (const graphene_matrix_t *m, - const graphene_rect_t *r, - graphene_rect_t *res) +gsk_matrix_transform_rect (const graphene_matrix_t *m, + const graphene_rect_t *r, + graphene_quad_t *res) { graphene_point_t ret[4]; - float min_x, min_y; - float max_x, max_y; graphene_rect_t rr; graphene_rect_normalize_r (r, &rr); @@ -2233,12 +2231,15 @@ gsk_matrix_transform_bounds (const graphene_matrix_t *m, #undef TRANSFORM_POINT - /* FIXME: graphene doesn't export a fast way to do this */ - min_x = MIN (MIN (ret[0].x, ret[1].x), MIN (ret[2].x, ret[3].x)); - min_y = MIN (MIN (ret[0].y, ret[1].y), MIN (ret[2].y, ret[3].y)); - - max_x = MAX (MAX (ret[0].x, ret[1].x), MAX (ret[2].x, ret[3].x)); - max_y = MAX (MAX (ret[0].y, ret[1].y), MAX (ret[2].y, ret[3].y)); + graphene_quad_init (res, &ret[0], &ret[1], &ret[2], &ret[3]); +} +void +gsk_matrix_transform_bounds (const graphene_matrix_t *m, + const graphene_rect_t *r, + graphene_rect_t *res) +{ + graphene_quad_t q; - graphene_rect_init (res, min_x, min_y, max_x - min_x, max_y - min_y); + gsk_matrix_transform_rect (m, r, &q); + graphene_quad_bounds (&q, res); } diff --git a/gsk/gsktransformprivate.h b/gsk/gsktransformprivate.h index 2c2f97448c..9f88e9a002 100644 --- a/gsk/gsktransformprivate.h +++ b/gsk/gsktransformprivate.h @@ -41,7 +41,9 @@ void gsk_matrix_transform_point3d (const graphene_matrix_t *m, void gsk_matrix_transform_bounds (const graphene_matrix_t *m, const graphene_rect_t *r, graphene_rect_t *res); - +void gsk_matrix_transform_rect (const graphene_matrix_t *m, + const graphene_rect_t *r, + graphene_quad_t *res); G_END_DECLS |