properly indent code

felipesanches-svg
don bright 2013-02-01 02:47:12 +01:00
parent f8ebf1c963
commit 466490a55a
2 changed files with 223 additions and 223 deletions

View File

@ -6,49 +6,49 @@
void bind_offscreen_context(OffscreenContext *ctx) void bind_offscreen_context(OffscreenContext *ctx)
{ {
if (ctx) fbo_bind(ctx->fbo); if (ctx) fbo_bind(ctx->fbo);
} }
/* /*
Capture framebuffer from OpenGL and write it to the given filename as PNG. Capture framebuffer from OpenGL and write it to the given filename as PNG.
*/ */
bool save_framebuffer(OffscreenContext *ctx, const char *filename) bool save_framebuffer(OffscreenContext *ctx, const char *filename)
{ {
std::ofstream fstream(filename,std::ios::out|std::ios::binary); std::ofstream fstream(filename,std::ios::out|std::ios::binary);
if (!fstream.is_open()) { if (!fstream.is_open()) {
std::cerr << "Can't open file " << filename << " for writing"; std::cerr << "Can't open file " << filename << " for writing";
return false; return false;
} else { } else {
save_framebuffer(ctx, fstream); save_framebuffer(ctx, fstream);
fstream.close(); fstream.close();
} }
return true; return true;
} }
/*! /*!
Capture framebuffer from OpenGL and write it to the given ostream. Capture framebuffer from OpenGL and write it to the given ostream.
Called by save_framebuffer() from platform-specific code. Called by save_framebuffer() from platform-specific code.
*/ */
bool save_framebuffer_common(OffscreenContext *ctx, std::ostream &output) bool save_framebuffer_common(OffscreenContext *ctx, std::ostream &output)
{ {
if (!ctx) return false; if (!ctx) return false;
int samplesPerPixel = 4; // R, G, B and A int samplesPerPixel = 4; // R, G, B and A
std::vector<GLubyte> pixels(ctx->width * ctx->height * samplesPerPixel); std::vector<GLubyte> pixels(ctx->width * ctx->height * samplesPerPixel);
glReadPixels(0, 0, ctx->width, ctx->height, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]); glReadPixels(0, 0, ctx->width, ctx->height, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
// Flip it vertically - images read from OpenGL buffers are upside-down // Flip it vertically - images read from OpenGL buffers are upside-down
int rowBytes = samplesPerPixel * ctx->width; int rowBytes = samplesPerPixel * ctx->width;
unsigned char *flippedBuffer = (unsigned char *)malloc(rowBytes * ctx->height); unsigned char *flippedBuffer = (unsigned char *)malloc(rowBytes * ctx->height);
if (!flippedBuffer) { if (!flippedBuffer) {
std::cerr << "Unable to allocate flipped buffer for corrected image."; std::cerr << "Unable to allocate flipped buffer for corrected image.";
return 1; return 1;
} }
flip_image(&pixels[0], flippedBuffer, samplesPerPixel, ctx->width, ctx->height); flip_image(&pixels[0], flippedBuffer, samplesPerPixel, ctx->width, ctx->height);
bool writeok = write_png(output, flippedBuffer, ctx->width, ctx->height); bool writeok = write_png(output, flippedBuffer, ctx->width, ctx->height);
free(flippedBuffer); free(flippedBuffer);
return writeok; return writeok;
} }
@ -58,17 +58,17 @@ OffscreenContext *create_offscreen_context_common(OffscreenContext *ctx)
{ {
if (!ctx) return NULL; if (!ctx) return NULL;
GLenum err = glewInit(); // must come after Context creation and before FBO c$ GLenum err = glewInit(); // must come after Context creation and before FBO c$
if (GLEW_OK != err) { if (GLEW_OK != err) {
std::cerr << "Unable to init GLEW: " << glewGetErrorString(err) << "\n"; std::cerr << "Unable to init GLEW: " << glewGetErrorString(err) << "\n";
return NULL; return NULL;
} }
//cerr << glew_dump(0); //cerr << glew_dump(0);
ctx->fbo = fbo_new(); ctx->fbo = fbo_new();
if (!fbo_init(ctx->fbo, ctx->width, ctx->height)) { if (!fbo_init(ctx->fbo, ctx->width, ctx->height)) {
return NULL; return NULL;
} }
return ctx; return ctx;
} }

