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)
This commit is contained in:
parent
362db1c445
commit
6cfc93f26f
7 changed files with 88 additions and 7 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 |=
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue