From fbdf8c337805b02385bf43b65aad93c20a2e3ad2 Mon Sep 17 00:00:00 2001
From: Gerard Ziemski <gerard.ziemski@sun.com>
Date: Sun, 12 Oct 2003 06:31:59 +0000
Subject: Implemented PBuffers (available in >= Panther). Reimplemented window
 resizing using update listener

git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@67 232f8b59-042b-4e1e-8c03-345bb8c30851
---
 src/native/jogl/ContextUpdater.h              |  40 ++++
 src/native/jogl/ContextUpdater.m              |  83 +++++++
 src/native/jogl/MacOSXWindowSystemInterface.m | 306 ++++++++++++++++++--------
 3 files changed, 342 insertions(+), 87 deletions(-)
 create mode 100644 src/native/jogl/ContextUpdater.h
 create mode 100644 src/native/jogl/ContextUpdater.m

(limited to 'src/native')

diff --git a/src/native/jogl/ContextUpdater.h b/src/native/jogl/ContextUpdater.h
new file mode 100644
index 000000000..e8b757fac
--- /dev/null
+++ b/src/native/jogl/ContextUpdater.h
@@ -0,0 +1,40 @@
+/*
+
+Listens to NSViewGlobalFrameDidChangeNotification
+
+This notification is sent whenever an NSView that has an attached NSSurface changes size or changes screens (thus potentially changing graphics hardware drivers.)
+
+*/
+
+#import <Cocoa/Cocoa.h>
+#import <Foundation/Foundation.h>
+#import <AppKit/NSView.h>
+#import <OpenGL/OpenGL.h>
+#import <OpenGL/gl.h>
+
+//#define DEBUG_GL_LOCKS
+
+#ifdef DEBUG_GL_LOCKS
+	#define LOCK_GL(func, line) [ContextUpdater lockInFunction:func atLine:line];
+	#define UNLOCK_GL(func, line) [ContextUpdater unlockInFunction:func atLine:line];
+#else
+	#define LOCK_GL(func, line) [ContextUpdater lock];
+	#define UNLOCK_GL(func, line) [ContextUpdater unlock];
+#endif
+
+// gznote: OpenGL NOT thread safe - need to sync on update and paints
+
+@interface ContextUpdater : NSObject
+{
+}
+
++ (void) lock;
++ (void) lockInFunction:(char *)func atLine:(int)line;
++ (void) unlock;
++ (void) unlockInFunction:(char *)func atLine:(int)line;
+
+- (void) registerFor:(NSOpenGLContext *)context with: (NSView *)window;
+
+- (void) update:(NSNotification *)notification;
+
+@end
diff --git a/src/native/jogl/ContextUpdater.m b/src/native/jogl/ContextUpdater.m
new file mode 100644
index 000000000..587782c98
--- /dev/null
+++ b/src/native/jogl/ContextUpdater.m
@@ -0,0 +1,83 @@
+#import "ContextUpdater.h"
+#import <pthread.h>
+
+@implementation ContextUpdater
+{
+}
+
+static NSOpenGLContext *theContext;
+static pthread_mutex_t resourceLock = PTHREAD_MUTEX_INITIALIZER;
+
+static void printLockDebugInfo(char *message, char *func, int line)
+{
+	fprintf(stderr, "%s in function: \"%s\" at line: %d\n", message, func, line);
+	fflush(stderr);
+}
+
++ (void) lock
+{
+	if (theContext != NULL)
+	{
+		pthread_mutex_lock(&resourceLock);
+	}
+}
+
++ (void) lockInFunction:(char *)func atLine:(int)line
+{
+	if (theContext != NULL)
+	{
+		printLockDebugInfo("locked  ", func, line);
+		[self lock];
+	}
+}
+
++ (void) unlock
+{
+	if (theContext != NULL)
+	{
+		pthread_mutex_unlock(&resourceLock);
+	}
+}
+
++ (void) unlockInFunction:(char *)func atLine:(int)line
+{
+	if (theContext != NULL)
+	{
+		printLockDebugInfo("unlocked", func, line);
+		[self unlock];
+	}
+}
+
+- (void) registerFor:(NSOpenGLContext *)context with: (NSView *)view
+{
+	if (view != NULL)
+	{
+		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(update:) name:NSViewGlobalFrameDidChangeNotification object: view];
+		theContext = context;
+	}
+}
+
+- (void) update:(NSNotification *)notification
+{
+	[ContextUpdater lock];
+	
+	[theContext update];
+	
+	[ContextUpdater unlock];
+}
+
+- (id) init
+{	
+	theContext = NULL;
+	
+	return [super init];
+}
+
+- (void) dealloc
+{
+	[[NSNotificationCenter defaultCenter] removeObserver:self];
+	
+	[super dealloc];
+}
+
+@end
\ No newline at end of file
diff --git a/src/native/jogl/MacOSXWindowSystemInterface.m b/src/native/jogl/MacOSXWindowSystemInterface.m
index 0499984c3..ceb07a63d 100644
--- a/src/native/jogl/MacOSXWindowSystemInterface.m
+++ b/src/native/jogl/MacOSXWindowSystemInterface.m
@@ -1,83 +1,210 @@
 #import <Cocoa/Cocoa.h>
 #import <OpenGL/gl.h>
