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.
This commit is contained in:
Robert Bragg 2010-07-06 20:18:26 +01:00
parent a17dfcf1c2
commit 8098052d56
7 changed files with 143 additions and 49 deletions

View File

@ -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 ("");

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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 (&current_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

View File

@ -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