[cogl/wip/cogl-1.14: 64/177] clip-stack: workaround intel gen6 viewport clip bug



commit 0b270a736487e541392019d20285bc41bfc19061
Author: Robert Bragg <robert linux intel com>
Date:   Tue Oct 2 11:44:00 2012 +0100

    clip-stack: workaround intel gen6 viewport clip bug
    
    The Intel Mesa gen6 driver doesn't currently handle scissoring offset
    viewports correctly, so this implements a workaround to intersect the
    current viewport bounds with the scissor rectangle.
    
    (cherry picked from commit afc5daab85e5faca99d6d6866658cb82c3954830)

 cogl/cogl-clip-stack.c              |   12 +++++++---
 cogl/cogl-context-private.h         |    3 ++
 cogl/cogl-context.c                 |   17 +++++++++++++++
 cogl/cogl-framebuffer-private.h     |    2 +
 cogl/cogl-framebuffer.c             |    6 +++++
 cogl/cogl-util.h                    |   16 ++++++++++++++
 cogl/driver/gl/cogl-clip-stack-gl.c |   39 ++++++++++++++++++++++++++++++++--
 7 files changed, 88 insertions(+), 7 deletions(-)
---
diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c
index ad23409..7ecf83f 100644
--- a/cogl/cogl-clip-stack.c
+++ b/cogl/cogl-clip-stack.c
@@ -447,10 +447,14 @@ _cogl_clip_stack_get_bounds (CoglClipStack *stack,
     {
       /* Get the intersection of the current scissor and the bounding
          box of this clip */
-      *scissor_x0 = MAX (*scissor_x0, entry->bounds_x0);
-      *scissor_y0 = MAX (*scissor_y0, entry->bounds_y0);
-      *scissor_x1 = MIN (*scissor_x1, entry->bounds_x1);
-      *scissor_y1 = MIN (*scissor_y1, entry->bounds_y1);
+      _cogl_util_scissor_intersect (entry->bounds_x0,
+                                    entry->bounds_y0,
+                                    entry->bounds_x1,
+                                    entry->bounds_y1,
+                                    scissor_x0,
+                                    scissor_y0,
+                                    scissor_x1,
+                                    scissor_y1);
     }
 }
 
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 788cf3d..06acc3c 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -83,6 +83,9 @@ struct _CoglContext
   CoglFeatureFlags feature_flags; /* legacy/deprecated feature flags */
   CoglPrivateFeatureFlags private_feature_flags;
 
+  CoglBool needs_viewport_scissor_workaround;
+  CoglFramebuffer *viewport_scissor_workaround_framebuffer;
+
   CoglPipeline *default_pipeline;
   CoglPipelineLayer *default_layer_0;
   CoglPipelineLayer *default_layer_n;
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 8bf4430..207d68c 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -52,6 +52,7 @@
 #include "cogl-error-private.h"
 
 #include <string.h>
+#include <stdlib.h>
 
 #ifdef HAVE_COGL_GL
 #include "cogl-pipeline-fragend-arbfp-private.h"
