From 5369b3c601fc537db6712c27a5453fa11236c66b Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 8 Nov 2011 13:58:33 +0000 Subject: [PATCH] pipeline: Make the backface culling experimental public This adds two new experimental public functions to replace the old internal _cogl_pipeline_set_cull_face_state function: void cogl_pipeline_set_cull_face_mode (CoglPipeline *pipeline, CoglPipelineCullFaceMode cull_face_mode); void cogl_pipeline_set_front_face_winding (CoglPipeline *pipeline, CoglWinding front_winding); There are also the corresponding getters. https://bugzilla.gnome.org/show_bug.cgi?id=663628 Reviewed-by: Robert Bragg --- cogl/cogl-framebuffer.c | 2 +- cogl/cogl-pipeline-private.h | 14 --- cogl/cogl-pipeline-state-private.h | 8 -- cogl/cogl-pipeline-state.c | 60 ++++++++++-- cogl/cogl-pipeline-state.h | 91 +++++++++++++++++++ cogl/cogl-pipeline.c | 8 +- cogl/cogl-types.h | 15 +++ .../cogl-2.0-experimental-sections.txt | 5 + 8 files changed, 165 insertions(+), 38 deletions(-) diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c index 3144c9527..e28d44899 100644 --- a/cogl/cogl-framebuffer.c +++ b/cogl/cogl-framebuffer.c @@ -1132,7 +1132,7 @@ notify_buffers_changed (CoglFramebuffer *old_draw_buffer, 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_get_cull_face_mode (ctx->current_pipeline) != COGL_PIPELINE_CULL_FACE_MODE_NONE) { ctx->current_pipeline_changes_since_flush |= diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h index 57f3503e6..4d0453644 100644 --- a/cogl/cogl-pipeline-private.h +++ b/cogl/cogl-pipeline-private.h @@ -298,20 +298,6 @@ typedef enum _CoglPipelineBlendEnable COGL_PIPELINE_BLEND_ENABLE_AUTOMATIC } CoglPipelineBlendEnable; -typedef enum -{ - COGL_PIPELINE_CULL_FACE_MODE_NONE, - COGL_PIPELINE_CULL_FACE_MODE_FRONT, - COGL_PIPELINE_CULL_FACE_MODE_BACK, - COGL_PIPELINE_CULL_FACE_MODE_BOTH -} CoglPipelineCullFaceMode; - -typedef enum -{ - COGL_WINDING_CLOCKWISE, - COGL_WINDING_COUNTER_CLOCKWISE -} CoglWinding; - typedef struct { /* Determines how this pipeline is blended with other primitives */ diff --git a/cogl/cogl-pipeline-state-private.h b/cogl/cogl-pipeline-state-private.h index dd00f005c..d93771bc9 100644 --- a/cogl/cogl-pipeline-state-private.h +++ b/cogl/cogl-pipeline-state-private.h @@ -35,14 +35,6 @@ void _cogl_pipeline_set_fog_state (CoglPipeline *pipeline, const CoglPipelineFogState *fog_state); -void -_cogl_pipeline_set_cull_face_state (CoglPipeline *pipeline, - const CoglPipelineCullFaceState * - cull_face_state); - -CoglPipelineCullFaceMode -_cogl_pipeline_get_cull_face_mode (CoglPipeline *pipeline); - gboolean _cogl_pipeline_color_equal (CoglPipeline *authority0, CoglPipeline *authority1); diff --git a/cogl/cogl-pipeline-state.c b/cogl/cogl-pipeline-state.c index 78102d866..db662f4fa 100644 --- a/cogl/cogl-pipeline-state.c +++ b/cogl/cogl-pipeline-state.c @@ -1177,22 +1177,20 @@ _cogl_pipeline_set_fog_state (CoglPipeline *pipeline, } void -_cogl_pipeline_set_cull_face_state (CoglPipeline *pipeline, - const CoglPipelineCullFaceState * - cull_face_state) +cogl_pipeline_set_cull_face_mode (CoglPipeline *pipeline, + CoglPipelineCullFaceMode cull_face_mode) { CoglPipelineState state = COGL_PIPELINE_STATE_CULL_FACE; CoglPipeline *authority; - CoglPipelineCullFaceState *current_cull_face_state; + CoglPipelineCullFaceState *cull_face_state; _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); authority = _cogl_pipeline_get_authority (pipeline, state); - current_cull_face_state = &authority->big_state->cull_face_state; + cull_face_state = &authority->big_state->cull_face_state; - if (current_cull_face_state->mode == cull_face_state->mode && - current_cull_face_state->front_winding == cull_face_state->front_winding) + if (cull_face_state->mode == cull_face_mode) return; /* - Flush journal primitives referencing the current state. @@ -1202,14 +1200,44 @@ _cogl_pipeline_set_cull_face_state (CoglPipeline *pipeline, */ _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); - pipeline->big_state->cull_face_state = *cull_face_state; + pipeline->big_state->cull_face_state.mode = cull_face_mode; + + _cogl_pipeline_update_authority (pipeline, authority, state, + _cogl_pipeline_cull_face_state_equal); +} + +void +cogl_pipeline_set_front_face_winding (CoglPipeline *pipeline, + CoglWinding front_winding) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_CULL_FACE; + CoglPipeline *authority; + CoglPipelineCullFaceState *cull_face_state; + + _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline)); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + cull_face_state = &authority->big_state->cull_face_state; + + if (cull_face_state->front_winding == front_winding) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the pipeline has no dependants so it may be modified. + * - If the pipeline isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE); + + pipeline->big_state->cull_face_state.front_winding = front_winding; _cogl_pipeline_update_authority (pipeline, authority, state, _cogl_pipeline_cull_face_state_equal); } CoglPipelineCullFaceMode -_cogl_pipeline_get_cull_face_mode (CoglPipeline *pipeline) +cogl_pipeline_get_cull_face_mode (CoglPipeline *pipeline) { CoglPipelineState state = COGL_PIPELINE_STATE_CULL_FACE; CoglPipeline *authority; @@ -1222,6 +1250,20 @@ _cogl_pipeline_get_cull_face_mode (CoglPipeline *pipeline) return authority->big_state->cull_face_state.mode; } +CoglWinding +cogl_pipeline_get_front_face_winding (CoglPipeline *pipeline) +{ + CoglPipelineState state = COGL_PIPELINE_STATE_CULL_FACE; + CoglPipeline *authority; + + _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), + COGL_PIPELINE_CULL_FACE_MODE_NONE); + + authority = _cogl_pipeline_get_authority (pipeline, state); + + return authority->big_state->cull_face_state.front_winding; +} + float cogl_pipeline_get_point_size (CoglPipeline *pipeline) { diff --git a/cogl/cogl-pipeline-state.h b/cogl/cogl-pipeline-state.h index 7015b00c0..5dfd21a1b 100644 --- a/cogl/cogl-pipeline-state.h +++ b/cogl/cogl-pipeline-state.h @@ -686,6 +686,97 @@ void cogl_pipeline_get_depth_state (CoglPipeline *pipeline, CoglDepthState *state_out); +/** + * CoglPipelineCullFaceMode: + * @COGL_PIPELINE_CULL_FACE_MODE_NONE: Neither face will be + * called. This is the default. + * @COGL_PIPELINE_CULL_FACE_MODE_FRONT: Front faces will be called. + * @COGL_PIPELINE_CULL_FACE_MODE_BACK: Back faces will be called. + * @COGL_PIPELINE_CULL_FACE_MODE_BOTH: All faces will be called. + * + * Specifies which faces should be called. This can be set on a + * pipeline using cogl_pipeline_set_cull_face_mode(). + */ +typedef enum +{ + COGL_PIPELINE_CULL_FACE_MODE_NONE, + COGL_PIPELINE_CULL_FACE_MODE_FRONT, + COGL_PIPELINE_CULL_FACE_MODE_BACK, + COGL_PIPELINE_CULL_FACE_MODE_BOTH +} CoglPipelineCullFaceMode; + +/** + * cogl_pipeline_set_cull_face_mode: + * @pipeline: A #CoglPipeline + * @cull_face_mode: The new mode to set + * + * Sets which faces will be culled when drawing. Face culling can be + * used to increase efficiency by avoiding drawing faces that would + * get overridden. For example, if a model has gaps so that it is + * impossible to see the inside then faces which are facing away from + * the screen will never be seen so there is no point in drawing + * them. This can be acheived by setting the cull face mode to + * %COGL_PIPELINE_CULL_FACE_MODE_BACK. + * + * Face culling relies on the primitives being drawn with a specific + * order to represent which faces are facing inside and outside the + * model. This order can be specified by calling + * cogl_pipeline_set_front_face_winding(). + * + * Status: Unstable + * Since: 2.0 + */ +void +cogl_pipeline_set_cull_face_mode (CoglPipeline *pipeline, + CoglPipelineCullFaceMode cull_face_mode); + +/** + * cogl_pipeline_get_cull_face_mode: + * + * Return value: the cull face mode that was previously set with + * cogl_pipeline_set_cull_face_mode(). + * + * Status: Unstable + * Since: 2.0 + */ +CoglPipelineCullFaceMode +cogl_pipeline_get_cull_face_mode (CoglPipeline *pipeline); + +/** + * cogl_pipeline_set_front_face_winding: + * + * The order of the vertices within a primitive specifies whether it + * is considered to be front or back facing. This function specifies + * which order is considered to be the front + * faces. %COGL_WINDING_COUNTER_CLOCKWISE sets the front faces to + * primitives with vertices in a counter-clockwise order and + * %COGL_WINDING_CLOCKWISE sets them to be clockwise. The default is + * %COGL_WINDING_COUNTER_CLOCKWISE. + * + * Status: Unstable + * Since: 2.0 + */ +void +cogl_pipeline_set_front_face_winding (CoglPipeline *pipeline, + CoglWinding front_winding); + +/** + * cogl_pipeline_set_front_face_winding: + * + * The order of the vertices within a primitive specifies whether it + * is considered to be front or back facing. This function specifies + * which order is considered to be the front + * faces. %COGL_WINDING_COUNTER_CLOCKWISE sets the front faces to + * primitives with vertices in a counter-clockwise order and + * %COGL_WINDING_CLOCKWISE sets them to be clockwise. The default is + * %COGL_WINDING_COUNTER_CLOCKWISE. + * + * Status: Unstable + * Since: 2.0 + */ +CoglWinding +cogl_pipeline_get_front_face_winding (CoglPipeline *pipeline); + #endif /* COGL_ENABLE_EXPERIMENTAL_API */ G_END_DECLS diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c index 60e96eb22..907f692c7 100644 --- a/cogl/cogl-pipeline.c +++ b/cogl/cogl-pipeline.c @@ -2460,12 +2460,8 @@ _cogl_pipeline_apply_legacy_state (CoglPipeline *pipeline) _cogl_pipeline_set_fog_state (pipeline, &ctx->legacy_fog_state); if (ctx->legacy_backface_culling_enabled) - { - CoglPipelineCullFaceState state; - state.mode = COGL_PIPELINE_CULL_FACE_MODE_BACK; - state.front_winding = COGL_WINDING_COUNTER_CLOCKWISE; - _cogl_pipeline_set_cull_face_state (pipeline, &state); - } + cogl_pipeline_set_cull_face_mode (pipeline, + COGL_PIPELINE_CULL_FACE_MODE_BACK); } void diff --git a/cogl/cogl-types.h b/cogl/cogl-types.h index c93bde842..b8edb695e 100644 --- a/cogl/cogl-types.h +++ b/cogl/cogl-types.h @@ -702,6 +702,21 @@ typedef enum COGL_COLOR_MASK_ALL = (COGL_COLOR_MASK_RED | COGL_COLOR_MASK_GREEN | COGL_COLOR_MASK_BLUE | COGL_COLOR_MASK_ALPHA) } CoglColorMask; +/** + * CoglWinding: + * @COGL_WINDING_CLOCKWISE: Vertices are in a clockwise order + * @COGL_WINDING_COUNTER_CLOCKWISE: Vertices are in a counter-clockwise order + * + * Enum used to represent the two directions of rotation. This can be + * used to set the front face for culling by calling + * cogl_pipeline_set_front_face_winding(). + */ +typedef enum +{ + COGL_WINDING_CLOCKWISE, + COGL_WINDING_COUNTER_CLOCKWISE +} CoglWinding; + G_END_DECLS #endif /* __COGL_TYPES_H__ */ diff --git a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt index f8a1185aa..0073408ef 100644 --- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt +++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt @@ -570,6 +570,11 @@ cogl_pipeline_get_point_size cogl_pipeline_get_color_mask cogl_pipeline_set_color_mask +CoglPipelineCullFaceMode +cogl_pipeline_set_cull_face_mode +CoglWinding +cogl_pipeline_set_front_face_winding + cogl_pipeline_set_layer_texture cogl_pipeline_get_layer_texture CoglMaterialFilter