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

View File

@ -26,6 +26,7 @@
#include "cogl2-path.h" #include "cogl2-path.h"
#include "cogl-matrix.h" #include "cogl-matrix.h"
#include "cogl.h"
/* The clip stack works like a GSList where only a pointer to the top /* 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 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); int *scissor_y1);
void void
_cogl_clip_stack_flush (CoglClipStack *stack); _cogl_clip_stack_flush (CoglClipStack *stack,
CoglFramebuffer *framebuffer);
CoglClipStack * CoglClipStack *
_cogl_clip_stack_ref (CoglClipStack *stack); _cogl_clip_stack_ref (CoglClipStack *stack);

View File

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

View File

@ -146,11 +146,13 @@ cogl_clip_pop (void)
} }
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 /* Flush the topmost stack. The clip stack code will bail out early
if this is already flushed */ 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! */ /* 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 application however so it makes sense to flush the journal
here */ here */
_cogl_framebuffer_flush_journal (framebuffer); _cogl_framebuffer_flush_journal (framebuffer);
_cogl_clip_state_flush (clip_state); _cogl_clip_state_flush (clip_state, framebuffer);
} }
static void static void

View File

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

View File

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

View File

@ -95,6 +95,8 @@ typedef struct _CoglJournalFlushState
{ {
CoglJournal *journal; CoglJournal *journal;
CoglFramebuffer *framebuffer;
CoglAttributeBuffer *attribute_buffer; CoglAttributeBuffer *attribute_buffer;
GArray *attributes; GArray *attributes;
int current_attribute; 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))) if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
g_print ("BATCHING: clip stack batch len = %d\n", batch_len); 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); _cogl_matrix_stack_push (state->modelview_stack);
@ -1352,6 +1354,7 @@ _cogl_journal_flush (CoglJournal *journal,
* that the timer isn't started recursively. */ * that the timer isn't started recursively. */
COGL_TIMER_START (_cogl_uprof_context, flush_timer); COGL_TIMER_START (_cogl_uprof_context, flush_timer);
state.framebuffer = framebuffer;
cogl_push_framebuffer (framebuffer); cogl_push_framebuffer (framebuffer);
if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING))) 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 will have set up a scissor for the minimum bounding box of
all of the clips. That box will likely mean that this all of the clips. That box will likely mean that this
_cogl_clear won't need to clear the entire _cogl_clear won't need to clear the entire
buffer. _cogl_clear4f is used instead of cogl_clear because buffer. _cogl_framebuffer_clear_without_flush4f is used instead
it won't try to flush the journal */ of cogl_clear because it won't try to flush the journal */
_cogl_clear4f (COGL_BUFFER_BIT_STENCIL, 0, 0, 0, 0); _cogl_framebuffer_clear_without_flush4f (framebuffer,
COGL_BUFFER_BIT_STENCIL,
0, 0, 0, 0);
else else
{ {
/* Just clear the bounding box */ /* Just clear the bounding box */