summaryrefslogtreecommitdiff
path: root/gsk/gskglrenderer.c
diff options
context:
space:
mode:
Diffstat (limited to 'gsk/gskglrenderer.c')
-rw-r--r--gsk/gskglrenderer.c94
1 files changed, 63 insertions, 31 deletions
diff --git a/gsk/gskglrenderer.c b/gsk/gskglrenderer.c
index 3ec9327f7e..c0d528871c 100644
--- a/gsk/gskglrenderer.c
+++ b/gsk/gskglrenderer.c
@@ -90,6 +90,11 @@ typedef struct {
} ProfileTimers;
#endif
+typedef enum {
+ RENDER_FULL,
+ RENDER_SCISSOR
+} RenderMode;
+
struct _GskGLRenderer
{
GskRenderer parent_instance;
@@ -118,6 +123,8 @@ struct _GskGLRenderer
ProfileTimers profile_timers;
#endif
+ RenderMode render_mode;
+
gboolean has_buffers : 1;
};
@@ -322,48 +329,45 @@ gsk_gl_renderer_unrealize (GskRenderer *renderer)
static GdkDrawingContext *
gsk_gl_renderer_begin_draw_frame (GskRenderer *renderer,
- const cairo_region_t *region)
+ const cairo_region_t *update_area)
{
GskGLRenderer *self = GSK_GL_RENDERER (renderer);
- cairo_region_t *whole_window;
+ cairo_region_t *damage;
GdkDrawingContext *result;
+ GdkRectangle whole_window;
GdkWindow *window;
window = gsk_renderer_get_window (renderer);
+ whole_window = (GdkRectangle) {
+ 0, 0,
+ gdk_window_get_width (window),
+ gdk_window_get_height (window)
+ };
+ damage = gdk_gl_context_get_damage (self->gl_context);
+ cairo_region_union (damage, update_area);
- whole_window = cairo_region_create_rectangle (&(GdkRectangle) {
- 0, 0,
- gdk_window_get_width (window),
- gdk_window_get_height (window)
- });
-
- return gdk_window_begin_draw_frame (window,
- GDK_DRAW_CONTEXT (self->gl_context),
- region);
-
- cairo_region_destroy (whole_window);
-
- return result;
-}
+ if (cairo_region_contains_rectangle (damage, &whole_window) == CAIRO_REGION_OVERLAP_IN)
+ {
+ self->render_mode = RENDER_FULL;
+ }
+ else
+ {
+ GdkRectangle extents;
-static GdkDrawingContext *
-gsk_gl_renderer_begin_draw_frame (GskRenderer *renderer,
- const cairo_region_t *region)
-{
- cairo_region_t *whole_window;
- GdkDrawingContext *result;
- GdkWindow *window;
+ cairo_region_get_extents (damage, &extents);
+ cairo_region_union_rectangle (damage, &extents);
- window = gsk_renderer_get_window (renderer);
-
- whole_window = cairo_region_create_rectangle (&(GdkRectangle) {
- 0, 0,
- gdk_window_get_width (window),
- gdk_window_get_height (window) });
+ if (gdk_rectangle_equal (&extents, &whole_window))
+ self->render_mode = RENDER_FULL;
+ else
+ self->render_mode = RENDER_SCISSOR;
+ }
- result = GSK_RENDERER_CLASS (gsk_gl_renderer_parent_class)->begin_draw_frame (renderer, whole_window);
+ result = gdk_window_begin_draw_frame (window,
+ GDK_DRAW_CONTEXT (self->gl_context),
+ damage);
- cairo_region_destroy (whole_window);
+ cairo_region_destroy (damage);
return result;
}
@@ -859,6 +863,32 @@ gsk_gl_renderer_clear (GskGLRenderer *self)
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
+static void
+gsk_gl_renderer_setup_render_mode (GskGLRenderer *self)
+{
+ switch (self->render_mode)
+ {
+ case RENDER_FULL:
+ glDisable (GL_SCISSOR_TEST);
+ break;
+
+ case RENDER_SCISSOR:
+ {
+ GdkDrawingContext *context = gsk_renderer_get_drawing_context (GSK_RENDERER (self));
+ GdkWindow *window = gsk_renderer_get_window (GSK_RENDERER (self));
+ GdkRectangle extents;
+ cairo_region_get_extents (gdk_drawing_context_get_clip (context), &extents);
+ glScissor (extents.x, gdk_window_get_height (window) - extents.height - extents.y, extents.width, extents.height);
+ glEnable (GL_SCISSOR_TEST);
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
#define ORTHO_NEAR_PLANE -10000
#define ORTHO_FAR_PLANE 10000
@@ -916,6 +946,8 @@ gsk_gl_renderer_render (GskRenderer *renderer,
if (gsk_gl_driver_bind_render_target (self->gl_driver, 0))
gsk_gl_renderer_resize_viewport (self, &viewport, scale_factor);
+ gsk_gl_renderer_setup_render_mode (self);
+
gsk_gl_renderer_clear (self);
glEnable (GL_DEPTH_TEST);