[cogl/wip/rib/master-next: 21/36] features: Support more than 32 features!



commit 68ac5d8659e19bff2c4172ee48b0beef509c5e50
Author: Robert Bragg <robert linux intel com>
Date:   Wed Oct 12 22:31:12 2011 +0100

    features: Support more than 32 features!
    
    Currently features are represented as bits in a 32bit mask so we
    obviously can't have more than 32 features with that approach. The new
    approach is to use a CoglBitmask which doesn't have a size limit and
    instead define the public api to accept individual feature enums instead
    of a mask. This way there is no limit on the number of features we add
    to Cogl.
    
    Instead of using cogl_features_available() there is a new
    cogl_has_feature() function and for checking multiple features there is
    cogl_has_features() which takes a zero terminated vararg list of
    features.
    
    In addition to being able to check for individual features this also
    adds a way to query all the features currently available via
    cogl_foreach_feature() which will call a callback for each feature.
    
    Since the new functions take an explicit context pointer there is also
    no longer any ambiguity over when users can first start to query
    features.

 cogl/cogl-atlas-texture.c                          |    2 +-
 cogl/cogl-buffer.c                                 |    4 +-
 cogl/cogl-context-private.h                        |    3 +-
 cogl/cogl-context.c                                |   30 +++-
 cogl/cogl-depth-state.h                            |    4 +-
 cogl/cogl-framebuffer.c                            |    6 +-
 cogl/cogl-pipeline-fragend-arbfp.c                 |    2 +-
 cogl/cogl-pipeline-fragend-glsl.c                  |    2 +-
 cogl/cogl-pipeline-layer-state.c                   |    4 +-
 cogl/cogl-pipeline-opengl.c                        |    6 +-
 cogl/cogl-pipeline-vertend-glsl.c                  |    2 +-
 cogl/cogl-shader.c                                 |    2 +-
 cogl/cogl-texture-2d-sliced.c                      |    2 +-
 cogl/cogl-texture-2d.c                             |    8 +-
 cogl/cogl-texture-2d.h                             |   12 +-
 cogl/cogl-texture-3d.c                             |    8 +-
 cogl/cogl-texture-rectangle.c                      |    2 +-
 cogl/cogl-texture.c                                |    2 +-
 cogl/cogl.c                                        |   30 ++++
 cogl/cogl.h                                        |  147 ++++++++++++++++++++
 cogl/driver/gl/cogl-gl.c                           |   51 ++++++-
 cogl/driver/gl/cogl-texture-driver-gl.c            |    4 +-
 cogl/driver/gles/cogl-gles.c                       |   62 +++++++--
 cogl/winsys/cogl-winsys-egl.c                      |    2 +
 cogl/winsys/cogl-winsys-glx.c                      |    8 +-
 cogl/winsys/cogl-winsys-wgl.c                      |    2 +
 .../cogl-2.0-experimental-sections.txt             |    7 +
 27 files changed, 349 insertions(+), 65 deletions(-)
---
diff --git a/cogl/cogl-atlas-texture.c b/cogl/cogl-atlas-texture.c
index 042cd7b..3fc459b 100644
--- a/cogl/cogl-atlas-texture.c
+++ b/cogl/cogl-atlas-texture.c
@@ -657,7 +657,7 @@ _cogl_atlas_texture_new_with_size (unsigned int width,
 
   /* If we can't use FBOs then it will be too slow to migrate textures
      and we shouldn't use the atlas */
-  if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
     return COGL_INVALID_HANDLE;
 
   COGL_NOTE (ATLAS, "Adding texture of size %ix%i", width, height);
diff --git a/cogl/cogl-buffer.c b/cogl/cogl-buffer.c
index 7a6c77a..9fff90a 100644
--- a/cogl/cogl-buffer.c
+++ b/cogl/cogl-buffer.c
@@ -134,10 +134,10 @@ bo_map (CoglBuffer       *buffer,
   _COGL_GET_CONTEXT (ctx, NULL);
 
   if ((access & COGL_BUFFER_ACCESS_READ) &&
-      !cogl_features_available (COGL_FEATURE_MAP_BUFFER_FOR_READ))
+      !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_READ))
     return NULL;
   if ((access & COGL_BUFFER_ACCESS_WRITE) &&
-      !cogl_features_available (COGL_FEATURE_MAP_BUFFER_FOR_WRITE))
+      !cogl_has_feature (ctx, COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE))
     return NULL;
 
   target = buffer->last_target;
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 3981f7b..02efc04 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -63,7 +63,8 @@ struct _CoglContext
   const CoglTextureDriver *texture_driver;
 
   /* Features cache */
-  CoglFeatureFlags feature_flags;
+  CoglBitmask features;
+  CoglFeatureFlags feature_flags; /* legacy/deprecated feature flags */
   CoglPrivateFeatureFlags private_feature_flags;
 
   CoglHandle        default_pipeline;
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 452c675..cd09cbc 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -80,16 +80,31 @@ _cogl_init_feature_overrides (CoglContext *ctx)
     ctx->private_feature_flags &= ~COGL_PRIVATE_FEATURE_PBOS;
 
   if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_ARBFP)))
-    ctx->feature_flags &= ~COGL_FEATURE_SHADERS_ARBFP;
+    {
+      ctx->feature_flags &= ~COGL_FEATURE_SHADERS_ARBFP;
+      _cogl_bitmask_set (&ctx->features, COGL_FEATURE_ID_ARBFP, FALSE);
+    }
 
   if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_GLSL)))
