From 7a7dedebd515c0064809719cdd3a7b8b9f0f1935 Mon Sep 17 00:00:00 2001
From: Emmanuele Bassi <ebassi@linux.intel.com>
Date: Wed, 26 May 2010 17:14:53 +0100
Subject: [PATCH] cogl-framebuffer: Use the FBO extension for color sizes

OpenGL 3.0 deprecated querying of the GL_{RED,GREEN,BLUE}_BITS
constants, and the FBO extension provides a mechanism to query for the
color buffer sizes which *should* work even with the default
framebuffer. Unfortunately, this doesn't seem to hold for Mesa - so we
just use this for the offscreen CoglFramebuffer type, and we fall back
to glGetIntegerv() for the onscreen one.

http://bugzilla.openedhand.com/show_bug.cgi?id=2094
---
 cogl/cogl-debug.c                         |  4 +-
 cogl/cogl-framebuffer.c                   | 78 +++++++++++++++++++++--
 cogl/driver/gl/cogl-feature-functions.h   |  5 ++
 cogl/driver/gles/cogl-feature-functions.h |  5 ++
 4 files changed, 87 insertions(+), 5 deletions(-)

diff --git a/cogl/cogl-debug.c b/cogl/cogl-debug.c
index 930491960..df985fa4b 100644
--- a/cogl/cogl-debug.c
+++ b/cogl/cogl-debug.c
@@ -50,7 +50,8 @@ static const GDebugKey cogl_log_debug_keys[] = {
   { "draw", COGL_DEBUG_DRAW },
   { "opengl", COGL_DEBUG_OPENGL },
   { "pango", COGL_DEBUG_PANGO },
-  { "show-source", COGL_DEBUG_SHOW_SOURCE}
+  { "show-source", COGL_DEBUG_SHOW_SOURCE},
+  { "offscreen", COGL_DEBUG_OFFSCREEN }
 };
 static const int n_cogl_log_debug_keys =
   G_N_ELEMENTS (cogl_log_debug_keys);
