[mutter] cogl/clip-stack: Restore old matrices after drawing to stencil buffer



commit 72054332c574634c754c4ad0f1ee0df88d57da21
Author: Jonas Dreßler <verdre v0yd nl>
Date:   Wed Feb 26 16:30:29 2020 +0100

    cogl/clip-stack: Restore old matrices after drawing to stencil buffer
    
    When using a region clip and something has a rectangle clip pushed, a
    special drawing method for ClutterTexts (emit_vertex_buffer_geometry()
    in cogl-pango-display-list.c) starts to fail and clipping issues with
    long texts (because emit_vertex_buffer_geometry() is only used for texts
    longer than 25 characters) start to appear. This specifically happened
    in Looking Glass, where the StViewport of the ScrollView sets a
    rectangle clips and the texts are usually longer than 25 characters.
    
    This is caused by the changing of the perspective and modelview matrix
    when drawing to the stencil buffer and started happening when
    region-clipping was introduced with commit 8598b654. Even though the
    changing of the matrices was done before that, too, the issue probably
    didn't happen because `rect->can_be_scissor` was TRUE and no stencil
    buffer clipping was used at all.
    
    To fix this, temporarily save the old matrices, then set the new ones
    and restore the old ones when we're done drawing to the stencil buffer.
    
    Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/2246
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/1096

 cogl/cogl/driver/gl/cogl-clip-stack-gl.c | 41 ++++++++++++++++++++++----------
 1 file changed, 29 insertions(+), 12 deletions(-)
