mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -05:00
framebuffer: deal with winding state like other state
We should not be deciding whether we need to really update the GL face winding state at the point where a new framebuffer has been pushed, we should be waiting until we have really been asked to flush some framebuffer state otherwise we may do redundant work if multiple framebuffers are pushed/popped before something is really drawn. This integrates the face winding state tracking with the design we have for handling most of the other framebuffer state so we benefit from the optimizations for minimizing the cost of _cogl_framebuffer_flush_state() Reviewed-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
parent
cf4b228fc0
commit
2112af0bc5
@ -65,25 +65,27 @@ typedef enum
|
||||
*/
|
||||
typedef enum _CoglFramebufferStateIndex
|
||||
{
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_BIND = 0,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_VIEWPORT = 1,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_CLIP = 2,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_DITHER = 3,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_MODELVIEW = 4,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_PROJECTION = 5,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_COLOR_MASK = 6,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_MAX = 7
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_BIND = 0,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_VIEWPORT = 1,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_CLIP = 2,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_DITHER = 3,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_MODELVIEW = 4,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_PROJECTION = 5,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_COLOR_MASK = 6,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING = 7,
|
||||
COGL_FRAMEBUFFER_STATE_INDEX_MAX = 8
|
||||
} CoglFramebufferStateIndex;
|
||||
|
||||
typedef enum _CoglFramebufferState
|
||||
{
|
||||
COGL_FRAMEBUFFER_STATE_BIND = 1<<0,
|
||||
COGL_FRAMEBUFFER_STATE_VIEWPORT = 1<<1,
|
||||
COGL_FRAMEBUFFER_STATE_CLIP = 1<<2,
|
||||
COGL_FRAMEBUFFER_STATE_DITHER = 1<<3,
|
||||
COGL_FRAMEBUFFER_STATE_MODELVIEW = 1<<4,
|
||||
COGL_FRAMEBUFFER_STATE_PROJECTION = 1<<5,
|
||||
COGL_FRAMEBUFFER_STATE_COLOR_MASK = 1<<6
|
||||
COGL_FRAMEBUFFER_STATE_BIND = 1<<0,
|
||||
COGL_FRAMEBUFFER_STATE_VIEWPORT = 1<<1,
|
||||
COGL_FRAMEBUFFER_STATE_CLIP = 1<<2,
|
||||
COGL_FRAMEBUFFER_STATE_DITHER = 1<<3,
|
||||
COGL_FRAMEBUFFER_STATE_MODELVIEW = 1<<4,
|
||||
COGL_FRAMEBUFFER_STATE_PROJECTION = 1<<5,
|
||||
COGL_FRAMEBUFFER_STATE_COLOR_MASK = 1<<6,
|
||||
COGL_FRAMEBUFFER_STATE_FRONT_FACE_WINDING = 1<<7
|
||||
} CoglFramebufferState;
|
||||
|
||||
#define COGL_FRAMEBUFFER_STATE_ALL ((1<<COGL_FRAMEBUFFER_STATE_INDEX_MAX) - 1)
|
||||
|
@ -1104,25 +1104,6 @@ notify_buffers_changed (CoglFramebuffer *old_draw_buffer,
|
||||
CoglFramebuffer *old_read_buffer,
|
||||
CoglFramebuffer *new_read_buffer)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
if (old_draw_buffer && new_draw_buffer)
|
||||
{
|
||||
/* If we're switching from onscreen to offscreen and the last
|
||||
flush pipeline is using backface culling then we also need to
|
||||
reflush the cull face state because the winding order of the
|
||||
front face is flipped for offscreen buffers */
|
||||
if (old_draw_buffer->type != new_draw_buffer->type &&
|
||||
ctx->current_pipeline &&
|
||||
cogl_pipeline_get_cull_face_mode (ctx->current_pipeline) !=
|
||||
COGL_PIPELINE_CULL_FACE_MODE_NONE)
|
||||
{
|
||||
ctx->current_pipeline_changes_since_flush |=
|
||||
COGL_PIPELINE_STATE_CULL_FACE;
|
||||
ctx->current_pipeline_age--;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: To support the deprecated cogl_set_draw_buffer API we keep
|
||||
* track of the last onscreen framebuffer that was set so that it
|
||||
* can be restored if the COGL_WINDOW_BUFFER enum is used. A
|
||||
@ -1132,7 +1113,7 @@ notify_buffers_changed (CoglFramebuffer *old_draw_buffer,
|
||||
* _cogl_onscreen_free as a kind of a cheap weak reference */
|
||||
if (new_draw_buffer &&
|
||||
new_draw_buffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
|
||||
ctx->window_buffer = new_draw_buffer;
|
||||
new_draw_buffer->context->window_buffer = new_draw_buffer;
|
||||
}
|
||||
|
||||
/* Set the current framebuffer without checking if it's already the
|
||||
@ -1428,6 +1409,16 @@ _cogl_framebuffer_compare_color_mask_state (CoglFramebuffer *a,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
_cogl_framebuffer_compare_front_face_winding_state (CoglFramebuffer *a,
|
||||
CoglFramebuffer *b)
|
||||
{
|
||||
if (a->type != b->type)
|
||||
return COGL_FRAMEBUFFER_STATE_FRONT_FACE_WINDING;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
_cogl_framebuffer_compare (CoglFramebuffer *a,
|
||||
CoglFramebuffer *b,
|
||||
@ -1472,6 +1463,10 @@ _cogl_framebuffer_compare (CoglFramebuffer *a,
|
||||
differences |=
|
||||
_cogl_framebuffer_compare_color_mask_state (a, b);
|
||||
break;
|
||||
case COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING:
|
||||
differences |=
|
||||
_cogl_framebuffer_compare_front_face_winding_state (a, b);
|
||||
break;
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
}
|
||||
@ -1565,6 +1560,38 @@ _cogl_framebuffer_flush_color_mask_state (CoglFramebuffer *framebuffer)
|
||||
context->current_pipeline_age--;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_framebuffer_flush_front_face_winding_state (CoglFramebuffer *framebuffer)
|
||||
{
|
||||
CoglContext *context = framebuffer->context;
|
||||
CoglPipelineCullFaceMode mode;
|
||||
|
||||
/* NB: The face winding state is actually owned by the current
|
||||
* CoglPipeline.
|
||||
*
|
||||
* If we don't have a current pipeline then we can just assume that
|
||||
* when we later do flush a pipeline we will check the current
|
||||
* framebuffer to know how to setup the winding */
|
||||
if (!context->current_pipeline)
|
||||
return;
|
||||
|
||||
mode = cogl_pipeline_get_cull_face_mode (context->current_pipeline);
|
||||
|
||||
/* If the current CoglPipeline has a culling mode that doesn't care
|
||||
* about the winding we can avoid forcing an update of the state and
|
||||
* bail out. */
|
||||
if (mode == COGL_PIPELINE_CULL_FACE_MODE_NONE ||
|
||||
mode == COGL_PIPELINE_CULL_FACE_MODE_BOTH)
|
||||
return;
|
||||
|
||||
/* Since the winding state is really owned by the current pipeline
|
||||
* the way we "flush" an updated winding is to dirty the pipeline
|
||||
* state... */
|
||||
context->current_pipeline_changes_since_flush |=
|
||||
COGL_PIPELINE_STATE_CULL_FACE;
|
||||
context->current_pipeline_age--;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
|
||||
CoglFramebuffer *read_buffer,
|
||||
@ -1668,6 +1695,9 @@ _cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
|
||||
case COGL_FRAMEBUFFER_STATE_INDEX_COLOR_MASK:
|
||||
_cogl_framebuffer_flush_color_mask_state (draw_buffer);
|
||||
break;
|
||||
case COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING:
|
||||
_cogl_framebuffer_flush_front_face_winding_state (draw_buffer);
|
||||
break;
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user