-    ctx->feature_flags &= ~COGL_FEATURE_SHADERS_GLSL;
+    {
+      ctx->feature_flags &= ~COGL_FEATURE_SHADERS_GLSL;
+      _cogl_bitmask_set (&ctx->features, COGL_FEATURE_ID_GLSL, FALSE);
+    }
 
   if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_NPOT_TEXTURES)))
-    ctx->feature_flags &= ~(COGL_FEATURE_TEXTURE_NPOT |
-                            COGL_FEATURE_TEXTURE_NPOT_BASIC |
-                            COGL_FEATURE_TEXTURE_NPOT_MIPMAP |
-                            COGL_FEATURE_TEXTURE_NPOT_REPEAT);
+    {
+      ctx->feature_flags &= ~(COGL_FEATURE_TEXTURE_NPOT |
+                              COGL_FEATURE_TEXTURE_NPOT_BASIC |
+                              COGL_FEATURE_TEXTURE_NPOT_MIPMAP |
+                              COGL_FEATURE_TEXTURE_NPOT_REPEAT);
+      _cogl_bitmask_set (&ctx->features, COGL_FEATURE_ID_TEXTURE_NPOT, FALSE);
+      _cogl_bitmask_set (&ctx->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, FALSE);
+      _cogl_bitmask_set (&ctx->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, FALSE);
+      _cogl_bitmask_set (&ctx->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, FALSE);
+    }
 }
 
 const CoglWinsysVtable *
@@ -148,6 +163,7 @@ cogl_context_new (CoglDisplay *display,
   _context = context;
 
   /* Init default values */
+  _cogl_bitmask_init (&context->features);
   context->feature_flags = 0;
   context->private_feature_flags = 0;
 
@@ -378,7 +394,7 @@ cogl_context_new (CoglDisplay *display,
      coords enabled. We don't need to do this for GLES2 because point
      sprites are handled using a builtin varying in the shader. */
   if (_context->driver != COGL_DRIVER_GLES2 &&
-      cogl_features_available (COGL_FEATURE_POINT_SPRITE))
+      cogl_has_feature (context, COGL_FEATURE_ID_POINT_SPRITE))
     GE (context, glEnable (GL_POINT_SPRITE));
 
   return _cogl_context_object_new (context);
diff --git a/cogl/cogl-depth-state.h b/cogl/cogl-depth-state.h
index 89dcbe6..0fff9a0 100644
--- a/cogl/cogl-depth-state.h
+++ b/cogl/cogl-depth-state.h
@@ -219,8 +219,8 @@ cogl_depth_state_get_test_function (CoglDepthState *state);
  * using GLES 1 drivers) then if you don't use the default range
  * values you will get an error reported when calling
  * cogl_pipeline_set_depth_state (). You can check ahead of time for
- * the %COGL_FEATURE_DEPTH_RANGE feature with
- * cogl_features_available() to know if this function will succeed.
+ * the %COGL_FEATURE_ID_DEPTH_RANGE feature with
+ * cogl_has_feature() to know if this function will succeed.
  *
  * By default normalized device coordinate depth values are mapped to
  * the full range of depth buffer values, [0, 1].
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 2fd079c..a09176f 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -629,7 +629,7 @@ _cogl_framebuffer_init_bits (CoglFramebuffer *framebuffer)
 
 #ifdef HAVE_COGL_GL
   if (ctx->driver == COGL_DRIVER_GL &&
-      cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
+      cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN) &&
       framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
     {
       GLenum attachment, pname;
@@ -701,7 +701,7 @@ _cogl_offscreen_new_to_texture_full (CoglTexture *texture,
 
   _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
 
-  if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
     return COGL_INVALID_HANDLE;
 
   /* Make texture is a valid texture object */
@@ -1469,7 +1469,7 @@ bind_gl_framebuffer (CoglContext *ctx,
         _cogl_framebuffer_get_winsys (framebuffer);
       winsys->onscreen_bind (COGL_ONSCREEN (framebuffer));
       /* glBindFramebuffer is an an extension with OpenGL ES 1.1 */
-      if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
+      if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
         GE (ctx, glBindFramebuffer (target, 0));
     }
 }
diff --git a/cogl/cogl-pipeline-fragend-arbfp.c b/cogl/cogl-pipeline-fragend-arbfp.c
index 3eda26a..0ee035f 100644
--- a/cogl/cogl-pipeline-fragend-arbfp.c
+++ b/cogl/cogl-pipeline-fragend-arbfp.c
@@ -163,7 +163,7 @@ _cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
   /* First validate that we can handle the current state using ARBfp
    */
 
-  if (!cogl_features_available (COGL_FEATURE_SHADERS_ARBFP))
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP))
     return FALSE;
 
   /* TODO: support fog */
diff --git a/cogl/cogl-pipeline-fragend-glsl.c b/cogl/cogl-pipeline-fragend-glsl.c
index bc77095..4728236 100644
--- a/cogl/cogl-pipeline-fragend-glsl.c
+++ b/cogl/cogl-pipeline-fragend-glsl.c
@@ -190,7 +190,7 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
 
   _COGL_GET_CONTEXT (ctx, FALSE);
 
-  if (!cogl_features_available (COGL_FEATURE_SHADERS_GLSL))
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
     return FALSE;
 
   user_program = cogl_pipeline_get_user_program (pipeline);
