diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c index b9436f703..200627be3 100644 --- a/cogl/cogl-context.c +++ b/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/cogl/cogl-context.h b/cogl/cogl-context.h index 645bb4151..156a36155 100644 --- a/cogl/cogl-context.h +++ b/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/cogl/cogl-material-arbfp.c b/cogl/cogl-material-arbfp.c index cdf54e199..dea77f973 100644 --- a/cogl/cogl-material-arbfp.c +++ b/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/cogl/cogl-material-fixed.c b/cogl/cogl-material-fixed.c index d2348715e..d79a98d2f 100644 --- a/cogl/cogl-material-fixed.c +++ b/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/cogl/cogl-material-private.h b/cogl/cogl-material-private.h index b6a3524b3..28f1fe9e0 100644 --- a/cogl/cogl-material-private.h +++ b/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/cogl/cogl-material.c b/cogl/cogl-material.c index 683dc1698..6a0bda21b 100644 --- a/cogl/cogl-material.c +++ b/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/cogl/cogl.c b/cogl/cogl.c index 73f1c403a..bcec7f0c2 100644 --- a/cogl/cogl.c +++ b/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