summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/OffscreenContext.cc207
-rw-r--r--tests/fbo.h2
2 files changed, 126 insertions, 83 deletions
diff --git a/tests/OffscreenContext.cc b/tests/OffscreenContext.cc
index f1046ba..aa52705 100644
--- a/tests/OffscreenContext.cc
+++ b/tests/OffscreenContext.cc
@@ -24,103 +24,145 @@ using namespace std;
struct OffscreenContext
{
GLXContext openGLContext;
- Display *xDisplay;
- GLXPixmap glx_pixmap;
- Pixmap x11_pixmap;
+ Display *xdisplay;
+ Window xwindow;
int width;
int height;
fbo_t *fbo;
};
-Bool glx_1_3_pixmap_dummy_context(OffscreenContext *ctx, Bool hybrid)
+void offscreen_context_init(OffscreenContext &ctx, int width, int height)
{
- XVisualInfo *vInfo;
- GLXFBConfig *fbConfigs;
+ ctx.width = width;
+ ctx.height = height;
+ ctx.openGLContext = NULL;
+ ctx.xdisplay = NULL;
+ ctx.xwindow = NULL;
+ ctx.fbo = NULL;
+}
+
+static XErrorHandler original_xlib_handler = (XErrorHandler) NULL;
+static bool XCreateWindow_failed = false;
+static int XCreateWindow_error(Display *dpy, XErrorEvent *event)
+{
+ cerr << "XCreateWindow failed: XID: " << event->resourceid
+ << " request: " << (int)event->request_code
+ << " minor: " << (int)event->minor_code << "\n";
+ char description[1024];
+ XGetErrorText( dpy, event->error_code, description, 1023 );
+ cerr << " error message: " << description << "\n";
+ XCreateWindow_failed = true;
+ return 0;
+}
+
+bool create_glx_dummy_window(OffscreenContext &ctx)
+{
+ /*
+ create a dummy X window without showing it. (without 'mapping' it)
+ save information to the ctx
+
+ based on http://www.opengl.org/sdk/docs/man/xhtml/glXIntro.xml
+ which was originally Copyright © 1991-2006 Silicon Graphics, Inc.
+ licensed under the SGI Free Software B License.
+ See http://oss.sgi.com/projects/FreeB/.
+
+ also based on glxgears.c by Brian Paul from mesa-demos (mesa3d.org)
- int numReturned;
- int result;
- int dummyAttributes_1_3[] = {
- GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
+ purposely does not use glxCreateWindow, to avoid Mesa warnings.
+
+ this will alter ctx.openGLContext and ctx.xwindow if successfull
+ */
+
+ int attributes[] = {
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
None
};
- fbConfigs = glXChooseFBConfig( ctx->xDisplay,
- DefaultScreen(ctx->xDisplay),
- dummyAttributes_1_3, &numReturned );
- if ( fbConfigs == NULL ) {
- cerr << "GLX error: glXChooseFBConfig failed";
- return False;
- }
+ Display *dpy = ctx.xdisplay;
- vInfo = glXGetVisualFromFBConfig( ctx->xDisplay, fbConfigs[0] );
- if ( vInfo == NULL ) {
- cerr << "GLX error: glXGetVisualFromFBConfig failed";
- return False;
+ int numReturned = 0;
+ GLXFBConfig *fbconfigs = glXChooseFBConfig( dpy, DefaultScreen(dpy), attributes, &numReturned );
+ if ( fbconfigs == NULL ) {
+ cerr << "glXChooseFBConfig failed\n";
+ 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
+ XVisualInfo *visinfo = glXGetVisualFromFBConfig( dpy, fbconfigs[0] );
+ if ( visinfo == NULL ) {
+ cerr << "glXGetVisualFromFBConfig failed\n";
+ XFree( fbconfigs );
+ return false;
}
- ctx->openGLContext = glXCreateNewContext( ctx->xDisplay, fbConfigs[0], GLX_RGBA_TYPE, NULL, True );
- if ( ctx->openGLContext == NULL ) {
- cerr << "GLX error: glXCreateNewContext failed";
- return False;
+ original_xlib_handler = XSetErrorHandler( XCreateWindow_error );
+ Window xWin = XCreateSimpleWindow( dpy, DefaultRootWindow(dpy), 0,0,10,10, 0,0,0 );
+ // can't depend on xWin==NULL at failure. catch Xlib Errors instead.
+ XSync( dpy, false );
+ if ( XCreateWindow_failed ) {
+ XFree( visinfo );
+ XFree( fbconfigs );
+ return false;
}
-
- result = glXMakeContextCurrent( ctx->xDisplay, ctx->glx_pixmap, ctx->glx_pixmap, ctx->openGLContext );
- if ( result == False ) {
- cerr << "GLX error: glXMakeContextCurrent failed";
- return False;
+ XSetErrorHandler( original_xlib_handler );
+ // do not call XMapWindow - keep the window hidden
+
+ GLXContext context = glXCreateNewContext( dpy, fbconfigs[0], GLX_RGBA_TYPE, NULL, True );
+ if ( context == NULL ) {
+ cerr << "glXGetVisualFromFBConfig failed\n";
+ XDestroyWindow( dpy, xWin );
+ XFree( visinfo );
+ XFree( fbconfigs );
+ return false;
+ }
+
+ if (!glXMakeContextCurrent( dpy, xWin, xWin, context )) {
+ cerr << "glXMakeContextCurrent failed\n";
+ XDestroyWindow( dpy, xWin );
+ glXDestroyContext( dpy, context );
+ XFree( visinfo );
+ XFree( fbconfigs );
+ return false;
}
- return True;
+ ctx.openGLContext = context;
+ ctx.xwindow = xWin;
+
+ XFree( visinfo );
+ XFree( fbconfigs );
+
+ return true;
}
-Bool make_glx_dummy_context(OffscreenContext *ctx)
+
+Bool create_glx_dummy_context(OffscreenContext &ctx)
{
- /*
- 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.
- */
+ // This will alter ctx.openGLContext and ctx.xdisplay and ctx.xwindow if successfull
int major;
int minor;
+ Bool result = False;
- ctx->xDisplay = XOpenDisplay( NULL );
- if ( ctx->xDisplay == NULL ) {
+ ctx.xdisplay = XOpenDisplay( NULL );
+ if ( ctx.xdisplay == NULL ) {
cerr << "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.
+ glXQueryVersion(ctx.xdisplay, &major, &minor);
- 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 {
- cerr << "OpenGL error: GLX version 1.3 functions missing. Your GLX: " << major << "." << minor << endl;
- return False;
- }
- } else if (major>=1 && minor>=3) {
- return glx_1_3_pixmap_dummy_context(ctx,False);
+ if ( major==1 && minor<=2 && glXGetVisualFromFBConfig==NULL ) {
+ cerr << "Error: GLX version 1.3 functions missing. "
+ << "Your GLX version: " << major << "." << minor << endl;
+ XCloseDisplay( ctx.xdisplay );
+ } else {
+ // if glXGetVisualFromFBConfig exists, pretend we have >=1.3
+ result = create_glx_dummy_window(ctx);
}
+
+ return result;
}
void glewCheck() {
@@ -145,16 +187,11 @@ void glewCheck() {
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)) {
+ offscreen_context_init( *ctx, w, h );
+
+ // before an FBO can be setup, a GLX context must be created
+ // this call alters ctx->xDisplay and ctx->openGLContext
+ if (!create_glx_dummy_context( *ctx )) {
return NULL;
}
@@ -171,12 +208,15 @@ OffscreenContext *create_offscreen_context(int w, int h)
bool teardown_offscreen_context(OffscreenContext *ctx)
{
- 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;
+ if (ctx) {
+ fbo_unbind(ctx->fbo);
+ fbo_delete(ctx->fbo);
+ XDestroyWindow( ctx->xdisplay, ctx->xwindow );
+ glXDestroyContext( ctx->xdisplay, ctx->openGLContext );
+ XCloseDisplay( ctx->xdisplay );
+ return true;
+ }
+ return false;
}
/*!
@@ -184,6 +224,7 @@ bool teardown_offscreen_context(OffscreenContext *ctx)
*/
bool save_framebuffer(OffscreenContext *ctx, const char *filename)
{
+ if (!ctx || !filename) return false;
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);
@@ -206,5 +247,5 @@ bool save_framebuffer(OffscreenContext *ctx, const char *filename)
void bind_offscreen_context(OffscreenContext *ctx)
{
- fbo_bind(ctx->fbo);
+ if (ctx) fbo_bind(ctx->fbo);
}
diff --git a/tests/fbo.h b/tests/fbo.h
index 1ee9007..943862f 100644
--- a/tests/fbo.h
+++ b/tests/fbo.h
@@ -20,4 +20,6 @@ void fbo_delete(fbo_t *fbo);
GLuint fbo_bind(fbo_t *fbo);
void fbo_unbind(fbo_t *fbo);
+bool REPORTGLERROR(const char * task);
+
#endif
contact: Jan Huwald // Impressum