Repository: glium/glium (language: rust)

Issue:
Error with GtkGlArea
Hi!

I'm trying to use Glium with a GtkGlArea, and all goes more or less ok, just a "glium has triggered an OpenGL error during initialization. Please report this error" warning, that I ignored, until I tried to use a depth buffer, then I get a `NoDepthBuffer` error.

Debugging the initialization of the context I found that the error is in capabilities checking for `depth_bits` [here](https://github.com/glium/glium/blob/master/src/context/capabilities.rs#L331), that triggers a `GL_INVALID_ENUM`:
```
let mut ty = 0;
gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::DEPTH,
    gl::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
    &mut ty);
```
According to the [GL docs](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glGetFramebufferAttachmentParameter.xhtml):
> If the specified framebuffer is a framebuffer object, attachment must be one of GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT GL_DEPTH_STENCIL_ATTACHMENT, or GL_COLOR_ATTACHMENTi, [...].
> If the specified framebuffer is a default framebuffer, target, attachment must be one of GL_FRONT_LEFT, GL_FRONT_RIGHT, GL_BACK_LEFT, GL_BACK_RIGHT, GL_DEPTH or GL_STENCIL, [...].

I think that this is the issue here, Glium assumes that `gl::FRAMEBUFFER` will always be the default framebuffer, so it applies the second paragraph. But GtkGlArea uses a FBO to do some kind of render-to-texture-to-cairo [dance](https://code.woboq.org/gtk/gtk/gtk/gtkglarea.c.html#gtk_gl_area_attach_buffers), so it needs to apply the first one.

The solution I found is to call `glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING)` first, and depending on whether this returns 0 or not, use `GL_DEPTH` or `GL_DEPTH_ATTACHMENT`.
```
--- a/src/context/capabilities.rs
+++ b/src/context/capabilities.rs
@ -327,15 +330,18 @@ pub unsafe fn get_capabilities(gl: &gl::Gl, version: &Version, extensions: &Exte
             // doesn't even though it provides this extension. I'm not sure whether this is a bug
             // with OS/X or just the extension actually not providing it.
             if version >= &Version(Api::Gl, 3, 0) && !extensions.gl_arb_compatibility {
+                let mut fb = 0;
+                gl.GetIntegerv(gl::DRAW_FRAMEBUFFER_BINDING, &mut fb);
+                let attachment = if fb == 0 { gl::DEPTH } else { gl::DEPTH_ATTACHMENT };
                 let mut ty = 0;
-                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::DEPTH,
+                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, attachment,
                                                        gl::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
                                                        &mut ty);
```
Doing a similar thing for `srgb` and `stencil_bits` fixes all these initialization errors.

I'm guessing that these comments about `glGetFramebufferAttachmentParameteriv incorrectly returns GL_INVALID_ENUM on some drivers` may be related to this. Hey, maybe they get fixed with this change.



Discussion / hints:

Fix patch:
diff --git a/src/context/capabilities.rs b/src/context/capabilities.rs
index b5241059a9..a6054f5493 100644
--- a/src/context/capabilities.rs
+++ b/src/context/capabilities.rs
@@ -301,8 +301,11 @@ pub unsafe fn get_capabilities(gl: &gl::Gl, version: &Version, extensions: &Exte
             // `glGetFramebufferAttachmentParameteriv` incorrectly returns GL_INVALID_ENUM on some
             // drivers, so we prefer using `glGetIntegerv` if possible.
             if version >= &Version(Api::Gl, 3, 0) && !extensions.gl_ext_framebuffer_srgb {
+                let mut fb = 0;
+                gl.GetIntegerv(gl::DRAW_FRAMEBUFFER_BINDING, &mut fb);
+                let attachment = if fb == 0 { gl::FRONT_LEFT } else { gl::COLOR_ATTACHMENT0 };
                 let mut value = 0;
-                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::FRONT_LEFT,
+                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, attachment,
                                                        gl::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING,
                                                        &mut value);
                 value as gl::types::GLenum == gl::SRGB
@@ -327,15 +330,18 @@ pub unsafe fn get_capabilities(gl: &gl::Gl, version: &Version, extensions: &Exte
             // doesn't even though it provides this extension. I'm not sure whether this is a bug
             // with OS/X or just the extension actually not providing it.
             if version >= &Version(Api::Gl, 3, 0) && !extensions.gl_arb_compatibility {
+                let mut fb = 0;
+                gl.GetIntegerv(gl::DRAW_FRAMEBUFFER_BINDING, &mut fb);
+                let attachment = if fb == 0 { gl::DEPTH } else { gl::DEPTH_ATTACHMENT };
                 let mut ty = 0;
-                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::DEPTH,
+                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, attachment,
                                                        gl::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
                                                        &mut ty);
 
                 if ty as gl::types::GLenum == gl::NONE {
                     value = 0;
                 } else {
-                    gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::DEPTH,
+                    gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, attachment,
                                                            gl::FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
                                                            &mut value);
                 }
@@ -360,15 +366,18 @@ pub unsafe fn get_capabilities(gl: &gl::Gl, version: &Version, extensions: &Exte
             // doesn't even though it provides this extension. I'm not sure whether this is a bug
             // with OS/X or just the extension actually not providing it.
             if version >= &Version(Api::Gl, 3, 0) && !extensions.gl_arb_compatibility {
+                let mut fb = 0;
+                gl.GetIntegerv(gl::DRAW_FRAMEBUFFER_BINDING, &mut fb);
+                let attachment = if fb == 0 { gl::STENCIL } else { gl::STENCIL_ATTACHMENT };
                 let mut ty = 0;
-                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::STENCIL,
+                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, attachment,
                                                        gl::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
                                                        &mut ty);
 
                 if ty as gl::types::GLenum == gl::NONE {
                     value = 0;
                 } else {
-                    gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::STENCIL,
+                    gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, attachment,
                                                            gl::FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
                                                            &mut value);
                 }


Test patch: