framebuffer: don't reference default fb in _clear apis

Some of the functions we were calling in cogl_framebuffer_clear[4f] were
referring to the current framebuffer, which would result in a crash
if nothing had been pushed before trying to explicitly clear a given
framebuffer.

Reviewed-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
Robert Bragg 2011-08-03 17:06:10 +01:00
parent 19d12e65e5
commit f7b1bab1ad
8 changed files with 59 additions and 47 deletions

View File

@ -67,14 +67,14 @@ project_vertex (const CoglMatrix *modelview_projection,
}
static void
set_clip_plane (GLint plane_num,
set_clip_plane (CoglFramebuffer *framebuffer,
GLint plane_num,
const float *vertex_a,
const float *vertex_b)
{
GLfloat planef[4];
double planed[4];
GLfloat angle;
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
CoglMatrixStack *projection_stack =
@ -135,12 +135,12 @@ set_clip_plane (GLint plane_num,
}
static void
set_clip_planes (float x_1,
set_clip_planes (CoglFramebuffer *framebuffer,
float x_1,
float y_1,
float x_2,
float y_2)
{
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
CoglMatrix modelview_matrix;
@ -179,29 +179,29 @@ set_clip_planes (float x_1,
if (signed_area > 0.0f)
{
/* counter-clockwise */
set_clip_plane (GL_CLIP_PLANE0, vertex_tl, vertex_bl);
set_clip_plane (GL_CLIP_PLANE1, vertex_bl, vertex_br);
set_clip_plane (GL_CLIP_PLANE2, vertex_br, vertex_tr);
set_clip_plane (GL_CLIP_PLANE3, vertex_tr, vertex_tl);
set_clip_plane (framebuffer, GL_CLIP_PLANE0, vertex_tl, vertex_bl);
set_clip_plane (framebuffer, GL_CLIP_PLANE1, vertex_bl, vertex_br);
set_clip_plane (framebuffer, GL_CLIP_PLANE2, vertex_br, vertex_tr);
set_clip_plane (framebuffer, GL_CLIP_PLANE3, vertex_tr, vertex_tl);
}
else
{
/* clockwise */
set_clip_plane (GL_CLIP_PLANE0, vertex_tl, vertex_tr);
set_clip_plane (GL_CLIP_PLANE1, vertex_tr, vertex_br);
set_clip_plane (GL_CLIP_PLANE2, vertex_br, vertex_bl);
set_clip_plane (GL_CLIP_PLANE3, vertex_bl, vertex_tl);
set_clip_plane (framebuffer, GL_CLIP_PLANE0, vertex_tl, vertex_tr);
set_clip_plane (framebuffer, GL_CLIP_PLANE1, vertex_tr, vertex_br);
set_clip_plane (framebuffer, GL_CLIP_PLANE2, vertex_br, vertex_bl);
set_clip_plane (framebuffer, GL_CLIP_PLANE3, vertex_bl, vertex_tl);
}
}
static void
add_stencil_clip_rectangle (float x_1,
add_stencil_clip_rectangle (CoglFramebuffer *framebuffer,
float x_1,
float y_1,
float x_2,
float y_2,
gboolean first)
{
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
CoglMatrixStack *modelview_stack =
_cogl_framebuffer_get_modelview_stack (framebuffer);
CoglMatrixStack *projection_stack =
@ -584,7 +584,8 @@ _cogl_clip_stack_get_bounds (CoglClipStack *stack,
}
void
_cogl_clip_stack_flush (CoglClipStack *stack)
_cogl_clip_stack_flush (CoglClipStack *stack,
CoglFramebuffer *framebuffer)
{
int has_clip_planes;
gboolean using_clip_planes = FALSE;
@ -613,7 +614,7 @@ _cogl_clip_stack_flush (CoglClipStack *stack)
ctx->current_clip_stack = _cogl_clip_stack_ref (stack);
modelview_stack =
_cogl_framebuffer_get_modelview_stack (cogl_get_draw_framebuffer ());
_cogl_framebuffer_get_modelview_stack (framebuffer);
has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES);
@ -644,8 +645,6 @@ _cogl_clip_stack_flush (CoglClipStack *stack)
scissor_x0 = scissor_y0 = scissor_x1 = scissor_y1 = scissor_y_start = 0;
else
{
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
/* We store the entry coordinates in Cogl coordinate space
* but OpenGL requires the window origin to be the bottom
* left so we may need to convert the incoming coordinates.
@ -714,7 +713,8 @@ _cogl_clip_stack_flush (CoglClipStack *stack)
{
COGL_NOTE (CLIPPING, "Adding clip planes clip for rectangle");
set_clip_planes (rect->x0,
set_clip_planes (framebuffer,
rect->x0,
rect->y0,
rect->x1,
rect->y1);
@ -726,7 +726,8 @@ _cogl_clip_stack_flush (CoglClipStack *stack)
{
COGL_NOTE (CLIPPING, "Adding stencil clip for rectangle");
add_stencil_clip_rectangle (rect->x0,
add_stencil_clip_rectangle (framebuffer,
rect->x0,
rect->y0,
rect->x1,
rect->y1,

View File

@ -26,6 +26,7 @@
#include "cogl2-path.h"
#include "cogl-matrix.h"
#include "cogl.h"
/* The clip stack works like a GSList where only a pointer to the top
of the stack is stored. The empty clip stack is represented simply
@ -178,7 +179,8 @@ _cogl_clip_stack_get_bounds (CoglClipStack *stack,
int *scissor_y1);
void
_cogl_clip_stack_flush (CoglClipStack *stack);
_cogl_clip_stack_flush (CoglClipStack *stack,
CoglFramebuffer *framebuffer);
CoglClipStack *
_cogl_clip_stack_ref (CoglClipStack *stack);

View File

@ -41,7 +41,8 @@ void
_cogl_clip_state_destroy (CoglClipState *state);
void
_cogl_clip_state_flush (CoglClipState *clip_state);
_cogl_clip_state_flush (CoglClipState *clip_state,
CoglFramebuffer *framebuffer);
CoglClipStack *
_cogl_clip_state_get_stack (CoglClipState *clip_state);

View File

@ -146,11 +146,13 @@ cogl_clip_pop (void)
}
void
_cogl_clip_state_flush (CoglClipState *clip_state)
_cogl_clip_state_flush (CoglClipState *clip_state,
CoglFramebuffer *framebuffer)
{
/* Flush the topmost stack. The clip stack code will bail out early
if this is already flushed */
_cogl_clip_stack_flush (clip_state->stacks->data);
_cogl_clip_stack_flush (clip_state->stacks->data,
framebuffer);
}
/* XXX: This should never have been made public API! */
@ -166,7 +168,7 @@ cogl_clip_ensure (void)
application however so it makes sense to flush the journal
here */
_cogl_framebuffer_flush_journal (framebuffer);
_cogl_clip_state_flush (clip_state);
_cogl_clip_state_flush (clip_state, framebuffer);
}
static void

View File

@ -146,7 +146,8 @@ _cogl_framebuffer_winsys_update_size (CoglFramebuffer *framebuffer,
int width, int height);
void
_cogl_clear4f (unsigned long buffers,
_cogl_framebuffer_clear_without_flush4f (CoglFramebuffer *framebuffer,
unsigned long buffers,
float red,
float green,
float blue,

View File

@ -228,7 +228,8 @@ _cogl_framebuffer_get_winsys (CoglFramebuffer *framebuffer)
* needed when doing operations that may be called whiling flushing
* the journal */
void
_cogl_clear4f (unsigned long buffers,
_cogl_framebuffer_clear_without_flush4f (CoglFramebuffer *framebuffer,
unsigned long buffers,
float red,
float green,
float blue,
@ -240,15 +241,12 @@ _cogl_clear4f (unsigned long buffers,
if (buffers & COGL_BUFFER_BIT_COLOR)
{
CoglFramebuffer *draw_framebuffer;
GE( ctx, glClearColor (red, green, blue, alpha) );
gl_buffers |= GL_COLOR_BUFFER_BIT;
draw_framebuffer = cogl_get_draw_framebuffer ();
if (ctx->current_gl_color_mask != draw_framebuffer->color_mask)
if (ctx->current_gl_color_mask != framebuffer->color_mask)
{
CoglColorMask color_mask = draw_framebuffer->color_mask;
CoglColorMask color_mask = framebuffer->color_mask;
GE( ctx, glColorMask (!!(color_mask & COGL_COLOR_MASK_RED),
!!(color_mask & COGL_COLOR_MASK_GREEN),
!!(color_mask & COGL_COLOR_MASK_BLUE),
@ -396,7 +394,8 @@ _cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
* always be done first when preparing to draw. */
_cogl_framebuffer_flush_state (framebuffer, framebuffer, 0);
_cogl_clear4f (buffers, red, green, blue, alpha);;
_cogl_framebuffer_clear_without_flush4f (framebuffer, buffers,
red, green, blue, alpha);
/* This is a debugging variable used to visually display the quad
* batches from the journal. It is reset here to increase the
@ -1463,7 +1462,8 @@ _cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
* matrices so we must do it before flushing the matrices...
*/
if (!(flags & COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE))
_cogl_clip_state_flush (&draw_buffer->clip_state);
_cogl_clip_state_flush (&draw_buffer->clip_state,
draw_buffer);
if (!(flags & COGL_FRAMEBUFFER_FLUSH_SKIP_MODELVIEW))
_cogl_matrix_stack_flush_to_gl (draw_buffer->modelview_stack,
@ -1651,7 +1651,7 @@ _cogl_blit_framebuffer (unsigned int src_x,
by the scissor and we want to hide this feature for the Cogl API
because it's not obvious to an app how the clip state will affect
the scissor */
_cogl_clip_stack_flush (NULL);
_cogl_clip_stack_flush (NULL, draw_buffer);
ctx->glBlitFramebuffer (src_x, src_y,
src_x + width, src_y + height,

View File

@ -95,6 +95,8 @@ typedef struct _CoglJournalFlushState
{
CoglJournal *journal;
CoglFramebuffer *framebuffer;
CoglAttributeBuffer *attribute_buffer;
GArray *attributes;
int current_attribute;
@ -705,7 +707,7 @@ _cogl_journal_flush_clip_stacks_and_entries (CoglJournalEntry *batch_start,
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
g_print ("BATCHING: clip stack batch len = %d\n", batch_len);
_cogl_clip_stack_flush (batch_start->clip_stack);
_cogl_clip_stack_flush (batch_start->clip_stack, state->framebuffer);
_cogl_matrix_stack_push (state->modelview_stack);
@ -1352,6 +1354,7 @@ _cogl_journal_flush (CoglJournal *journal,
* that the timer isn't started recursively. */
COGL_TIMER_START (_cogl_uprof_context, flush_timer);
state.framebuffer = framebuffer;
cogl_push_framebuffer (framebuffer);
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))

View File

@ -401,9 +401,11 @@ _cogl_add_path_to_stencil_buffer (CoglPath *path,
will have set up a scissor for the minimum bounding box of
all of the clips. That box will likely mean that this
_cogl_clear won't need to clear the entire
buffer. _cogl_clear4f is used instead of cogl_clear because
it won't try to flush the journal */
_cogl_clear4f (COGL_BUFFER_BIT_STENCIL, 0, 0, 0, 0);
buffer. _cogl_framebuffer_clear_without_flush4f is used instead
of cogl_clear because it won't try to flush the journal */
_cogl_framebuffer_clear_without_flush4f (framebuffer,
COGL_BUFFER_BIT_STENCIL,
0, 0, 0, 0);
else
{
/* Just clear the bounding box */