diff --git a/cogl/cogl-pipeline-layer-state.c b/cogl/cogl-pipeline-layer-state.c
index c369c6d..d87772f 100644
--- a/cogl/cogl-pipeline-layer-state.c
+++ b/cogl/cogl-pipeline-layer-state.c
@@ -664,11 +664,13 @@ cogl_pipeline_set_layer_point_sprite_coords_enabled (CoglPipeline *pipeline,
   CoglPipelineLayer           *new;
   CoglPipelineLayer           *authority;
 
+  _COGL_GET_CONTEXT (ctx, FALSE);
+
   g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
 
   /* Don't allow point sprite coordinates to be enabled if the driver
      doesn't support it */
-  if (enable && !cogl_features_available (COGL_FEATURE_POINT_SPRITE))
+  if (enable && !cogl_has_feature (ctx, COGL_FEATURE_ID_POINT_SPRITE))
     {
       if (error)
         {
diff --git a/cogl/cogl-pipeline-opengl.c b/cogl/cogl-pipeline-opengl.c
index 552fa49..361364e 100644
--- a/cogl/cogl-pipeline-opengl.c
+++ b/cogl/cogl-pipeline-opengl.c
@@ -687,8 +687,8 @@ get_max_activateable_texture_units (void)
              defines the number of texture coordinates that can be
              uploaded (but doesn't necessarily relate to how many texture
              images can be sampled) */
-          if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL) ||
-              cogl_features_available (COGL_FEATURE_SHADERS_ARBFP))
+          if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL) ||
+              cogl_has_feature (ctx, COGL_FEATURE_ID_ARBFP))
             /* Previously this code subtracted the value by one but there
                was no explanation for why it did this and it doesn't seem
                to make sense so it has been removed */
@@ -697,7 +697,7 @@ get_max_activateable_texture_units (void)
 
           /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is defined for GLSL but
              not ARBfp */
-          if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL))
+          if (cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
             GE (ctx, glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
                                     values + n_values++));
         }
diff --git a/cogl/cogl-pipeline-vertend-glsl.c b/cogl/cogl-pipeline-vertend-glsl.c
index ee1ec14..a3a460d 100644
--- a/cogl/cogl-pipeline-vertend-glsl.c
+++ b/cogl/cogl-pipeline-vertend-glsl.c
@@ -134,7 +134,7 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
 
   _COGL_GET_CONTEXT (ctx, FALSE);
 
-  if (!cogl_features_available (COGL_FEATURE_SHADERS_GLSL))
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_GLSL))
     return FALSE;
 
   user_program = cogl_pipeline_get_user_program (pipeline);
diff --git a/cogl/cogl-shader.c b/cogl/cogl-shader.c
index 4d662ab..b94f23d 100644
--- a/cogl/cogl-shader.c
+++ b/cogl/cogl-shader.c
@@ -203,7 +203,7 @@ _cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
     }
 
   if (ctx->driver == COGL_DRIVER_GLES2 &&
-      cogl_features_available (COGL_FEATURE_TEXTURE_3D))
+      cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D))
     {
       static const char texture_3d_extension[] =
         "#extension GL_OES_texture_3D : enable\n";
diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c
index 8d922ec..03a2538 100644
--- a/cogl/cogl-texture-2d-sliced.c
+++ b/cogl/cogl-texture-2d-sliced.c
@@ -702,7 +702,7 @@ _cogl_texture_2d_sliced_slices_create (CoglContext *ctx,
   int   (*slices_for_size) (int, int, int, GArray*);
 
   /* Initialize size of largest slice according to supported features */
-  if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT))
+  if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT))
     {
       max_width = width;
       max_height = height;
diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c
index f800fcb..4697917 100644
--- a/cogl/cogl-texture-2d.c
+++ b/cogl/cogl-texture-2d.c
@@ -181,7 +181,7 @@ _cogl_texture_2d_can_create (unsigned int width,
 
   /* If NPOT textures aren't supported then the size must be a power
      of two */
-  if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT) &&
       (!_cogl_util_is_pot (width) ||
        !_cogl_util_is_pot (height)))
     return FALSE;