View File

@ -2,14 +2,14 @@
Create an OpenGL context without creating an OpenGL Window. for Linux. Create an OpenGL context without creating an OpenGL Window. for Linux.
See Also See also
glxgears.c by Brian Paul from mesa-demos (mesa3d.org) glxgears.c by Brian Paul from mesa-demos (mesa3d.org)
http://cgit.freedesktop.org/mesa/demos/tree/src/xdemos?id=mesa-demos-8.0.1 http://cgit.freedesktop.org/mesa/demos/tree/src/xdemos?id=mesa-demos-8.0.1
http://www.opengl.org/sdk/docs/man/xhtml/glXIntro.xml http://www.opengl.org/sdk/docs/man/xhtml/glXIntro.xml
http://www.mesa3d.org/brianp/sig97/offscrn.htm http://www.mesa3d.org/brianp/sig97/offscrn.htm
http://glprogramming.com/blue/ch07.html http://glprogramming.com/blue/ch07.html
OffscreenContext.mm (Mac OSX version) OffscreenContext.mm (Mac OSX version)
*/ */
@ -53,241 +53,241 @@ using namespace std;
struct OffscreenContext struct OffscreenContext
{ {
GLXContext openGLContext; GLXContext openGLContext;
Display *xdisplay; Display *xdisplay;
Window xwindow; Window xwindow;
int width; int width;
int height; int height;
fbo_t *fbo; fbo_t *fbo;
}; };
#include "OffscreenContextAll.hpp" #include "OffscreenContextAll.hpp"
void offscreen_context_init(OffscreenContext &ctx, int width, int height) void offscreen_context_init(OffscreenContext &ctx, int width, int height)
{ {
ctx.width = width; ctx.width = width;
ctx.height = height; ctx.height = height;
ctx.openGLContext = NULL; ctx.openGLContext = NULL;
ctx.xdisplay = NULL; ctx.xdisplay = NULL;
ctx.xwindow = (Window)NULL; ctx.xwindow = (Window)NULL;
ctx.fbo = NULL; ctx.fbo = NULL;
} }
string get_os_info() string get_os_info()
{ {
struct utsname u; struct utsname u;
stringstream out; stringstream out;
if (uname(&u) < 0) if (uname(&u) < 0)
out << "OS info: unknown, uname() error\n"; out << "OS info: unknown, uname() error\n";
else { else {
out << "OS info: " out << "OS info: "
<< u.sysname << " " << u.sysname << " "
<< u.release << " " << u.release << " "
<< u.version << "\n"; << u.version << "\n";
out << "Machine: " << u.machine; out << "Machine: " << u.machine;
} }
return out.str(); return out.str();
} }
string offscreen_context_getinfo(OffscreenContext *ctx) string offscreen_context_getinfo(OffscreenContext *ctx)
{ {
assert(ctx); assert(ctx);
if (!ctx->xdisplay) if (!ctx->xdisplay)
return string("No GL Context initialized. No information to report\n"); return string("No GL Context initialized. No information to report\n");
int major, minor; int major, minor;
glXQueryVersion(ctx->xdisplay, &major, &minor); glXQueryVersion(ctx->xdisplay, &major, &minor);
stringstream out; stringstream out;
out << "GL context creator: GLX\n" out << "GL context creator: GLX\n"
<< "PNG generator: lodepng\n" << "PNG generator: lodepng\n"
<< "GLX version: " << major << "." << minor << "\n" << "GLX version: " << major << "." << minor << "\n"
<< get_os_info(); << get_os_info();
return out.str(); return out.str();
} }
static XErrorHandler original_xlib_handler = (XErrorHandler) NULL; static XErrorHandler original_xlib_handler = (XErrorHandler) NULL;
static bool XCreateWindow_failed = false; static bool XCreateWindow_failed = false;
static int XCreateWindow_error(Display *dpy, XErrorEvent *event) static int XCreateWindow_error(Display *dpy, XErrorEvent *event)
{ {
cerr << "XCreateWindow failed: XID: " << event->resourceid cerr << "XCreateWindow failed: XID: " << event->resourceid
<< " request: " << (int)event->request_code << " request: " << (int)event->request_code
<< " minor: " << (int)event->minor_code << "\n"; << " minor: " << (int)event->minor_code << "\n";
char description[1024]; char description[1024];
XGetErrorText( dpy, event->error_code, description, 1023 ); XGetErrorText( dpy, event->error_code, description, 1023 );
cerr << " error message: " << description << "\n"; cerr << " error message: " << description << "\n";
XCreateWindow_failed = true; XCreateWindow_failed = true;
return 0; return 0;
} }
bool create_glx_dummy_window(OffscreenContext &ctx) bool create_glx_dummy_window(OffscreenContext &ctx)
{ {
/* /*
create a dummy X window without showing it. (without 'mapping' it) create a dummy X window without showing it. (without 'mapping' it)
and save information to the ctx. and save information to the ctx.
This purposely does not use glxCreateWindow, to avoid crashes, This purposely does not use glxCreateWindow, to avoid crashes,
"failed to create drawable" errors, and Mesa "WARNING: Application calling "failed to create drawable" errors, and Mesa "WARNING: Application calling
GLX 1.3 function when GLX 1.3 is not supported! This is an application bug!" GLX 1.3 function when GLX 1.3 is not supported! This is an application bug!"
This function will alter ctx.openGLContext and ctx.xwindow if successfull This function will alter ctx.openGLContext and ctx.xwindow if successfull
*/ */
int attributes[] = { int attributes[] = {
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT, //support all 3, for OpenCSG GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT, //support all 3, for OpenCSG
GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_RED_SIZE, 8, GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8, GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8, GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8, GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 24, // depth-stencil for OpenCSG GLX_DEPTH_SIZE, 24, // depth-stencil for OpenCSG
GLX_STENCIL_SIZE, 8, GLX_STENCIL_SIZE, 8,
GLX_DOUBLEBUFFER, True, GLX_DOUBLEBUFFER, True,
None None
}; };
Display *dpy = ctx.xdisplay; Display *dpy = ctx.xdisplay;
int num_returned = 0; int num_returned = 0;
GLXFBConfig *fbconfigs = glXChooseFBConfig( dpy, DefaultScreen(dpy), attributes, &num_returned ); GLXFBConfig *fbconfigs = glXChooseFBConfig( dpy, DefaultScreen(dpy), attributes, &num_returned );
if ( fbconfigs == NULL ) { if ( fbconfigs == NULL ) {
cerr << "glXChooseFBConfig failed\n"; cerr << "glXChooseFBConfig failed\n";
return false; return false;
} }
XVisualInfo *visinfo = glXGetVisualFromFBConfig( dpy, fbconfigs[0] ); XVisualInfo *visinfo = glXGetVisualFromFBConfig( dpy, fbconfigs[0] );
if ( visinfo == NULL ) { if ( visinfo == NULL ) {
cerr << "glXGetVisualFromFBConfig failed\n"; cerr << "glXGetVisualFromFBConfig failed\n";
XFree( fbconfigs ); XFree( fbconfigs );
return false; return false;
} }
// can't depend on xWin==NULL at failure. use a custom Xlib error handler instead. // can't depend on xWin==NULL at failure. use a custom Xlib error handler instead.
original_xlib_handler = XSetErrorHandler( XCreateWindow_error ); original_xlib_handler = XSetErrorHandler( XCreateWindow_error );
Window root = DefaultRootWindow( dpy ); Window root = DefaultRootWindow( dpy );
XSetWindowAttributes xwin_attr; XSetWindowAttributes xwin_attr;
int width = ctx.width; int width = ctx.width;
int height = ctx.height; int height = ctx.height;
xwin_attr.background_pixmap = None; xwin_attr.background_pixmap = None;
xwin_attr.background_pixel = 0; xwin_attr.background_pixel = 0;
xwin_attr.border_pixel = 0; xwin_attr.border_pixel = 0;
xwin_attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); xwin_attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
xwin_attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; xwin_attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
unsigned long int mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; unsigned long int mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
Window xWin = XCreateWindow( dpy, root, 0, 0, width, height, Window xWin = XCreateWindow( dpy, root, 0, 0, width, height,
0, visinfo->depth, InputOutput, 0, visinfo->depth, InputOutput,
visinfo->visual, mask, &xwin_attr ); visinfo->visual, mask, &xwin_attr );
// Window xWin = XCreateSimpleWindow( dpy, DefaultRootWindow(dpy), 0,0,42,42, 0,0,0 ); // Window xWin = XCreateSimpleWindow( dpy, DefaultRootWindow(dpy), 0,0,42,42, 0,0,0 );
XSync( dpy, false ); XSync( dpy, false );
if ( XCreateWindow_failed ) { if ( XCreateWindow_failed ) {
XFree( visinfo ); XFree( visinfo );
XFree( fbconfigs ); XFree( fbconfigs );
return false; return false;
} }
XSetErrorHandler( original_xlib_handler ); XSetErrorHandler( original_xlib_handler );
// Most programs would call XMapWindow here. But we don't, to keep the window hidden // Most programs would call XMapWindow here. But we don't, to keep the window hidden
// XMapWindow( dpy, xWin ); // XMapWindow( dpy, xWin );
GLXContext context = glXCreateNewContext( dpy, fbconfigs[0], GLX_RGBA_TYPE, NULL, True ); GLXContext context = glXCreateNewContext( dpy, fbconfigs[0], GLX_RGBA_TYPE, NULL, True );
if ( context == NULL ) { if ( context == NULL ) {
cerr << "glXCreateNewContext failed\n"; cerr << "glXCreateNewContext failed\n";
XDestroyWindow( dpy, xWin ); XDestroyWindow( dpy, xWin );
XFree( visinfo ); XFree( visinfo );
XFree( fbconfigs ); XFree( fbconfigs );
return false; return false;
} }
//GLXWindow glxWin = glXCreateWindow( dpy, fbconfigs[0], xWin, NULL ); //GLXWindow glxWin = glXCreateWindow( dpy, fbconfigs[0], xWin, NULL );
if (!glXMakeContextCurrent( dpy, xWin, xWin, context )) { if (!glXMakeContextCurrent( dpy, xWin, xWin, context )) {
//if (!glXMakeContextCurrent( dpy, glxWin, glxWin, context )) { //if (!glXMakeContextCurrent( dpy, glxWin, glxWin, context )) {
cerr << "glXMakeContextCurrent failed\n"; cerr << "glXMakeContextCurrent failed\n";
glXDestroyContext( dpy, context ); glXDestroyContext( dpy, context );
XDestroyWindow( dpy, xWin ); XDestroyWindow( dpy, xWin );
XFree( visinfo ); XFree( visinfo );
XFree( fbconfigs ); XFree( fbconfigs );
return false; return false;
} }
ctx.openGLContext = context; ctx.openGLContext = context;
ctx.xwindow = xWin; ctx.xwindow = xWin;
XFree( visinfo ); XFree( visinfo );
XFree( fbconfigs ); XFree( fbconfigs );
return true; return true;
} }
Bool create_glx_dummy_context(OffscreenContext &ctx); Bool create_glx_dummy_context(OffscreenContext &ctx);
OffscreenContext *create_offscreen_context(int w, int h) OffscreenContext *create_offscreen_context(int w, int h)
{ {
OffscreenContext *ctx = new OffscreenContext; OffscreenContext *ctx = new OffscreenContext;
offscreen_context_init( *ctx, w, h ); offscreen_context_init( *ctx, w, h );
// before an FBO can be setup, a GLX context must be created // before an FBO can be setup, a GLX context must be created
// this call alters ctx->xDisplay and ctx->openGLContext // this call alters ctx->xDisplay and ctx->openGLContext
// and ctx->xwindow if successfull // and ctx->xwindow if successfull
if (!create_glx_dummy_context( *ctx )) { if (!create_glx_dummy_context( *ctx )) {
return NULL; return NULL;
} }
return create_offscreen_context_common( ctx ); return create_offscreen_context_common( ctx );
} }
bool teardown_offscreen_context(OffscreenContext *ctx) bool teardown_offscreen_context(OffscreenContext *ctx)
{ {
if (ctx) { if (ctx) {
fbo_unbind(ctx->fbo); fbo_unbind(ctx->fbo);
fbo_delete(ctx->fbo); fbo_delete(ctx->fbo);
XDestroyWindow( ctx->xdisplay, ctx->xwindow ); XDestroyWindow( ctx->xdisplay, ctx->xwindow );
glXDestroyContext( ctx->xdisplay, ctx->openGLContext ); glXDestroyContext( ctx->xdisplay, ctx->openGLContext );
XCloseDisplay( ctx->xdisplay ); XCloseDisplay( ctx->xdisplay );
return true; return true;
} }
return false; return false;
} }
bool save_framebuffer(OffscreenContext *ctx, std::ostream &output) bool save_framebuffer(OffscreenContext *ctx, std::ostream &output)
{ {
glXSwapBuffers(ctx->xdisplay, ctx->xwindow); glXSwapBuffers(ctx->xdisplay, ctx->xwindow);
return save_framebuffer_common(ctx, output); return save_framebuffer_common(ctx, output);
} }
#pragma GCC diagnostic ignored "-Waddress" #pragma GCC diagnostic ignored "-Waddress"
Bool create_glx_dummy_context(OffscreenContext &ctx) Bool create_glx_dummy_context(OffscreenContext &ctx)
{ {
// This will alter ctx.openGLContext and ctx.xdisplay and ctx.xwindow if successfull // This will alter ctx.openGLContext and ctx.xdisplay and ctx.xwindow if successfull
int major; int major;
int minor; int minor;
Bool result = False; Bool result = False;
ctx.xdisplay = XOpenDisplay( NULL ); ctx.xdisplay = XOpenDisplay( NULL );
if ( ctx.xdisplay == NULL ) { if ( ctx.xdisplay == NULL ) {
cerr << "Unable to open a connection to the X server\n"; cerr << "Unable to open a connection to the X server\n";
return False; return False;
} }
// glxQueryVersion is not always reliable. Use it, but then // glxQueryVersion is not always reliable. Use it, but then
// also check to see if GLX 1.3 functions exist // also check to see if GLX 1.3 functions exist
glXQueryVersion(ctx.xdisplay, &major, &minor); glXQueryVersion(ctx.xdisplay, &major, &minor);
if ( major==1 && minor<=2 && glXGetVisualFromFBConfig==NULL ) { if ( major==1 && minor<=2 && glXGetVisualFromFBConfig==NULL ) {
cerr << "Error: GLX version 1.3 functions missing. " cerr << "Error: GLX version 1.3 functions missing. "
<< "Your GLX version: " << major << "." << minor << endl; << "Your GLX version: " << major << "." << minor << endl;
} else { } else {
result = create_glx_dummy_window(ctx); result = create_glx_dummy_window(ctx);
} }
if (!result) XCloseDisplay( ctx.xdisplay ); if (!result) XCloseDisplay( ctx.xdisplay );
return result; return result;
} }