From 9b9e764dc1dcc2025e3cabb63ea118fa37ed373d Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 6 Jul 2010 20:18:26 +0100 Subject: [PATCH] material: route fogging state through CoglMaterial Previously cogl_set_fog would cause a flush of the Cogl journal and would directly bang the GL state machine to setup fogging. As part of the ongoing effort to track most state in CoglMaterial to support renderlists this now adds an indirection so that cogl_set_fog now just updates ctx->legacy_fog_state. The fogging state then gets enabled as a legacy override similar to how the old depth testing API is handled. --- clutter/cogl/cogl/cogl-context.c | 3 +- clutter/cogl/cogl/cogl-context.h | 3 +- clutter/cogl/cogl/cogl-material-arbfp.c | 2 +- clutter/cogl/cogl/cogl-material-fixed.c | 48 ++++++++++++++++++ clutter/cogl/cogl/cogl-material-private.h | 20 ++++++-- clutter/cogl/cogl/cogl-material.c | 62 +++++++++++++++++++++++ clutter/cogl/cogl/cogl.c | 54 ++++---------------- 7 files changed, 143 insertions(+), 49 deletions(-) diff --git a/clutter/cogl/cogl/cogl-context.c b/clutter/cogl/cogl/cogl-context.c index b9436f703..200627be3 100644 --- a/clutter/cogl/cogl/cogl-context.c +++ b/clutter/cogl/cogl/cogl-context.c @@ -84,7 +84,6 @@ cogl_create_context (void) _cogl_material_init_default_layers (); _context->enable_flags = 0; - _context->fog_enabled = FALSE; _context->enable_backface_culling = FALSE; _context->flushed_front_winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE; @@ -105,6 +104,8 @@ cogl_create_context (void) _context->active_texture_unit = 1; GE (glActiveTexture (GL_TEXTURE1)); + _context->legacy_fog_state.enabled = FALSE; + _context->simple_material = cogl_material_new (); _context->source_material = NULL; _context->arbfp_source_buffer = g_string_new (""); diff --git a/clutter/cogl/cogl/cogl-context.h b/clutter/cogl/cogl/cogl-context.h index 645bb4151..156a36155 100644 --- a/clutter/cogl/cogl/cogl-context.h +++ b/clutter/cogl/cogl/cogl-context.h @@ -56,7 +56,6 @@ typedef struct /* Enable cache */ unsigned long enable_flags; - gboolean fog_enabled; gboolean enable_backface_culling; CoglFrontWinding flushed_front_winding; @@ -73,6 +72,8 @@ typedef struct GArray *texture_units; int active_texture_unit; + CoglMaterialFogState legacy_fog_state; + /* Materials */ CoglMaterial *simple_material; CoglMaterial *source_material; diff --git a/clutter/cogl/cogl/cogl-material-arbfp.c b/clutter/cogl/cogl/cogl-material-arbfp.c index cdf54e199..dea77f973 100644 --- a/clutter/cogl/cogl/cogl-material-arbfp.c +++ b/clutter/cogl/cogl/cogl-material-arbfp.c @@ -250,7 +250,7 @@ _cogl_material_backend_arbfp_start (CoglMaterial *material, return FALSE; /* TODO: support fog */ - if (ctx->fog_enabled) + if (ctx->legacy_fog_state.enabled) return FALSE; /* Note: we allocate ARBfp private state for both the given material diff --git a/clutter/cogl/cogl/cogl-material-fixed.c b/clutter/cogl/cogl/cogl-material-fixed.c index d2348715e..d79a98d2f 100644 --- a/clutter/cogl/cogl/cogl-material-fixed.c +++ b/clutter/cogl/cogl/cogl-material-fixed.c @@ -186,6 +186,54 @@ static gboolean _cogl_material_backend_fixed_end (CoglMaterial *material, unsigned long materials_difference) { + if (materials_difference & COGL_MATERIAL_STATE_FOG) + { + CoglMaterial *authority = + _cogl_material_get_authority (material, COGL_MATERIAL_STATE_FOG); + CoglMaterialFogState *fog_state = &authority->big_state->fog_state; + + if (fog_state->enabled) + { + GLfloat fogColor[4]; + GLenum gl_mode = GL_LINEAR; + + fogColor[0] = cogl_color_get_red_float (&fog_state->color); + fogColor[1] = cogl_color_get_green_float (&fog_state->color); + fogColor[2] = cogl_color_get_blue_float (&fog_state->color); + fogColor[3] = cogl_color_get_alpha_float (&fog_state->color); + + GE (glEnable (GL_FOG)); + + GE (glFogfv (GL_FOG_COLOR, fogColor)); + +#if HAVE_COGL_GLES + switch (fog_state->mode) + { + case COGL_FOG_MODE_LINEAR: + gl_mode = GL_LINEAR; + break; + case COGL_FOG_MODE_EXPONENTIAL: + gl_mode = GL_EXP; + break; + case COGL_FOG_MODE_EXPONENTIAL_SQUARED: + gl_mode = GL_EXP2; + break; + } +#endif + /* TODO: support other modes for GLES2 */ + + /* NB: GLES doesn't have glFogi */ + GE (glFogf (GL_FOG_MODE, gl_mode)); + GE (glHint (GL_FOG_HINT, GL_NICEST)); + + GE (glFogf (GL_FOG_DENSITY, fog_state->density)); + GE (glFogf (GL_FOG_START, fog_state->z_near)); + GE (glFogf (GL_FOG_END, fog_state->z_far)); + } + else + GE (glDisable (GL_FOG)); + } + return TRUE; } diff --git a/clutter/cogl/cogl/cogl-material-private.h b/clutter/cogl/cogl/cogl-material-private.h index b6a3524b3..28f1fe9e0 100644 --- a/clutter/cogl/cogl/cogl-material-private.h +++ b/clutter/cogl/cogl/cogl-material-private.h @@ -332,8 +332,9 @@ typedef enum _CoglMaterialState COGL_MATERIAL_STATE_BLEND = 1L<<5, COGL_MATERIAL_STATE_USER_SHADER = 1L<<6, COGL_MATERIAL_STATE_DEPTH = 1L<<7, + COGL_MATERIAL_STATE_FOG = 1L<<8, - COGL_MATERIAL_STATE_REAL_BLEND_ENABLE = 1L<<8, + COGL_MATERIAL_STATE_REAL_BLEND_ENABLE = 1L<<9, COGL_MATERIAL_STATE_ALL_SPARSE = COGL_MATERIAL_STATE_COLOR | @@ -343,7 +344,8 @@ typedef enum _CoglMaterialState COGL_MATERIAL_STATE_ALPHA_FUNC | COGL_MATERIAL_STATE_BLEND | COGL_MATERIAL_STATE_USER_SHADER | - COGL_MATERIAL_STATE_DEPTH, + COGL_MATERIAL_STATE_DEPTH | + COGL_MATERIAL_STATE_FOG, COGL_MATERIAL_STATE_AFFECTS_BLENDING = COGL_MATERIAL_STATE_COLOR | @@ -358,7 +360,8 @@ typedef enum _CoglMaterialState COGL_MATERIAL_STATE_ALPHA_FUNC | COGL_MATERIAL_STATE_BLEND | COGL_MATERIAL_STATE_USER_SHADER | - COGL_MATERIAL_STATE_DEPTH + COGL_MATERIAL_STATE_DEPTH | + COGL_MATERIAL_STATE_FOG } CoglMaterialState; @@ -420,6 +423,16 @@ typedef struct float depth_range_far; } CoglMaterialDepthState; +typedef struct +{ + gboolean enabled; + CoglColor color; + CoglFogMode mode; + float density; + float z_near; + float z_far; +} CoglMaterialFogState; + typedef struct { CoglMaterialLightingState lighting_state; @@ -427,6 +440,7 @@ typedef struct CoglMaterialBlendState blend_state; CoglHandle user_program; CoglMaterialDepthState depth_state; + CoglMaterialFogState fog_state; } CoglMaterialBigState; typedef enum diff --git a/clutter/cogl/cogl/cogl-material.c b/clutter/cogl/cogl/cogl-material.c index 683dc1698..6a0bda21b 100644 --- a/clutter/cogl/cogl/cogl-material.c +++ b/clutter/cogl/cogl/cogl-material.c @@ -2934,6 +2934,24 @@ _cogl_material_depth_state_equal (CoglMaterial *authority0, sizeof (CoglMaterialDepthState)) == 0; } +static gboolean +_cogl_material_fog_state_equal (CoglMaterial *authority0, + CoglMaterial *authority1) +{ + CoglMaterialFogState *fog_state0 = &authority0->big_state->fog_state; + CoglMaterialFogState *fog_state1 = &authority1->big_state->fog_state; + + if (fog_state0->enabled == fog_state1->enabled && + cogl_color_equal (&fog_state0->color, &fog_state1->color) && + fog_state0->mode == fog_state1->mode && + fog_state0->density == fog_state1->density && + fog_state0->z_near == fog_state1->z_near && + fog_state0->z_far == fog_state1->z_far) + return TRUE; + else + return FALSE; +} + static gboolean _cogl_material_layers_equal (CoglMaterial *authority0, CoglMaterial *authority1) @@ -3151,6 +3169,12 @@ _cogl_material_equal (CoglMaterial *material0, _cogl_material_depth_state_equal)) return FALSE; + if (!simple_property_equal (material0, material1, + materials_difference, + COGL_MATERIAL_STATE_FOG, + _cogl_material_fog_state_equal)) + return FALSE; + if (!simple_property_equal (material0, material1, materials_difference, COGL_MATERIAL_STATE_LAYERS, @@ -4097,6 +4121,41 @@ cogl_material_get_depth_range (CoglMaterial *material, *far_val = authority->big_state->depth_state.depth_range_far; } +static void +_cogl_material_set_fog_state (CoglMaterial *material, + const CoglMaterialFogState *fog_state) +{ + CoglMaterialState state = COGL_MATERIAL_STATE_FOG; + CoglMaterial *authority; + CoglMaterialFogState *current_fog_state; + + g_return_if_fail (cogl_is_material (material)); + + authority = _cogl_material_get_authority (material, state); + + current_fog_state = &authority->big_state->fog_state; + + if (current_fog_state->enabled == fog_state->enabled && + cogl_color_equal (¤t_fog_state->color, &fog_state->color) && + current_fog_state->mode == fog_state->mode && + current_fog_state->density == fog_state->density && + current_fog_state->z_near == fog_state->z_near && + current_fog_state->z_far == fog_state->z_far) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the material has no dependants so it may be modified. + * - If the material isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_material_pre_change_notify (material, state, NULL); + + material->big_state->fog_state = *fog_state; + + _cogl_material_update_authority (material, authority, state, + _cogl_material_fog_state_equal); +} + unsigned long _cogl_material_get_age (CoglMaterial *material) { @@ -5895,6 +5954,9 @@ _cogl_material_apply_legacy_state (CoglMaterial *material) if (ctx->legacy_depth_test_enabled) cogl_material_set_depth_test_enabled (material, TRUE); + + if (ctx->legacy_fog_state.enabled) + _cogl_material_set_fog_state (material, &ctx->legacy_fog_state); } void diff --git a/clutter/cogl/cogl/cogl.c b/clutter/cogl/cogl/cogl.c index 73f1c403a..bcec7f0c2 100644 --- a/clutter/cogl/cogl/cogl.c +++ b/clutter/cogl/cogl/cogl.c @@ -576,48 +576,17 @@ cogl_set_fog (const CoglColor *fog_color, float z_near, float z_far) { - GLfloat fogColor[4]; - GLenum gl_mode = GL_LINEAR; - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - /* The cogl journal doesn't currently track fog state changes */ - _cogl_journal_flush (); + if (ctx->legacy_fog_state.enabled == FALSE) + ctx->legacy_state_set++; - fogColor[0] = cogl_color_get_red_float (fog_color); - fogColor[1] = cogl_color_get_green_float (fog_color); - fogColor[2] = cogl_color_get_blue_float (fog_color); - fogColor[3] = cogl_color_get_alpha_float (fog_color); - - glEnable (GL_FOG); - - glFogfv (GL_FOG_COLOR, fogColor); - -#if HAVE_COGL_GLES - switch (mode) - { - case COGL_FOG_MODE_LINEAR: - gl_mode = GL_LINEAR; - break; - case COGL_FOG_MODE_EXPONENTIAL: - gl_mode = GL_EXP; - break; - case COGL_FOG_MODE_EXPONENTIAL_SQUARED: - gl_mode = GL_EXP2; - break; - } -#endif - /* TODO: support other modes for GLES2 */ - - /* NB: GLES doesn't have glFogi */ - glFogf (GL_FOG_MODE, gl_mode); - glHint (GL_FOG_HINT, GL_NICEST); - - glFogf (GL_FOG_DENSITY, (GLfloat) density); - glFogf (GL_FOG_START, (GLfloat) z_near); - glFogf (GL_FOG_END, (GLfloat) z_far); - - ctx->fog_enabled = TRUE; + ctx->legacy_fog_state.enabled = TRUE; + ctx->legacy_fog_state.color = *fog_color; + ctx->legacy_fog_state.mode = mode; + ctx->legacy_fog_state.density = density; + ctx->legacy_fog_state.z_near = z_near; + ctx->legacy_fog_state.z_far = z_far; } void @@ -625,11 +594,10 @@ cogl_disable_fog (void) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); - /* Currently the journal can't track changes to fog state... */ - _cogl_journal_flush (); + if (ctx->legacy_fog_state.enabled == TRUE) + ctx->legacy_state_set--; - glDisable (GL_FOG); - ctx->fog_enabled = FALSE; + ctx->legacy_fog_state.enabled = FALSE; } void