/*From: dek@socrates.cgl.ucsf.edu (David Konerding)*/ /*Newsgroups: comp.sys.sgi.graphics*/ /*Subject: Re: GL rendering to pixmap*/ /*Date: 4 Aug 1998 16:38:42 GMT*/ #include #include #include #include #include #include #include #include #include #include #define DEPTH 16 #define WIDTH 320 #define HEIGHT 200 static FILE *TiffFileP; static int Orient; static int ImgW, ImgH; static Bool OutOfMemory; static Display *Dpy; static Pixmap XPix = 0; static GLXPixmap GPix = 0; static GLXContext OldCtx, Ctx; static void destroyPixmap(void) { glXDestroyGLXPixmap(Dpy, GPix); GPix = 0; XFreePixmap(Dpy, XPix); XPix = 0; } static int myXErrorHandler(Display *p_disp, XErrorEvent *p_error) { char err_msg[80]; XGetErrorText(p_disp, p_error->error_code, err_msg, 80); printf("Error detected: %s\n", err_msg); printf("Protocol request: %d\n", p_error->request_code); printf("Resource ID: %d\n", p_error->resourceid); exit(1); return 0; } void RaiseError(const char *msg) { fprintf(stderr, msg); exit(1); } int StartDump(char *fileName, int orient, int w, int h) { XErrorHandler oldHandler; int attrList[10]; XVisualInfo *visP; int n; TiffFileP = fopen(fileName, "w"); if (TiffFileP == NULL) { RaiseError("could not open output file"); return 1; } if (GPix != 0 && (w != ImgW || h != ImgH)) destroyPixmap(); Orient = orient; ImgW = w; ImgH = h; Dpy=XOpenDisplay(0); n = 0; attrList[n++] = GLX_RGBA; attrList[n++] = GLX_RED_SIZE; attrList[n++] = 8; attrList[n++] = GLX_GREEN_SIZE; attrList[n++] = 8; attrList[n++] = GLX_BLUE_SIZE; attrList[n++] = 8; attrList[n++] = GLX_DEPTH_SIZE; attrList[n++] = 1; attrList[n++] = None; visP = glXChooseVisual(Dpy, DefaultScreen(Dpy), attrList); if (visP == NULL) { RaiseError("no 24-bit true color visual available"); return 1; } oldHandler = XSetErrorHandler(myXErrorHandler); if (XPix == 0) { XPix = XCreatePixmap(Dpy, RootWindow(Dpy, visP->screen), w, h, DEPTH); XSync(Dpy, False); /* error comes too late otherwise */ } if (GPix == 0) { GPix = glXCreateGLXPixmap(Dpy, visP, XPix); XSync(Dpy, False); XSetErrorHandler(oldHandler); if (OutOfMemory) { GPix = 0; XFreePixmap(Dpy, XPix); XPix = 0; RaiseError("could not allocate Pixmap"); return 1; } } Ctx = glXCreateContext(Dpy, visP, NULL, False); if (Ctx == NULL) { destroyPixmap(); RaiseError("could not create rendering context"); return 1; } OldCtx = glXGetCurrentContext(); (void) glXMakeCurrent(Dpy, GPix, Ctx); return 0; } static int writeTiff(void) { TIFF *tif; int tiffW, tiffH; int bufSize, rowI; unsigned char *buf; int res; tif = TIFFFdOpen(fileno(TiffFileP), "output file", "w"); if (tif == NULL) { RaiseError("could not create TIFF file"); return 1; } if (Orient == 0) { tiffW = ImgW; tiffH = ImgH; bufSize = 4 * ((3 * tiffW + 3) / 4); glPixelStorei(GL_PACK_ALIGNMENT, 4); } else { tiffW = ImgH; tiffH = ImgW; bufSize = 3 * tiffW; glPixelStorei(GL_PACK_ALIGNMENT, 1); } TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, tiffW); TIFFSetField(tif, TIFFTAG_IMAGELENGTH, tiffH); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW); TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); TIFFSetField(tif, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, "My Name"); TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "My Description"); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3); TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, (8 * 1024) / (3 * tiffW)); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); buf = malloc(bufSize * sizeof(*buf)); res = 0; for (rowI = 0; rowI < tiffH; rowI++) { if (Orient == 0) glReadPixels(0, ImgH - 1 - rowI, ImgW, 1, GL_RGB, GL_UNSIGNED_BYTE, buf); else glReadPixels(rowI, 0, 1, ImgH, GL_RGB, GL_UNSIGNED_BYTE, buf); if (TIFFWriteScanline(tif, buf, rowI, 0) < 0) { RaiseError("error while writing TIFF file"); res = 1; break; } } free(buf); TIFFFlushData(tif); TIFFClose(tif); return res; } int EndDump(void) { int res; res = writeTiff(); (void) fclose(TiffFileP); (void) glXMakeCurrent(Dpy, XOpenDisplay(0), OldCtx); destroyPixmap(); glXDestroyContext(Dpy, Ctx); return res; } int render(int width, int height) { float trans[3] = { 0, 0, 0 }; float rot[4] = { 0, 0, 0, 0 }; /* glViewport(0, 0, (GLint)width, (GLint)height); */ /* glMatrixMode(GL_PROJECTION); */ /* glLoadIdentity(); */ /* glMatrixMode(GL_MODELVIEW); */ glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_LIGHTING); glPushMatrix(); glTranslatef(trans[0], trans[1], trans[2]); glRotatef(rot[0], rot[1], rot[2], rot[3]); glBegin(GL_QUADS); glColor3f(1,0,0); glVertex2f(-1,-1); glColor3f(0,1,0); glVertex2f(-1,1); glColor3f(0,0,1); glVertex2f(1,1); glColor3f(1,1,0); glVertex2f(1,-1); glEnd(); glPopMatrix(); return 0; } /* To use: Call StartDump Render Call EndDump */ int main(void) { StartDump("out.tiff", 0, WIDTH, HEIGHT); render(WIDTH, HEIGHT); EndDump(); exit(0); }