Created
April 26, 2009 08:39
-
-
Save nevyn/101958 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSImageGLTextureAdditions.h | |
// SkryllePhoto | |
// | |
// Created by Joachim Bengtsson on 2007-05-14. | |
// Copyright 2007 Joachim Bengtsson. All rights reserved. | |
// | |
#import <Cocoa/Cocoa.h> | |
#import <OpenGL/gl.h> | |
@interface GLTexture : NSObject { | |
GLuint texID; | |
NSBitmapImageRep *cache; | |
NSSize size; | |
} | |
/// Just takes ownership. NOTE: does not store size! | |
-(GLTexture*)initWithTexID:(GLuint)tid; | |
/// Creates a texture from src | |
-(GLTexture*)initWithNSImage:(NSImage*)src; | |
/// Does the expensive part of -[GLTexture useImage]. Can be called from any thread. | |
-(void)prepareCacheForImage:(NSImage*)src; | |
/// Converts src to an OpenGL texture. | |
/// @arg src may be nil if -[GLTexture prepareCacheForImage] has been called. | |
/// @note Calling this method invalidates the cache generated by -[GLTexture prepareCacheForImage] | |
/// @note Must be called from the same thread that the OpenGL context was created in. | |
-(GLTexture*)useImage:(NSImage*)src; | |
-(void)deleteTexture; | |
-(NSSize)size; | |
-(void)apply; | |
-(void)unapply; | |
// Private | |
-(void)makeOpenGLTextureOfInternalCache; | |
@end | |
@interface NSImage(NSImageGLTextureAdditions) | |
-(GLTexture*)glTexture; | |
-(NSSize)pixelSize; | |
+(NSImage*)imageWithContentsOfPath:(NSString*)path; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSImageGLTextureAdditions.m | |
// SkryllePhoto | |
// | |
// Created by Joachim Bengtsson on 2007-05-14. | |
// Copyright 2007 Joachim Bengtsson. All rights reserved. | |
// | |
#import "GLTexture.h" | |
#import <OpenGL/glu.h> | |
#import "NCCommon.h" | |
@implementation GLTexture | |
-(GLTexture*)initWithTexID:(GLuint)tid; | |
{ | |
if(![super init]) return nil; | |
cache = nil; | |
texID = tid; | |
return self; | |
} | |
-(GLTexture*)initWithNSImage:(NSImage*)src; | |
{ | |
if(![super init]) return nil; | |
cache = nil; | |
[self useImage:src]; | |
return self; | |
} | |
-(void)prepareCacheForImage:(NSImage*)src; | |
{ | |
[cache release]; | |
size = [src size]; | |
size.width = floorf( size.width ); | |
size.height = floorf( size.height ); | |
cache = [[NSBitmapImageRep alloc] | |
initWithBitmapDataPlanes: NULL | |
pixelsWide: size.width | |
pixelsHigh: size.height | |
bitsPerSample: 8 | |
samplesPerPixel: 4 | |
hasAlpha: YES | |
isPlanar: NO | |
colorSpaceName: NSDeviceRGBColorSpace | |
bitmapFormat: 0 | |
bytesPerRow: 0 | |
bitsPerPixel: 32]; | |
bzero( [cache bitmapData], size.height * [cache bytesPerRow] ); | |
NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep: cache]; | |
NSGraphicsContext *old = [[NSGraphicsContext currentContext] retain]; | |
[NSGraphicsContext setCurrentContext: ctx]; | |
NSRect rect = { NSZeroPoint, size }; | |
[src drawInRect: rect fromRect: rect operation: NSCompositeSourceOver fraction: 1.0]; // 500 ms for 3mpx | |
[NSGraphicsContext setCurrentContext: old]; [old release]; | |
} | |
-(GLTexture*)useImage:(NSImage*)src; | |
{ | |
if(!cache) | |
[self prepareCacheForImage:src]; | |
[self makeOpenGLTextureOfInternalCache]; | |
[cache release]; cache = nil; | |
return self; | |
} | |
-(void)deleteTexture; | |
{ | |
if(texID) | |
glDeleteTextures(1,&texID); | |
texID = 0; // ensure it is zeroed for failure cases | |
} | |
-(void)dealloc; | |
{ | |
[self deleteTexture]; | |
[super dealloc]; | |
} | |
-(NSSize)size; | |
{ | |
return size; | |
} | |
-(void)apply; | |
{ | |
glEnable(GL_TEXTURE_RECTANGLE_EXT); | |
glBindTexture (GL_TEXTURE_RECTANGLE_EXT, texID); | |
} | |
-(void)unapply; | |
{ | |
glDisable(GL_TEXTURE_RECTANGLE_EXT); | |
} | |
-(void)makeOpenGLTextureOfInternalCache; | |
{ | |
if(texID == 0) | |
glGenTextures(1, &texID); | |
glBindTexture( GL_TEXTURE_RECTANGLE_EXT, texID); | |
glReportError(); | |
glTexParameteri( GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP ); | |
glTexParameteri( GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP ); | |
glTexParameteri( GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); | |
glTexParameteri( GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); | |
glReportError(); | |
glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); | |
glPixelStorei( GL_UNPACK_ROW_LENGTH, [cache bytesPerRow] / 4 ); | |
glReportError(); | |
glTexImage2D( GL_TEXTURE_RECTANGLE_EXT, | |
0, | |
GL_RGBA, | |
size.width, | |
size.height, | |
0, | |
GL_RGBA, | |
GL_UNSIGNED_BYTE, | |
[cache bitmapData] ); | |
glReportError(); | |
} | |
-(NSString*)description; | |
{ | |
return sf(@"<GLTexture@%p wraps texid %d of size (%.2f, %.2f)>", self, texID, size.width, size.height); | |
} | |
@end | |
static unsigned int truncPowerOf2(unsigned int x) | |
{ | |
int i = 0; | |
while (x = x>>1) i++; | |
return (1<<i); | |
} | |
@implementation NSImage(NSImageGLTextureAdditions) | |
-(GLTexture*)glTexture; | |
{ | |
return [[[GLTexture alloc] initWithNSImage:self] autorelease]; | |
} | |
-(NSSize)pixelSize; | |
{ | |
NSImageRep *r = [self bestRepresentationForDevice:nil]; | |
return NSMakeSize([r pixelsWide],[r pixelsHigh]); | |
} | |
+(NSImage*)imageWithContentsOfPath:(NSString*)path; | |
{ | |
return [[[NSImage alloc] initWithContentsOfFile:path] autorelease]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment