diff options
Diffstat (limited to 'tests/OffscreenContext.mm')
-rw-r--r-- | tests/OffscreenContext.mm | 120 |
1 files changed, 28 insertions, 92 deletions
diff --git a/tests/OffscreenContext.mm b/tests/OffscreenContext.mm index 9a6a5e2..8797e49 100644 --- a/tests/OffscreenContext.mm +++ b/tests/OffscreenContext.mm @@ -1,4 +1,5 @@ #include "OffscreenContext.h" +#include "imageutils.h" #import <OpenGL/OpenGL.h> #import <OpenGL/glu.h> // for gluCheckExtension @@ -26,37 +27,32 @@ OffscreenContext *create_offscreen_context(int w, int h) ctx->pool = [NSAutoreleasePool new]; - /* - * Create an OpenGL context just so that OpenGL calls will work. I'm not - using it for actual rendering. - */ + // Create an OpenGL context just so that OpenGL calls will work. + // Will not be used for actual rendering. - NSOpenGLPixelFormatAttribute attributes[] = { + NSOpenGLPixelFormatAttribute attributes[] = { NSOpenGLPFAPixelBuffer, NSOpenGLPFANoRecovery, NSOpenGLPFAAccelerated, NSOpenGLPFADepthSize, 24, (NSOpenGLPixelFormatAttribute) 0 }; - NSOpenGLPixelFormat* pixFormat = [[[NSOpenGLPixelFormat - alloc] initWithAttributes:attributes] autorelease]; - // Create the OpenGL context to render with (with color and depth buffers) - ctx->openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixFormat - shareContext:nil]; + NSOpenGLPixelFormat *pixFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease]; + + // Create and make current the OpenGL context to render with (with color and depth buffers) + ctx->openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixFormat shareContext:nil]; NULL_ERROR_EXIT(ctx->openGLContext, "Unable to create NSOpenGLContext"); [ctx->openGLContext makeCurrentContext]; - /* - * Test if framebuffer objects are supported - */ + // Test if framebuffer objects are supported + // FIXME: Use GLEW const GLubyte* strExt = glGetString(GL_EXTENSIONS); GLboolean fboSupported = gluCheckExtension((const GLubyte*)"GL_EXT_framebuffer_object", strExt); if (!fboSupported) REPORT_ERROR_AND_EXIT("Your system does not support framebuffer extension - unable to render scene"); - /* - * Create an FBO - */ + + // Create an FBO GLuint renderBuffer = 0; GLuint depthBuffer = 0; // Depth buffer to use for depth testing - optional if you're not using depth testing @@ -79,17 +75,16 @@ OffscreenContext *create_offscreen_context(int w, int h) GL_RENDERBUFFER_EXT, renderBuffer); REPORTGLERROR("specifying color render buffer"); - if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != - GL_FRAMEBUFFER_COMPLETE_EXT) + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { REPORT_ERROR_AND_EXIT("Problem with OpenGL framebuffer after specifying color render buffer."); + } - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, depthBuffer); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer); REPORTGLERROR("specifying depth render buffer"); - if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != - GL_FRAMEBUFFER_COMPLETE_EXT) + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { REPORT_ERROR_AND_EXIT("Problem with OpenGL framebuffer after specifying depth render buffer."); + } return ctx; } @@ -109,96 +104,37 @@ bool teardown_offscreen_context(OffscreenContext *ctx) return true; } +/*! + Capture framebuffer from OpenGL and write it to the given filename as PNG. +*/ bool save_framebuffer(OffscreenContext *ctx, const char *filename) { - /* - * Extract the resulting rendering as an image - */ - + // Read pixels from OpenGL int samplesPerPixel = 4; // R, G, B and A int rowBytes = samplesPerPixel * ctx->width; - char* bufferData = (char*)malloc(rowBytes * ctx->height); + unsigned char *bufferData = (unsigned char *)malloc(rowBytes * ctx->height); if (!bufferData) { std::cerr << "Unable to allocate buffer for image extraction."; return 1; } - glReadPixels(0, 0, ctx->width, ctx->height, GL_BGRA, GL_UNSIGNED_BYTE, + glReadPixels(0, 0, ctx->width, ctx->height, GL_RGBA, GL_UNSIGNED_BYTE, bufferData); REPORTGLERROR("reading pixels from framebuffer"); // Flip it vertically - images read from OpenGL buffers are upside-down - char* flippedBuffer = (char*)malloc(rowBytes * ctx->height); + unsigned char *flippedBuffer = (unsigned char *)malloc(rowBytes * ctx->height); if (!flippedBuffer) { std::cout << "Unable to allocate flipped buffer for corrected image."; return 1; } - for (int i = 0 ; i < ctx->height ; i++) { - bcopy(bufferData + i * rowBytes, flippedBuffer + (ctx->height - i - 1) * - rowBytes, rowBytes); - } + flip_image(bufferData, flippedBuffer, samplesPerPixel, ctx->width, ctx->height); - /* - * Output the image to a file - */ - CGColorSpaceRef colorSpace = - CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - CGBitmapInfo bitmapInfo = kCGImageAlphaNoneSkipFirst | - kCGBitmapByteOrder32Little; // XRGB Little Endian - int bitsPerComponent = 8; - CGContextRef contextRef = CGBitmapContextCreate(flippedBuffer, - ctx->width, ctx->height, bitsPerComponent, rowBytes, - colorSpace, bitmapInfo); - if (!contextRef) { - std::cerr << "Unable to create CGContextRef."; - return false; - } - - CGImageRef imageRef = CGBitmapContextCreateImage(contextRef); - if (!imageRef) { - std::cerr << "Unable to create CGImageRef."; - return false; - } - Boolean isDirectory = false; - CFStringRef fname = CFStringCreateWithCString(kCFAllocatorDefault, filename, kCFStringEncodingUTF8); - CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, - fname, kCFURLPOSIXPathStyle, isDirectory); - if (!fileURL) { - std::cerr << "Unable to create file URL ref."; - return false; - } - CGDataConsumerRef dataconsumer = CGDataConsumerCreateWithURL(fileURL); - - CFIndex fileImageIndex = 1; - CFMutableDictionaryRef fileDict = NULL; - CFStringRef fileUTType = kUTTypePNG; - // Create an image destination opaque reference for authoring an image file - CGImageDestinationRef imageDest = CGImageDestinationCreateWithDataConsumer(dataconsumer, - fileUTType, - fileImageIndex, - fileDict); - if (!imageDest) { - std::cerr << "Unable to create CGImageDestinationRef."; - return false; - } - CFIndex capacity = 1; - CFMutableDictionaryRef imageProps = - CFDictionaryCreateMutable(kCFAllocatorDefault, - capacity, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - CGImageDestinationAddImage(imageDest, imageRef, imageProps); - CGImageDestinationFinalize(imageDest); + bool writeok = write_png(filename, flippedBuffer, ctx->width, ctx->height); free(flippedBuffer); free(bufferData); - CFRelease(imageDest); - CFRelease(dataconsumer); - CFRelease(fileURL); - CFRelease(fname); - CFRelease(imageProps); - CGColorSpaceRelease(colorSpace); - CGImageRelease(imageRef); - return true; + + return writeok; } void bind_offscreen_context(OffscreenContext *ctx) |