@@ -240,6 +241,22 @@ cogl_context_new (CoglDisplay *display,
   /* Initialise the driver specific state */
   _cogl_init_feature_overrides (context);
 
+  /* XXX: ONGOING BUG: Intel viewport scissor
+   *
+   * Intel gen6 drivers don't currently correctly handle offset
+   * viewports, since primitives aren't clipped within the bounds of
+   * the viewport.  To workaround this we push our own clip for the
+   * viewport that will use scissoring to ensure we clip as expected.
+   *
+   * TODO: file a bug upstream!
+   */
+  if (context->gpu.driver_package == COGL_GPU_INFO_DRIVER_PACKAGE_MESA &&
+      context->gpu.architecture == COGL_GPU_INFO_ARCHITECTURE_SANDYBRIDGE &&
+      !getenv ("COGL_DISABLE_INTEL_VIEWPORT_SCISSORT_WORKAROUND"))
+    context->needs_viewport_scissor_workaround = TRUE;
+  else
+    context->needs_viewport_scissor_workaround = FALSE;
+
   context->sampler_cache = _cogl_sampler_cache_new (context);
 
   _cogl_pipeline_init_default_pipeline ();
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index d2c2c36..8db49ec 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -127,6 +127,8 @@ struct _CoglFramebuffer
   float               viewport_y;
   float               viewport_width;
   float               viewport_height;
+  int                 viewport_age;
+  int                 viewport_age_for_scissor_workaround;
 
   CoglClipState       clip_state;
 
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index fd646b1..f7f2983 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -112,6 +112,8 @@ _cogl_framebuffer_init (CoglFramebuffer *framebuffer,
   framebuffer->viewport_y = 0;
   framebuffer->viewport_width = width;
   framebuffer->viewport_height = height;
+  framebuffer->viewport_age = 0;
+  framebuffer->viewport_age_for_scissor_workaround = -1;
   framebuffer->dither_enabled = TRUE;
 
   framebuffer->modelview_stack = _cogl_matrix_stack_new ();
@@ -179,6 +181,9 @@ _cogl_framebuffer_free (CoglFramebuffer *framebuffer)
 
   cogl_object_unref (framebuffer->journal);
 
+  if (ctx->viewport_scissor_workaround_framebuffer == framebuffer)
+    ctx->viewport_scissor_workaround_framebuffer = NULL;
+
   ctx->framebuffers = g_list_remove (ctx->framebuffers, framebuffer);
 
   if (ctx->current_draw_buffer == framebuffer)
@@ -458,6 +463,7 @@ cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
   framebuffer->viewport_y = y;
   framebuffer->viewport_width = width;
   framebuffer->viewport_height = height;
+  framebuffer->viewport_age++;
 
   if (framebuffer->context->current_draw_buffer == framebuffer)
     framebuffer->context->current_draw_buffer_changes |=
diff --git a/cogl/cogl-util.h b/cogl/cogl-util.h
index 4fb4227..1f3d266 100644
--- a/cogl/cogl-util.h
+++ b/cogl/cogl-util.h
@@ -278,4 +278,20 @@ _cogl_util_memmem (const void *haystack,
                    size_t needle_len);
 #endif
 
+static inline void
+_cogl_util_scissor_intersect (int rect_x0,
+                              int rect_y0,
+                              int rect_x1,
+                              int rect_y1,
+                              int *scissor_x0,
+                              int *scissor_y0,
+                              int *scissor_x1,
+                              int *scissor_y1)
+{
+  *scissor_x0 = MAX (*scissor_x0, rect_x0);
+  *scissor_y0 = MAX (*scissor_y0, rect_y0);
+  *scissor_x1 = MIN (*scissor_x1, rect_x1);
+  *scissor_y1 = MIN (*scissor_y1, rect_y1);
+}
+
 #endif /* __COGL_UTIL_H */
diff --git a/cogl/driver/gl/cogl-clip-stack-gl.c b/cogl/driver/gl/cogl-clip-stack-gl.c
index db9fbd4..c816994 100644
--- a/cogl/driver/gl/cogl-clip-stack-gl.c
+++ b/cogl/driver/gl/cogl-clip-stack-gl.c
@@ -467,7 +467,12 @@ _cogl_clip_stack_gl_flush (CoglClipStack *stack,
      anything */
   if (ctx->current_clip_stack_valid)
     {
-      if (ctx->current_clip_stack == stack)
+      if (ctx->current_clip_stack == stack &&
+          (ctx->needs_viewport_scissor_workaround == FALSE ||
+           (framebuffer->viewport_age ==
+            framebuffer->viewport_age_for_scissor_workaround &&
+            ctx->viewport_scissor_workaround_framebuffer ==
+            framebuffer)))
         return;
 
       _cogl_clip_stack_unref (ctx->current_clip_stack);
@@ -483,8 +488,11 @@ _cogl_clip_stack_gl_flush (CoglClipStack *stack,
     disable_clip_planes (ctx);
   GE( ctx, glDisable (GL_STENCIL_TEST) );
 
-  /* If the stack is empty then there's nothing else to do */
-  if (stack == NULL)
+  /* If the stack is empty then there's nothing else to do
+   *
+   * See comment below about ctx->needs_viewport_scissor_workaround
+   */
+  if (stack == NULL && !ctx->needs_viewport_scissor_workaround)
     {
       COGL_NOTE (CLIPPING, "Flushed empty clip stack");
 
@@ -501,6 +509,31 @@ _cogl_clip_stack_gl_flush (CoglClipStack *stack,
                                &scissor_x0, &scissor_y0,
                                &scissor_x1, &scissor_y1);
 
+  /* XXX: ONGOING BUG: Intel viewport scissor
+   *
+   * Intel gen6 drivers don't correctly handle offset viewports, since
+   * primitives aren't clipped within the bounds of the viewport.  To
+   * workaround this we push our own clip for the viewport that will
+   * use scissoring to ensure we clip as expected.
+   *
+   * TODO: file a bug upstream!
+   */
+  if (ctx->needs_viewport_scissor_workaround)
+    {
+      _cogl_util_scissor_intersect (framebuffer->viewport_x,
+                                    framebuffer->viewport_y,
+                                    framebuffer->viewport_x +
+                                      framebuffer->viewport_width,
+                                    framebuffer->viewport_y +
+                                      framebuffer->viewport_height,
+                                    &scissor_x0, &scissor_y0,
+                                    &scissor_x1, &scissor_y1);
+      framebuffer->viewport_age_for_scissor_workaround =
+        framebuffer->viewport_age;
+      ctx->viewport_scissor_workaround_framebuffer =
+        framebuffer;
+    }
+
   /* Enable scissoring as soon as possible */
   if (scissor_x0 >= scissor_x1 || scissor_y0 >= scissor_y1)
     scissor_x0 = scissor_y0 = scissor_x1 = scissor_y1 = scissor_y_start = 0;



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