[cogl] framebuffer: Support texture based depth buffers



commit 32cc59ad2b152e07969e020d84176ff49e83f1c6
Author: Damien Lespiau <damien lespiau intel com>
Date:   Wed May 23 18:19:29 2012 +0100

    framebuffer: Support texture based depth buffers
    
    This commit introduces some new framebuffer api to be able to
    enable texture based depth buffers for a framebuffer (currently
    only supported for offscreen framebuffers) and once allocated
    to be able to retrieve the depth buffer as a texture for further
    usage, say, to implement shadow mapping.
    
    The API works as follow:
      * Before the framebuffer is allocated, you can request that a depth
        texture is created with
        cogl_framebuffer_set_depth_texture_enabled()
      * cogl_framebuffer_get_depth_texture() can then be used to grab a
        CoglTexture once the framebuffer has been allocated.

 cogl/cogl-bitmap-conversion.c   |    3 +
 cogl/cogl-bitmap-packing.h      |    6 ++
 cogl/cogl-context.h             |    4 +-
 cogl/cogl-framebuffer-private.h |    4 +
 cogl/cogl-framebuffer.c         |  170 +++++++++++++++++++++++++++++++++++++--
 cogl/cogl-framebuffer.h         |   56 +++++++++++++
 cogl/cogl-gles2-context.c       |    1 +
 cogl/cogl-types.h               |   26 +++++--
 cogl/driver/gl/cogl-gl.c        |   24 ++++++
 cogl/driver/gles/cogl-gles.c    |   30 +++++++
 examples/cogl-info.c            |    6 ++
 11 files changed, 315 insertions(+), 15 deletions(-)