+#import "ContextUpdater.h"
+
+#ifndef GL_TEXTURE_RECTANGLE_EXT
+	#define GL_TEXTURE_RECTANGLE_EXT 0x84F5
+#endif
 
 typedef int Bool;
 
-void* createContext(void* nsView, void* shareContext) {
-  NSView *view = nsView;
-  NSOpenGLContext *share = shareContext;
-
-  // FIXME: hardcoded pixel format. Instead pass these attributes down
-  // as arguments. There is really no way to enumerate the possible
-  // pixel formats for a given window on Mac OS X, so we will assume
-  // that we can match the requested capabilities and leave the
-  // selection up to the built-in pixel format selection algorithm.
-  GLuint attribs[] = {
-    NSOpenGLPFANoRecovery,
-    NSOpenGLPFAWindow,
-    NSOpenGLPFAAccelerated,
-    NSOpenGLPFADoubleBuffer,
-    NSOpenGLPFAColorSize, 32,
-    NSOpenGLPFAAlphaSize, 8,
-    NSOpenGLPFADepthSize, 24,
-    NSOpenGLPFAStencilSize, 8,
-    NSOpenGLPFAAccumSize, 0,
-    0
-  };
-
-  NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: (NSOpenGLPixelFormatAttribute*) attribs];
-
-  NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat: [fmt autorelease] shareContext: share];
-
-  if (view != nil) {
-    [context setView: view];
-
-    [context makeCurrentContext];
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-    [context update];
-    [context flushBuffer];
-  }
-
-  return context;
+NSAutoreleasePool* gAutoreleasePool = NULL;
+
+void* createContext(void* shareContext, void* view)
+{
+//fprintf(stderr, "createContext shareContext=%p view=%p\n", shareContext, view);
+	NSOpenGLContext *nsChareCtx = (NSOpenGLContext*)shareContext;
+	NSView *nsView = (NSView*)view;
+	
+	if (gAutoreleasePool == NULL)
+	{
+		gAutoreleasePool = [[NSAutoreleasePool alloc] init];
+	}
+	
+	// FIXME: hardcoded pixel format. Instead pass these attributes down
+	// as arguments. There is really no way to enumerate the possible
+	// pixel formats for a given window on Mac OS X, so we will assume
+	// that we can match the requested capabilities and leave the
+	// selection up to the built-in pixel format selection algorithm.
+	NSOpenGLPixelFormatAttribute attribs[] =
+	{
+		NSOpenGLPFANoRecovery, YES,
+		NSOpenGLPFAAccelerated, YES,
+		NSOpenGLPFADoubleBuffer, YES,
+		NSOpenGLPFAColorSize, 32,
+		NSOpenGLPFAAlphaSize, 8,
+		NSOpenGLPFADepthSize, 8,
+		NSOpenGLPFAStencilSize, 8,
+		NSOpenGLPFAAccumSize, 0,
+		0
+	};
+	
+	if (nsView == NULL)
+	{
+		attribs[12] = 0; // no stencil, no accums fo pBuffers
+	}
+	
+	NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+	
+	NSOpenGLContext* nsContext = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nsChareCtx];
+	
+	[fmt release];
+	
+	if (nsView != nil)
+	{
+		[nsContext setView: nsView];		
+	}
+		
+	[nsContext retain];
+	
+//fprintf(stderr, "	nsContext=%p\n", nsContext);
+	return nsContext;
 }
 
