diff options
author | Don Bright <hugh.m.bright@gmail.com> | 2011-10-09 01:02:40 (GMT) |
---|---|---|
committer | Don Bright <hugh.m.bright@gmail.com> | 2011-10-09 01:02:40 (GMT) |
commit | 589991c41e5420e68a8504670c25b0dba9e6628e (patch) | |
tree | 792553691ad1d6a1c5258d532003e1eea900ffec /tests/fbo.cc | |
parent | 872fc643218ef642544612954272e89629e145c5 (diff) |
Linux offscreen OpenGL using glxpixmaps. also fix FBO ARB/EXT issues
Diffstat (limited to 'tests/fbo.cc')
-rw-r--r-- | tests/fbo.cc | 144 |
1 files changed, 132 insertions, 12 deletions
diff --git a/tests/fbo.cc b/tests/fbo.cc index 403a32e..b7bf1c0 100644 --- a/tests/fbo.cc +++ b/tests/fbo.cc @@ -15,13 +15,94 @@ fbo_t *fbo_new() #define REPORTGLERROR(task) { GLenum tGLErr = glGetError(); if (tGLErr != GL_NO_ERROR) { std::cout << "OpenGL error " << tGLErr << " while " << task << "\n"; } } -bool fbo_init(fbo_t *fbo, size_t width, size_t height) +bool use_ext() +{ + // do we need to use the EXT or ARB version? + if (!glewIsSupported("GL_ARB_framebuffer_object") && + glewIsSupported("GL_EXT_framebuffer_object")) { + return true; + } else { + return false; + } +} + +bool check_fbo_status() { - if (!glewIsSupported("GL_ARB_framebuffer_object")) { - fprintf(stderr, "Framebuffer extension not found\n"); + /* This code is based on user V-man code from + http://www.opengl.org/wiki/GL_EXT_framebuffer_multisample + See also: http://www.songho.ca/opengl/gl_fbo.html */ + GLenum status; + bool result = false; + if (use_ext()) + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + else + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + + if (glGetError() != GL_NO_ERROR) + fprintf(stderr, "OpenGL Error %i\n",glGetError()); + + if (status == GL_FRAMEBUFFER_COMPLETE) + result = true; + else if (status == GL_FRAMEBUFFER_UNSUPPORTED) + fprintf(stderr, "GL_FRAMEBUFFER_UNSUPPORTED\n"); + else if (status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) + fprintf(stderr, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT\n"); + else if (status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT) + fprintf(stderr, "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\n"); + else if (status == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT) + fprintf(stderr, "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n"); + else if (status == GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT) + fprintf(stderr, "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n"); + else if (status == GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT) + fprintf(stderr, "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n"); + else if (status == GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT) + fprintf(stderr, "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n"); + else if (status == GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT) + fprintf(stderr, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT\n"); + else + fprintf(stderr, "Unknown Code: glCheckFramebufferStatusEXT returned %i\n",status); + return result; +} + +bool fbo_ext_init(fbo_t *fbo, size_t width, size_t height) +{ + // Generate and bind FBO + glGenFramebuffersEXT(1, &fbo->fbo_id); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->fbo_id); + REPORTGLERROR("binding framebuffer"); + + // Generate depth and render buffers + glGenRenderbuffersEXT(1, &fbo->depthbuf_id); + glGenRenderbuffersEXT(1, &fbo->renderbuf_id); + + // Create buffers with correct size + if (!fbo_resize(fbo, width, height)) return false; + + // Attach render and depth buffers + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_RENDERBUFFER_EXT, fbo->renderbuf_id); + REPORTGLERROR("specifying color render buffer"); + + + if (!check_fbo_status()) { + fprintf(stderr, "Problem with OpenGL framebuffer after specifying color render buffer.\n"); + return false; + } + + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, fbo->depthbuf_id); + REPORTGLERROR("specifying depth render buffer"); + + if (!check_fbo_status()) { + fprintf(stderr, "Problem with OpenGL framebuffer after specifying depth render buffer.\n"); return false; } + return true; +} + +bool fbo_arb_init(fbo_t *fbo, size_t width, size_t height) +{ // Generate and bind FBO glGenFramebuffers(1, &fbo->fbo_id); glBindFramebuffer(GL_FRAMEBUFFER, fbo->fbo_id); @@ -56,15 +137,48 @@ bool fbo_init(fbo_t *fbo, size_t width, size_t height) return true; } -bool fbo_resize(fbo_t *fbo, size_t width, size_t height) + +bool fbo_init(fbo_t *fbo, size_t width, size_t height) { - glBindRenderbuffer(GL_RENDERBUFFER, fbo->depthbuf_id); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); - REPORTGLERROR("creating depth render buffer"); + /* + Some OpenGL drivers include the framebuffer functions but not with + core or ARB names, only with the EXT name. This has been worked-around + by deciding at runtime, using GLEW, which version needs to be used. See also: + + http://www.opengl.org/wiki/Framebuffer_Object + http://stackoverflow.com/questions/6912988/glgenframebuffers-or-glgenframebuffersex + http://www.devmaster.net/forums/showthread.php?t=10967 + */ + + bool result = false; + if (glewIsSupported("GL_ARB_framebuffer_object")) + result = fbo_arb_init(fbo, width, height); + else if (use_ext()) + result = fbo_ext_init(fbo, width, height); + else + fprintf(stderr, "Framebuffer Object extension not found by GLEW\n"); + return result; +} - glBindRenderbuffer(GL_RENDERBUFFER, fbo->renderbuf_id); - glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); - REPORTGLERROR("creating color render buffer"); +bool fbo_resize(fbo_t *fbo, size_t width, size_t height) +{ + if (use_ext()) { + glBindRenderbufferEXT(GL_RENDERBUFFER, fbo->depthbuf_id); + glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); + REPORTGLERROR("creating depth render buffer"); + + glBindRenderbufferEXT(GL_RENDERBUFFER, fbo->renderbuf_id); + glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_RGBA8, width, height); + REPORTGLERROR("creating color render buffer"); + } else { + glBindRenderbuffer(GL_RENDERBUFFER, fbo->depthbuf_id); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); + REPORTGLERROR("creating depth render buffer"); + + glBindRenderbuffer(GL_RENDERBUFFER, fbo->renderbuf_id); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); + REPORTGLERROR("creating color render buffer"); + } return true; } @@ -77,11 +191,17 @@ void fbo_delete(fbo_t *fbo) GLuint fbo_bind(fbo_t *fbo) { glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&fbo->old_fbo_id); - glBindFramebuffer(GL_FRAMEBUFFER, fbo->fbo_id); + if (use_ext()) + glBindFramebufferEXT(GL_FRAMEBUFFER, fbo->fbo_id); + else + glBindFramebuffer(GL_FRAMEBUFFER, fbo->fbo_id); return fbo->old_fbo_id; } void fbo_unbind(fbo_t *fbo) { - glBindFramebuffer(GL_FRAMEBUFFER, fbo->old_fbo_id); + if (use_ext()) + glBindFramebufferEXT(GL_FRAMEBUFFER, fbo->old_fbo_id); + else + glBindFramebuffer(GL_FRAMEBUFFER, fbo->old_fbo_id); } |