---
diff --git a/cogl/cogl-bitmap-conversion.c b/cogl/cogl-bitmap-conversion.c
index 17b26e6..ca611ee 100644
--- a/cogl/cogl-bitmap-conversion.c
+++ b/cogl/cogl-bitmap-conversion.c
@@ -306,6 +306,9 @@ _cogl_bitmap_needs_short_temp_buffer (CoglPixelFormat format)
      floats */
   switch (format)
     {
+    case COGL_PIXEL_FORMAT_DEPTH_16:
+    case COGL_PIXEL_FORMAT_DEPTH_32:
+    case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8:
     case COGL_PIXEL_FORMAT_ANY:
     case COGL_PIXEL_FORMAT_YUV:
       g_assert_not_reached ();
diff --git a/cogl/cogl-bitmap-packing.h b/cogl/cogl-bitmap-packing.h
index f84af02..d2fc4fb 100644
--- a/cogl/cogl-bitmap-packing.h
+++ b/cogl/cogl-bitmap-packing.h
@@ -370,6 +370,9 @@ G_PASTE (_cogl_unpack_, component_type) (CoglPixelFormat format,
     case COGL_PIXEL_FORMAT_ABGR_2101010_PRE:
       G_PASTE (_cogl_unpack_abgr_2101010_, component_type) (src, dst, width);
       break;
+    case COGL_PIXEL_FORMAT_DEPTH_16:
+    case COGL_PIXEL_FORMAT_DEPTH_32:
+    case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8:
     case COGL_PIXEL_FORMAT_ANY:
     case COGL_PIXEL_FORMAT_YUV:
       g_assert_not_reached ();
@@ -711,6 +714,9 @@ G_PASTE (_cogl_pack_, component_type) (CoglPixelFormat format,
     case COGL_PIXEL_FORMAT_ABGR_2101010_PRE:
       G_PASTE (_cogl_pack_abgr_2101010_, component_type) (src, dst, width);
       break;
+    case COGL_PIXEL_FORMAT_DEPTH_16:
+    case COGL_PIXEL_FORMAT_DEPTH_32:
+    case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8:
     case COGL_PIXEL_FORMAT_ANY:
     case COGL_PIXEL_FORMAT_YUV:
       g_assert_not_reached ();
diff --git a/cogl/cogl-context.h b/cogl/cogl-context.h
index 980636b..78c9f8f 100644
--- a/cogl/cogl-context.h
+++ b/cogl/cogl-context.h
@@ -183,7 +183,8 @@ cogl_is_context (void *object);
  *     for swap buffer completions.
  * @COGL_FEATURE_ID_GLES2_CONTEXT: Whether creating new GLES2 contexts is
  *    suported.
- *
+ * @COGL_FEATURE_ID_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering
+ *     the depth buffer to a texture.
  *
  * All the capabilities that can vary between different GPUs supported
  * by Cogl. Applications that depend on any of these features should explicitly
@@ -212,6 +213,7 @@ typedef enum _CoglFeatureID
   COGL_FEATURE_ID_MIRRORED_REPEAT,
   COGL_FEATURE_ID_SWAP_BUFFERS_EVENT,
   COGL_FEATURE_ID_GLES2_CONTEXT,
+  COGL_FEATURE_ID_DEPTH_TEXTURE,
 
   /*< private > */
   _COGL_N_FEATURE_IDS
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index fe3fe25..a13f2b9 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -53,6 +53,7 @@ typedef struct
   CoglBool need_stencil;
   int samples_per_pixel;
   CoglBool swap_throttled;
+  CoglBool depth_texture_enabled;
 } CoglFramebufferConfig;
 
 /* Flags to pass to _cogl_offscreen_new_to_texture_full */
@@ -190,6 +191,8 @@ struct _CoglOffscreen
   int             texture_level_width;
   int             texture_level_height;
 
+  CoglTexture *depth_texture;
+
   CoglOffscreenAllocateFlags allocation_flags;
 
   /* FIXME: _cogl_offscreen_new_to_texture_full should be made to use
@@ -421,6 +424,7 @@ _cogl_framebuffer_try_creating_gl_fbo (CoglContext *ctx,
                                        int texture_level,
                                        int texture_level_width,
                                        int texture_level_height,
+                                       CoglTexture *depth_texture,
                                        CoglFramebufferConfig *config,
                                        CoglOffscreenAllocateFlags flags,
                                        CoglGLFramebuffer *gl_framebuffer);
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 53bd139..6aeb99b 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -818,9 +818,83 @@ _cogl_offscreen_free (CoglOffscreen *offscreen)
   if (offscreen->texture != NULL)
     cogl_object_unref (offscreen->texture);
 
+  if (offscreen->depth_texture != NULL)
+    cogl_object_unref (offscreen->depth_texture);
+
   g_free (offscreen);
 }
 
+static CoglTexture *
+create_depth_texture (CoglContext *ctx,
+                      int width,
+                      int height)
+{
+  CoglPixelFormat format;
+  CoglTexture2D *depth_texture;
+
+  if (ctx->private_feature_flags &
+      (COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL |
+       COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL))
+    {
+      format = COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8;
+    }
+  else
+    format = COGL_PIXEL_FORMAT_DEPTH_16;
+
+  depth_texture =  cogl_texture_2d_new_with_size (ctx,
+                                                  width, height,
+                                                  format,
+                                                  NULL);
+
+  return COGL_TEXTURE (depth_texture);
+}
+
+static CoglTexture *
+attach_depth_texture (CoglContext *ctx,
+                       CoglTexture *depth_texture,
+                       CoglOffscreenAllocateFlags flags)
+{
+  GLuint tex_gl_handle;
+  GLenum tex_gl_target;
+
+  if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL)
+    {
+      /* attach a GL_DEPTH_STENCIL texture to the GL_DEPTH_ATTACHMENT and
+       * GL_STENCIL_ATTACHMENT attachement points */
+      g_assert (cogl_texture_get_format (depth_texture) ==
+                COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8);
+
+      cogl_texture_get_gl_texture (depth_texture,
+                                   &tex_gl_handle, &tex_gl_target);
+
+      GE (ctx, glFramebufferTexture2D (GL_FRAMEBUFFER,
+                                       GL_DEPTH_ATTACHMENT,
+                                       tex_gl_target, tex_gl_handle,
+                                       0));
+      GE (ctx, glFramebufferTexture2D (GL_FRAMEBUFFER,
+                                       GL_STENCIL_ATTACHMENT,
+                                       tex_gl_target, tex_gl_handle,
+                                       0));
+    }
+  else if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH)
+    {
+      /* attach a newly created GL_DEPTH_COMPONENT16 texture to the
+       * GL_DEPTH_ATTACHMENT attachement point */
+      g_assert (cogl_texture_get_format (depth_texture) ==
+                COGL_PIXEL_FORMAT_DEPTH_16);
+
+      cogl_texture_get_gl_texture (COGL_TEXTURE (depth_texture),
+                                   &tex_gl_handle, &tex_gl_target);
+
+      GE (ctx, glFramebufferTexture2D (GL_FRAMEBUFFER,
+                                       GL_DEPTH_ATTACHMENT,
+                                       tex_gl_target, tex_gl_handle,
+                                       0));
+    }
+
+  return COGL_TEXTURE (depth_texture);
+}
+
 static GList *
 try_creating_renderbuffers (CoglContext *ctx,
                             int width,
@@ -938,6 +1012,7 @@ try_creating_fbo (CoglContext *ctx,
                   int texture_level,
                   int texture_level_width,
                   int texture_level_height,
+                  CoglTexture *depth_texture,
                   CoglFramebufferConfig *config,
                   CoglOffscreenAllocateFlags flags,
                   CoglGLFramebuffer *gl_framebuffer)
@@ -988,12 +1063,31 @@ try_creating_fbo (CoglContext *ctx,
                                      tex_gl_target, tex_gl_handle,
                                      texture_level));
 
