summaryrefslogtreecommitdiff
path: root/gsk
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-09-07 21:27:09 +0000
committerMatthias Clasen <mclasen@redhat.com>2020-09-07 21:27:09 +0000
commitbab7092a69a42fe05c97a6bfb9a829a818623953 (patch)
tree51b6a08c861e932b91e88d655bb961f233059310 /gsk
parentfe429ffc4581554ea4f015f647b2742251951bbe (diff)
parent3b6941b04bd4de4c7aa47ee140d347e8b9e8e6df (diff)
downloadgtk+-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.c4
-rw-r--r--gsk/gl/gskgldriverprivate.h2
-rw-r--r--gsk/gl/gskglrenderer.c106
-rw-r--r--gsk/gsktransform.c25
-rw-r--r--gsk/gsktransformprivate.h4
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,
&region, &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,
- &region,
- 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,
+ &region,
+ 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