@@ -124,6 +125,7 @@ _cogl_parse_debug_string (const char *value,
       OPT ("disable-glsl:", "disable use of GLSL");
       OPT ("show-source:", "show generated ARBfp/GLSL");
       OPT ("opengl:", "traces some select OpenGL calls");
+      OPT ("offscreen:", "debug offscreen support");
       g_printerr ("\n%28s\n", "Special debug values:");
       OPT ("all:", "Enables all non-behavioural debug options");
       OPT ("verbose:", "Enables all non-behavioural debug options");
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 981b4a171..07b437c04 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -51,6 +51,8 @@
 #define glFramebufferRenderbuffer         ctx->drv.pf_glFramebufferRenderbuffer
 #define glCheckFramebufferStatus          ctx->drv.pf_glCheckFramebufferStatus
 #define glDeleteFramebuffers              ctx->drv.pf_glDeleteFramebuffers
+#define glGetFramebufferAttachmentParameteriv \
+                                          ctx->drv.pf_glGetFramebufferAttachmentParameteriv
 
 #endif
 
@@ -81,6 +83,24 @@
 #ifndef GL_DEPTH_COMPONENT16
 #define GL_DEPTH_COMPONENT16    0x81A5
 #endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE      0x8212
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE    0x8213
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE     0x8214
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE    0x8215
+#endif
+#ifndef GL_FRAMEBUFFER_ATTCHMENT_DEPTH_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE    0x8216
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE  0x8217
+#endif
 
 typedef enum {
   _TRY_DEPTH_STENCIL = 1L<<0,
@@ -253,13 +273,63 @@ _cogl_framebuffer_get_projection_stack (CoglHandle handle)
 static inline void
 _cogl_framebuffer_init_bits (CoglFramebuffer *framebuffer)
 {
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
   if (G_LIKELY (!framebuffer->dirty_bitmasks))
     return;
 
-  GE( glGetIntegerv (GL_RED_BITS,   &framebuffer->red_bits)   );
-  GE( glGetIntegerv (GL_GREEN_BITS, &framebuffer->green_bits) );
-  GE( glGetIntegerv (GL_BLUE_BITS,  &framebuffer->blue_bits)  );
-  GE( glGetIntegerv (GL_ALPHA_BITS, &framebuffer->alpha_bits) );
+#ifdef HAVE_COGL_GL
+  if (cogl_features_available (COGL_FEATURE_OFFSCREEN)
+      && framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
+    {
+      GLenum attachment, pname;
+
+      attachment = GL_COLOR_ATTACHMENT0;
+
+      pname = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
+      GE( glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
+                                                 attachment,
+                                                 pname,
+                                                 &framebuffer->red_bits) );
+
+      pname = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
+      GE( glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
+                                                 attachment,
+                                                 pname,
+                                                 &framebuffer->green_bits) );
+
+      pname = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
+      GE( glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
+                                                 attachment,
+                                                 pname,
+                                                 &framebuffer->blue_bits) );
+
+      pname = GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE;
+      GE( glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
+                                                 attachment,
+                                                 pname,
+                                                 &framebuffer->alpha_bits) );
+    }
+  else
+#endif /* HAVE_COGL_GL */
+    {
+      GE( glGetIntegerv (GL_RED_BITS,   &framebuffer->red_bits)   );
+      GE( glGetIntegerv (GL_GREEN_BITS, &framebuffer->green_bits) );
+      GE( glGetIntegerv (GL_BLUE_BITS,  &framebuffer->blue_bits)  );
+      GE( glGetIntegerv (GL_ALPHA_BITS, &framebuffer->alpha_bits) );
+    }
+
+
+  COGL_NOTE (OFFSCREEN,
+             "RGBA Bits for framebuffer[%p, %s]: %d, %d, %d, %d",
+             framebuffer,
+             framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN
+               ? "offscreen"
+               : "onscreen",
+             framebuffer->red_bits,
+             framebuffer->blue_bits,
+             framebuffer->green_bits,
+             framebuffer->alpha_bits);
 
   framebuffer->dirty_bitmasks = FALSE;
 }
diff --git a/cogl/driver/gl/cogl-feature-functions.h b/cogl/driver/gl/cogl-feature-functions.h
index d26c6472f..a6a82d39c 100644
--- a/cogl/driver/gl/cogl-feature-functions.h
+++ b/cogl/driver/gl/cogl-feature-functions.h
@@ -70,6 +70,11 @@ COGL_FEATURE_FUNCTION (void, glDeleteFramebuffers,
                         const                 GLuint *framebuffers))
 COGL_FEATURE_FUNCTION (void, glGenerateMipmap,
                        (GLenum                target))
+COGL_FEATURE_FUNCTION (void, glGetFramebufferAttachmentParameteriv,
+                       (GLenum                target,
+                        GLenum                attachment,
+                        GLenum                pname,
+                        GLint                *params))
 COGL_FEATURE_END ()
 
 COGL_FEATURE_BEGIN (offscreen_blit, 255, 255,
diff --git a/cogl/driver/gles/cogl-feature-functions.h b/cogl/driver/gles/cogl-feature-functions.h
index de6a24c19..8aba5af34 100644
--- a/cogl/driver/gles/cogl-feature-functions.h
+++ b/cogl/driver/gles/cogl-feature-functions.h
@@ -67,6 +67,11 @@ COGL_FEATURE_FUNCTION (void, glDeleteFramebuffers,
                         const                 GLuint *framebuffers))
 COGL_FEATURE_FUNCTION (void, glGenerateMipmap,
                        (GLenum                target))
+COGL_FEATURE_FUNCTION (void, glGetFramebufferAttachmentParameteriv,
+                       (GLenum                target,
+                        GLenum                attachment,
+                        GLenum                pname,
+                        GLint                *params))
 COGL_FEATURE_END ()
 
 COGL_FEATURE_BEGIN (element_index_uint, 255, 255,