@@ -329,7 +329,7 @@ _cogl_texture_2d_new_from_bitmap (CoglBitmap      *bmp,
 
   /* Keep a copy of the first pixel so that if glGenerateMipmap isn't
      supported we can fallback to using GL_GENERATE_MIPMAP */
-  if (!cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN) &&
       (data = _cogl_bitmap_map (dst_bmp,
                                 COGL_BUFFER_ACCESS_READ, 0)))
     {
@@ -771,7 +771,7 @@ _cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
       /* glGenerateMipmap is defined in the FBO extension. If it's not
          available we'll fallback to temporarily enabling
          GL_GENERATE_MIPMAP and reuploading the first pixel */
-      if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
+      if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
         ctx->texture_driver->gl_generate_mipmaps (GL_TEXTURE_2D);
 #if defined(HAVE_COGL_GLES) || defined(HAVE_COGL_GL)
       else
@@ -825,7 +825,7 @@ _cogl_texture_2d_set_region (CoglTexture    *tex,
 
   /* If this touches the first pixel then we'll update our copy */
   if (dst_x == 0 && dst_y == 0 &&
-      !cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
+      !cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN) &&
       (data = _cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0)))
     {
       CoglPixelFormat bpp =
diff --git a/cogl/cogl-texture-2d.h b/cogl/cogl-texture-2d.h
index 2a51664..8e2e710 100644
--- a/cogl/cogl-texture-2d.h
+++ b/cogl/cogl-texture-2d.h
@@ -49,8 +49,8 @@ G_BEGIN_DECLS
  *
  * You should be aware that many GPUs only support power of two sizes
  * for #CoglTexture2D textures. You can check support for non power of
- * two textures by checking for the %COGL_FEATURE_TEXTURE_NPOT feature
- * via cogl_features_available ().
+ * two textures by checking for the %COGL_FEATURE_ID_TEXTURE_NPOT feature
+ * via cogl_has_feature().
  */
 
 typedef struct _CoglTexture2D CoglTexture2D;
@@ -87,8 +87,8 @@ cogl_is_texture_2d (void *object);
  *
  * <note>Many GPUs only support power of two sizes for #CoglTexture2D
  * textures. You can check support for non power of two textures by
- * checking for the %COGL_FEATURE_TEXTURE_NPOT feature via
- * cogl_features_available ().</note>
+ * checking for the %COGL_FEATURE_ID_TEXTURE_NPOT feature via
+ * cogl_has_feature().</note>
  *
  * Returns: A newly allocated #CoglTexture2D, or if the size is not
  *          supported (because it is too large or a non-power-of-two
@@ -132,8 +132,8 @@ cogl_texture_2d_new_with_size (CoglContext *ctx,
  *
  * <note>Many GPUs only support power of two sizes for #CoglTexture2D
  * textures. You can check support for non power of two textures by
- * checking for the %COGL_FEATURE_TEXTURE_NPOT feature via
- * cogl_features_available ().</note>
+ * checking for the %COGL_FEATURE_ID_TEXTURE_NPOT feature via
+ * cogl_has_feature().</note>
  *
  * Returns: A newly allocated #CoglTexture2D, or if the size is not
  *          supported (because it is too large or a non-power-of-two
diff --git a/cogl/cogl-texture-3d.c b/cogl/cogl-texture-3d.c
index a64c3d2..58adee6 100644
--- a/cogl/cogl-texture-3d.c
+++ b/cogl/cogl-texture-3d.c
@@ -219,7 +219,7 @@ _cogl_texture_3d_can_create (unsigned int     width,
   _COGL_GET_CONTEXT (ctx, FALSE);
 
   /* This should only happen on GLES */
-  if (!cogl_features_available (COGL_FEATURE_TEXTURE_3D))
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D))
     {
       g_set_error (error,
                    COGL_ERROR,
@@ -230,7 +230,7 @@ _cogl_texture_3d_can_create (unsigned int     width,
 
   /* If NPOT textures aren't supported then the size must be a power
      of two */
-  if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_NPOT) &&
       (!_cogl_util_is_pot (width) ||
        !_cogl_util_is_pot (height) ||
        !_cogl_util_is_pot (depth)))
@@ -357,7 +357,7 @@ _cogl_texture_3d_new_from_bitmap (CoglBitmap      *bmp,
 
   /* Keep a copy of the first pixel so that if glGenerateMipmap isn't
      supported we can fallback to using GL_GENERATE_MIPMAP */
-  if (!cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN) &&
       (data = _cogl_bitmap_map (dst_bmp,
                                 COGL_BUFFER_ACCESS_READ, 0)))
     {
@@ -578,7 +578,7 @@ _cogl_texture_3d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
       /* glGenerateMipmap is defined in the FBO extension. If it's not
          available we'll fallback to temporarily enabling
          GL_GENERATE_MIPMAP and reuploading the first pixel */
-      if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
+      if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
         ctx->texture_driver->gl_generate_mipmaps (GL_TEXTURE_3D);
 #if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
       else if (ctx->driver != COGL_DRIVER_GLES2)
diff --git a/cogl/cogl-texture-rectangle.c b/cogl/cogl-texture-rectangle.c
index ca12fcb..558def6 100644
--- a/cogl/cogl-texture-rectangle.c
+++ b/cogl/cogl-texture-rectangle.c
@@ -198,7 +198,7 @@ _cogl_texture_rectangle_can_create (unsigned int width,
 
   _COGL_GET_CONTEXT (ctx, FALSE);
 
-  if (!cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE))
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE))
     return FALSE;
 
   ctx->texture_driver->pixel_format_to_gl (internal_format,
diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c
index 7bf0d64..b2e0a40 100644
--- a/cogl/cogl-texture.c
+++ b/cogl/cogl-texture.c
@@ -1121,7 +1121,7 @@ get_texture_bits_via_offscreen (CoglTexture    *texture,
 
   _COGL_GET_CONTEXT (ctx, FALSE);
 
-  if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
+  if (!cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
     return FALSE;
 
   framebuffer = _cogl_offscreen_new_to_texture_full
diff --git a/cogl/cogl.c b/cogl/cogl.c
index e81caa7..d41de2d 100644
--- a/cogl/cogl.c
+++ b/cogl/cogl.c
@@ -319,6 +319,36 @@ cogl_features_available (CoglFeatureFlags features)
   return (ctx->feature_flags & features) == features;
 }
 
+gboolean
+cogl_has_feature (CoglContext *ctx, CoglFeatureID feature)
+{
+  return _cogl_bitmask_get (&ctx->features, feature);
+}
+
+gboolean
+cogl_has_features (CoglContext *ctx, ...)
+{
+  va_list args;
+  CoglFeatureID feature;
+
+  va_start (args, ctx);
+  while ((feature = va_arg (args, CoglFeatureID)))
+    if (!cogl_has_feature (ctx, feature))
+      return FALSE;
+  va_end (args);
+
+  return TRUE;
+}
+
+void
+cogl_foreach_feature (CoglContext *ctx,
+                      CoglFeatureCallback callback,
+                      void *user_data)
+{
+  _cogl_bitmask_foreach (&ctx->features,
+                         (CoglBitmaskForeachFunc)callback, user_data);
+}
+
 /* XXX: This function should either be replaced with one returning
  * integers, or removed/deprecated and make the
  * _cogl_framebuffer_get_viewport* functions public.
diff --git a/cogl/cogl.h b/cogl/cogl.h
index 08f4402..1276c08 100644
--- a/cogl/cogl.h
+++ b/cogl/cogl.h
@@ -157,6 +157,153 @@ cogl_get_features (void);
 gboolean
 cogl_features_available (CoglFeatureFlags features);
 
+/* XXX: not guarded by the EXPERIMENTAL_2_0_API defines to avoid
+ * upsetting glib-mkenums, but this can still be considered implicitly
+ * experimental since it's only useable with experimental API... */
+/**
+ * CoglFeatureID:
+ * @COGL_FEATURE_ID_TEXTURE_NPOT_BASIC: The hardware supports non power
+ *     of two textures, but you also need to check the
+ *     %COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP and %COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT
+ *     features to know if the hardware supports npot texture mipmaps
+ *     or repeat modes other than
+ *     %COGL_RENDERER_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE respectively.
+ * @COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP: Mipmapping is supported in
+ *     conjuntion with non power of two textures.
+ * @COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT: Repeat modes other than
+ *     %COGL_RENDERER_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE are supported by the
+ *     hardware.
+ * @COGL_FEATURE_ID_TEXTURE_NPOT: Non power of two textures are supported
+ *    by the hardware. This is a equivalent to the
+ *    %COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, %COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP
+ *    and %COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT features combined.
+ * @COGL_FEATURE_ID_TEXTURE_RECTANGLE: Support for rectangular
+ *    textures with non-normalized texture coordinates.
+ * @COGL_FEATURE_ID_TEXTURE_3D: 3D texture support
+ * @COGL_FEATURE_ID_OFFSCREEN: Offscreen rendering support
+ * @COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE: Multisample support for
+ *    offscreen framebuffers
+ * @COGL_FEATURE_ID_ONSCREEN_MULTIPLE: Multiple onscreen framebuffers
+ *    supported.
+ * @COGL_FEATURE_ID_GLSL: GLSL support
+ * @COGL_FEATURE_ID_ARBFP: ARBFP support
+ * @COGL_FEATURE_ID_UNSIGNED_INT_INDICES: Set if
+ *     %COGL_RENDERER_INDICES_TYPE_UNSIGNED_INT is supported in
+ *     cogl_indices_new().
+ * @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_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
+ *     supported with CoglBufferAccess including write support.
+ *
+ *
+ * All the capabilities that can vary between different GPUs supported
+ * by Cogl. Applications that depend on any of these features should explicitly
+ * check for them using cogl_has_feature() or cogl_has_features().
+ *
+ * Since: 1.10
+ */
+typedef enum _CoglFeatureID
+{
+  COGL_FEATURE_ID_TEXTURE_NPOT_BASIC = 1,
+  COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP,
+  COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT,
+  COGL_FEATURE_ID_TEXTURE_NPOT,
+  COGL_FEATURE_ID_TEXTURE_RECTANGLE,
+  COGL_FEATURE_ID_TEXTURE_3D,
+  COGL_FEATURE_ID_GLSL,
+  COGL_FEATURE_ID_ARBFP,
+  COGL_FEATURE_ID_OFFSCREEN,
+  COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE,
+  COGL_FEATURE_ID_ONSCREEN_MULTIPLE,
+  COGL_FEATURE_ID_UNSIGNED_INT_INDICES,
+  COGL_FEATURE_ID_DEPTH_RANGE,
+  COGL_FEATURE_ID_POINT_SPRITE,
+  COGL_FEATURE_ID_MAP_BUFFER_FOR_READ,
+  COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE
+} CoglFeatureID;
+
+
+#ifdef COGL_ENABLE_EXPERIMENTAL_2_0_API
+
+#define cogl_has_feature cogl_has_feature_EXP
+/**
+ * cogl_has_feature:
+ * @context: A #CoglContext pointer
+ * @feature: A #CoglFeatureID
+ *
+ * Checks if a given @feature is currently available
+ *
+ * Cogl does not aim to be a lowest common denominator API, it aims to
+ * expose all the interesting features of GPUs to application which
+ * means applications have some responsibility to explicitly check
+ * that certain features are available before depending on them.
+ *
+ * Returns: %TRUE if the @feature is currently supported or %FALSE if
+ * not.
+ *
+ * Since: 1.1.0
+ * Stability: unstable
+ */
+gboolean
+cogl_has_feature (CoglContext *context, CoglFeatureID feature);
+
+#define cogl_has_features cogl_has_features_EXP
+/**
+ * cogl_has_features:
+ * @context: A #CoglContext pointer
+ * @...: A 0 terminated list of CoglFeatureID<!-- -->s
+ *
+ * Checks if a list of features are all currently available.
+ *
+ * This checks all of the listed features using cogl_has_feature() and
+ * returns %TRUE if all the features are available or %FALSE
+ * otherwise.
+ *
+ * Return value: %TRUE if all the features are available, %FALSE
+ * otherwise.
+ *
+ * Since: 1.1.0
+ * Stability: unstable
+ */
+gboolean
+cogl_has_features (CoglContext *context, ...);
+
+/**
+ * CoglFeatureCallback:
+ * @feature: A single feature currently supported by Cogl
+ * @user_data: A private pointer passed to cogl_foreach_feature().
+ *
+ * A callback used with cogl_foreach_feature() for enumerating all
+ * context level features supported by Cogl.
+ *
+ * Since: 1.1.0
+ * Stability: unstable
+ */
+typedef void (*CoglFeatureCallback) (CoglFeatureID feature, void *user_data);
+
+#define cogl_foreach_feature cogl_foreach_feature_EXP
+/**
+ * cogl_foreach_feature:
+ * @context: A #CoglContext pointer
+ * @callback: A #CoglFeatureCallback called for each supported feature
+ * @user_data: Private data to pass to the callback
+ *
+ * Iterates through all the context level features currently supported
+ * for a given @context and for each feature @callback is called.
+ *
+ * Since: 1.10
+ * Stability: unstable
+ */
+void
+cogl_foreach_feature (CoglContext *context,
+                      CoglFeatureCallback callback,
+                      void *user_data);
+
+#endif /* COGL_ENABLE_EXPERIMENTAL_2_0_API */
+
 /**
  * cogl_get_proc_address:
  * @name: the name of the function.
diff --git a/cogl/driver/gl/cogl-gl.c b/cogl/driver/gl/cogl-gl.c
index efe27c0..f1bea59 100644
--- a/cogl/driver/gl/cogl-gl.c
+++ b/cogl/driver/gl/cogl-gl.c
@@ -160,6 +160,9 @@ _cogl_gl_update_features (CoglContext *context,
   flags = (COGL_FEATURE_TEXTURE_READ_PIXELS
            | COGL_FEATURE_UNSIGNED_INT_INDICES
            | COGL_FEATURE_DEPTH_RANGE);
+  _cogl_bitmask_set (&ctx->features,
+                     COGL_FEATURE_ID_UNSIGNED_INT_INDICES, TRUE);
+  _cogl_bitmask_set (&ctx->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE);
 
   gl_extensions = (const char *)ctx->glGetString (GL_EXTENSIONS);
 
@@ -175,6 +178,13 @@ _cogl_gl_update_features (CoglContext *context,
         | COGL_FEATURE_TEXTURE_NPOT_BASIC
         | COGL_FEATURE_TEXTURE_NPOT_MIPMAP
         | COGL_FEATURE_TEXTURE_NPOT_REPEAT;
+      _cogl_bitmask_set (&ctx->features, COGL_FEATURE_ID_TEXTURE_NPOT, TRUE);
+      _cogl_bitmask_set (&ctx->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE);
+      _cogl_bitmask_set (&ctx->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE);
+      _cogl_bitmask_set (&ctx->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, TRUE);
     }
 
   if (_cogl_check_extension ("GL_MESA_pack_invert", gl_extensions))
@@ -190,13 +200,20 @@ _cogl_gl_update_features (CoglContext *context,
     private_flags |= COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES;
 
   if (context->glGenRenderbuffers)
-    flags |= COGL_FEATURE_OFFSCREEN;
+    {
+      flags |= COGL_FEATURE_OFFSCREEN;
+      _cogl_bitmask_set (&ctx->features, COGL_FEATURE_ID_OFFSCREEN, TRUE);
+    }
 
   if (context->glBlitFramebuffer)
     private_flags |= COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT;
 
   if (context->glRenderbufferStorageMultisample)
-    flags |= COGL_FEATURE_OFFSCREEN_MULTISAMPLE;
+    {
+      flags |= COGL_FEATURE_OFFSCREEN_MULTISAMPLE;
+      _cogl_bitmask_set (&ctx->features,
+                         COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE, TRUE);
+    }
 
   if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 1) ||
       _cogl_check_extension ("GL_EXT_pixel_buffer_object", gl_extensions))
@@ -204,26 +221,46 @@ _cogl_gl_update_features (CoglContext *context,
 
   if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0) ||
       _cogl_check_extension ("GL_ARB_point_sprite", gl_extensions))
-    flags |= COGL_FEATURE_POINT_SPRITE;
+    {
+      flags |= COGL_FEATURE_POINT_SPRITE;
+      _cogl_bitmask_set (&ctx->features, COGL_FEATURE_ID_POINT_SPRITE, TRUE);
+    }
 
   if (context->glGenPrograms)
-    flags |= COGL_FEATURE_SHADERS_ARBFP;
+    {
+      flags |= COGL_FEATURE_SHADERS_ARBFP;
+      _cogl_bitmask_set (&ctx->features, COGL_FEATURE_ID_ARBFP, TRUE);
+    }
 
   if (context->glCreateProgram)
-    flags |= COGL_FEATURE_SHADERS_GLSL;
+    {
+      flags |= COGL_FEATURE_SHADERS_GLSL;
+      _cogl_bitmask_set (&ctx->features, COGL_FEATURE_ID_GLSL, TRUE);
+    }
 
   if (context->glGenBuffers)
     {
       private_flags |= COGL_PRIVATE_FEATURE_VBOS;
       flags |= (COGL_FEATURE_MAP_BUFFER_FOR_READ |
                 COGL_FEATURE_MAP_BUFFER_FOR_WRITE);
+      _cogl_bitmask_set (&ctx->features,
+                         COGL_FEATURE_ID_MAP_BUFFER_FOR_READ, TRUE);
+      _cogl_bitmask_set (&ctx->features,
+                         COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, TRUE);
     }
 
   if (_cogl_check_extension ("GL_ARB_texture_rectangle", gl_extensions))
-    flags |= COGL_FEATURE_TEXTURE_RECTANGLE;
+    {
+      flags |= COGL_FEATURE_TEXTURE_RECTANGLE;
+      _cogl_bitmask_set (&ctx->features,
+                         COGL_FEATURE_ID_TEXTURE_RECTANGLE, TRUE);
+    }
 
   if (context->glTexImage3D)
-    flags |= COGL_FEATURE_TEXTURE_3D;
+    {
+      flags |= COGL_FEATURE_TEXTURE_3D;
+      _cogl_bitmask_set (&ctx->features, COGL_FEATURE_ID_TEXTURE_3D, TRUE);
+    }
 
   if (context->glEGLImageTargetTexture2D)
     private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE;
diff --git a/cogl/driver/gl/cogl-texture-driver-gl.c b/cogl/driver/gl/cogl-texture-driver-gl.c
index f68a95d..6ab1b3e 100644
--- a/cogl/driver/gl/cogl-texture-driver-gl.c
+++ b/cogl/driver/gl/cogl-texture-driver-gl.c
@@ -101,7 +101,7 @@ prep_gl_for_pixels_upload_full (int pixels_rowstride,
   GE( ctx, glPixelStorei (GL_UNPACK_SKIP_PIXELS, pixels_src_x) );
   GE( ctx, glPixelStorei (GL_UNPACK_SKIP_ROWS, pixels_src_y) );
 
-  if (cogl_features_available (COGL_FEATURE_TEXTURE_3D))
+  if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D))
     GE( ctx, glPixelStorei (GL_UNPACK_IMAGE_HEIGHT, image_height) );
 
   _cogl_texture_prep_gl_alignment_for_pixels_upload (pixels_rowstride);
@@ -130,7 +130,7 @@ prep_gl_for_pixels_download_full (int pixels_rowstride,
   GE( ctx, glPixelStorei (GL_PACK_SKIP_PIXELS, pixels_src_x) );
   GE( ctx, glPixelStorei (GL_PACK_SKIP_ROWS, pixels_src_y) );
 
-  if (cogl_features_available (COGL_FEATURE_TEXTURE_3D))
+  if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_3D))
     GE( ctx, glPixelStorei (GL_PACK_IMAGE_HEIGHT, image_height) );
 
   _cogl_texture_prep_gl_alignment_for_pixels_download (pixels_rowstride);
diff --git a/cogl/driver/gles/cogl-gles.c b/cogl/driver/gles/cogl-gles.c
index 9b2f331..da969ac 100644
--- a/cogl/driver/gles/cogl-gles.c
+++ b/cogl/driver/gles/cogl-gles.c
@@ -89,36 +89,74 @@ _cogl_gles_update_features (CoglContext *context,
        * repeat modes other than CLAMP_TO_EDGE. */
       flags |= COGL_FEATURE_TEXTURE_NPOT_BASIC;
       flags |= COGL_FEATURE_DEPTH_RANGE;
+      _cogl_bitmask_set (&context->features, COGL_FEATURE_ID_GLSL, TRUE);
+      _cogl_bitmask_set (&context->features, COGL_FEATURE_ID_OFFSCREEN, TRUE);
+      _cogl_bitmask_set (&context->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE);
+      _cogl_bitmask_set (&context->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE);
     }
 
   private_flags |= COGL_PRIVATE_FEATURE_VBOS;
 
   /* Both GLES 1.1 and GLES 2.0 support point sprites in core */
   flags |= COGL_FEATURE_POINT_SPRITE;
+  _cogl_bitmask_set (&context->features, COGL_FEATURE_ID_POINT_SPRITE, TRUE);
 
   if (context->glGenRenderbuffers)
-    flags |= COGL_FEATURE_OFFSCREEN;
+    {
+      flags |= COGL_FEATURE_OFFSCREEN;
+      _cogl_bitmask_set (&context->features, COGL_FEATURE_ID_OFFSCREEN, TRUE);
+    }
 
   if (context->glBlitFramebuffer)
     private_flags |= COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT;
 
   if (_cogl_check_extension ("GL_OES_element_index_uint", gl_extensions))
-    flags |= COGL_FEATURE_UNSIGNED_INT_INDICES;
+    {
+      flags |= COGL_FEATURE_UNSIGNED_INT_INDICES;
+      _cogl_bitmask_set (&context->features,
+                         COGL_FEATURE_ID_UNSIGNED_INT_INDICES, TRUE);
+    }
 
-  if (_cogl_check_extension ("GL_OES_texture_npot", gl_extensions) ||
-      _cogl_check_extension ("GL_IMG_texture_npot", gl_extensions))
-    flags |= (COGL_FEATURE_TEXTURE_NPOT |
-              COGL_FEATURE_TEXTURE_NPOT_BASIC |
-              COGL_FEATURE_TEXTURE_NPOT_MIPMAP |
-              COGL_FEATURE_TEXTURE_NPOT_REPEAT);
+  if (_cogl_check_extension ("GL_OES_texture_npot", gl_extensions))
+    {
+      flags |= (COGL_FEATURE_TEXTURE_NPOT |
+                COGL_FEATURE_TEXTURE_NPOT_BASIC |
+                COGL_FEATURE_TEXTURE_NPOT_MIPMAP |
+                COGL_FEATURE_TEXTURE_NPOT_REPEAT);
+      _cogl_bitmask_set (&context->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT, TRUE);
+      _cogl_bitmask_set (&context->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE);
+      _cogl_bitmask_set (&context->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE);
+      _cogl_bitmask_set (&context->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT, TRUE);
+    }
+  else if (_cogl_check_extension ("GL_IMG_texture_npot", gl_extensions))
+    {
+      flags |= (COGL_FEATURE_TEXTURE_NPOT_BASIC |
+                COGL_FEATURE_TEXTURE_NPOT_MIPMAP);
+      _cogl_bitmask_set (&context->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE);
+      _cogl_bitmask_set (&context->features,
+                         COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP, TRUE);
+    }
 
   if (context->glTexImage3D)
-    flags |= COGL_FEATURE_TEXTURE_3D;
+    {
+      flags |= COGL_FEATURE_TEXTURE_3D;
+      _cogl_bitmask_set (&context->features, COGL_FEATURE_ID_TEXTURE_3D, TRUE);
+    }
 
   if (context->glMapBuffer)
-    /* The GL_OES_mapbuffer extension doesn't support mapping for
-       read */
-    flags |= COGL_FEATURE_MAP_BUFFER_FOR_WRITE;
+    {
+      /* The GL_OES_mapbuffer extension doesn't support mapping for
+         read */
+      flags |= COGL_FEATURE_MAP_BUFFER_FOR_WRITE;
+      _cogl_bitmask_set (&context->features,
+                         COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, TRUE);
+    }
 
   if (context->glEGLImageTargetTexture2D)
     private_flags |= COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE;
diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c
index 8c16c70..5bdbc01 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -533,6 +533,8 @@ update_winsys_features (CoglContext *context, GError **error)
 #if defined (COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT) || \
     defined (COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT)
   context->feature_flags |= COGL_FEATURE_ONSCREEN_MULTIPLE;
+  _cogl_bitmask_set (&context->features,
+                     COGL_FEATURE_ID_ONSCREEN_MULTIPLE, TRUE);
   COGL_FLAGS_SET (context->winsys_features,
                   COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
                   TRUE);
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index f2742ca..104120f 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -395,6 +395,8 @@ update_winsys_features (CoglContext *context, GError **error)
   COGL_NOTE (WINSYS, "  GLX Extensions: %s", glx_extensions);
 
   context->feature_flags |= COGL_FEATURE_ONSCREEN_MULTIPLE;
+  _cogl_bitmask_set (&context->features,
+                     COGL_FEATURE_ID_ONSCREEN_MULTIPLE, TRUE);
   COGL_FLAGS_SET (context->winsys_features,
                   COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
                   TRUE);
@@ -1604,7 +1606,7 @@ get_fbconfig_for_depth (CoglContext *context,
       stencil = value;
 
       /* glGenerateMipmap is defined in the offscreen extension */
-      if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
+      if (cogl_has_feature (context, COGL_FEATURE_ID_OFFSCREEN))
         {
           glx_renderer->glXGetFBConfigAttrib (dpy,
                                               fbconfigs[i],
@@ -1639,7 +1641,7 @@ should_use_rectangle (CoglContext *context)
 
   if (context->rectangle_state == COGL_WINSYS_RECTANGLE_STATE_UNKNOWN)
     {
-      if (cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE))
+      if (cogl_has_feature (context, COGL_FEATURE_ID_TEXTURE_RECTANGLE))
         {
           const char *rect_env;
 
@@ -1654,7 +1656,7 @@ should_use_rectangle (CoglContext *context)
              are not available */
 
           context->rectangle_state =
-            cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) ?
+            cogl_has_feature (context, COGL_FEATURE_ID_TEXTURE_NPOT) ?
             COGL_WINSYS_RECTANGLE_STATE_DISABLE :
             COGL_WINSYS_RECTANGLE_STATE_ENABLE;
 
diff --git a/cogl/winsys/cogl-winsys-wgl.c b/cogl/winsys/cogl-winsys-wgl.c
index 8306f27..ed13828 100644
--- a/cogl/winsys/cogl-winsys-wgl.c
+++ b/cogl/winsys/cogl-winsys-wgl.c
@@ -588,6 +588,8 @@ update_winsys_features (CoglContext *context, GError **error)
   memset (context->winsys_features, 0, sizeof (context->winsys_features));
 
   context->feature_flags |= COGL_FEATURE_ONSCREEN_MULTIPLE;
+  _cogl_bitmask_set (&context->features,
+                     COGL_FEATURE_ID_ONSCREEN_MULTIPLE, TRUE);
   COGL_FLAGS_SET (context->winsys_features,
                   COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
                   TRUE);
diff --git a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
index c3a9679..d97ddcc 100644
--- a/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
+++ b/doc/reference/cogl-2.0-experimental/cogl-2.0-experimental-sections.txt
@@ -77,6 +77,13 @@ cogl_context_new
 cogl_context_get_display
 
 <SUBSECTION>
+CoglFeatureID
+cogl_has_feature
+cogl_has_features
+CoglFeatureCallback
+cogl_foreach_feature
+
+<SUBSECTION>
 cogl_push_matrix
 cogl_pop_matrix
 cogl_scale



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]