[cogl-material] Some improvements for how we sync CoglMaterial state with OpenGL

This flattens the three functions: cogl_material_flush_gl_material_state,
.._flush_gl_alpha_func and .._flush_gl_blend_func into one:
cogl_flush_material_gl_state which doesn't takes a material handle. (the handle
is instead taken from the context.)

This has allows us to avoid re-submitting some state to OpenGL when the
material has not been replaced.

Note: Avoiding redundant state changes for material layers isn't dealt with
in this patch.
This commit is contained in:
Robert Bragg 2008-12-23 23:22:40 +00:00
parent ef992f55db
commit e4548bcdc5
5 changed files with 97 additions and 98 deletions

View File

@ -152,20 +152,6 @@ void cogl_material_set_shininess (CoglHandle material,
void cogl_material_set_emission (CoglHandle material, void cogl_material_set_emission (CoglHandle material,
const CoglColor *emission); const CoglColor *emission);
/**
* cogl_set_source:
* @material: A CoglMaterial object
*
* This function sets the source material that will be used to fill
* subsequent geometry emitted via the cogl API.
*
* XXX: This doesn't really belong to the cogl-material API, it should
* move to cogl.h
*
* Since 1.0
*/
void cogl_set_source (CoglHandle material);
/** /**
* CoglMaterialAlphaFunc: * CoglMaterialAlphaFunc:
* @COGL_MATERIAL_ALPHA_FUNC_NEVER: Never let the fragment through. * @COGL_MATERIAL_ALPHA_FUNC_NEVER: Never let the fragment through.
@ -586,34 +572,10 @@ void cogl_material_set_layer_matrix (CoglHandle material,
* Note: This API is hopfully just a stop-gap solution. Ideally * Note: This API is hopfully just a stop-gap solution. Ideally
* cogl_enable will be replaced. * cogl_enable will be replaced.
*/ */
/* TODO: find a nicer solution! */
gulong gulong
cogl_material_get_cogl_enable_flags (CoglHandle handle); cogl_material_get_cogl_enable_flags (CoglHandle handle);
/**
* cogl_material_flush_gl_material_state:
* @material: A CoglMaterial object
*
* This commits the glMaterial state to the OpenGL driver. Normally you
* shouldn't need to use this function directly, since Cogl will do this
* internally, but if you are developing custom primitives directly with
* OpenGL you may want to use this.
*/
void cogl_material_flush_gl_material_state (CoglHandle material_handle);
/**
* cogl_material_flush_gl_alpha_func:
* @material: A CoglMaterial object
*
*/
void cogl_material_flush_gl_alpha_func (CoglHandle material_handle);
/**
* cogl_material_flush_gl_blend_func:
* @material: A CoglMaterial object
*
*/
void cogl_material_flush_gl_blend_func (CoglHandle material_handle);
/** /**
* cogl_material_get_layers: * cogl_material_get_layers:
* @material: A CoglMaterial object * @material: A CoglMaterial object
@ -691,6 +653,38 @@ CoglHandle cogl_material_layer_get_texture (CoglHandle layer_handle);
*/ */
void cogl_material_layer_flush_gl_sampler_state (CoglHandle layer_handle); void cogl_material_layer_flush_gl_sampler_state (CoglHandle layer_handle);
/**
* cogl_set_source:
* @material: A CoglMaterial object
*
* This function sets the source material that will be used to fill
* subsequent geometry emitted via the cogl API.
*
* Note: in the future we may add the ability to set a front facing
* material, and a back facing material, in which case this function
* will set both to the same.
*
* Since 1.0
*/
/* XXX: This doesn't really belong to the cogl-material API, it should
* move to cogl.h */
void cogl_set_source (CoglHandle material);
/**
* cogl_flush_material_gl_state:
*
* This function commits all the state of the source CoglMaterial - not
* including the per-layer state - to the OpenGL[ES] driver.
*
* Normally you shouldn't need to use this function directly, but if you
* are developing a custom primitive using raw OpenGL that works with
* CoglMaterials, then you may want to use this function.
*
* Since 1.0
*/
/* XXX: This should be moved with cogl_set_source to cogl.h */
void cogl_flush_material_gl_state (void);
G_END_DECLS G_END_DECLS
#endif /* __COGL_MATERIAL_H__ */ #endif /* __COGL_MATERIAL_H__ */

View File

@ -79,7 +79,8 @@ cogl_material_set_ambient (CoglHandle handle,
ambient[1] = cogl_color_get_green_float (ambient_color); ambient[1] = cogl_color_get_green_float (ambient_color);
ambient[2] = cogl_color_get_blue_float (ambient_color); ambient[2] = cogl_color_get_blue_float (ambient_color);
ambient[3] = cogl_color_get_alpha_float (ambient_color); ambient[3] = cogl_color_get_alpha_float (ambient_color);
/* material->ambient = *ambient_color; */
material->flags |= COGL_MATERIAL_FLAG_DIRTY;
} }
void void
@ -98,7 +99,8 @@ cogl_material_set_diffuse (CoglHandle handle,
diffuse[1] = cogl_color_get_green_float (diffuse_color); diffuse[1] = cogl_color_get_green_float (diffuse_color);
diffuse[2] = cogl_color_get_blue_float (diffuse_color); diffuse[2] = cogl_color_get_blue_float (diffuse_color);
diffuse[3] = cogl_color_get_alpha_float (diffuse_color); diffuse[3] = cogl_color_get_alpha_float (diffuse_color);
/* material->diffuse = *diffuse_color; */
material->flags |= COGL_MATERIAL_FLAG_DIRTY;
} }
void void
@ -125,7 +127,8 @@ cogl_material_set_specular (CoglHandle handle,
specular[1] = cogl_color_get_green_float (specular_color); specular[1] = cogl_color_get_green_float (specular_color);
specular[2] = cogl_color_get_blue_float (specular_color); specular[2] = cogl_color_get_blue_float (specular_color);
specular[3] = cogl_color_get_alpha_float (specular_color); specular[3] = cogl_color_get_alpha_float (specular_color);
/* material->specular = *specular_color; */
material->flags |= COGL_MATERIAL_FLAG_DIRTY;
} }
void void
@ -143,6 +146,8 @@ cogl_material_set_shininess (CoglHandle handle,
material = _cogl_material_pointer_from_handle (handle); material = _cogl_material_pointer_from_handle (handle);
material->shininess = (GLfloat)shininess * 128.0; material->shininess = (GLfloat)shininess * 128.0;
material->flags |= COGL_MATERIAL_FLAG_DIRTY;
} }
void void
@ -161,22 +166,8 @@ cogl_material_set_emission (CoglHandle handle,
emission[1] = cogl_color_get_green_float (emission_color); emission[1] = cogl_color_get_green_float (emission_color);
emission[2] = cogl_color_get_blue_float (emission_color); emission[2] = cogl_color_get_blue_float (emission_color);
emission[3] = cogl_color_get_alpha_float (emission_color); emission[3] = cogl_color_get_alpha_float (emission_color);
/* material->emission = *emission_color; */
}
/* TODO: Should go in cogl.c */ material->flags |= COGL_MATERIAL_FLAG_DIRTY;
void
cogl_set_source (CoglHandle material_handle)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
g_return_if_fail (cogl_is_material (material_handle));
if (ctx->source_material)
cogl_material_unref (ctx->source_material);
cogl_material_ref (material_handle);
ctx->source_material = material_handle;
} }
void void
@ -191,6 +182,8 @@ cogl_material_set_alpha_test_function (CoglHandle handle,
material = _cogl_material_pointer_from_handle (handle); material = _cogl_material_pointer_from_handle (handle);
material->alpha_func = alpha_func; material->alpha_func = alpha_func;
material->alpha_func_reference = (GLfloat)alpha_reference; material->alpha_func_reference = (GLfloat)alpha_reference;
material->flags |= COGL_MATERIAL_FLAG_DIRTY;
} }
void void
@ -205,6 +198,8 @@ cogl_material_set_blend_factors (CoglHandle handle,
material = _cogl_material_pointer_from_handle (handle); material = _cogl_material_pointer_from_handle (handle);
material->blend_src_factor = src_factor; material->blend_src_factor = src_factor;
material->blend_dst_factor = dst_factor; material->blend_dst_factor = dst_factor;
material->flags |= COGL_MATERIAL_FLAG_DIRTY;
} }
/* Asserts that a layer corresponding to the given index exists. If no /* Asserts that a layer corresponding to the given index exists. If no
@ -492,44 +487,6 @@ cogl_material_get_cogl_enable_flags (CoglHandle material_handle)
return enable_flags; return enable_flags;
} }
void
cogl_material_flush_gl_material_state (CoglHandle material_handle)
{
CoglMaterial *material;
g_return_if_fail (cogl_is_material (material_handle));
material = _cogl_material_pointer_from_handle (material_handle);
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, material->ambient));
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, material->diffuse));
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, material->specular));
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, material->emission));
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &material->shininess));
}
void
cogl_material_flush_gl_alpha_func (CoglHandle material_handle)
{
CoglMaterial *material;
g_return_if_fail (cogl_is_material (material_handle));
material = _cogl_material_pointer_from_handle (material_handle);
/* NB: Currently the Cogl defines are compatible with the GL ones: */
GE (glAlphaFunc (material->alpha_func, material->alpha_func_reference));
}
void
cogl_material_flush_gl_blend_func (CoglHandle material_handle)
{
CoglMaterial *material;
g_return_if_fail (cogl_is_material (material_handle));
GE (glBlendFunc (material->blend_src_factor, material->blend_dst_factor));
}
/* It's a bit out of the ordinary to return a const GList *, but it's /* It's a bit out of the ordinary to return a const GList *, but it's
* probably sensible to try and avoid list manipulation for every * probably sensible to try and avoid list manipulation for every
* primitive emitted in a scene, every frame. * primitive emitted in a scene, every frame.
@ -678,3 +635,50 @@ cogl_material_layer_flush_gl_sampler_state (CoglHandle layer_handle)
} }
} }
/* TODO: Should go in cogl.c, but that implies duplication which is also
* not ideal. */
void
cogl_set_source (CoglHandle material_handle)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
g_return_if_fail (cogl_is_material (material_handle));
if (ctx->source_material == material_handle)
return;
if (ctx->source_material)
cogl_material_unref (ctx->source_material);
cogl_material_ref (material_handle);
ctx->source_material = material_handle;
}
/* TODO: add cogl_set_front_source (), and cogl_set_back_source () */
void
cogl_flush_material_gl_state (void)
{
CoglMaterial *material;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
material = _cogl_material_pointer_from_handle (ctx->source_material);
if (ctx->source_material == ctx->current_material
&& !(material->flags & COGL_MATERIAL_FLAG_DIRTY))
return;
/* FIXME - we only need to set these if lighting is enabled... */
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, material->ambient));
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, material->diffuse));
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, material->specular));
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, material->emission));
GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS, &material->shininess));
/* NB: Currently the Cogl defines are compatible with the GL ones: */
GE (glAlphaFunc (material->alpha_func, material->alpha_func_reference));
GE (glBlendFunc (material->blend_src_factor, material->blend_dst_factor));
ctx->current_material = ctx->source_material;
}

