mirror of
https://github.com/brl/mutter.git
synced 2024-11-29 11:30:45 -05:00
cogl-clip-stack: Don't convert rect clips to window clips
Previously in cogl-clip-state.c when it detected that the current modelview matrix is screen-aligned it would convert the clip entry to a window clip. Instead of doing this cogl-clip-stack.c now contains the detection and keeps the entry as a rectangle clip but marks that it is entirely described by its scissor rect. When flusing the clip stack it doesn't do anything extra for entries that have this mark (because the clip will already been setup by the scissor). This is needed so that we can still track the original rectangle coordinates and modelview matrix to help detect when it would be faster to modify the rectangle when adding it to the journal rather than having to break up the batch to set the clip state.
This commit is contained in:
parent
b14c2f799c
commit
07e49d5257
@ -122,6 +122,16 @@ struct _CoglClipStackRect
|
||||
float x1;
|
||||
float y1;
|
||||
|
||||
/* If this is true then the clip for this rectangle is entirely
|
||||
described by the scissor bounds. This implies that the rectangle
|
||||
is screen aligned and we don't need to use the stencil buffer to
|
||||
set the clip. We keep the entry as a rect entry rather than a
|
||||
window rect entry so that it will be easier to detect if the
|
||||
modelview matrix is that same as when a rectangle is added to the
|
||||
journal. In that case we can use the original clip coordinates
|
||||
and modify the rectangle instead. */
|
||||
gboolean can_be_scissor;
|
||||
|
||||
/* The matrix that was current when the clip was set */
|
||||
CoglMatrix matrix;
|
||||
};
|
||||
@ -470,6 +480,8 @@ _cogl_clip_stack_push_rectangle (CoglClipStack *stack,
|
||||
const CoglMatrix *modelview_matrix)
|
||||
{
|
||||
CoglClipStackRect *entry;
|
||||
CoglMatrix matrix_p;
|
||||
float v[4];
|
||||
|
||||
/* Make a new entry */
|
||||
entry = _cogl_clip_stack_push_entry (stack,
|
||||
@ -483,8 +495,48 @@ _cogl_clip_stack_push_rectangle (CoglClipStack *stack,
|
||||
|
||||
entry->matrix = *modelview_matrix;
|
||||
|
||||
_cogl_clip_stack_entry_set_bounds ((CoglClipStack *) entry,
|
||||
x_1, y_1, x_2, y_2, modelview_matrix);
|
||||
/* If the modelview meets these constraints then a transformed rectangle
|
||||
* should still be a rectangle when it reaches screen coordinates.
|
||||
*
|
||||
* FIXME: we are are making certain assumptions about the projection
|
||||
* matrix a.t.m and should really be looking at the combined modelview
|
||||
* and projection matrix.
|
||||
* FIXME: we don't consider rotations that are a multiple of 90 degrees
|
||||
* which could be quite common.
|
||||
*/
|
||||
if (modelview_matrix->xy != 0 || modelview_matrix->xz != 0 ||
|
||||
modelview_matrix->yx != 0 || modelview_matrix->yz != 0 ||
|
||||
modelview_matrix->zx != 0 || modelview_matrix->zy != 0)
|
||||
{
|
||||
entry->can_be_scissor = FALSE;
|
||||
_cogl_clip_stack_entry_set_bounds ((CoglClipStack *) entry,
|
||||
x_1, y_1, x_2, y_2, modelview_matrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
CoglClipStack *base_entry = (CoglClipStack *) entry;
|
||||
|
||||
cogl_get_projection_matrix (&matrix_p);
|
||||
cogl_get_viewport (v);
|
||||
|
||||
_cogl_transform_point (modelview_matrix, &matrix_p, v, &x_1, &y_1);
|
||||
_cogl_transform_point (modelview_matrix, &matrix_p, v, &x_2, &y_2);
|
||||
|
||||
/* Consider that the modelview matrix may flip the rectangle
|
||||
* along the x or y axis... */
|
||||
#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0)
|
||||
if (x_1 > x_2)
|
||||
SWAP (x_1, x_2);
|
||||
if (y_1 > y_2)
|
||||
SWAP (y_1, y_2);
|
||||
#undef SWAP
|
||||
|
||||
base_entry->bounds_x0 = COGL_UTIL_NEARBYINT (x_1);
|
||||
base_entry->bounds_y0 = COGL_UTIL_NEARBYINT (y_1);
|
||||
base_entry->bounds_x1 = COGL_UTIL_NEARBYINT (x_2);
|
||||
base_entry->bounds_y1 = COGL_UTIL_NEARBYINT (y_2);
|
||||
entry->can_be_scissor = TRUE;
|
||||
}
|
||||
|
||||
return (CoglClipStack *) entry;
|
||||
}
|
||||
@ -696,32 +748,37 @@ _cogl_clip_stack_flush (CoglClipStack *stack)
|
||||
{
|
||||
CoglClipStackRect *rect = (CoglClipStackRect *) entry;
|
||||
|
||||
_cogl_matrix_stack_push (modelview_stack);
|
||||
_cogl_matrix_stack_set (modelview_stack, &rect->matrix);
|
||||
|
||||
/* If we support clip planes and we haven't already used
|
||||
them then use that instead */
|
||||
if (has_clip_planes)
|
||||
/* We don't need to do anything extra if the clip for this
|
||||
rectangle was entirely described by its scissor bounds */
|
||||
if (!rect->can_be_scissor)
|
||||
{
|
||||
set_clip_planes (rect->x0,
|
||||
rect->y0,
|
||||
rect->x1,
|
||||
rect->y1);
|
||||
using_clip_planes = TRUE;
|
||||
/* We can't use clip planes a second time */
|
||||
has_clip_planes = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
add_stencil_clip_rectangle (rect->x0,
|
||||
rect->y0,
|
||||
rect->x1,
|
||||
rect->y1,
|
||||
!using_stencil_buffer);
|
||||
using_stencil_buffer = TRUE;
|
||||
}
|
||||
_cogl_matrix_stack_push (modelview_stack);
|
||||
_cogl_matrix_stack_set (modelview_stack, &rect->matrix);
|
||||
|
||||
_cogl_matrix_stack_pop (modelview_stack);
|
||||
/* If we support clip planes and we haven't already used
|
||||
them then use that instead */
|
||||
if (has_clip_planes)
|
||||
{
|
||||
set_clip_planes (rect->x0,
|
||||
rect->y0,
|
||||
rect->x1,
|
||||
rect->y1);
|
||||
using_clip_planes = TRUE;
|
||||
/* We can't use clip planes a second time */
|
||||
has_clip_planes = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
add_stencil_clip_rectangle (rect->x0,
|
||||
rect->y0,
|
||||
rect->x1,
|
||||
rect->y1,
|
||||
!using_stencil_buffer);
|
||||
using_stencil_buffer = TRUE;
|
||||
}
|
||||
|
||||
_cogl_matrix_stack_pop (modelview_stack);
|
||||
}
|
||||
}
|
||||
/* We don't need to do anything for window space rectangles
|
||||
because their functionality is entirely implemented by the
|
||||
|
@ -70,56 +70,6 @@ cogl_clip_push_window_rect (float x_offset,
|
||||
cogl_clip_push_window_rectangle (x_offset, y_offset, width, height);
|
||||
}
|
||||
|
||||
/* Try to push a rectangle given in object coordinates as a rectangle in window
|
||||
* coordinates instead of object coordinates */
|
||||
static gboolean
|
||||
try_pushing_rect_as_window_rect (float x_1,
|
||||
float y_1,
|
||||
float x_2,
|
||||
float y_2)
|
||||
{
|
||||
CoglMatrix matrix;
|
||||
CoglMatrix matrix_p;
|
||||
float v[4];
|
||||
|
||||
cogl_get_modelview_matrix (&matrix);
|
||||
|
||||
/* If the modelview meets these constraints then a transformed rectangle
|
||||
* should still be a rectangle when it reaches screen coordinates.
|
||||
*
|
||||
* FIXME: we are are making certain assumptions about the projection
|
||||
* matrix a.t.m and should really be looking at the combined modelview
|
||||
* and projection matrix.
|
||||
* FIXME: we don't consider rotations that are a multiple of 90 degrees
|
||||
* which could be quite common.
|
||||
*/
|
||||
if (matrix.xy != 0 || matrix.xz != 0 ||
|
||||
matrix.yx != 0 || matrix.yz != 0 ||
|
||||
matrix.zx != 0 || matrix.zy != 0)
|
||||
return FALSE;
|
||||
|
||||
cogl_get_projection_matrix (&matrix_p);
|
||||
cogl_get_viewport (v);
|
||||
|
||||
_cogl_transform_point (&matrix, &matrix_p, v, &x_1, &y_1);
|
||||
_cogl_transform_point (&matrix, &matrix_p, v, &x_2, &y_2);
|
||||
|
||||
/* Consider that the modelview matrix may flip the rectangle
|
||||
* along the x or y axis... */
|
||||
#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0)
|
||||
if (x_1 > x_2)
|
||||
SWAP (x_1, x_2);
|
||||
if (y_1 > y_2)
|
||||
SWAP (y_1, y_2);
|
||||
#undef SWAP
|
||||
|
||||
cogl_clip_push_window_rectangle (COGL_UTIL_NEARBYINT (x_1),
|
||||
COGL_UTIL_NEARBYINT (y_1),
|
||||
COGL_UTIL_NEARBYINT (x_2 - x_1),
|
||||
COGL_UTIL_NEARBYINT (y_2 - y_1));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_clip_push_rectangle (float x_1,
|
||||
float y_1,
|
||||
@ -132,11 +82,6 @@ cogl_clip_push_rectangle (float x_1,
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Try and catch window space rectangles so we can redirect to
|
||||
* cogl_clip_push_window_rect which will use scissoring. */
|
||||
if (try_pushing_rect_as_window_rect (x_1, y_1, x_2, y_2))
|
||||
return;
|
||||
|
||||
framebuffer = _cogl_get_framebuffer ();
|
||||
clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user