[cogl/cogl-1.14: 55/174] clip-stack: workaround intel gen6 viewport clip bug
- From: Robert Bragg <rbragg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/cogl-1.14: 55/174] clip-stack: workaround intel gen6 viewport clip bug
- Date: Tue, 22 Jan 2013 18:35:23 +0000 (UTC)
commit 6cfc93f26f64c506922bf119d5079d83de7543d2
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]