View File

@ -62,6 +62,7 @@ cogl_create_context ()
_context->material_handles = NULL; _context->material_handles = NULL;
_context->material_layer_handles = NULL; _context->material_layer_handles = NULL;
_context->source_material = NULL; _context->source_material = NULL;
_context->current_material = NULL;
_context->fbo_handles = NULL; _context->fbo_handles = NULL;
_context->draw_buffer = COGL_WINDOW_BUFFER; _context->draw_buffer = COGL_WINDOW_BUFFER;

View File

@ -70,6 +70,7 @@ typedef struct
GArray *material_handles; GArray *material_handles;
GArray *material_layer_handles; GArray *material_layer_handles;
CoglHandle source_material; CoglHandle source_material;
CoglHandle current_material;
/* Framebuffer objects */ /* Framebuffer objects */
GArray *fbo_handles; GArray *fbo_handles;

View File

@ -2531,9 +2531,8 @@ cogl_material_rectangle (CoglFixed x1,
GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords)); GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords));
/* Setup the remaining GL state according to this material... */ /* Setup the remaining GL state according to this material... */
cogl_material_flush_gl_material_state (material); cogl_flush_material_gl_state ();
cogl_material_flush_gl_alpha_func (material);
cogl_material_flush_gl_blend_func (material);
/* FIXME: This api is a bit yukky, ideally it will be removed if we /* FIXME: This api is a bit yukky, ideally it will be removed if we
* re-work the cogl_enable mechanism */ * re-work the cogl_enable mechanism */
enable_flags |= cogl_material_get_cogl_enable_flags (material); enable_flags |= cogl_material_get_cogl_enable_flags (material);