---
diff --git a/cogl/cogl/driver/gl/cogl-clip-stack-gl.c b/cogl/cogl/driver/gl/cogl-clip-stack-gl.c
index 64fb50558..01c97cbc8 100644
--- a/cogl/cogl/driver/gl/cogl-clip-stack-gl.c
+++ b/cogl/cogl/driver/gl/cogl-clip-stack-gl.c
@@ -62,14 +62,16 @@ add_stencil_clip_rectangle (CoglFramebuffer *framebuffer,
   CoglMatrixStack *projection_stack =
     _cogl_framebuffer_get_projection_stack (framebuffer);
   CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
+  CoglMatrixEntry *old_projection_entry, *old_modelview_entry;
 
   /* NB: This can be called while flushing the journal so we need
    * to be very conservative with what state we change.
    */
+  old_projection_entry = g_steal_pointer (&ctx->current_projection_entry);
+  old_modelview_entry = g_steal_pointer (&ctx->current_modelview_entry);
 
-  _cogl_context_set_current_projection_entry (ctx,
-                                              projection_stack->last_entry);
-  _cogl_context_set_current_modelview_entry (ctx, modelview_entry);
+  ctx->current_projection_entry = projection_stack->last_entry;
+  ctx->current_modelview_entry = modelview_entry;
 
   if (merge)
     {
@@ -86,8 +88,8 @@ add_stencil_clip_rectangle (CoglFramebuffer *framebuffer,
         rectangle are set will be valid */
       GE( ctx, glStencilOp (GL_DECR, GL_DECR, GL_DECR) );
 
-      _cogl_context_set_current_projection_entry (ctx, &ctx->identity_entry);
-      _cogl_context_set_current_modelview_entry (ctx, &ctx->identity_entry);
+      ctx->current_projection_entry = &ctx->identity_entry;
+      ctx->current_modelview_entry = &ctx->identity_entry;
 
       _cogl_rectangle_immediate (framebuffer,
                                  ctx->stencil_pipeline,
@@ -109,6 +111,9 @@ add_stencil_clip_rectangle (CoglFramebuffer *framebuffer,
                                  x_1, y_1, x_2, y_2);
     }
 
+  ctx->current_projection_entry = old_projection_entry;
+  ctx->current_modelview_entry = old_modelview_entry;
+
   /* Restore the stencil mode */
   GE( ctx, glStencilFunc (GL_EQUAL, 0x1, 0x1) );
   GE( ctx, glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
@@ -120,6 +125,7 @@ add_stencil_clip_region (CoglFramebuffer *framebuffer,
                          gboolean         merge)
 {
   CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
+  CoglMatrixEntry *old_projection_entry, *old_modelview_entry;
   CoglMatrix matrix;
   int num_rectangles = cairo_region_num_rectangles (region);
   int i;
@@ -128,8 +134,11 @@ add_stencil_clip_region (CoglFramebuffer *framebuffer,
   /* NB: This can be called while flushing the journal so we need
    * to be very conservative with what state we change.
    */
-  _cogl_context_set_current_projection_entry (ctx, &ctx->identity_entry);
-  _cogl_context_set_current_modelview_entry (ctx, &ctx->identity_entry);
+  old_projection_entry = g_steal_pointer (&ctx->current_projection_entry);
+  old_modelview_entry = g_steal_pointer (&ctx->current_modelview_entry);
+
+  ctx->current_projection_entry = &ctx->identity_entry;
+  ctx->current_modelview_entry = &ctx->identity_entry;
 
   /* The coordinates in the region are meant to be window coordinates,
    * make a matrix that translates those across the viewport, and into
@@ -223,6 +232,9 @@ add_stencil_clip_region (CoglFramebuffer *framebuffer,
                                  -1.0, -1.0, 1.0, 1.0);
     }
 
+  ctx->current_projection_entry = old_projection_entry;
+  ctx->current_modelview_entry = old_modelview_entry;
+
   /* Restore the stencil mode */
   GE (ctx, glDepthMask (TRUE));
   GE (ctx, glColorMask (TRUE, TRUE, TRUE, TRUE));
@@ -249,14 +261,16 @@ add_stencil_clip_silhouette (CoglFramebuffer *framebuffer,
   CoglMatrixStack *projection_stack =
     _cogl_framebuffer_get_projection_stack (framebuffer);
   CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
+  CoglMatrixEntry *old_projection_entry, *old_modelview_entry;
 
   /* NB: This can be called while flushing the journal so we need
    * to be very conservative with what state we change.
    */
+  old_projection_entry = g_steal_pointer (&ctx->current_projection_entry);
+  old_modelview_entry = g_steal_pointer (&ctx->current_modelview_entry);
 
-  _cogl_context_set_current_projection_entry (ctx,
-                                              projection_stack->last_entry);
-  _cogl_context_set_current_modelview_entry (ctx, modelview_entry);
+  ctx->current_projection_entry = projection_stack->last_entry;
+  ctx->current_modelview_entry = modelview_entry;
 
   _cogl_pipeline_flush_gl_state (ctx, ctx->stencil_pipeline,
                                  framebuffer, FALSE, FALSE);
@@ -314,8 +328,8 @@ add_stencil_clip_silhouette (CoglFramebuffer *framebuffer,
       /* Decrement all of the bits twice so that only pixels where the
          value is 3 will remain */
 
-      _cogl_context_set_current_projection_entry (ctx, &ctx->identity_entry);
-      _cogl_context_set_current_modelview_entry (ctx, &ctx->identity_entry);
+      ctx->current_projection_entry = &ctx->identity_entry;
+      ctx->current_modelview_entry = &ctx->identity_entry;
 
       _cogl_rectangle_immediate (framebuffer, ctx->stencil_pipeline,
                                  -1.0, -1.0, 1.0, 1.0);
@@ -323,6 +337,9 @@ add_stencil_clip_silhouette (CoglFramebuffer *framebuffer,
                                  -1.0, -1.0, 1.0, 1.0);
     }
 
+  ctx->current_projection_entry = old_projection_entry;
+  ctx->current_modelview_entry = old_modelview_entry;
+
   GE (ctx, glStencilMask (~(GLuint) 0));
   GE (ctx, glDepthMask (TRUE));
   GE (ctx, glColorMask (TRUE, TRUE, TRUE, TRUE));


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]