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 279e68d8d9
commit 9b9e764dc1
7 changed files with 143 additions and 49 deletions

View File

@ -84,7 +84,6 @@ cogl_create_context (void)
_cogl_material_init_default_layers (); _cogl_material_init_default_layers ();
_context->enable_flags = 0; _context->enable_flags = 0;
_context->fog_enabled = FALSE;
_context->enable_backface_culling = FALSE; _context->enable_backface_culling = FALSE;
_context->flushed_front_winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE; _context->flushed_front_winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE;
@ -105,6 +104,8 @@ cogl_create_context (void)
_context->active_texture_unit = 1; _context->active_texture_unit = 1;
GE (glActiveTexture (GL_TEXTURE1)); GE (glActiveTexture (GL_TEXTURE1));
_context->legacy_fog_state.enabled = FALSE;
_context->simple_material = cogl_material_new (); _context->simple_material = cogl_material_new ();
_context->source_material = NULL; _context->source_material = NULL;
_context->arbfp_source_buffer = g_string_new (""); _context->arbfp_source_buffer = g_string_new ("");

View File

@ -56,7 +56,6 @@ typedef struct
/* Enable cache */ /* Enable cache */
unsigned long enable_flags; unsigned long enable_flags;
gboolean fog_enabled;
gboolean enable_backface_culling; gboolean enable_backface_culling;
CoglFrontWinding flushed_front_winding; CoglFrontWinding flushed_front_winding;
@ -73,6 +72,8 @@ typedef struct
GArray *texture_units; GArray *texture_units;
int active_texture_unit; int active_texture_unit;
CoglMaterialFogState legacy_fog_state;
/* Materials */ /* Materials */
CoglMaterial *simple_material; CoglMaterial *simple_material;
CoglMaterial *source_material; CoglMaterial *source_material;

View File

@ -250,7 +250,7 @@ _cogl_material_backend_arbfp_start (CoglMaterial *material,
return FALSE; return FALSE;
/* TODO: support fog */ /* TODO: support fog */
if (ctx->fog_enabled) if (ctx->legacy_fog_state.enabled)
return FALSE; return FALSE;
/* Note: we allocate ARBfp private state for both the given material /* 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, _cogl_material_backend_fixed_end (CoglMaterial *material,
unsigned long materials_difference) 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; return TRUE;
} }

View File

@ -332,8 +332,9 @@ typedef enum _CoglMaterialState
COGL_MATERIAL_STATE_BLEND = 1L<<5, COGL_MATERIAL_STATE_BLEND = 1L<<5,
COGL_MATERIAL_STATE_USER_SHADER = 1L<<6, COGL_MATERIAL_STATE_USER_SHADER = 1L<<6,
COGL_MATERIAL_STATE_DEPTH = 1L<<7, 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_ALL_SPARSE =
COGL_MATERIAL_STATE_COLOR | COGL_MATERIAL_STATE_COLOR |
@ -343,7 +344,8 @@ typedef enum _CoglMaterialState
COGL_MATERIAL_STATE_ALPHA_FUNC | COGL_MATERIAL_STATE_ALPHA_FUNC |
COGL_MATERIAL_STATE_BLEND | COGL_MATERIAL_STATE_BLEND |
COGL_MATERIAL_STATE_USER_SHADER | 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_AFFECTS_BLENDING =
COGL_MATERIAL_STATE_COLOR | COGL_MATERIAL_STATE_COLOR |
@ -358,7 +360,8 @@ typedef enum _CoglMaterialState
COGL_MATERIAL_STATE_ALPHA_FUNC | COGL_MATERIAL_STATE_ALPHA_FUNC |
COGL_MATERIAL_STATE_BLEND | COGL_MATERIAL_STATE_BLEND |
COGL_MATERIAL_STATE_USER_SHADER | COGL_MATERIAL_STATE_USER_SHADER |
COGL_MATERIAL_STATE_DEPTH COGL_MATERIAL_STATE_DEPTH |
COGL_MATERIAL_STATE_FOG
} CoglMaterialState; } CoglMaterialState;
@ -420,6 +423,16 @@ typedef struct
float depth_range_far; float depth_range_far;
} CoglMaterialDepthState; } CoglMaterialDepthState;
typedef struct
{
gboolean enabled;
CoglColor color;
CoglFogMode mode;
float density;
float z_near;
float z_far;
} CoglMaterialFogState;
typedef struct typedef struct
{ {
CoglMaterialLightingState lighting_state; CoglMaterialLightingState lighting_state;
@ -427,6 +440,7 @@ typedef struct
CoglMaterialBlendState blend_state; CoglMaterialBlendState blend_state;
CoglHandle user_program; CoglHandle user_program;
CoglMaterialDepthState depth_state; CoglMaterialDepthState depth_state;
CoglMaterialFogState fog_state;
} CoglMaterialBigState; } CoglMaterialBigState;
typedef enum typedef enum

View File

@ -2934,6 +2934,24 @@ _cogl_material_depth_state_equal (CoglMaterial *authority0,
sizeof (CoglMaterialDepthState)) == 0; 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 static gboolean
_cogl_material_layers_equal (CoglMaterial *authority0, _cogl_material_layers_equal (CoglMaterial *authority0,
CoglMaterial *authority1) CoglMaterial *authority1)
@ -3151,6 +3169,12 @@ _cogl_material_equal (CoglMaterial *material0,
_cogl_material_depth_state_equal)) _cogl_material_depth_state_equal))
return FALSE; 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, if (!simple_property_equal (material0, material1,
materials_difference, materials_difference,
COGL_MATERIAL_STATE_LAYERS, 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; *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 unsigned long
_cogl_material_get_age (CoglMaterial *material) _cogl_material_get_age (CoglMaterial *material)
{ {
@ -5895,6 +5954,9 @@ _cogl_material_apply_legacy_state (CoglMaterial *material)
if (ctx->legacy_depth_test_enabled) if (ctx->legacy_depth_test_enabled)
cogl_material_set_depth_test_enabled (material, TRUE); 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 void

View File

@ -576,48 +576,17 @@ cogl_set_fog (const CoglColor *fog_color,
float z_near, float z_near,
float z_far) float z_far)
{ {
GLfloat fogColor[4];
GLenum gl_mode = GL_LINEAR;
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* The cogl journal doesn't currently track fog state changes */ if (ctx->legacy_fog_state.enabled == FALSE)
_cogl_journal_flush (); ctx->legacy_state_set++;
fogColor[0] = cogl_color_get_red_float (fog_color); ctx->legacy_fog_state.enabled = TRUE;
fogColor[1] = cogl_color_get_green_float (fog_color); ctx->legacy_fog_state.color = *fog_color;
fogColor[2] = cogl_color_get_blue_float (fog_color); ctx->legacy_fog_state.mode = mode;
fogColor[3] = cogl_color_get_alpha_float (fog_color); ctx->legacy_fog_state.density = density;
ctx->legacy_fog_state.z_near = z_near;
glEnable (GL_FOG); ctx->legacy_fog_state.z_far = z_far;
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;
} }
void void
@ -625,11 +594,10 @@ cogl_disable_fog (void)
{ {
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* Currently the journal can't track changes to fog state... */ if (ctx->legacy_fog_state.enabled == TRUE)
_cogl_journal_flush (); ctx->legacy_state_set--;
glDisable (GL_FOG); ctx->legacy_fog_state.enabled = FALSE;
ctx->fog_enabled = FALSE;
} }
void void