#import <Cocoa/Cocoa.h> #import <OpenGL/gl.h> #import <jni.h> #import "ContextUpdater.h" // see MacOSXPbufferGLContext.java createPbuffer #define USE_GL_TEXTURE_RECTANGLE_EXT #ifdef USE_GL_TEXTURE_RECTANGLE_EXT #ifndef GL_TEXTURE_RECTANGLE_EXT #define GL_TEXTURE_RECTANGLE_EXT 0x84F5 #endif #endif typedef int Bool; NSAutoreleasePool* gAutoreleasePool = NULL; void* createContext(void* shareContext, void* view, int redBits, int greenBits, int blueBits, int alphaBits, int depthBits, int stencilBits, int accumRedBits, int accumGreenBits, int accumBlueBits, int accumAlphaBits, int sampleBuffers, int numSamples) { int colorSize = redBits + greenBits + blueBits; int accumSize = accumRedBits + accumGreenBits + accumBlueBits; NSOpenGLContext *nsChareCtx = (NSOpenGLContext*)shareContext; NSView *nsView = (NSView*)view; if (nsView != NULL) { NSRect frame = [nsView frame]; if ((frame.size.width == 0) || (frame.size.height == 0)) { fprintf(stderr, "Error: view width or height == 0at \"%s:%s:%d\"\n", __FILE__, __FUNCTION__, __LINE__); // the view is not ready yet return NULL; } else if ([nsView lockFocusIfCanDraw] == NO) { fprintf(stderr, "Error: view not ready, cannot lock focus at \"%s:%s:%d\"\n", __FILE__, __FUNCTION__, __LINE__); // the view is not ready yet return NULL; } } if (gAutoreleasePool == NULL) { gAutoreleasePool = [[NSAutoreleasePool alloc] init]; } NSOpenGLPixelFormatAttribute attribs[] = { NSOpenGLPFANoRecovery, YES, NSOpenGLPFAAccelerated, YES, NSOpenGLPFADoubleBuffer, YES, NSOpenGLPFAColorSize, colorSize, NSOpenGLPFAAlphaSize, alphaBits, NSOpenGLPFADepthSize, depthBits, NSOpenGLPFAStencilSize, stencilBits, NSOpenGLPFAAccumSize, accumSize, NSOpenGLPFASampleBuffers, sampleBuffers, NSOpenGLPFASamples, numSamples, 0 }; NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; NSOpenGLContext* nsContext = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nsChareCtx]; [fmt release]; if (nsView != nil) { [nsContext setView:nsView]; [nsView unlockFocus]; } [nsContext retain]; //fprintf(stderr, " nsContext=%p\n", nsContext); return nsContext; } Bool makeCurrentContext(void* context, void* view) { //fprintf(stderr, "makeCurrentContext context=%p, view=%p\n", context, view); NSOpenGLContext *nsContext = (NSOpenGLContext*)context; [nsContext makeCurrentContext]; return true; } Bool clearCurrentContext(void* context, void* view) { //fprintf(stderr, "clearCurrentContext context=%p, view=%p\n", context, view); [NSOpenGLContext clearCurrentContext]; return true; } Bool deleteContext(void* context, void* view) { //fprintf(stderr, "deleteContext context=%p, view=%p\n", context, view); NSOpenGLContext *nsContext = (NSOpenGLContext*)context; [nsContext clearDrawable]; [nsContext release]; return true; } Bool flushBuffer(void* context, void* view) { //fprintf(stderr, "flushBuffer context=%p, view=%p\n", context, view); NSOpenGLContext *nsContext = (NSOpenGLContext*)context; [nsContext flushBuffer]; return true; } void updateContext(void* context, void* view) { //fprintf(stderr, "updateContext context=%p, view=%p\n", context, view); NSOpenGLContext *nsContext = (NSOpenGLContext*)context; [nsContext update]; } void* updateContextRegister(void* context, void* view) { //fprintf(stderr, "updateContextRegister context=%p, view=%p\n", context, view); NSOpenGLContext *nsContext = (NSOpenGLContext*)context; NSView *nsView = (NSView*)view; ContextUpdater *contextUpdater = [[ContextUpdater alloc] init]; [contextUpdater registerFor:nsContext with:nsView]; } void updateContextUnregister(void* context, void* view, void* updater) { //fprintf(stderr, "updateContextUnregister context=%p, view=%p\n", context, view); ContextUpdater *contextUpdater = (ContextUpdater *)updater; [contextUpdater release]; } #ifndef USE_GL_TEXTURE_RECTANGLE_EXT static int getNextPowerOf2(int number) { if (((number-1) & number) == 0) { //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0 return number; } int power = 0; while (number > 0) { number = number>>1; power++; } return (1<<power); } #endif void* createPBuffer(void* context, int width, int height) { ///fprintf(stderr, "createPBuffer context=%p width=%d height=%d\n", context, width, height); #ifdef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER) NSOpenGLContext *nsContext = (NSOpenGLContext*)context; #ifdef USE_GL_TEXTURE_RECTANGLE_EXT unsigned long taget = GL_TEXTURE_RECTANGLE_EXT; #else unsigned long taget = GL_TEXTURE_2D; // texture size must be a multiple of power of 2 width = getNextPowerOf2(width); height = getNextPowerOf2(height); #endif NSOpenGLPixelBuffer* pBuffer = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:taget textureInternalFormat:GL_RGBA textureMaxMipMapLevel:0 pixelsWide:width pixelsHigh:height]; [nsContext setPixelBuffer:pBuffer cubeMapFace:0 mipMapLevel:0 currentVirtualScreen:0]; [nsContext update]; return pBuffer; #else return NULL; #endif } Bool destroyPBuffer(void* context, void* buffer) { //fprintf(stderr, "destroyPBuffer context=%p, buffer=%p\n", context, buffer); #ifdef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER) NSOpenGLContext *nsContext = (NSOpenGLContext*)context; NSOpenGLPixelBuffer *pBuffer = (NSOpenGLPixelBuffer*)buffer; if (nsContext != NULL) { [nsContext clearDrawable]; } [pBuffer release]; return true; #else return false; #endif } int bindPBuffer(void* context, void* buffer) { //fprintf(stderr, "bindPBuffer context=%p, buffer=%p\n", context, buffer); #ifdef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER) NSOpenGLContext *nsContext = (NSOpenGLContext*)context; NSOpenGLPixelBuffer *pBuffer = (NSOpenGLPixelBuffer*)buffer; glPushMatrix(); glPushAttrib(GL_CURRENT_BIT|GL_ENABLE_BIT|GL_TEXTURE_BIT|GL_TRANSFORM_BIT); GLuint pBufferTextureName; glGenTextures(1, &pBufferTextureName); glBindTexture([pBuffer textureTarget], pBufferTextureName); glTexParameteri([pBuffer textureTarget], GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri([pBuffer textureTarget], GL_TEXTURE_MAG_FILTER, GL_NEAREST); [nsContext setTextureImageToPixelBuffer:pBuffer colorBuffer:GL_FRONT_LEFT]; glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable([pBuffer textureTarget]); #ifdef USE_GL_TEXTURE_RECTANGLE_EXT //GLint matrixMode; //glGetIntegerv(GL_MATRIX_MODE, &matrixMode); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScalef([pBuffer pixelsWide], [pBuffer pixelsHigh], 1.0f); // GL_TEXTURE_RECTANGLE_EXT wants texture coordinates in texture image space (not 0 to 1) //glMatrixMode(matrixMode); #endif return pBufferTextureName; #else return 0; #endif } void unbindPBuffer(void* context, void* buffer, int texture) { //fprintf(stderr, "unbindPBuffer context=%p, buffer=%p\n", context, buffer); #ifdef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER) NSOpenGLPixelBuffer *pBuffer = (NSOpenGLPixelBuffer*)buffer; GLuint pBufferTextureName = (GLuint)texture; glDeleteTextures(1, &pBufferTextureName); glPopAttrib(); glPopMatrix(); #endif } #include <mach-o/dyld.h> Bool imagesInitialized = false; static char libGLStr[] = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"; static char libGLUStr[] = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib"; static const struct mach_header *libGLImage; static const struct mach_header *libGLUImage; void* getProcAddress(const char *procname) { if (imagesInitialized == false) { imagesInitialized = true; unsigned long options = NSADDIMAGE_OPTION_RETURN_ON_ERROR; libGLImage = NSAddImage(libGLStr, options); libGLUImage = NSAddImage(libGLUStr, options); } unsigned long options = NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR; char underscoreName[512] = "_"; strcat(underscoreName, procname); if (NSIsSymbolNameDefinedInImage(libGLImage, underscoreName) == YES) { NSSymbol sym = NSLookupSymbolInImage(libGLImage, underscoreName, options); return NSAddressOfSymbol(sym); } if (NSIsSymbolNameDefinedInImage(libGLUImage, underscoreName) == YES) { NSSymbol sym = NSLookupSymbolInImage(libGLUImage, underscoreName, options); return NSAddressOfSymbol(sym); } if (NSIsSymbolNameDefinedWithHint(underscoreName, "GL")) { NSSymbol sym = NSLookupAndBindSymbol(underscoreName); return NSAddressOfSymbol(sym); } return NULL; }