-  gl_framebuffer->renderbuffers =
-    try_creating_renderbuffers (ctx,
-                                texture_level_width,
-                                texture_level_height,
-                                flags,
-                                n_samples);
+  /* attach either a depth/stencil texture, a depth texture or render buffers
+   * depending on what we've been asked to provide */
+
+  if (depth_texture &&
+      flags & (COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL |
+               COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH))
+    {
+      attach_depth_texture (ctx, depth_texture, flags);
+
+      /* Let's clear the flags that are now fulfilled as we might need to
+       * create renderbuffers (for the ALLOCATE_FLAG_DEPTH |
+       * ALLOCATE_FLAG_STENCIL case) */
+      flags &= ~(COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL |
+                 COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH);
+    }
+
+  if (flags)
+    {
+      gl_framebuffer->renderbuffers =
+        try_creating_renderbuffers (ctx,
+                                    texture_level_width,
+                                    texture_level_height,
+                                    flags,
+                                    n_samples);
+    }
 
   /* Make sure it's complete */
   status = ctx->glCheckFramebufferStatus (GL_FRAMEBUFFER);
@@ -1032,6 +1126,7 @@ _cogl_framebuffer_try_creating_gl_fbo (CoglContext *ctx,
                                        int texture_level,
                                        int texture_level_width,
                                        int texture_level_height,
+                                       CoglTexture *depth_texture,
                                        CoglFramebufferConfig *config,
                                        CoglOffscreenAllocateFlags flags,
                                        CoglGLFramebuffer *gl_framebuffer)
@@ -1041,6 +1136,7 @@ _cogl_framebuffer_try_creating_gl_fbo (CoglContext *ctx,
                            texture_level,
                            texture_level_width,
                            texture_level_height,
+                           depth_texture,
                            config,
                            flags,
                            gl_framebuffer);