-Bool makeCurrentContext(void* nsView, void* nsContext) {
-  NSOpenGLContext *context = 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;
+}
 
-  [context makeCurrentContext];
-  return true;
+Bool clearCurrentContext(void* context, void* view)
+{
+//fprintf(stderr, "clearCurrentContext context=%p, view=%p\n", context, view);
+	[NSOpenGLContext clearCurrentContext];
+	return true;
 }
 
-Bool clearCurrentContext(void* nsView, void* nsContext) {
-  NSView *view = nsView;
-  NSOpenGLContext *context = nsContext;
+Bool deleteContext(void* context, void* view)
+{
+//fprintf(stderr, "deleteContext context=%p, view=%p\n", context, view);
+	NSOpenGLContext *nsContext = (NSOpenGLContext*)context;
+	
+	[nsContext setView: nil];
+	[nsContext release];
+	return true;
+}
 
-  [NSOpenGLContext clearCurrentContext];
-  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* nsView, void* nsContext) {
-  NSView *view = nsView;
-  NSOpenGLContext *context = nsContext;
+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];
+}
 
-  [context update];
+void updateContextUnregister(void* context, void* view, void* updater)
+{
+//fprintf(stderr, "updateContextUnregister context=%p, view=%p\n", context, view);
+	ContextUpdater *contextUpdater = (ContextUpdater *)updater;
+	
+	[contextUpdater release];
 }
 
-Bool deleteContext(void* nsView, void* nsContext) {
-  NSOpenGLContext *context = nsContext;
+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);
+}
 
-  [context setView: nil];
-  [context release];
-  return true;
+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;
+	
+	//unsigned long taget = GL_TEXTURE_RECTANGLE_EXT;
+	unsigned long taget = GL_TEXTURE_2D; // texture size must be a multiple of power of 2
+	
+	width = getNextPowerOf2(width);
+	height = getNextPowerOf2(height);
+	
+	NSOpenGLPixelBuffer* pBuffer = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:taget textureInternalFormat:GL_RGBA textureMaxMipMapLevel:0 pixelsWide:width pixelsHigh:height];
+	
+	[nsContext setPixelBuffer:pBuffer cubeMapFace:0 mipMapLevel:0 currentVirtualScreen:0];
+	
+	return pBuffer;
+#else
+	return NULL;
+#endif
 }
 
-Bool flushBuffer(void* nsView, void* nsContext) {
-  NSOpenGLContext *context = nsContext;
+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;
+	
+	[nsContext setPixelBuffer:NULL cubeMapFace:0 mipMapLevel:0 currentVirtualScreen:0];
+	[pBuffer release];
+	
+	return true;
+#else
+	return false;
+#endif
+}
 
-  [context flushBuffer];
-  return true;
+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;
+			
+	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]);
+	
+	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;
+	
+	//glDisable([pBuffer textureTarget]);
+	glDeleteTextures(1, &pBufferTextureName);
+#endif
+}
 
 #include <mach-o/dyld.h>
 Bool imagesInitialized = false;
@@ -85,32 +212,37 @@ static char libGLStr[] = "/System/Library/Frameworks/OpenGL.framework/Libraries/
 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;
-}
+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;
+}
\ No newline at end of file
-- 
cgit v1.2.3