summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorDon Bright <hugh.m.bright@gmail.com>2011-10-09 01:02:40 (GMT)
committerDon Bright <hugh.m.bright@gmail.com>2011-10-09 01:02:40 (GMT)
commit589991c41e5420e68a8504670c25b0dba9e6628e (patch)
tree792553691ad1d6a1c5258d532003e1eea900ffec /tests
parent872fc643218ef642544612954272e89629e145c5 (diff)
Linux offscreen OpenGL using glxpixmaps. also fix FBO ARB/EXT issues
Diffstat (limited to 'tests')
-rw-r--r--tests/CMakeLists.txt15
-rw-r--r--tests/OffscreenContext.cc204
-rw-r--r--tests/OffscreenView.cc5
-rw-r--r--tests/cgalpngtest.cc7
-rw-r--r--tests/csgtestcore.cc7
-rw-r--r--tests/fbo.cc144
6 files changed, 297 insertions, 85 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index eb3e911..9e6640e 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -57,21 +57,6 @@ if (NOT OPENCSG_INCLUDE_DIR)
endif()
include_directories(${OPENCSG_INCLUDE_DIR})
-# SDL (for OpenCSG on Linux & other platforms)
-if (NOT $ENV{MACOSX_DEPLOY_DIR} STREQUAL "")
- message(STATU "SDL not needed for Mac OSX")
-else()
- find_package(SDL REQUIRED)
- if (NOT SDL_FOUND)
- message(FATAL_ERROR "SDL not found.")
- else()
- message(STATUS "SDL library found in " ${SDL_LIBRARY})
- message(STATUS "SDL header found in " ${SDL_INCLUDE_DIR})
- set(OPENGL_LIBRARY ${OPENGL_LIBRARY} ${SDL_LIBRARY})
- endif()
-endif()
-include_directories(${SDL_INCLUDE_DIR})
-
# GLEW
if (NOT $ENV{MACOSX_DEPLOY_DIR} STREQUAL "")
diff --git a/tests/OffscreenContext.cc b/tests/OffscreenContext.cc
index fa1afde..775491e 100644
--- a/tests/OffscreenContext.cc
+++ b/tests/OffscreenContext.cc
@@ -1,85 +1,182 @@
+/*
+
+Create an OpenGL context without creating an OpenGL Window. for Linux.
+
+based on
+
+ http://www.opengl.org/sdk/docs/man/xhtml/glXIntro.xml
+ http://www.mesa3d.org/brianp/sig97/offscrn.htm
+ http://glprogramming.com/blue/ch07.html
+ OffscreenContext.mm (Mac OSX version)
+
+*/
+
#include "OffscreenContext.h"
#include "printutils.h"
#include "imageutils.h"
+#include "fbo.h"
-// see http://www.gamedev.net/topic/552607-conflict-between-glew-and-sdl/
-#define NO_SDL_GLEXT
-#include <GL/glew.h>
-
-#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
-#include <GL/glext.h>
+#include <GL/glx.h>
-//#include <GL/gl.h>
-//#include <GL/glu.h> // for gluCheckExtension
-#include <SDL.h>
+#define REPORTGLERROR(task) { GLenum tGLErr = glGetError(); if (tGLErr != GL_NO_ERROR) { std::cout << "OpenGL error " << tGLErr << " while " << task << "\n"; } }
struct OffscreenContext
{
+ GLXContext openGLContext;
+ Display *xDisplay;
+ GLXPixmap glx_pixmap;
+ Pixmap x11_pixmap;
int width;
int height;
- GLuint fbo;
- GLuint colorbo;
- GLuint depthbo;
+ fbo_t *fbo;
};
-void write_targa(const char *filename, GLubyte *pixels, int width, int height)
+Bool glx_1_3_pixmap_dummy_context(OffscreenContext *ctx, Bool hybrid)
+{
+ XVisualInfo *vInfo;
+ GLXFBConfig *fbConfigs;
+
+ int numReturned;
+ int result;
+ int dummyAttributes_1_3[] = {
+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ None
+ };
+
+ fbConfigs = glXChooseFBConfig( ctx->xDisplay,
+ DefaultScreen(ctx->xDisplay),
+ dummyAttributes_1_3, &numReturned );
+ if ( fbConfigs == NULL ) {
+ REPORTGLERROR("glXChooseFBConfig failed") ;
+ return False;
+ }
+
+ vInfo = glXGetVisualFromFBConfig( ctx->xDisplay, fbConfigs[0] );
+ if ( vInfo == NULL ) {
+ REPORTGLERROR("glXGetVisualFromFBConfig failed") ;
+ return False;
+ }
+
+ ctx->x11_pixmap = XCreatePixmap( ctx->xDisplay, DefaultRootWindow(ctx->xDisplay) , 10, 10, 8 );
+
+ if (hybrid) {
+ // GLX 1.2 - prevent Mesa warning
+ ctx->glx_pixmap = glXCreateGLXPixmap( ctx->xDisplay, vInfo, ctx->x11_pixmap );
+ } else {
+ // GLX 1.3
+ ctx->glx_pixmap = glXCreatePixmap( ctx->xDisplay, fbConfigs[0], ctx->x11_pixmap, NULL ); // GLX 1.3
+ }
+
+ ctx->openGLContext = glXCreateNewContext( ctx->xDisplay, fbConfigs[0], GLX_RGBA_TYPE, NULL, True );
+ if ( ctx->openGLContext == NULL ) {
+ REPORTGLERROR("glXCreateNewContext failed" );
+ return False;
+ }
+
+ result = glXMakeContextCurrent( ctx->xDisplay, ctx->glx_pixmap, ctx->glx_pixmap, ctx->openGLContext );
+ if ( result == False ) {
+ REPORTGLERROR("glXMakeContextCurrent failed" );
+ return False;
+ }
+
+ return True;
+}
+
+Bool make_glx_dummy_context(OffscreenContext *ctx)
{
- FILE *f = fopen( filename, "w" );
- int y;
- if (f) {
- GLubyte header[] = {
- 00,00,02, 00,00,00, 00,00,00, 00,00,00,
- 0xff & width, 0xff & width >> 8,
- 0xff & height, 0xff & height >> 8,
- 32, 0x20 }; // next-to-last = bit depth
- fwrite( header, sizeof(header), 1, f);
- for (y=height-1; y>=0; y--)
- fwrite( pixels + y*width*4, 4, width, f);
- fclose(f);
+ /*
+ Before opening a framebuffer, an OpenGL context must be created.
+ For GLX, you can do this by creating a 'Pixmap' drawable then
+ creating the Context off of that. The Pixmap is then never used.
+ */
+ int major;
+ int minor;
+
+ ctx->xDisplay = XOpenDisplay( NULL );
+ if ( ctx->xDisplay == NULL ) {
+ fprintf(stderr, "Unable to open a connection to the X server\n" );
+ return False;
+ }
+
+ /*
+ On some systems, the GLX library will report that it is version
+ 1.2, but some 1.3 functions will be implemented, and, furthermore,
+ some 1.2 functions won't work right, while the 1.3 functions will,
+ but glXCreatePixmp will still generate a MESA GLX 1.3 runtime warning.
+
+ To workaround this, detect the situation and use 'hybrid' mix of
+ 1.2 and 1.3 as needed.
+ */
+ glXQueryVersion(ctx->xDisplay, &major, &minor);
+
+ if (major==1 && minor<=2) {
+ if (glXCreatePixmap!=NULL) { // 1.3 function exists, even though its 1.2
+ return glx_1_3_pixmap_dummy_context(ctx,True);
+ } else {
+ fprintf(stderr,"OpenGL error: GLX version 1.3 functions missing. Your GLX: %i.%i\n",major,minor);
+ return False;
+ }
+ } else if (major>=1 && minor>=3) {
+ return glx_1_3_pixmap_dummy_context(ctx,False);
}
}
+void glewCheck() {
+#ifdef DEBUG
+ cout << "GLEW version " << glewGetString(GLEW_VERSION) << "\n";
+ cout << (const char *)glGetString(GL_RENDERER) << "(" << (const char *)glGetString(GL_VENDOR) << ")\n"
+ << "OpenGL version " << (const char *)glGetString(GL_VERSION) << "\n";
+ cout << "Extensions: " << (const char *)glGetString(GL_EXTENSIONS) << "\n";
+
+ if (GLEW_ARB_framebuffer_object) {
+ cout << "ARB_FBO supported\n";
+ }
+ if (GLEW_EXT_framebuffer_object) {
+ cout << "EXT_FBO supported\n";
+ }
+ if (GLEW_EXT_packed_depth_stencil) {
+ cout << "EXT_packed_depth_stencil\n";
+ }
+#endif
+}
+
OffscreenContext *create_offscreen_context(int w, int h)
{
OffscreenContext *ctx = new OffscreenContext;
ctx->width = w;
ctx->height = h;
+ ctx->openGLContext = NULL;
+ ctx->xDisplay = NULL;
+ ctx->glx_pixmap = NULL;
+ ctx->x11_pixmap = NULL;
+ ctx->fbo = NULL;
+
+ // fill ctx->xDisplay, ctx->openGLContext, x11_pixmap, glx_pixmap
+ if (!make_glx_dummy_context(ctx)) {
+ return NULL;
+ }
- // dummy window
- SDL_Init(SDL_INIT_VIDEO);
- SDL_SetVideoMode(ctx->width,ctx->height,32,SDL_OPENGL);
-
- // must come after openGL context init (done by dummy window)
- // but must also come before various EXT calls
- //glewInit();
+ glewInit(); //must come after Context creation and before FBO calls.
+ glewCheck();
-/*
- glClearColor(1, 1, 1, 1);
- glClear(GL_COLOR_BUFFER_BIT);
- glBegin(GL_TRIANGLES);
- glColor3f( 1, 0, 0);
- glVertex3f( 0, 0, 0);
- glVertex3f( 1, 0, 0);
- glVertex3f( 0, 1, 0);
- glEnd();
- SDL_GL_SwapBuffers();
-// sleep(2);
-*/
-
- int samplesPerPixel = 4; // R, G, B and A
+ ctx->fbo = fbo_new();
+ if (!fbo_init(ctx->fbo, w, h)) {
+ return NULL;
+ }
-/* char * filename = "blah.tga";
- GLubyte pixels[ ctx->width * ctx->height * samplesPerPixel ];
- glReadPixels(0, 0, ctx->width, ctx->height, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
- printf("writing %s\n",filename);
- write_targa(filename,pixels,ctx->width, ctx->height);*/
return ctx;
}
bool teardown_offscreen_context(OffscreenContext *ctx)
{
- return true;
+ fbo_unbind(ctx->fbo);
+ fbo_delete(ctx->fbo);
+ glXDestroyPixmap(ctx->xDisplay, ctx->glx_pixmap );
+ XFreePixmap(ctx->xDisplay, ctx->x11_pixmap );
+ glXDestroyContext( ctx->xDisplay, ctx->openGLContext );
+ return true;
}
/*!
@@ -87,8 +184,6 @@ bool teardown_offscreen_context(OffscreenContext *ctx)
*/
bool save_framebuffer(OffscreenContext *ctx, const char *filename)
{
- SDL_GL_SwapBuffers(); // show image
-
int samplesPerPixel = 4; // R, G, B and A
GLubyte pixels[ctx->width * ctx->height * samplesPerPixel];
glReadPixels(0, 0, ctx->width, ctx->height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
@@ -111,4 +206,5 @@ bool save_framebuffer(OffscreenContext *ctx, const char *filename)
void bind_offscreen_context(OffscreenContext *ctx)
{
+ fbo_bind(ctx->fbo);
}
diff --git a/tests/OffscreenView.cc b/tests/OffscreenView.cc
index 8a4b57d..d188d0d 100644
--- a/tests/OffscreenView.cc
+++ b/tests/OffscreenView.cc
@@ -14,7 +14,8 @@ OffscreenView::OffscreenView(size_t width, size_t height)
object_rot(35, 0, 25), camera_eye(0, 0, 0), camera_center(0, 0, 0)
{
for (int i = 0; i < 10; i++) this->shaderinfo[i] = 0;
- this->ctx = create_offscreen_context(width, height);
+ this->ctx = create_offscreen_context(width, height);
+ if ( this->ctx == NULL ) throw -1;
initializeGL();
resizeGL(width, height);
}
@@ -185,7 +186,7 @@ void OffscreenView::paintGL()
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- glClearColor(1.0, 1.0, 0.92, 0.0);
+ glClearColor(1.0, 1.0, 0.92, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
diff --git a/tests/cgalpngtest.cc b/tests/cgalpngtest.cc
index 638c088..447df45 100644
--- a/tests/cgalpngtest.cc
+++ b/tests/cgalpngtest.cc
@@ -179,7 +179,12 @@ int main(int argc, char **argv)
QDir::setCurrent(original_path.absolutePath());
// match with csgtest ends
- csgInfo.glview = new OffscreenView(512,512);
+ try {
+ csgInfo.glview = new OffscreenView(512,512);
+ } catch (int error) {
+ fprintf(stderr,"Can't create OpenGL OffscreenView. exiting.\n");
+ exit(1);
+ }
GLenum err = glewInit();
if (GLEW_OK != err) {
diff --git a/tests/csgtestcore.cc b/tests/csgtestcore.cc
index 6ef05f3..2e28bf6 100644
--- a/tests/csgtestcore.cc
+++ b/tests/csgtestcore.cc
@@ -218,7 +218,12 @@ int csgtestcore(int argc, char *argv[], test_type_e test_type)
QDir::setCurrent(original_path.absolutePath());
- csgInfo.glview = new OffscreenView(512,512);
+ try {
+ csgInfo.glview = new OffscreenView(512,512);
+ } catch (int error) {
+ fprintf(stderr,"Can't create OpenGL OffscreenView. exiting.\n");
+ exit(1);
+ }
BoundingBox bbox = csgInfo.root_chain->getBoundingBox();
Vector3d center = (bbox.min() + bbox.max()) / 2;
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);
}
contact: Jan Huwald // Impressum