@@ -1055,6 +1151,24 @@ _cogl_offscreen_allocate (CoglOffscreen *offscreen,
   CoglOffscreenAllocateFlags flags;
   CoglGLFramebuffer *gl_framebuffer = &offscreen->gl_framebuffer;
 
+  if (fb->config.depth_texture_enabled &&
+      offscreen->depth_texture == NULL)
+    {
+      offscreen->depth_texture =
+        create_depth_texture (ctx,
+                              offscreen->texture_level_width,
+                              offscreen->texture_level_height);
+
+      if (offscreen->depth_texture)
+        _cogl_texture_associate_framebuffer (offscreen->depth_texture, fb);
+      else
+        {
+          _cogl_set_error (error, COGL_FRAMEBUFFER_ERROR,
+                           COGL_FRAMEBUFFER_ERROR_ALLOCATE,
+                           "Failed to allocate depth texture for framebuffer");
+        }
+    }
+
   /* XXX: The framebuffer_object spec isn't clear in defining whether attaching
    * a texture as a renderbuffer with mipmap filtering enabled while the
    * mipmaps have not been uploaded should result in an incomplete framebuffer
@@ -1073,6 +1187,7 @@ _cogl_offscreen_allocate (CoglOffscreen *offscreen,
                          offscreen->texture_level,
                          offscreen->texture_level_width,
                          offscreen->texture_level_height,
+                         offscreen->depth_texture,
                          &fb->config,
                          flags = 0,
                          gl_framebuffer)) ||
@@ -1083,6 +1198,7 @@ _cogl_offscreen_allocate (CoglOffscreen *offscreen,
                          offscreen->texture_level,
                          offscreen->texture_level_width,
                          offscreen->texture_level_height,
+                         offscreen->depth_texture,
                          &fb->config,
                          flags = ctx->last_offscreen_allocate_flags,
                          gl_framebuffer)) ||
@@ -1095,6 +1211,7 @@ _cogl_offscreen_allocate (CoglOffscreen *offscreen,
                          offscreen->texture_level,
                          offscreen->texture_level_width,
                          offscreen->texture_level_height,
+                         offscreen->depth_texture,
                          &fb->config,
                          flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL,
                          gl_framebuffer)) ||
@@ -1104,6 +1221,7 @@ _cogl_offscreen_allocate (CoglOffscreen *offscreen,
                         offscreen->texture_level,
                         offscreen->texture_level_width,
                         offscreen->texture_level_height,
+                        offscreen->depth_texture,
                         &fb->config,
                         flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH |
                         COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL,
@@ -1114,6 +1232,7 @@ _cogl_offscreen_allocate (CoglOffscreen *offscreen,
                         offscreen->texture_level,
                         offscreen->texture_level_width,
                         offscreen->texture_level_height,
+                        offscreen->depth_texture,
                         &fb->config,
                         flags = COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL,
                         gl_framebuffer) ||
@@ -1123,6 +1242,7 @@ _cogl_offscreen_allocate (CoglOffscreen *offscreen,
                         offscreen->texture_level,
                         offscreen->texture_level_width,
                         offscreen->texture_level_height,
+                        offscreen->depth_texture,
                         &fb->config,
                         flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH,
                         gl_framebuffer) ||
@@ -1132,6 +1252,7 @@ _cogl_offscreen_allocate (CoglOffscreen *offscreen,
                         offscreen->texture_level,
                         offscreen->texture_level_width,
                         offscreen->texture_level_height,
+                        offscreen->depth_texture,
                         &fb->config,
                         flags = 0,
                         gl_framebuffer))
@@ -1146,7 +1267,7 @@ _cogl_offscreen_allocate (CoglOffscreen *offscreen,
           ctx->have_last_offscreen_allocate_flags = TRUE;
         }
 
-      /* Save the flags we managed so successfully allocate the
+      /* Save the flags we managed to successfully allocate the
        * renderbuffers with in case we need to make renderbuffers for a
        * GLES2 context later */
       offscreen->allocation_flags = flags;
@@ -1174,6 +1295,15 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
 
   if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
     {
+      if (framebuffer->config.depth_texture_enabled)
+        {
+          _cogl_set_error (error, COGL_FRAMEBUFFER_ERROR,
+                           COGL_FRAMEBUFFER_ERROR_ALLOCATE,
+                           "Can't allocate onscreen framebuffer with a "
+                           "texture based depth buffer");
+          return FALSE;
+        }
+
       if (!winsys->onscreen_init (onscreen, error))
         return FALSE;
     }
@@ -1914,6 +2044,32 @@ cogl_framebuffer_get_color_format (CoglFramebuffer *framebuffer)
   return framebuffer->format;
 }
 
