From dd5f3ac5040a64578d69a9532f7491253d8364b6 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 8 Dec 2008 15:42:54 -0700 Subject: glut: added GLUT_PPM_FILE env var to dump first frame to a PPM file Set GLUT_PPM_FILE to the desired filename. The first frame rendered will be written to that file. --- src/glut/glx/Makefile | 1 + src/glut/glx/glut_init.c | 4 +++ src/glut/glx/glut_ppm.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ src/glut/glx/glut_swap.c | 4 +++ src/glut/glx/glutint.h | 5 +++ 5 files changed, 94 insertions(+) create mode 100644 src/glut/glx/glut_ppm.c diff --git a/src/glut/glx/Makefile b/src/glut/glx/Makefile index 7378739..bcbf2f5 100644 --- a/src/glut/glx/Makefile +++ b/src/glut/glx/Makefile @@ -56,6 +56,7 @@ SOURCES = \ glut_modifier.c \ glut_mroman.c \ glut_overlay.c \ + glut_ppm.c \ glut_roman.c \ glut_shapes.c \ glut_space.c \ diff --git a/src/glut/glx/glut_init.c b/src/glut/glx/glut_init.c index b1a42a3..78843e9 100644 --- a/src/glut/glx/glut_init.c +++ b/src/glut/glx/glut_init.c @@ -51,6 +51,7 @@ int __glutInitX = -1, __glutInitY = -1; GLboolean __glutForceDirect = GL_FALSE, __glutTryDirect = GL_TRUE; Atom __glutWMDeleteWindow; +char *__glutPPMFile = NULL; /* *INDENT-ON* */ #ifdef _WIN32 @@ -341,6 +342,9 @@ glutInit(int *argcp, char **argv) __glutFPS = 5000; /* 5000 milliseconds */ } } + + /* check if GLUT_PPM_FILE env var is set */ + __glutPPMFile = getenv("GLUT_PPM_FILE"); } #ifdef _WIN32 diff --git a/src/glut/glx/glut_ppm.c b/src/glut/glx/glut_ppm.c new file mode 100644 index 0000000..49dca85 --- /dev/null +++ b/src/glut/glx/glut_ppm.c @@ -0,0 +1,80 @@ +/* + * PPM file output + * Brian Paul + * 8 Dec 2008 + */ + +#include +#include +#include +#include "glutint.h" + + +static void +write_ppm_file(const char *filename, const GLubyte *buffer, + int width, int height) +{ + const int binary = 1; + FILE *f = fopen( filename, "w" ); + if (f) { + const GLubyte *ptr = buffer; + int i, x, y; + if (binary) { + fprintf(f,"P6\n"); + fprintf(f,"# ppm-file created by GLUT\n"); + fprintf(f,"%i %i\n", width, height); + fprintf(f,"255\n"); + fclose(f); + f = fopen( filename, "ab" ); /* reopen in binary append mode */ + for (y = height - 1; y >= 0; y--) { + for (x = 0; x < width; x++) { + i = (y * width + x) * 4; + fputc(ptr[i], f); /* write red */ + fputc(ptr[i+1], f); /* write green */ + fputc(ptr[i+2], f); /* write blue */ + } + } + } + else { + /*ASCII*/ + int counter = 0; + fprintf(f,"P3\n"); + fprintf(f,"# ascii ppm file created by GLUT\n"); + fprintf(f,"%i %i\n", width, height); + fprintf(f,"255\n"); + for (y = height - 1; y >= 0; y--) { + for (x = 0; x < width; x++) { + i = (y * width + x) * 4; + fprintf(f, " %3d %3d %3d", ptr[i], ptr[i+1], ptr[i+2]); + counter++; + if (counter % 5 == 0) + fprintf(f, "\n"); + } + } + } + fclose(f); + } +} + + +/** + * Called from SwapBuffers if the GLUT_PPM_FILE env var is set. + */ +void __glutWritePPMFile(void) +{ + int w = glutGet(GLUT_WINDOW_WIDTH); + int h = glutGet(GLUT_WINDOW_HEIGHT); + GLubyte *buf; + + assert(__glutPPMFile); + + buf = (GLubyte *) malloc(w * h * 4); + if (buf) { + /* XXX save/restore pixel packing */ + glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buf); + write_ppm_file(__glutPPMFile, buf, w, h); + free(buf); + } + + __glutPPMFile = NULL; /* only write one file */ +} diff --git a/src/glut/glx/glut_swap.c b/src/glut/glx/glut_swap.c index 4831b8e..07a2da8 100644 --- a/src/glut/glx/glut_swap.c +++ b/src/glut/glx/glut_swap.c @@ -18,6 +18,10 @@ glutSwapBuffers(void) { GLUTwindow *window = __glutCurrentWindow; + if (__glutPPMFile) { + __glutWritePPMFile(); + } + if (window->renderWin == window->win) { if (__glutCurrentWindow->treatAsSingle) { /* Pretend the double buffered window is single buffered, diff --git a/src/glut/glx/glutint.h b/src/glut/glx/glutint.h index de506a5..fe4e038 100644 --- a/src/glut/glx/glutint.h +++ b/src/glut/glx/glutint.h @@ -664,6 +664,7 @@ extern unsigned int __glutModifierMask; #ifdef _WIN32 extern void (__cdecl *__glutExitFunc)(int retval); #endif +extern char *__glutPPMFile; /* private variables from glut_menu.c */ extern GLUTmenuItem *__glutItemSelected; @@ -684,6 +685,9 @@ extern void __glutFreeOverlay(GLUToverlay * overlay); extern XVisualInfo *__glutDetermineWindowVisual(Bool * treatAsSingle, Bool * visAlloced, void **fbc); +/* private variables from glut_ppm.c */ +extern void __glutWritePPMFile(void); + /* private variables from glut_mesa.c */ extern int __glutMesaSwapHackSupport; @@ -812,4 +816,5 @@ extern LONG WINAPI __glutWindowProc(HWND win, UINT msg, WPARAM w, LPARAM l); extern HDC XHDC; #endif + #endif /* __glutint_h__ */ -- cgit v1.2.1