Use GL_ARB_sampler_objects

GL_ARB_sampler_objects provides a GL object which overrides the
sampler state part of a texture object with different values. The
sampler state that Cogl currently exposes is the wrap modes and
filters. Cogl exposes the state as part of the pipeline layer state
but without this extension GL only exposes it as part of the texture
object state. This means that it won't work to use a single texture
multiple times in one primitive with different sampler states. It also
makes switching between different sampler states with a single texture
not terribly efficient because it has to change the texture object
state every time.

This patch adds a cache for sampler states in a shared hash table
attached to the CoglContext. The entire set of parameters for the
sampler state is used as the key for the hash table. When a unique
state is encountered the sampler cache will create a new entry,
otherwise it will return a const pointer to an existing entry. That
means we can have a single pointer to represent any combination of
sampler state.

Pipeline layers now just store this single pointer rather than storing
all of the sampler state. The two separate state flags for wrap modes
and filters have now been combined into one. It should be faster to
compare the sampler state now because instead of comparing each value
it can just compare the pointers to the cached sampler entries. The
hash table of cached sampler states should only need to perform its
more expensive hash on the state when a property is changed on a
pipeline, not every time it is flushed.

When the sampler objects extension is available each cached sampler
state will also get a sampler object to represent it. The common code
to flush the GL state will now simply bind this object to a unit
instead of flushing the state though the CoglTexture when possible.

Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts
2012-04-04 22:20:04 +01:00
parent 4229d61d3b
commit c33ce5fc6b
15 changed files with 669 additions and 264 deletions

View File

@@ -844,6 +844,16 @@ flush_layers_common_gl_state_cb (CoglPipelineLayer *layer, void *user_data)
unit->texture_storage_changed = FALSE;
}
if ((layers_difference & COGL_PIPELINE_LAYER_STATE_SAMPLER) &&
(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS))
{
const CoglSamplerCacheEntry *sampler_state;
sampler_state = _cogl_pipeline_layer_get_sampler_state (layer);
GE( ctx, glBindSampler (unit_index, sampler_state->sampler_object) );
}
/* Under GLES2 the fragment shader will use gl_PointCoord instead of
replacing the texture coordinates */
#if defined (HAVE_COGL_GLES) || defined (HAVE_COGL_GL)
@@ -904,7 +914,7 @@ static void
_cogl_pipeline_layer_forward_wrap_modes (CoglPipelineLayer *layer,
CoglTexture *texture)
{
CoglPipelineWrapModeInternal wrap_mode_s, wrap_mode_t, wrap_mode_p;
CoglSamplerCacheWrapMode wrap_mode_s, wrap_mode_t, wrap_mode_p;
GLenum gl_wrap_mode_s, gl_wrap_mode_t, gl_wrap_mode_p;
if (texture == NULL)
@@ -926,17 +936,17 @@ _cogl_pipeline_layer_forward_wrap_modes (CoglPipelineLayer *layer,
will break if the application tries to use different modes in
different layers using the same texture. */
if (wrap_mode_s == COGL_PIPELINE_WRAP_MODE_INTERNAL_AUTOMATIC)
if (wrap_mode_s == COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC)
gl_wrap_mode_s = GL_CLAMP_TO_EDGE;
else
gl_wrap_mode_s = wrap_mode_s;
if (wrap_mode_t == COGL_PIPELINE_WRAP_MODE_INTERNAL_AUTOMATIC)
if (wrap_mode_t == COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC)
gl_wrap_mode_t = GL_CLAMP_TO_EDGE;
else
gl_wrap_mode_t = wrap_mode_t;
if (wrap_mode_p == COGL_PIPELINE_WRAP_MODE_INTERNAL_AUTOMATIC)
if (wrap_mode_p == COGL_SAMPLER_CACHE_WRAP_MODE_AUTOMATIC)
gl_wrap_mode_p = GL_CLAMP_TO_EDGE;
else
gl_wrap_mode_p = wrap_mode_p;
@@ -952,8 +962,10 @@ _cogl_pipeline_layer_forward_wrap_modes (CoglPipelineLayer *layer,
* the filter and repeat modes whenever we use a texture since it may
* be referenced by multiple pipelines with different modes.
*
* XXX: GL_ARB_sampler_objects fixes this in OpenGL so we should
* eventually look at using this extension when available.
* This function is bypassed in favour of sampler objects if
* GL_ARB_sampler_objects is advertised. This fallback won't work if
* the same texture is bound to multiple layers with different sampler
* state.
*/
static void
foreach_texture_unit_update_filter_and_wrap_modes (void)
@@ -1399,7 +1411,8 @@ done:
/* Handle the fact that OpenGL associates texture filter and wrap
* modes with the texture objects not the texture units... */
foreach_texture_unit_update_filter_and_wrap_modes ();
if (!(ctx->private_feature_flags & COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS))
foreach_texture_unit_update_filter_and_wrap_modes ();
/* If this pipeline has more than one layer then we always need
* to make sure we rebind the texture for unit 1.