+void
+cogl_framebuffer_set_depth_texture_enabled (CoglFramebuffer *framebuffer,
+                                            CoglBool enabled)
+{
+  _COGL_RETURN_IF_FAIL (!framebuffer->allocated);
+
+  framebuffer->config.depth_texture_enabled = enabled;
+}
+
+CoglBool
+cogl_framebuffer_get_depth_texture_enabled (CoglFramebuffer *framebuffer)
+{
+  return framebuffer->config.depth_texture_enabled;
+}
+
+CoglTexture *
+cogl_framebuffer_get_depth_texture (CoglFramebuffer *framebuffer)
+{
+  /* lazily allocate the framebuffer... */
+  if (!cogl_framebuffer_allocate (framebuffer, NULL))
+    return NULL;
+
+  _COGL_RETURN_VAL_IF_FAIL (cogl_is_offscreen (framebuffer), NULL);
+  return COGL_OFFSCREEN(framebuffer)->depth_texture;
+}
+
 int
 cogl_framebuffer_get_samples_per_pixel (CoglFramebuffer *framebuffer)
 {
diff --git a/cogl/cogl-framebuffer.h b/cogl/cogl-framebuffer.h
index 1ea2aee..a38a2a3 100644
--- a/cogl/cogl-framebuffer.h
+++ b/cogl/cogl-framebuffer.h
@@ -800,6 +800,62 @@ CoglPixelFormat
 cogl_framebuffer_get_color_format (CoglFramebuffer *framebuffer);
 
 /**
+ * cogl_framebuffer_set_depth_texture_enabled:
+ * @framebuffer: A #CoglFramebuffer
+ * @enabled: TRUE or FALSE
+ *
+ * If @enabled is #TRUE, the depth buffer used when rendering to @framebuffer
+ * is available as a texture. You can retrieve the texture with
+ * cogl_framebuffer_get_depth_texture().
+ *
+ * <note>It's possible that your GPU does not support depth textures. You
+ * should check the %COGL_FEATURE_ID_DEPTH_TEXTURE feature before using this
+ * function.</note>
+ * <note>It's not valid to call this function after the framebuffer has been
+ * allocated as the creation of the depth texture is done at allocation time.
+ * </note>
+ *
+ * Since: 2.0
+ */
+void
+cogl_framebuffer_set_depth_texture_enabled (CoglFramebuffer *framebuffer,
+                                            CoglBool enabled);
+
+/**
+ * cogl_framebuffer_get_depth_texture_enabled:
+ * @framebuffer: A #CoglFramebuffer
+ *
+ * Queries whether texture based depth buffer has been enabled via
+ * cogl_framebuffer_set_depth_texture_enabled().
+ *
+ * Return value: %TRUE if a depth texture has been enabled, else
+ *               %FALSE.
+ *
+ * Since: 2.0
+ */
+CoglBool
+cogl_framebuffer_get_depth_texture_enabled (CoglFramebuffer *framebuffer);
+
+/**
+ * cogl_framebuffer_get_depth_texture:
+ * @framebuffer: A #CoglFramebuffer
+ *
+ * Retrieves the depth buffer of @framebuffer as a #CoglTexture. You need to
+ * call cogl_framebuffer_get_depth_texture(fb, TRUE); before using this
+ * function.
+ *
+ * <note>Calling this function implicitely allocates the framebuffer.</note>
+ * <note>The texture returned stays valid as long as the framebuffer stays
+ * valid.</note>
+ *
+ * Returns: (transfer none): the depth texture
+ *
+ * Since: 2.0
+ */
+CoglTexture *
+cogl_framebuffer_get_depth_texture (CoglFramebuffer *framebuffer);
+
+/**
  * cogl_framebuffer_set_samples_per_pixel:
  * @framebuffer: A #CoglFramebuffer framebuffer
  * @samples_per_pixel: The minimum number of samples per pixel
diff --git a/cogl/cogl-gles2-context.c b/cogl/cogl-gles2-context.c
index cf8e921..37743b6 100644
--- a/cogl/cogl-gles2-context.c
+++ b/cogl/cogl-gles2-context.c
@@ -1757,6 +1757,7 @@ _cogl_gles2_offscreen_allocate (CoglOffscreen *offscreen,
                                               offscreen->texture_level,
                                               offscreen->texture_level_width,
                                               offscreen->texture_level_height,
+                                              offscreen->depth_texture,
                                               &COGL_FRAMEBUFFER (offscreen)->config,
                                               offscreen->allocation_flags,
                                               &gles2_offscreen->gl_framebuffer))
diff --git a/cogl/cogl-types.h b/cogl/cogl-types.h
index 44a13c2..389d8d3 100644
--- a/cogl/cogl-types.h
+++ b/cogl/cogl-types.h
@@ -154,18 +154,22 @@ typedef struct _CoglTextureVertex       CoglTextureVertex;
 #define COGL_BGR_BIT            (1 << 5)
 #define COGL_AFIRST_BIT         (1 << 6)
 #define COGL_PREMULT_BIT        (1 << 7)
+#define COGL_DEPTH_BIT          (1 << 8)
+#define COGL_STENCIL_BIT        (1 << 9)
 
 /* XXX: Notes to those adding new formats here...
  *
  * First this diagram outlines how we allocate the 32bits of a
  * CoglPixelFormat currently...
  *
- *                             4 bits for flags
- *                             |--|
+ *                            6 bits for flags
+ *                          |-----|
  *  enum        unused             4 bits for the bytes-per-pixel
  *                                 and component alignment info
- *  |------| |---------------|     |--|
- *  00000000 xxxxxxxx xxxxxxxx PFBA0000
+ *  |------| |-------------|       |--|
+ *  00000000 xxxxxxxx xxxxxxSD PFBA0000
+ *                          ^ stencil
+ *                           ^ depth
  *                             ^ premult
  *                              ^ alpha first
  *                               ^ bgr order
@@ -187,7 +191,7 @@ typedef struct _CoglTextureVertex       CoglTextureVertex;
  * 4-6   = 2 bpp, not aligned (e.g. 565, 4444, 5551)
  * 7     = YUV: undefined bpp, undefined alignment
  * 9     = 2 bpp, aligned
- * 10    = undefined
+ * 10    = depth, aligned (8, 16, 24, 32, 32f)
  * 11    = undefined
  * 12    = 3 bpp, not aligned
  * 13    = 4 bpp, not aligned (e.g. 2101010)
@@ -305,7 +309,12 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
   COGL_PIXEL_FORMAT_RGBA_1010102_PRE = (COGL_PIXEL_FORMAT_RGBA_1010102 | COGL_PREMULT_BIT),
   COGL_PIXEL_FORMAT_BGRA_1010102_PRE = (COGL_PIXEL_FORMAT_BGRA_1010102 | COGL_PREMULT_BIT),
   COGL_PIXEL_FORMAT_ARGB_2101010_PRE = (COGL_PIXEL_FORMAT_ARGB_2101010 | COGL_PREMULT_BIT),
-  COGL_PIXEL_FORMAT_ABGR_2101010_PRE = (COGL_PIXEL_FORMAT_ABGR_2101010 | COGL_PREMULT_BIT)
+  COGL_PIXEL_FORMAT_ABGR_2101010_PRE = (COGL_PIXEL_FORMAT_ABGR_2101010 | COGL_PREMULT_BIT),
+
+  COGL_PIXEL_FORMAT_DEPTH_16  = (9 | COGL_DEPTH_BIT),
+  COGL_PIXEL_FORMAT_DEPTH_32  = (3 | COGL_DEPTH_BIT),
+
+  COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8 = (3 | COGL_DEPTH_BIT | COGL_STENCIL_BIT)
 } CoglPixelFormat;
 
 /**
@@ -348,6 +357,8 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
  *     supported with CoglBufferAccess including read support.
  * @COGL_FEATURE_MAP_BUFFER_FOR_WRITE: Whether cogl_buffer_map() is
  *     supported with CoglBufferAccess including write support.
+ * @COGL_FEATURE_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering the
+ *     depth buffer to a texture.
  *
  * Flags for the supported features.
  *
@@ -377,7 +388,8 @@ typedef enum
   COGL_FEATURE_SHADERS_ARBFP          = (1 << 20),
   COGL_FEATURE_MAP_BUFFER_FOR_READ    = (1 << 21),
   COGL_FEATURE_MAP_BUFFER_FOR_WRITE   = (1 << 22),
-  COGL_FEATURE_ONSCREEN_MULTIPLE      = (1 << 23)
+  COGL_FEATURE_ONSCREEN_MULTIPLE      = (1 << 23),
+  COGL_FEATURE_DEPTH_TEXTURE          = (1 << 24)
 } CoglFeatureFlags;
 
 /**
diff --git a/cogl/driver/gl/cogl-gl.c b/cogl/driver/gl/cogl-gl.c
index fbe9e6d..8778f24 100644
--- a/cogl/driver/gl/cogl-gl.c
+++ b/cogl/driver/gl/cogl-gl.c
@@ -200,6 +200,23 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
       gltype = GL_UNSIGNED_SHORT_5_5_5_1;
       break;
 
+    case COGL_PIXEL_FORMAT_DEPTH_16:
+      glintformat = GL_DEPTH_COMPONENT16;
+      glformat = GL_DEPTH_COMPONENT;
+      gltype = GL_UNSIGNED_SHORT;
+      break;
+    case COGL_PIXEL_FORMAT_DEPTH_32:
+      glintformat = GL_DEPTH_COMPONENT32;
+      glformat = GL_DEPTH_COMPONENT;
+      gltype = GL_UNSIGNED_INT;
+      break;
+
+    case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8:
+      glintformat = GL_DEPTH_STENCIL;
+      glformat = GL_DEPTH_STENCIL;
+      gltype = GL_UNSIGNED_INT_24_8;
+      break;
+
     case COGL_PIXEL_FORMAT_ANY:
     case COGL_PIXEL_FORMAT_YUV:
       g_assert_not_reached ();
@@ -404,6 +421,13 @@ _cogl_driver_update_features (CoglContext *ctx,
                       COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE, TRUE);
     }
 
+  if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 3, 0) ||
+      _cogl_check_extension ("GL_ARB_depth_texture", gl_extensions))
+    {
+      flags |= COGL_FEATURE_DEPTH_TEXTURE;
+      COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_DEPTH_TEXTURE, TRUE);
+    }
+
   if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 1) ||
       _cogl_check_extension ("GL_EXT_pixel_buffer_object", gl_extensions))
     private_flags |= COGL_PRIVATE_FEATURE_PBOS;
diff --git a/cogl/driver/gles/cogl-gles.c b/cogl/driver/gles/cogl-gles.c
index da47e0b..fa6aae4 100644
--- a/cogl/driver/gles/cogl-gles.c
+++ b/cogl/driver/gles/cogl-gles.c
@@ -33,6 +33,13 @@
 #include "cogl-renderer-private.h"
 #include "cogl-private.h"
 
+#ifndef GL_UNSIGNED_INT_24_8
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#endif
+#ifndef GL_DEPTH_STENCIL
+#define GL_DEPTH_STENCIL 0x84F9
+#endif
+
 static CoglBool
 _cogl_driver_pixel_format_from_gl_internal (CoglContext *context,
                                             GLenum gl_int_format,
@@ -137,6 +144,23 @@ _cogl_driver_pixel_format_to_gl (CoglContext *context,
       gltype = GL_UNSIGNED_SHORT_5_5_5_1;
       break;
 
+    case COGL_PIXEL_FORMAT_DEPTH_16:
+      glintformat = GL_DEPTH_COMPONENT;
+      glformat = GL_DEPTH_COMPONENT;
+      gltype = GL_UNSIGNED_SHORT;
+      break;
+    case COGL_PIXEL_FORMAT_DEPTH_32:
+      glintformat = GL_DEPTH_COMPONENT;
+      glformat = GL_DEPTH_COMPONENT;
+      gltype = GL_UNSIGNED_INT;
+      break;
+
+    case COGL_PIXEL_FORMAT_DEPTH_24_STENCIL_8:
+      glintformat = GL_DEPTH_STENCIL;
+      glformat = GL_DEPTH_STENCIL;
+      gltype = GL_UNSIGNED_INT_24_8;
+      break;
+
     case COGL_PIXEL_FORMAT_ANY:
     case COGL_PIXEL_FORMAT_YUV:
       g_assert_not_reached ();
@@ -247,6 +271,12 @@ _cogl_driver_update_features (CoglContext *context,
                       COGL_FEATURE_ID_UNSIGNED_INT_INDICES, TRUE);
     }
 
+  if (_cogl_check_extension ("GL_OES_depth_texture", gl_extensions))
+    {
+      flags |= COGL_FEATURE_DEPTH_TEXTURE;
+      COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_TEXTURE, TRUE);
+    }
+
   if (_cogl_check_extension ("GL_OES_texture_npot", gl_extensions))
     {
       flags |= (COGL_FEATURE_TEXTURE_NPOT |
diff --git a/examples/cogl-info.c b/examples/cogl-info.c
index c576dbb..3eacdc3 100644
--- a/examples/cogl-info.c
+++ b/examples/cogl-info.c
@@ -109,6 +109,12 @@ struct {
     "GLES2 API integration supported",
     "Support for creating a GLES2 context for using the GLES2 API in a "
       "way that's integrated with Cogl."
+  },
+  {
+    COGL_FEATURE_ID_DEPTH_TEXTURE,
+    "Depth Textures",
+    "CoglFramebuffers can be configured to render their depth buffer into "
+    "a texture"
   }
 };
 



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