[Cogl] [PATCH] Add support for per-vertex point sizes

Robert Bragg robert at sixbynine.org
Fri Jun 7 08:17:51 PDT 2013


Yeah, I think we (or I) have deliberated over this one a lot, I think
for some relatively petty issues like:

- The _set_per_vertex_point_size() api name is a bit odd since it
reads as if you're going to pass that a value. Normally we'd follow a
_set_blah_enabled() naming pattern, but in this case the symbol would
be ridiculously long.
- It seems a bit of a shame to have to explicitly enable instead of
having it 'just work' when you draw points with a point-size
attribute, but I can see how come that's awkward to do.

I think at this point it's better to have the feature, with a maybe
in-perfect interface, than not at all.

Related to this, one thing that comes up each time we talk about
point-size handling in Cogl that seems worth noting is that we should
look at making the point-size undefined in the case where neither this
api or _set_point_size() have been used. It doesn't seem ideal that
currently all gles2 shaders have to explicitly output a point-size
even when points aren't being drawn.

I think this patch looks good to land to me:

Reviewed-by: Robert Bragg <robert at linux.intel.com>

thanks,
- Robert



On Thu, Jun 6, 2013 at 3:11 PM, Neil Roberts <neil at linux.intel.com> wrote:
> Here's a second rebase of the patch to help Chris Cummins who was
> hoping to experiment with it.
>
> -- >8 --
>
> This adds a new function to enable per-vertex point size on a
> pipeline. This can be set with
> cogl_pipeline_set_per_vertex_point_size(). Once enabled the point size
> can be set either by drawing with an attribute named
> 'cogl_point_size_in' or by writing to the 'cogl_point_size_out'
> builtin from a snippet.
>
> There is a feature flag which must be checked for before using
> per-vertex point sizes. This will only be set on GL >= 2.0 or on GLES
> 2.0. GL will only let you set a per-vertex point size from GLSL by
> writing to gl_PointSize. This is only available in GL2 and not in the
> older GLSL extensions.
>
> The per-vertex point size has its own pipeline state flag so that it
> can be part of the state that affects vertex shader generation.
>
> Having to enable the per vertex point size with a separate function is
> a bit awkward. Ideally it would work like the color attribute where
> you can just set it for every vertex in your primitive with
> cogl_pipeline_set_color or set it per-vertex by just using the
> attribute. This is harder to get working with the point size because
> we need to generate a different vertex shader depending on what
> attributes are bound. I think if we wanted to make this work
> transparently we would still want to internally have a pipeline
> property describing whether the shader was generated with per-vertex
> support so that it would work with the shader cache correctly.
> Potentially we could make the per-vertex property internal and
> automatically make a weak pipeline whenever the attribute is bound.
> However we would then also need to automatically detect when an
> application is writing to cogl_point_size_out from a snippet.
> ---
>  cogl/cogl-attribute-private.h                      |   1 +
>  cogl/cogl-attribute.c                              |  10 ++
>  cogl/cogl-attribute.h                              |   5 +
>  cogl/cogl-context.c                                |   7 +-
>  cogl/cogl-context.h                                |   3 +
>  cogl/cogl-glsl-shader-boilerplate.h                |   3 +-
>  cogl/cogl-pipeline-private.h                       |   6 +
>  cogl/cogl-pipeline-state-private.h                 |   7 +
>  cogl/cogl-pipeline-state.c                         |  75 ++++++++++
>  cogl/cogl-pipeline-state.h                         |  44 ++++++
>  cogl/cogl-pipeline.c                               |  13 +-
>  cogl/cogl-private.h                                |   3 +-
>  cogl/cogl-snippet.h                                |  48 ++++++
>  cogl/driver/gl/cogl-pipeline-opengl-private.h      |   2 +-
>  cogl/driver/gl/cogl-pipeline-opengl.c              |  19 ++-
>  cogl/driver/gl/cogl-pipeline-progend-fixed.c       |   5 +
>  cogl/driver/gl/cogl-pipeline-vertend-glsl.c        |  53 ++++++-
>  cogl/driver/gl/gl/cogl-driver-gl.c                 |  12 ++
>  .../gl/gl/cogl-pipeline-progend-fixed-arbfp.c      |   5 +
>  cogl/driver/gl/gles/cogl-driver-gles.c             |   2 +
>  doc/reference/cogl2/cogl2-sections.txt             |   2 +
>  examples/cogl-info.c                               |   6 +
>  tests/conform/Makefile.am                          |   1 +
>  tests/conform/test-conform-main.c                  |   5 +
>  tests/conform/test-point-size-attribute.c          | 166 +++++++++++++++++++++
>  tests/conform/test-utils.c                         |   6 +
>  tests/conform/test-utils.h                         |   3 +-
>  27 files changed, 497 insertions(+), 15 deletions(-)
>  create mode 100644 tests/conform/test-point-size-attribute.c
>
> diff --git a/cogl/cogl-attribute-private.h b/cogl/cogl-attribute-private.h
> index 943934f..c201067 100644
> --- a/cogl/cogl-attribute-private.h
> +++ b/cogl/cogl-attribute-private.h
> @@ -40,6 +40,7 @@ typedef enum
>    COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY,
>    COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY,
>    COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY,
> +  COGL_ATTRIBUTE_NAME_ID_POINT_SIZE_ARRAY,
>    COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY
>  } CoglAttributeNameID;
>
> diff --git a/cogl/cogl-attribute.c b/cogl/cogl-attribute.c
> index 60ce52c..963bfd2 100644
> --- a/cogl/cogl-attribute.c
> +++ b/cogl/cogl-attribute.c
> @@ -101,6 +101,8 @@ validate_cogl_attribute_name (const char *name,
>        *name_id = COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY;
>        *normalized = TRUE;
>      }
> +  else if (strcmp (name, "point_size_in") == 0)
> +    *name_id = COGL_ATTRIBUTE_NAME_ID_POINT_SIZE_ARRAY;
>    else
>      {
>        g_warning ("Unknown cogl_* attribute name cogl_%s\n", name);
> @@ -193,6 +195,14 @@ validate_n_components (const CoglAttributeNameState *name_state,
>            return FALSE;
>          }
>        break;
> +    case COGL_ATTRIBUTE_NAME_ID_POINT_SIZE_ARRAY:
> +      if (G_UNLIKELY (n_components != 1))
> +        {
> +          g_critical ("The point size attribute can only have one "
> +                      "component");
> +          return FALSE;
> +        }
> +      break;
>      case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
>        return TRUE;
>      }
> diff --git a/cogl/cogl-attribute.h b/cogl/cogl-attribute.h
> index 580446e..d350833 100644
> --- a/cogl/cogl-attribute.h
> +++ b/cogl/cogl-attribute.h
> @@ -76,6 +76,11 @@ COGL_BEGIN_DECLS
>   *    <listitem>"cogl_tex_coord0_in", "cogl_tex_coord1", ...
>   * (used for vertex texture coordinates)</listitem>
>   *    <listitem>"cogl_normal_in" (used for vertex normals)</listitem>
> + *    <listitem>"cogl_point_size_in" (used to set the size of points
> + *    per-vertex. Note this can only be used if
> + *    %COGL_FEATURE_ID_POINT_SIZE_ATTRIBUTE is advertised and
> + *    cogl_pipeline_set_per_vertex_point_size() is called on the pipeline.
> + *    </listitem>
>   *  </itemizedlist>
>   *
>   * The attribute values corresponding to different vertices can either
> diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
> index e3fae59..5ec88ba 100644
> --- a/cogl/cogl-context.c
> +++ b/cogl/cogl-context.c
> @@ -88,7 +88,12 @@ _cogl_init_feature_overrides (CoglContext *ctx)
>      ctx->private_feature_flags &= ~COGL_PRIVATE_FEATURE_ARBFP;
>
>    if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_GLSL)))
> -    COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_GLSL, FALSE);
> +    {
> +      COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_GLSL, FALSE);
> +      COGL_FLAGS_SET (ctx->features,
> +                      COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE,
> +                      FALSE);
> +    }
>
>    if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_NPOT_TEXTURES)))
>      {
> diff --git a/cogl/cogl-context.h b/cogl/cogl-context.h
> index 14f9f30..d50ce32 100644
> --- a/cogl/cogl-context.h
> +++ b/cogl/cogl-context.h
> @@ -209,6 +209,8 @@ cogl_is_context (void *object);
>   * @COGL_FEATURE_ID_DEPTH_RANGE: cogl_pipeline_set_depth_range() support
>   * @COGL_FEATURE_ID_POINT_SPRITE: Whether
>   *     cogl_pipeline_set_layer_point_sprite_coords_enabled() is supported.
> + * @COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE: Whether cogl_point_size_in
> + *     can be used as an attribute to set a per-vertex point size.
>   * @COGL_FEATURE_ID_MAP_BUFFER_FOR_READ: Whether cogl_buffer_map() is
>   *     supported with CoglBufferAccess including read support.
>   * @COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE: Whether cogl_buffer_map() is
> @@ -250,6 +252,7 @@ typedef enum _CoglFeatureID
>    COGL_FEATURE_ID_DEPTH_TEXTURE,
>    COGL_FEATURE_ID_PRESENTATION_TIME,
>    COGL_FEATURE_ID_FENCE,
> +  COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE,
>
>    /*< private >*/
>    _COGL_N_FEATURE_IDS   /*< skip >*/
> diff --git a/cogl/cogl-glsl-shader-boilerplate.h b/cogl/cogl-glsl-shader-boilerplate.h
> index 89b2c74..860854b 100644
> --- a/cogl/cogl-glsl-shader-boilerplate.h
> +++ b/cogl/cogl-glsl-shader-boilerplate.h
> @@ -32,8 +32,7 @@
>    "\n" \
>    "uniform mat4 cogl_modelview_matrix;\n" \
>    "uniform mat4 cogl_modelview_projection_matrix;\n"  \
> -  "uniform mat4 cogl_projection_matrix;\n" \
> -  "uniform float cogl_point_size_in;\n"
> +  "uniform mat4 cogl_projection_matrix;\n"
>
>  /* This declares all of the variables that we might need. This is
>   * working on the assumption that the compiler will optimise them out
> diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
> index 67fe5e4..3b97028 100644
> --- a/cogl/cogl-pipeline-private.h
> +++ b/cogl/cogl-pipeline-private.h
> @@ -115,6 +115,7 @@ typedef enum
>    COGL_PIPELINE_STATE_BLEND_INDEX,
>    COGL_PIPELINE_STATE_DEPTH_INDEX,
>    COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
> +  COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE_INDEX,
>    COGL_PIPELINE_STATE_LOGIC_OPS_INDEX,
>    COGL_PIPELINE_STATE_CULL_FACE_INDEX,
>    COGL_PIPELINE_STATE_UNIFORMS_INDEX,
> @@ -158,6 +159,8 @@ typedef enum _CoglPipelineState
>      1L<<COGL_PIPELINE_STATE_DEPTH_INDEX,
>    COGL_PIPELINE_STATE_POINT_SIZE =
>      1L<<COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
> +  COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE =
> +    1L<<COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE_INDEX,
>    COGL_PIPELINE_STATE_LOGIC_OPS =
>      1L<<COGL_PIPELINE_STATE_LOGIC_OPS_INDEX,
>    COGL_PIPELINE_STATE_CULL_FACE =
> @@ -199,6 +202,7 @@ typedef enum _CoglPipelineState
>     COGL_PIPELINE_STATE_BLEND | \
>     COGL_PIPELINE_STATE_DEPTH | \
>     COGL_PIPELINE_STATE_POINT_SIZE | \
> +   COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE | \
>     COGL_PIPELINE_STATE_LOGIC_OPS | \
>     COGL_PIPELINE_STATE_CULL_FACE | \
>     COGL_PIPELINE_STATE_UNIFORMS | \
> @@ -217,6 +221,7 @@ typedef enum _CoglPipelineState
>
>  #define COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN \
>    (COGL_PIPELINE_STATE_LAYERS | \
> +   COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE |  \
>     COGL_PIPELINE_STATE_VERTEX_SNIPPETS)
>
>  typedef struct
> @@ -280,6 +285,7 @@ typedef struct
>    CoglPipelineBlendState blend_state;
>    CoglDepthState depth_state;
>    float point_size;
> +  CoglBool per_vertex_point_size;
>    CoglPipelineLogicOpsState logic_ops_state;
>    CoglPipelineCullFaceState cull_face_state;
>    CoglPipelineUniformsState uniforms_state;
> diff --git a/cogl/cogl-pipeline-state-private.h b/cogl/cogl-pipeline-state-private.h
> index a4079a9..b22223d 100644
> --- a/cogl/cogl-pipeline-state-private.h
> +++ b/cogl/cogl-pipeline-state-private.h
> @@ -80,6 +80,9 @@ _cogl_pipeline_depth_state_equal (CoglPipeline *authority0,
>  CoglBool
>  _cogl_pipeline_point_size_equal (CoglPipeline *authority0,
>                                   CoglPipeline *authority1);
> +CoglBool
> +_cogl_pipeline_per_vertex_point_size_equal (CoglPipeline *authority0,
> +                                            CoglPipeline *authority1);
>
>  CoglBool
>  _cogl_pipeline_logic_ops_state_equal (CoglPipeline *authority0,
> @@ -142,6 +145,10 @@ _cogl_pipeline_hash_point_size_state (CoglPipeline *authority,
>                                        CoglPipelineHashState *state);
>
>  void
> +_cogl_pipeline_hash_per_vertex_point_size_state (CoglPipeline *authority,
> +                                                 CoglPipelineHashState *state);
> +
> +void
>  _cogl_pipeline_hash_logic_ops_state (CoglPipeline *authority,
>                                       CoglPipelineHashState *state);
>
> diff --git a/cogl/cogl-pipeline-state.c b/cogl/cogl-pipeline-state.c
> index 8a652e0..066f2b9 100644
> --- a/cogl/cogl-pipeline-state.c
> +++ b/cogl/cogl-pipeline-state.c
> @@ -145,6 +145,14 @@ _cogl_pipeline_point_size_equal (CoglPipeline *authority0,
>  }
>
>  CoglBool
> +_cogl_pipeline_per_vertex_point_size_equal (CoglPipeline *authority0,
> +                                            CoglPipeline *authority1)
> +{
> +  return (authority0->big_state->per_vertex_point_size ==
> +          authority1->big_state->per_vertex_point_size);
> +}
> +
> +CoglBool
>  _cogl_pipeline_logic_ops_state_equal (CoglPipeline *authority0,
>                                        CoglPipeline *authority1)
>  {
> @@ -959,6 +967,63 @@ cogl_pipeline_set_point_size (CoglPipeline *pipeline,
>                                     _cogl_pipeline_point_size_equal);
>  }
>
> +CoglBool
> +cogl_pipeline_set_per_vertex_point_size (CoglPipeline *pipeline,
> +                                         CoglBool enable,
> +                                         CoglError **error)
> +{
> +  CoglPipelineState state = COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE;
> +  CoglPipeline *authority;
> +
> +  _COGL_GET_CONTEXT (ctx, FALSE);
> +  _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE);
> +
> +  authority = _cogl_pipeline_get_authority (pipeline, state);
> +
> +  enable = !!enable;
> +
> +  if (authority->big_state->per_vertex_point_size == enable)
> +    return TRUE;
> +
> +  if (enable && !cogl_has_feature (ctx, COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE))
> +    {
> +      _cogl_set_error (error,
> +                       COGL_SYSTEM_ERROR,
> +                       COGL_SYSTEM_ERROR_UNSUPPORTED,
> +                       "Per-vertex point size is not supported");
> +
> +      return FALSE;
> +    }
> +
> +  /* - Flush journal primitives referencing the current state.
> +   * - Make sure the pipeline has no dependants so it may be modified.
> +   * - If the pipeline isn't currently an authority for the state being
> +   *   changed, then initialize that state from the current authority.
> +   */
> +  _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
> +
> +  pipeline->big_state->per_vertex_point_size = enable;
> +
> +  _cogl_pipeline_update_authority (pipeline, authority, state,
> +                                   _cogl_pipeline_point_size_equal);
> +
> +  return TRUE;
> +}
> +
> +CoglBool
> +cogl_pipeline_get_per_vertex_point_size (CoglPipeline *pipeline)
> +{
> +  CoglPipeline *authority;
> +
> +  _COGL_RETURN_VAL_IF_FAIL (cogl_is_pipeline (pipeline), FALSE);
> +
> +  authority =
> +    _cogl_pipeline_get_authority (pipeline,
> +                                  COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE);
> +
> +  return authority->big_state->per_vertex_point_size;
> +}
> +
>  static CoglBoxedValue *
>  _cogl_pipeline_override_uniform (CoglPipeline *pipeline,
>                                   int location)
> @@ -1357,6 +1422,16 @@ _cogl_pipeline_hash_point_size_state (CoglPipeline *authority,
>  }
>
>  void
> +_cogl_pipeline_hash_per_vertex_point_size_state (CoglPipeline *authority,
> +                                                 CoglPipelineHashState *state)
> +{
> +  CoglBool per_vertex_point_size = authority->big_state->per_vertex_point_size;
> +  state->hash = _cogl_util_one_at_a_time_hash (state->hash,
> +                                               &per_vertex_point_size,
> +                                               sizeof (per_vertex_point_size));
> +}
> +
> +void
>  _cogl_pipeline_hash_logic_ops_state (CoglPipeline *authority,
>                                       CoglPipelineHashState *state)
>  {
> diff --git a/cogl/cogl-pipeline-state.h b/cogl/cogl-pipeline-state.h
> index 3e1c187..ab5d8da 100644
> --- a/cogl/cogl-pipeline-state.h
> +++ b/cogl/cogl-pipeline-state.h
> @@ -332,6 +332,50 @@ float
>  cogl_pipeline_get_point_size (CoglPipeline *pipeline);
>
>  /**
> + * cogl_pipeline_set_per_vertex_point_size:
> + * @pipeline: a #CoglPipeline pointer
> + * @enable: whether to enable per-vertex point size
> + * @error: a location to store a #CoglError if the change failed
> + *
> + * Sets whether to use a per-vertex point size or to use the value set
> + * by cogl_pipeline_set_point_size(). If per-vertex point size is
> + * enabled then the point size can be set for an individual point
> + * either by drawing with a #CoglAttribute with the name
> + * ‘cogl_point_size_in’ or by writing to the GLSL builtin
> + * ‘cogl_point_size_out’ from a vertex shader snippet.
> + *
> + * If per-vertex point size is enabled and this attribute is not used
> + * and cogl_point_size_out is not written to then the results are
> + * undefined.
> + *
> + * Note that enabling this will only work if the
> + * %COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE feature is available. If
> + * this is not available then the function will return %FALSE and set
> + * a #CoglError.
> + *
> + * Since: 2.0
> + * Stability: Unstable
> + * Return value: %TRUE if the change suceeded or %FALSE otherwise
> + */
> +CoglBool
> +cogl_pipeline_set_per_vertex_point_size (CoglPipeline *pipeline,
> +                                         CoglBool enable,
> +                                         CoglError **error);
> +
> +/**
> + * cogl_pipeline_get_per_vertex_point_size:
> + * @pipeline: a #CoglPipeline pointer
> + *
> + * Since: 2.0
> + * Stability: Unstable
> + * Return value: %TRUE if the pipeline has per-vertex point size
> + *   enabled or %FALSE otherwise. The per-vertex point size can be
> + *   enabled with cogl_pipeline_set_per_vertex_point_size().
> + */
> +CoglBool
> +cogl_pipeline_get_per_vertex_point_size (CoglPipeline *pipeline);
> +
> +/**
>   * cogl_pipeline_get_color_mask:
>   * @pipeline: a #CoglPipeline object.
>   *
> diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
> index c397eb5..2c095c1 100644
> --- a/cogl/cogl-pipeline.c
> +++ b/cogl/cogl-pipeline.c
> @@ -882,6 +882,9 @@ _cogl_pipeline_copy_differences (CoglPipeline *dest,
>    if (differences & COGL_PIPELINE_STATE_POINT_SIZE)
>      big_state->point_size = src->big_state->point_size;
>
> +  if (differences & COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE)
> +    big_state->per_vertex_point_size = src->big_state->per_vertex_point_size;
> +
>    if (differences & COGL_PIPELINE_STATE_LOGIC_OPS)
>      {
>        memcpy (&big_state->logic_ops_state,
> @@ -964,6 +967,7 @@ _cogl_pipeline_init_multi_property_sparse_state (CoglPipeline *pipeline,
>      case COGL_PIPELINE_STATE_ALPHA_FUNC:
>      case COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE:
>      case COGL_PIPELINE_STATE_POINT_SIZE:
> +    case COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE:
>      case COGL_PIPELINE_STATE_REAL_BLEND_ENABLE:
>        g_return_if_reached ();
>
> @@ -2097,6 +2101,11 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
>                                                  authorities1[bit]))
>              goto done;
>            break;
> +        case COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE_INDEX:
> +          if (!_cogl_pipeline_per_vertex_point_size_equal (authorities0[bit],
> +                                                           authorities1[bit]))
> +            goto done;
> +          break;
>          case COGL_PIPELINE_STATE_LOGIC_OPS_INDEX:
>            if (!_cogl_pipeline_logic_ops_state_equal (authorities0[bit],
>                                                       authorities1[bit]))
> @@ -2449,6 +2458,8 @@ _cogl_pipeline_init_state_hash_functions (void)
>      _cogl_pipeline_hash_cull_face_state;
>    state_hash_functions[COGL_PIPELINE_STATE_POINT_SIZE_INDEX] =
>      _cogl_pipeline_hash_point_size_state;
> +  state_hash_functions[COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE_INDEX] =
> +    _cogl_pipeline_hash_per_vertex_point_size_state;
>    state_hash_functions[COGL_PIPELINE_STATE_LOGIC_OPS_INDEX] =
>      _cogl_pipeline_hash_logic_ops_state;
>    state_hash_functions[COGL_PIPELINE_STATE_UNIFORMS_INDEX] =
> @@ -2460,7 +2471,7 @@ _cogl_pipeline_init_state_hash_functions (void)
>
>    {
>    /* So we get a big error if we forget to update this code! */
> -  _COGL_STATIC_ASSERT (COGL_PIPELINE_STATE_SPARSE_COUNT == 13,
> +  _COGL_STATIC_ASSERT (COGL_PIPELINE_STATE_SPARSE_COUNT == 14,
>                         "Make sure to install a hash function for "
>                         "newly added pipeline state and update assert "
>                         "in _cogl_pipeline_init_state_hash_functions");
> diff --git a/cogl/cogl-private.h b/cogl/cogl-private.h
> index 52588db..83f2b09 100644
> --- a/cogl/cogl-private.h
> +++ b/cogl/cogl-private.h
> @@ -62,7 +62,8 @@ typedef enum
>    /* If this is set then the winsys is responsible for queueing dirty
>     * events. Otherwise a dirty event will be queued when the onscreen
>     * is first allocated or when it is shown or resized */
> -  COGL_PRIVATE_FEATURE_DIRTY_EVENTS = 1L<<26
> +  COGL_PRIVATE_FEATURE_DIRTY_EVENTS = 1L<<26,
> +  COGL_PRIVATE_FEATURE_ENABLE_PROGRAM_POINT_SIZE = 1L<<27
>  } CoglPrivateFeatureFlags;
>
>  /* Sometimes when evaluating pipelines, either during comparisons or
> diff --git a/cogl/cogl-snippet.h b/cogl/cogl-snippet.h
> index d6de2a4..9e83c54 100644
> --- a/cogl/cogl-snippet.h
> +++ b/cogl/cogl-snippet.h
> @@ -195,6 +195,16 @@ COGL_BEGIN_DECLS
>   *  </glossentry>
>   *  <glossentry>
>   *   <glossterm>float
> + *         <emphasis>cogl_point_size_in</emphasis></glossterm>
> + *   <glossdef><para>
> + *    The incoming point size from the cogl_point_size_in attribute.
> + *    This is only available if
> + *    cogl_pipeline_set_per_vertex_point_size() is set on the
> + *    pipeline.
> + *   </para></glossdef>
> + *  </glossentry>
> + *  <glossentry>
> + *   <glossterm>float
>   *         <emphasis>cogl_point_size_out</emphasis></glossterm>
>   *   <glossdef><para>
>   *    The calculated size of a point. This is equivalent to #gl_PointSize.
> @@ -311,6 +321,10 @@ typedef struct _CoglSnippet CoglSnippet;
>   * @COGL_SNIPPET_HOOK_VERTEX: A hook for the entire vertex processing
>   *   stage of the pipeline.
>   * @COGL_SNIPPET_HOOK_VERTEX_TRANSFORM: A hook for the vertex transformation.
> + * @COGL_SNIPPET_HOOK_POINT_SIZE: A hook for manipulating the point
> + *   size of a vertex. This is only used if
> + *   cogl_pipeline_set_per_vertex_point_size() is enabled on the
> + *   pipeline.
>   * @COGL_SNIPPET_HOOK_FRAGMENT: A hook for the entire fragment
>   *   processing stage of the pipeline.
>   * @COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM: A hook for transforming
> @@ -412,6 +426,39 @@ typedef struct _CoglSnippet CoglSnippet;
>   *   </glossdef>
>   *  </glossentry>
>   *  <glossentry>
> + *   <glossterm>%COGL_SNIPPET_HOOK_POINT_SIZE</glossterm>
> + *   <glossdef>
> + * <para>
> + * Adds a shader snippet that will hook on to the point size
> + * calculation step within the vertex shader stage. The snippet should
> + * write to the builtin cogl_point_size_out with the new point size.
> + * The snippet can either read cogl_point_size_in directly and write a
> + * new value or first read an existing value in cogl_point_size_out
> + * that would be set by a previous snippet. Note that this hook is
> + * only used if cogl_pipeline_set_per_vertex_point_size() is enabled
> + * on the pipeline.
> + * </para>
> + * <para>
> + * The ‘declarations’ string in @snippet will be inserted in the
> + * global scope of the shader. Use this to declare any uniforms,
> + * attributes or functions that the snippet requires.
> + * </para>
> + * <para>
> + * The ‘pre’ string in @snippet will be inserted just before
> + * calculating the point size.
> + * </para>
> + * <para>
> + * The ‘replace’ string in @snippet will be used instead of the
> + * generated point size calculation if it is present.
> + * </para>
> + * <para>
> + * The ‘post’ string in @snippet will be inserted after the
> + * standard point size calculation is done. This can be used to modify
> + * cogl_point_size_out in addition to the default processing.
> + * </para>
> + *   </glossdef>
> + *  </glossentry>
> + *  <glossentry>
>   *   <glossterm>%COGL_SNIPPET_HOOK_FRAGMENT</glossterm>
>   *   <glossdef>
>   * <para>
> @@ -570,6 +617,7 @@ typedef enum {
>    COGL_SNIPPET_HOOK_VERTEX = 0,
>    COGL_SNIPPET_HOOK_VERTEX_TRANSFORM,
>    COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
> +  COGL_SNIPPET_HOOK_POINT_SIZE,
>
>    /* Per pipeline fragment hooks */
>    COGL_SNIPPET_HOOK_FRAGMENT = 2048,
> diff --git a/cogl/driver/gl/cogl-pipeline-opengl-private.h b/cogl/driver/gl/cogl-pipeline-opengl-private.h
> index 294b611..7debe86 100644
> --- a/cogl/driver/gl/cogl-pipeline-opengl-private.h
> +++ b/cogl/driver/gl/cogl-pipeline-opengl-private.h
> @@ -144,7 +144,7 @@ _cogl_delete_gl_texture (GLuint gl_texture);
>  void
>  _cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
>                                 CoglFramebuffer *framebuffer,
> -                               CoglBool skip_gl_state);
> +                               CoglBool skip_gl_color);
>
>  #endif /* __COGL_PIPELINE_OPENGL_PRIVATE_H */
>
> diff --git a/cogl/driver/gl/cogl-pipeline-opengl.c b/cogl/driver/gl/cogl-pipeline-opengl.c
> index e4d2976..ef656ff 100644
> --- a/cogl/driver/gl/cogl-pipeline-opengl.c
> +++ b/cogl/driver/gl/cogl-pipeline-opengl.c
> @@ -58,7 +58,9 @@
>  #ifndef GL_CLAMP_TO_BORDER
>  #define GL_CLAMP_TO_BORDER 0x812d
>  #endif
> -
> +#ifndef GL_PROGRAM_POINT_SIZE
> +#define GL_PROGRAM_POINT_SIZE 0x8642
> +#endif
>
>  static void
>  texture_unit_init (CoglContext *ctx,
> @@ -630,6 +632,21 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state (
>          }
>      }
>
> +#ifdef HAVE_COGL_GL
> +  if ((ctx->private_feature_flags &
> +       COGL_PRIVATE_FEATURE_ENABLE_PROGRAM_POINT_SIZE) &&
> +      (pipelines_difference & COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE))
> +    {
> +      unsigned long state = COGL_PIPELINE_STATE_PER_VERTEX_POINT_SIZE;
> +      CoglPipeline *authority = _cogl_pipeline_get_authority (pipeline, state);
> +
> +      if (authority->big_state->per_vertex_point_size)
> +        GE( ctx, glEnable (GL_PROGRAM_POINT_SIZE) );
> +      else
> +        GE( ctx, glDisable (GL_PROGRAM_POINT_SIZE) );
> +    }
> +#endif
> +
>    if (pipeline->real_blend_enable != ctx->gl_blend_enable_cache)
>      {
>        if (pipeline->real_blend_enable)
> diff --git a/cogl/driver/gl/cogl-pipeline-progend-fixed.c b/cogl/driver/gl/cogl-pipeline-progend-fixed.c
> index 5a62a28..8072968 100644
> --- a/cogl/driver/gl/cogl-pipeline-progend-fixed.c
> +++ b/cogl/driver/gl/cogl-pipeline-progend-fixed.c
> @@ -59,6 +59,11 @@ _cogl_pipeline_progend_fixed_start (CoglPipeline *pipeline)
>    if (_cogl_pipeline_has_fragment_snippets (pipeline))
>      return FALSE;
>
> +  /* The fixed progend can't handle the per-vertex point size
> +   * attribute */
> +  if (cogl_pipeline_get_per_vertex_point_size (pipeline))
> +    return FALSE;
> +
>    return TRUE;
>  }
>
> diff --git a/cogl/driver/gl/cogl-pipeline-vertend-glsl.c b/cogl/driver/gl/cogl-pipeline-vertend-glsl.c
> index 9ae4a83..c5a5684 100644
> --- a/cogl/driver/gl/cogl-pipeline-vertend-glsl.c
> +++ b/cogl/driver/gl/cogl-pipeline-vertend-glsl.c
> @@ -279,12 +279,20 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
>                     "cogl_generated_source ()\n"
>                     "{\n");
>
> -  if (!(ctx->private_feature_flags &
> -        COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM))
> -    /* There is no builtin uniform for the pointsize on GLES2 so we need
> -       to copy it from the custom uniform in the vertex shader */
> -    g_string_append (shader_state->source,
> -                     "  cogl_point_size_out = cogl_point_size_in;\n");
> +  if (cogl_pipeline_get_per_vertex_point_size (pipeline))
> +    g_string_append (shader_state->header,
> +                     "attribute float cogl_point_size_in;\n");
> +  else if (!(ctx->private_feature_flags &
> +            COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM))
> +    {
> +      /* There is no builtin uniform for the point size on GLES2 so we
> +         need to copy it from the custom uniform in the vertex shader if
> +         we're not using per-vertex point sizes */
> +      g_string_append (shader_state->header,
> +                       "uniform float cogl_point_size_in;\n");
> +      g_string_append (shader_state->source,
> +                       "  cogl_point_size_out = cogl_point_size_in;\n");
> +    }
>  }
>
>  static CoglBool
> @@ -367,6 +375,8 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
>        GLuint shader;
>        CoglPipelineSnippetData snippet_data;
>        CoglPipelineSnippetList *vertex_snippets;
> +      CoglBool has_per_vertex_point_size =
> +        cogl_pipeline_get_per_vertex_point_size (pipeline);
>
>        COGL_STATIC_COUNTER (vertend_glsl_compile_counter,
>                             "glsl vertex compile counter",
> @@ -385,7 +395,21 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
>                         "}\n");
>
>        g_string_append (shader_state->source,
> -                       "  cogl_vertex_transform ();\n"
> +                       "  cogl_vertex_transform ();\n");
> +
> +      if (has_per_vertex_point_size)
> +        {
> +          g_string_append (shader_state->header,
> +                           "void\n"
> +                           "cogl_real_point_size_calculation ()\n"
> +                           "{\n"
> +                           "  cogl_point_size_out = cogl_point_size_in;\n"
> +                           "}\n");
> +          g_string_append (shader_state->source,
> +                           "  cogl_point_size_calculation ();\n");
> +        }
> +
> +      g_string_append (shader_state->source,
>                         "  cogl_color_out = cogl_color_in;\n"
>                         "}\n");
>
> @@ -401,6 +425,19 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
>        snippet_data.source_buf = shader_state->header;
>        _cogl_pipeline_snippet_generate_code (&snippet_data);
>
> +      /* Add hooks for the point size calculation part */
> +      if (has_per_vertex_point_size)
> +        {
> +          memset (&snippet_data, 0, sizeof (snippet_data));
> +          snippet_data.snippets = vertex_snippets;
> +          snippet_data.hook = COGL_SNIPPET_HOOK_POINT_SIZE;
> +          snippet_data.chain_function = "cogl_real_point_size_calculation";
> +          snippet_data.final_name = "cogl_point_size_calculation";
> +          snippet_data.function_prefix = "cogl_point_size_calculation";
> +          snippet_data.source_buf = shader_state->header;
> +          _cogl_pipeline_snippet_generate_code (&snippet_data);
> +        }
> +
>        /* Add all of the hooks for vertex processing */
>        memset (&snippet_data, 0, sizeof (snippet_data));
>        snippet_data.snippets = vertex_snippets;
> @@ -464,6 +501,7 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
>        shader_state->gl_shader = shader;
>      }
>
> +#ifdef HAVE_COGL_GL
>    if ((ctx->private_feature_flags &
>         COGL_PRIVATE_FEATURE_BUILTIN_POINT_SIZE_UNIFORM) &&
>        (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE))
> @@ -473,6 +511,7 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
>
>        GE( ctx, glPointSize (authority->big_state->point_size) );
>      }
> +#endif /* HAVE_COGL_GL */
>
>    return TRUE;
>  }
> diff --git a/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/driver/gl/gl/cogl-driver-gl.c
> index 9d5f4cd..9a36488 100644
> --- a/cogl/driver/gl/gl/cogl-driver-gl.c
> +++ b/cogl/driver/gl/gl/cogl-driver-gl.c
> @@ -526,11 +526,23 @@ _cogl_driver_update_features (CoglContext *ctx,
>    if (ctx->glGenSamplers)
>      private_flags |= COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS;
>
> +
>    if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 3, 3) ||
>        _cogl_check_extension ("GL_ARB_texture_swizzle", gl_extensions) ||
>        _cogl_check_extension ("GL_EXT_texture_swizzle", gl_extensions))
>      private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE;
>
> +  /* The per-vertex point size is only available via GLSL with the
> +   * gl_PointSize builtin. This is only available in GL 2.0 (not the
> +   * GLSL extensions) */
> +  if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0))
> +    {
> +      COGL_FLAGS_SET (ctx->features,
> +                      COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE,
> +                      TRUE);
> +      private_flags |= COGL_PRIVATE_FEATURE_ENABLE_PROGRAM_POINT_SIZE;
> +    }
> +
>    if (ctx->driver == COGL_DRIVER_GL)
>      {
>        int max_clip_planes = 0;
> diff --git a/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c b/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c
> index 3d41f92..e286e9a 100644
> --- a/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c
> +++ b/cogl/driver/gl/gl/cogl-pipeline-progend-fixed-arbfp.c
> @@ -65,6 +65,11 @@ _cogl_pipeline_progend_fixed_arbfp_start (CoglPipeline *pipeline)
>    if (_cogl_pipeline_has_fragment_snippets (pipeline))
>      return FALSE;
>
> +  /* The ARBfp progend can't handle the per-vertex point size
> +   * attribute */
> +  if (cogl_pipeline_get_per_vertex_point_size (pipeline))
> +    return FALSE;
> +
>    return TRUE;
>  }
>
> diff --git a/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/driver/gl/gles/cogl-driver-gles.c
> index 0438e34..2aa0af7 100644
> --- a/cogl/driver/gl/gles/cogl-driver-gles.c
> +++ b/cogl/driver/gl/gles/cogl-driver-gles.c
> @@ -246,6 +246,8 @@ _cogl_driver_update_features (CoglContext *context,
>        COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE);
>        COGL_FLAGS_SET (context->features,
>                        COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE);
> +      COGL_FLAGS_SET (context->features,
> +                      COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE, TRUE);
>
>        private_flags |= COGL_PRIVATE_FEATURE_BLEND_CONSTANT;
>      }
> diff --git a/doc/reference/cogl2/cogl2-sections.txt b/doc/reference/cogl2/cogl2-sections.txt
> index ee79fd9..2c7b225 100644
> --- a/doc/reference/cogl2/cogl2-sections.txt
> +++ b/doc/reference/cogl2/cogl2-sections.txt
> @@ -766,6 +766,8 @@ cogl_pipeline_set_blend
>  cogl_pipeline_set_blend_constant
>  cogl_pipeline_set_point_size
>  cogl_pipeline_get_point_size
> +cogl_pipeline_set_per_vertex_point_size
> +cogl_pipeline_get_per_vertex_point_size
>
>  cogl_pipeline_get_color_mask
>  cogl_pipeline_set_color_mask
> diff --git a/examples/cogl-info.c b/examples/cogl-info.c
> index 0a29d99..18101a8 100644
> --- a/examples/cogl-info.c
> +++ b/examples/cogl-info.c
> @@ -110,6 +110,12 @@ struct {
>      "Depth Textures",
>      "CoglFramebuffers can be configured to render their depth buffer into "
>      "a texture"
> +  },
> +  {
> +    COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE,
> +    "Per-vertex point size",
> +    "cogl_point_size_in can be used as an attribute to specify a per-vertex "
> +    "point size"
>    }
>  };
>
> diff --git a/tests/conform/Makefile.am b/tests/conform/Makefile.am
> index 8b73c53..bb41974 100644
> --- a/tests/conform/Makefile.am
> +++ b/tests/conform/Makefile.am
> @@ -48,6 +48,7 @@ test_sources = \
>         test-read-texture-formats.c \
>         test-write-texture-formats.c \
>         test-point-size.c \
> +       test-point-size-attribute.c \
>         test-point-sprite.c \
>         test-no-gl-header.c \
>         test-version.c \
> diff --git a/tests/conform/test-conform-main.c b/tests/conform/test-conform-main.c
> index 671d0b2..c7495d3 100644
> --- a/tests/conform/test-conform-main.c
> +++ b/tests/conform/test-conform-main.c
> @@ -105,6 +105,11 @@ main (int argc, char **argv)
>              0);
>
>    ADD_TEST (test_point_size, 0, 0);
> +  ADD_TEST (test_point_size_attribute,
> +            TEST_REQUIREMENT_PER_VERTEX_POINT_SIZE, 0);
> +  ADD_TEST (test_point_size_attribute_snippet,
> +            TEST_REQUIREMENT_PER_VERTEX_POINT_SIZE |
> +            TEST_REQUIREMENT_GLSL, 0);
>    ADD_TEST (test_point_sprite,
>              TEST_REQUIREMENT_POINT_SPRITE,
>              0);
> diff --git a/tests/conform/test-point-size-attribute.c b/tests/conform/test-point-size-attribute.c
> new file mode 100644
> index 0000000..81cae95
> --- /dev/null
> +++ b/tests/conform/test-point-size-attribute.c
> @@ -0,0 +1,166 @@
> +#include <cogl/cogl.h>
> +
> +#include "test-utils.h"
> +
> +/* This test assumes the GL driver supports point sizes up to 16
> +   pixels. Cogl should probably have some way of querying the size so
> +   we start from that instead */
> +#define MAX_POINT_SIZE 16
> +#define MIN_POINT_SIZE 4
> +#define N_POINTS (MAX_POINT_SIZE - MIN_POINT_SIZE + 1)
> +/* The size of the area that we'll paint each point in */
> +#define POINT_BOX_SIZE (MAX_POINT_SIZE * 2)
> +
> +typedef struct
> +{
> +  float x, y;
> +  float point_size;
> +} PointVertex;
> +
> +static int
> +calc_coord_offset (int pos, int pos_index, int point_size)
> +{
> +  switch (pos_index)
> +    {
> +    case 0: return pos - point_size / 2 - 2;
> +    case 1: return pos - point_size / 2 + 2;
> +    case 2: return pos + point_size / 2 - 2;
> +    case 3: return pos + point_size / 2 + 2;
> +    }
> +
> +  g_assert_not_reached ();
> +}
> +
> +static void
> +verify_point_size (CoglFramebuffer *test_fb,
> +                   int x_pos,
> +                   int y_pos,
> +                   int point_size)
> +{
> +  int y, x;
> +
> +  for (y = 0; y < 4; y++)
> +    for (x = 0; x < 4; x++)
> +      {
> +        CoglBool in_point = x >= 1 && x <= 2 && y >= 1 && y <= 2;
> +        uint32_t expected_pixel = in_point ? 0x00ff00ff : 0xff0000ff;
> +
> +        test_utils_check_pixel (test_fb,
> +                                calc_coord_offset (x_pos, x, point_size),
> +                                calc_coord_offset (y_pos, y, point_size),
> +                                expected_pixel);
> +      }
> +}
> +
> +static CoglPrimitive *
> +create_primitive (const char *attribute_name)
> +{
> +  PointVertex vertices[N_POINTS];
> +  CoglAttributeBuffer *buffer;
> +  CoglAttribute *attributes[2];
> +  CoglPrimitive *prim;
> +  int i;
> +
> +  for (i = 0; i < N_POINTS; i++)
> +    {
> +      vertices[i].x = i * POINT_BOX_SIZE + POINT_BOX_SIZE / 2;
> +      vertices[i].y = POINT_BOX_SIZE / 2;
> +      vertices[i].point_size = MAX_POINT_SIZE - i;
> +    }
> +
> +  buffer = cogl_attribute_buffer_new (test_ctx,
> +                                      sizeof (vertices),
> +                                      vertices);
> +
> +  attributes[0] = cogl_attribute_new (buffer,
> +                                      "cogl_position_in",
> +                                      sizeof (PointVertex),
> +                                      G_STRUCT_OFFSET (PointVertex, x),
> +                                      2, /* n_components */
> +                                      COGL_ATTRIBUTE_TYPE_FLOAT);
> +  attributes[1] = cogl_attribute_new (buffer,
> +                                      attribute_name,
> +                                      sizeof (PointVertex),
> +                                      G_STRUCT_OFFSET (PointVertex, point_size),
> +                                      1, /* n_components */
> +                                      COGL_ATTRIBUTE_TYPE_FLOAT);
> +
> +  prim = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_POINTS,
> +                                             N_POINTS,
> +                                             attributes,
> +                                             2 /* n_attributes */);
> +
> +  for (i = 0; i < 2; i++)
> +    cogl_object_unref (attributes[i]);
> +
> +  return prim;
> +}
> +
> +static void
> +do_test (const char *attribute_name,
> +         void (* pipeline_setup_func) (CoglPipeline *pipeline))
> +{
> +  int fb_width = cogl_framebuffer_get_width (test_fb);
> +  int fb_height = cogl_framebuffer_get_height (test_fb);
> +  CoglPrimitive *primitive;
> +  CoglPipeline *pipeline;
> +  int i;
> +
> +  cogl_framebuffer_orthographic (test_fb,
> +                                 0, 0, /* x_1, y_1 */
> +                                 fb_width, /* x_2 */
> +                                 fb_height /* y_2 */,
> +                                 -1, 100 /* near/far */);
> +
> +  cogl_framebuffer_clear4f (test_fb,
> +                            COGL_BUFFER_BIT_COLOR,
> +                            1.0f, 0.0f, 0.0f, 1.0f);
> +
> +  primitive = create_primitive (attribute_name);
> +  pipeline = cogl_pipeline_new (test_ctx);
> +  cogl_pipeline_set_color4ub (pipeline, 0x00, 0xff, 0x00, 0xff);
> +  cogl_pipeline_set_per_vertex_point_size (pipeline, TRUE, NULL);
> +  if (pipeline_setup_func)
> +    pipeline_setup_func (pipeline);
> +  cogl_framebuffer_draw_primitive (test_fb, pipeline, primitive);
> +  cogl_object_unref (pipeline);
> +  cogl_object_unref (primitive);
> +
> +  /* Verify all of the points where drawn at the right size */
> +  for (i = 0; i < N_POINTS; i++)
> +    verify_point_size (test_fb,
> +                       i * POINT_BOX_SIZE + POINT_BOX_SIZE / 2, /* x */
> +                       POINT_BOX_SIZE / 2, /* y */
> +                       MAX_POINT_SIZE - i /* point size */);
> +
> +  if (cogl_test_verbose ())
> +    g_print ("OK\n");
> +}
> +
> +void
> +test_point_size_attribute (void)
> +{
> +  do_test ("cogl_point_size_in", NULL);
> +}
> +
> +static void
> +setup_snippet (CoglPipeline *pipeline)
> +{
> +  CoglSnippet *snippet;
> +
> +  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_POINT_SIZE,
> +                              "attribute float "
> +                              "my_super_duper_point_size_attrib;\n",
> +                              NULL);
> +  cogl_snippet_set_replace (snippet,
> +                            "cogl_point_size_out = "
> +                            "my_super_duper_point_size_attrib;\n");
> +  cogl_pipeline_add_snippet (pipeline, snippet);
> +  cogl_object_unref (snippet);
> +}
> +
> +void
> +test_point_size_attribute_snippet (void)
> +{
> +  do_test ("my_super_duper_point_size_attrib", setup_snippet);
> +}
> diff --git a/tests/conform/test-utils.c b/tests/conform/test-utils.c
> index a10019a..ba4ad1a 100644
> --- a/tests/conform/test-utils.c
> +++ b/tests/conform/test-utils.c
> @@ -46,6 +46,12 @@ check_flags (TestFlags flags,
>        return FALSE;
>      }
>
> +  if (flags & TEST_REQUIREMENT_PER_VERTEX_POINT_SIZE &&
> +      !cogl_has_feature (test_ctx, COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE))
> +    {
> +      return FALSE;
> +    }
> +
>    if (flags & TEST_REQUIREMENT_GLES2_CONTEXT &&
>        !cogl_has_feature (test_ctx, COGL_FEATURE_ID_GLES2_CONTEXT))
>      {
> diff --git a/tests/conform/test-utils.h b/tests/conform/test-utils.h
> index ae2fb64..8d3526f 100644
> --- a/tests/conform/test-utils.h
> +++ b/tests/conform/test-utils.h
> @@ -21,7 +21,8 @@ typedef enum _TestFlags
>    TEST_REQUIREMENT_MAP_WRITE = 1<<7,
>    TEST_REQUIREMENT_GLSL = 1<<8,
>    TEST_REQUIREMENT_OFFSCREEN = 1<<9,
> -  TEST_REQUIREMENT_FENCE = 1<<10
> +  TEST_REQUIREMENT_FENCE = 1<<10,
> +  TEST_REQUIREMENT_PER_VERTEX_POINT_SIZE = 1<<11
>  } TestFlags;
>
>  extern CoglContext *test_ctx;
> --
> 1.7.11.3.g3c3efa5
>
> _______________________________________________
> Cogl mailing list
> Cogl at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/cogl


More information about the Cogl mailing list