From 0dda33cd2d7d25c416256137cd323b1c1f30f978 Mon Sep 17 00:00:00 2001 From: kappaOne Date: Sun, 13 Jan 2013 15:34:24 +0000 Subject: [PATCH] Implement CALayer rendering, no input yet --- src/java/org/lwjgl/opengl/MacOSXDisplay.java | 8 ++ src/native/macosx/context.h | 6 + src/native/macosx/org_lwjgl_opengl_Display.m | 50 ++++---- .../org_lwjgl_opengl_MacOSXCanvasPeerInfo.m | 116 ++++++++++++------ ...lwjgl_opengl_MacOSXContextImplementation.m | 9 +- 5 files changed, 126 insertions(+), 63 deletions(-) diff --git a/src/java/org/lwjgl/opengl/MacOSXDisplay.java b/src/java/org/lwjgl/opengl/MacOSXDisplay.java index 73f8831c..ea2d0168 100644 --- a/src/java/org/lwjgl/opengl/MacOSXDisplay.java +++ b/src/java/org/lwjgl/opengl/MacOSXDisplay.java @@ -84,6 +84,8 @@ final class MacOSXDisplay implements DisplayImplementation { private static final IntBuffer current_viewport = BufferUtils.createIntBuffer(16); private boolean close_requested; + + private boolean native_mode = true; MacOSXDisplay() { @@ -123,6 +125,8 @@ final class MacOSXDisplay implements DisplayImplementation { close_requested = false; + native_mode = isNativeMode(); + DrawableGL gl_drawable = (DrawableGL)Display.getDrawable(); PeerInfo peer_info = gl_drawable.peer_info; ByteBuffer peer_handle = peer_info.lockAndGetHandle(); @@ -148,6 +152,10 @@ final class MacOSXDisplay implements DisplayImplementation { peer_info.unlock(); } } + + private boolean isNativeMode() { + return true; + } public void doHandleQuit() { synchronized (this) { diff --git a/src/native/macosx/context.h b/src/native/macosx/context.h index 892f1ab0..e274eb5a 100644 --- a/src/native/macosx/context.h +++ b/src/native/macosx/context.h @@ -102,10 +102,16 @@ typedef struct { @private CGLContextObj contextObject; + int fboID; + int imageRenderBufferID; + int depthRenderBufferID; + int fboWidth; + int fboHeight; } - (void) attachLayer; - (void) removeLayer; +- (void) blitFrameBuffer; @end diff --git a/src/native/macosx/org_lwjgl_opengl_Display.m b/src/native/macosx/org_lwjgl_opengl_Display.m index 7890acc4..93eaadac 100644 --- a/src/native/macosx/org_lwjgl_opengl_Display.m +++ b/src/native/macosx/org_lwjgl_opengl_Display.m @@ -435,35 +435,29 @@ JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nCreateWindow(JNIE if (!fullscreen) { - int default_window_mask = NSBorderlessWindowMask; // undecorated - - if (!undecorated) { - default_window_mask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask; - } - - if (resizable) { - default_window_mask |= NSResizableWindowMask; - } - if (parented) { - if (peer_info->parent != nil) { - window_info->window = [peer_info->parent window]; + if (peer_info->isCALayer) { + window_info->window = [[MacOSXKeyableWindow alloc] initWithContentRect:window_info->display_rect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]; + [window_info->window setContentView:window_info->view]; } else { - window_info->window = nil; - } - - if (window_info->window != nil) { + window_info->window = [peer_info->parent window]; [peer_info->parent addSubview:window_info->view]; [window_info->view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; } - else { - // failed to get parent window, create a new window - window_info->window = [[MacOSXKeyableWindow alloc] initWithContentRect:window_info->display_rect styleMask:default_window_mask backing:NSBackingStoreBuffered defer:NO]; - [window_info->window setContentView:window_info->view]; - } } else { + + int default_window_mask = NSBorderlessWindowMask; // undecorated + + if (!undecorated) { + default_window_mask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask; + } + + if (resizable) { + default_window_mask |= NSResizableWindowMask; + } + window_info->window = [[MacOSXKeyableWindow alloc] initWithContentRect:window_info->display_rect styleMask:default_window_mask backing:NSBackingStoreBuffered defer:NO]; [window_info->window setContentView:window_info->view]; @@ -501,9 +495,15 @@ JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nCreateWindow(JNIE // Inform the view of its parent window info; [window_info->view setParent:window_info]; - [window_info->window performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:window_info->view waitUntilDone:NO]; - [window_info->window performSelectorOnMainThread:@selector(setInitialFirstResponder:) withObject:window_info->view waitUntilDone:NO]; - [window_info->window performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:[NSApplication sharedApplication] waitUntilDone:NO]; + if (peer_info->isCALayer) { + // hidden window when using CALayer + [window_info->window orderOut:nil]; + } + else { + [window_info->window performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:window_info->view waitUntilDone:NO]; + [window_info->window performSelectorOnMainThread:@selector(setInitialFirstResponder:) withObject:window_info->view waitUntilDone:NO]; + [window_info->window performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:[NSApplication sharedApplication] waitUntilDone:NO]; + } window_info->fullscreen = fullscreen; @@ -525,7 +525,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXDisplay_nDestroyWindow(JNIEnv [window_info->window close]; } else { - // the nsview has a parent, so remove it from there + // the nsview has a parent, remove it from there [window_info->view removeFromSuperviewWithoutNeedingDisplay]; } } diff --git a/src/native/macosx/org_lwjgl_opengl_MacOSXCanvasPeerInfo.m b/src/native/macosx/org_lwjgl_opengl_MacOSXCanvasPeerInfo.m index d12cbdf0..1b49e57d 100644 --- a/src/native/macosx/org_lwjgl_opengl_MacOSXCanvasPeerInfo.m +++ b/src/native/macosx/org_lwjgl_opengl_MacOSXCanvasPeerInfo.m @@ -98,6 +98,68 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXCanvasPeerInfo_nInitHandle surfaceLayers.layer = nil; } +- (void) blitFrameBuffer { + + // get the size of the CALayer/AWT Canvas + int width = self.bounds.size.width; + int height = self.bounds.size.height; + + if (width != fboWidth || height != fboHeight) { + + // store current fbo/renderbuffers for later deletion + int oldFboID = fboID; + int oldImageRenderBufferID = imageRenderBufferID; + int oldDepthRenderBufferID = depthRenderBufferID; + + // set the size of the offscreen frame buffer window + window_info->display_rect = NSMakeRect(0, 0, width, height); + [window_info->window setFrame:window_info->display_rect display:false]; + + // create new fbo + int tempFBO; + glGenFramebuffersEXT(1, &tempFBO); + + // create new render buffers + glGenRenderbuffersEXT(1, &imageRenderBufferID); + glGenRenderbuffersEXT(1, &depthRenderBufferID); + + // switch to new fbo to attach render buffers + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tempFBO); + + // initialize and attach image render buffer + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, imageRenderBufferID); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, width, height); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, imageRenderBufferID); + + // initialize and attach depth render buffer + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthRenderBufferID); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthRenderBufferID); + + // set new fbo and its sizes + fboID = tempFBO; + fboWidth = width; + fboHeight = height; + + // clean up the old fbo and renderBuffers + glDeleteFramebuffersEXT(1, &oldFboID); + glDeleteRenderbuffersEXT(1, &oldImageRenderBufferID); + glDeleteRenderbuffersEXT(1, &oldDepthRenderBufferID); + } + else { + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fboID); + + glBlitFramebufferEXT(0, 0, width, height, + 0, 0, width, height, + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, + GL_NEAREST); + } + + // restore default framebuffer + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +} + -(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval @@ -106,48 +168,30 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXCanvasPeerInfo_nInitHandle // set the current context CGLSetCurrentContext(glContext); - GLint originalFBO; + if (fboID == 0) { + // clear garbage background before lwjgl fbo is set + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + } + + // get the size of the CALayer + int width = fboWidth; + int height = fboHeight; + GLint originalReadFBO; - GLint originalDrawFBO; // get and save the current fbo values - glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &originalFBO); glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &originalReadFBO); - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &originalDrawFBO); - /*glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); + // read the LWJGL FBO and blit it into this CALayers FBO + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fboID); + glBlitFramebufferEXT(0, 0, width, height, + 0, 0, width, height, + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, + GL_NEAREST); - // copy/blit the LWJGL FBO to this CALayers FBO - // TODO - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 1);//lwjglFBO); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, originalFBO); - - glBlitFramebufferEXT(0, 0, 640, 480,//width, height, - 0, 0, 640, 480,//width, height, - GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, - GL_NEAREST);*/ - - // for testing, draw a single yellow quad spinning around based on the current time - GLfloat rotate = timeInterval * 60.0; // 60 degrees per second - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glRotatef(rotate, 0.0, 0.0, 1.0); - glBegin(GL_QUADS); - glColor3f(1.0, 1.0, 0.0); - glVertex2f(-0.5, -0.5); - glVertex2f(-0.5, 0.5); - glVertex2f( 0.5, 0.5); - glVertex2f( 0.5, -0.5); - glEnd(); - glPopMatrix(); - - - // restore original fbo read and draw values + // restore original fbo read value glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, originalReadFBO); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, originalDrawFBO); // call super to finalize the drawing - by default all it does is call glFlush() [super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:timeInterval displayTime:timeStamp]; @@ -177,4 +221,4 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXCanvasPeerInfo_nInitHandle } -@end +@end \ No newline at end of file diff --git a/src/native/macosx/org_lwjgl_opengl_MacOSXContextImplementation.m b/src/native/macosx/org_lwjgl_opengl_MacOSXContextImplementation.m index 4af0c256..ae6625d8 100644 --- a/src/native/macosx/org_lwjgl_opengl_MacOSXContextImplementation.m +++ b/src/native/macosx/org_lwjgl_opengl_MacOSXContextImplementation.m @@ -115,10 +115,15 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nSwapBu NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; MacOSXPeerInfo *peer_info = ((MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle))->peer_info; [[peer_info->window_info->view openGLContext] flushBuffer]; + + if (peer_info->isCALayer) { + // blit the contents of buffer to CALayer + [peer_info->glLayer blitFrameBuffer]; + } + [pool release]; } - JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nUpdate (JNIEnv *env, jclass clazz, jobject context_handle) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -128,7 +133,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_nUpdate } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_MacOSXContextImplementation_clearDrawable - (JNIEnv *env, jclass clazz, jobject context_handle) { +(JNIEnv *env, jclass clazz, jobject context_handle) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; MacOSXPeerInfo *peer_info = ((MacOSXContext *)(*env)->GetDirectBufferAddress(env, context_handle))->peer_info; [[peer_info->window_info->view openGLContext] clearDrawable];