diff options
author | Sven Gothel <sgothel@jausoft.com> | 2012-10-31 15:16:56 +0100 |
---|---|---|
committer | Sven Gothel <sgothel@jausoft.com> | 2012-10-31 15:16:56 +0100 |
commit | 7dff066bb823dddb5d6e0e7672f5599afa5a43b9 (patch) | |
tree | 1981fa4c69ae8c2037ed17af5d2987b8cf6b55b1 /src/jogl | |
parent | c2b328ea96b6cb16ca39f13d4bb4d1236c4b8a1d (diff) |
Add OSX CALayer OpenGL 3 (core) support: Derive pixelformat from parent (GL3), use GL3.2 compatible shader; Use VBO in general.
Covered by:
Auto unit tests: TestOffscreenLayer01GLCanvasAWT, TestOffscreenLayer02NewtCanvasAWT
Manual: TestGearsES2AWT '-gl3 -layered'
Diffstat (limited to 'src/jogl')
4 files changed, 227 insertions, 37 deletions
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index f6338b04c..518d97067 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -51,11 +51,14 @@ import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.OffscreenLayerSurface; import javax.media.nativewindow.ProxySurface; import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL3; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import javax.media.opengl.GLUniformData; import jogamp.nativewindow.macosx.OSXUtil; import jogamp.opengl.GLContextImpl; @@ -71,6 +74,9 @@ import com.jogamp.common.util.VersionNumber; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; import com.jogamp.opengl.GLExtensions; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; public abstract class MacOSXCGLContext extends GLContextImpl { @@ -132,6 +138,52 @@ public abstract class MacOSXCGLContext extends GLContextImpl } } + /** Static instances of GL3 core shader code, initialized lazy when required - never destroyed. */ + private static Object gl3ShaderLock = new Object(); + private static volatile boolean gl3VertexShaderInitialized = false; + private static ShaderCode gl3VertexShader = null; + private static ShaderCode gl3FragmentShader = null; + + private static ShaderProgram createCALayerShader(GL3 gl) { + // Create vertex & fragment shader code objects + if( !gl3VertexShaderInitialized ) { // volatile OK + synchronized( gl3ShaderLock ) { + if( !gl3VertexShaderInitialized ) { + final String shaderBasename = "texture01_xxx"; + gl3VertexShader = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MacOSXCGLContext.class, + "../../shader", "../../shader/bin", shaderBasename, true); + gl3FragmentShader = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MacOSXCGLContext.class, + "../../shader", "../../shader/bin", shaderBasename, true); + gl3VertexShader.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp); + gl3FragmentShader.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp); + gl3VertexShaderInitialized = true; + } + } + } + // Create & Link the shader program + final ShaderProgram sp = new ShaderProgram(); + sp.add(gl3VertexShader); + sp.add(gl3FragmentShader); + if(!sp.link(gl, System.err)) { + throw new GLException("Couldn't link program: "+sp); + } + sp.useProgram(gl, true); + + // setup mgl_PMVMatrix + final PMVMatrix pmvMatrix = new PMVMatrix(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv + pmvMatrixUniform.setLocation( gl.glGetUniformLocation( sp.program(), pmvMatrixUniform.getName() ) ); + gl.glUniform(pmvMatrixUniform); + + sp.useProgram(gl, false); + return sp; + } + + private boolean haveSetOpenGLMode = false; private GLBackendType openGLMode = GLBackendType.NSOPENGL; @@ -441,7 +493,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl private int vsyncTimeout; // microSec - for nsOpenGLLayer mode private int lastWidth=0, lastHeight=0; // allowing to detect size change private boolean needsSetContextPBuffer = false; - + private ShaderProgram gl3ShaderProgram = null; + @Override public boolean isNSContext() { return true; } @@ -611,7 +664,16 @@ public abstract class MacOSXCGLContext extends GLContextImpl if(0>=lastWidth || 0>=lastHeight || !drawable.isRealized()) { throw new GLException("Drawable not realized yet or invalid texture size, texSize "+lastWidth+"x"+lastHeight+", "+drawable); } - nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, /* MacOSXCGLContext.this.isGL3(), */ nsOpenGLLayerPFmt, pbufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight); + final int gl3ShaderProgramName; + if( MacOSXCGLContext.this.isGL3core() ) { + if( null == gl3ShaderProgram) { + gl3ShaderProgram = createCALayerShader(MacOSXCGLContext.this.gl.getGL3()); + } + gl3ShaderProgramName = gl3ShaderProgram.program(); + } else { + gl3ShaderProgramName = 0; + } + nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, gl3ShaderProgramName, nsOpenGLLayerPFmt, pbufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight); if (DEBUG) { System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(pbufferHandle)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", "+drawable); } @@ -632,7 +694,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl // still having a valid OLS attached to surface (parent OLS could have been removed) ols.detachSurfaceLayer(); } - CGL.releaseNSOpenGLLayer(nsOpenGLLayer); + CGL.releaseNSOpenGLLayer(nsOpenGLLayer); + if( null != gl3ShaderProgram ) { + gl3ShaderProgram.destroy(MacOSXCGLContext.this.gl.getGL3()); + gl3ShaderProgram = null; + } nsOpenGLLayer = 0; } if(0 != nsOpenGLLayerPFmt) { @@ -767,10 +833,10 @@ public abstract class MacOSXCGLContext extends GLContextImpl if(res) { if(isFBO) { // trigger CALayer to update incl. possible surface change (texture) - CGL.setNSOpenGLLayerNeedsDisplayFBO(nsOpenGLLayer, texID, lastWidth, lastHeight); + CGL.setNSOpenGLLayerNeedsDisplayFBO(nsOpenGLLayer, texID); } else { // trigger CALayer to update incl. possible surface change (new pbuffer handle) - CGL.setNSOpenGLLayerNeedsDisplayPBuffer(nsOpenGLLayer, drawable.getHandle(), lastWidth, lastHeight); + CGL.setNSOpenGLLayerNeedsDisplayPBuffer(nsOpenGLLayer, drawable.getHandle()); } } } else { diff --git a/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.fp b/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.fp new file mode 100644 index 000000000..8b30b65f9 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.fp @@ -0,0 +1,19 @@ +// Copyright 2012 JogAmp Community. All rights reserved. + +#if __VERSION__ >= 130 + #define varying in + out vec4 mgl_FragColor; + #define texture2D texture +#else + #define mgl_FragColor gl_FragColor +#endif + +varying vec2 mgl_texCoord; + +uniform sampler2D mgl_Texture0; + +void main (void) +{ + mgl_FragColor = texture2D(mgl_Texture0, mgl_texCoord); +} + diff --git a/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.vp b/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.vp new file mode 100644 index 000000000..d9ef6b493 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/shader/texture01_xxx.vp @@ -0,0 +1,19 @@ +// Copyright 2012 JogAmp Community. All rights reserved. + +#if __VERSION__ >= 130 + #define attribute in + #define varying out +#endif + +uniform mat4 mgl_PMVMatrix[2]; + +attribute vec4 mgl_Vertex; +attribute vec4 mgl_MultiTexCoord; + +varying vec2 mgl_texCoord; + +void main(void) +{ + mgl_texCoord = mgl_MultiTexCoord.st; + gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex; +} diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m index e83d0adcb..6ebf400e2 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m @@ -3,6 +3,22 @@ #import <pthread.h> #include "timespec.h" +#import <OpenGL/glext.h> + +/** + * Partial include of gl3.h - which we can only expect and use + * in case of a GL3 core context at runtime. + * Otherwise we would need to have 2 modules, one including GL2 + * and one inclusing GL3 headers. + */ +#ifndef GL_ARB_vertex_array_object +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +extern void glBindVertexArray (GLuint array); +extern void glDeleteVertexArrays (GLsizei n, const GLuint *arrays); +extern void glGenVertexArrays (GLsizei n, GLuint *arrays); +extern GLboolean glIsVertexArray (GLuint array); +#endif + // // CADisplayLink only available on iOS >= 3.1, sad, since it's convenient. // Use CVDisplayLink otherwise. @@ -82,11 +98,18 @@ @protected NSOpenGLContext* parentCtx; + GLuint gl3ShaderProgramName; + GLuint vboBufVert; + GLuint vboBufTexCoord; + GLint vertAttrLoc; + GLint texCoordAttrLoc; NSOpenGLPixelFormat* parentPixelFmt; + int texWidth; + int texHeight; + int newTexWidth; + int newTexHeight; volatile NSOpenGLPixelBuffer* pbuffer; volatile GLuint textureID; - volatile int texWidth; - volatile int texHeight; volatile NSOpenGLPixelBuffer* newPBuffer; #ifdef HAS_CADisplayLink CADisplayLink* displayLink; @@ -102,11 +125,10 @@ pthread_mutex_t renderLock; pthread_cond_t renderSignal; volatile Bool shallDraw; - volatile int newTexWidth; - volatile int newTexHeight; } - (id) setupWithContext: (NSOpenGLContext*) parentCtx + gl3ShaderProgramName: (GLuint) gl3ShaderProgramName pixelFormat: (NSOpenGLPixelFormat*) pfmt pbuffer: (NSOpenGLPixelBuffer*) p texIDArg: (GLuint) texID @@ -122,6 +144,7 @@ - (void) setNewPBuffer: (NSOpenGLPixelBuffer*)p; - (void) applyNewPBuffer; +- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask; - (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat; - (void)disableAnimation; - (void)pauseAnimation:(Bool)pause; @@ -172,6 +195,7 @@ static const GLfloat gl_verts[] = { @implementation MyNSOpenGLLayer - (id) setupWithContext: (NSOpenGLContext*) _parentCtx + gl3ShaderProgramName: (GLuint) _gl3ShaderProgramName pixelFormat: (NSOpenGLPixelFormat*) _parentPixelFmt pbuffer: (NSOpenGLPixelBuffer*) p texIDArg: (GLuint) texID @@ -192,6 +216,11 @@ static const GLfloat gl_verts[] = { } } parentCtx = _parentCtx; + gl3ShaderProgramName = _gl3ShaderProgramName; + vboBufVert = 0; + vboBufTexCoord = 0; + vertAttrLoc = 0; + texCoordAttrLoc = 0; parentPixelFmt = _parentPixelFmt; swapInterval = 1; // defaults to on (as w/ new GL profiles) swapIntervalCounter = 0; @@ -339,7 +368,7 @@ static const GLfloat gl_verts[] = { SYNC_PRINT("<NP-A %p -> %p>", pbuffer, newPBuffer); if( 0 != textureID ) { - glDeleteTextures(1, &textureID); + glDeleteTextures(1, (GLuint *)&textureID); [self setTextureID: 0]; } [pbuffer release]; @@ -359,7 +388,7 @@ static const GLfloat gl_verts[] = { DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (with ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)textureID); if( 0 != textureID ) { - glDeleteTextures(1, &textureID); + glDeleteTextures(1, (GLuint *)&textureID); [self setTextureID: 0]; } if(NULL != pbuffer) { @@ -378,13 +407,12 @@ static const GLfloat gl_verts[] = { } } -/** - (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask { DBG_PRINT("MyNSOpenGLLayer::openGLPixelFormatForDisplayMask: %p (refcnt %d) - parent-pfmt %p -> new-pfmt %p\n", self, (int)[self retainCount], parentPixelFmt, parentPixelFmt); return parentPixelFmt; -} */ +} - (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat { @@ -487,12 +515,16 @@ static const GLfloat gl_verts[] = { if( NULL != pbuffer ) { if( texSizeChanged && 0 != textureID ) { - glDeleteTextures(1, &textureID); + glDeleteTextures(1, (GLuint *)&textureID); [self setTextureID: 0]; } textureTarget = [pbuffer textureTarget]; + if( 0 != gl3ShaderProgramName ) { + glUseProgram(gl3ShaderProgramName); + glActiveTexture(GL_TEXTURE0); + } if( 0 == textureID ) { - glGenTextures(1, &textureID); + glGenTextures(1, (GLuint *)&textureID); glBindTexture(textureTarget, textureID); glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -501,26 +533,80 @@ static const GLfloat gl_verts[] = { } else { glBindTexture(textureTarget, textureID); } - [context setTextureImageToPixelBuffer: pbuffer colorBuffer: GL_FRONT]; + [context setTextureImageToPixelBuffer: (NSOpenGLPixelBuffer*) pbuffer colorBuffer: GL_FRONT]; } else { + if( 0 != gl3ShaderProgramName ) { + glUseProgram(gl3ShaderProgramName); + glActiveTexture(GL_TEXTURE0); + } textureTarget = GL_TEXTURE_2D; glBindTexture(textureTarget, textureID); } - SYNC_PRINT(" %d*>", (int)textureID); - - glEnable(textureTarget); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, gl_verts); - glTexCoordPointer(2, GL_FLOAT, 0, gl_texCoords); - - glDrawArrays(GL_QUADS, 0, 4); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glDisable(textureTarget); + SYNC_PRINT(" %d gl3Prog %d/%d*>", (int)textureID, (int)gl3ShaderProgramName, (int)glIsProgram (gl3ShaderProgramName)); + + if( 0 == vboBufVert ) { // Once: Init Data and Bind to Pointer + if( 0 != gl3ShaderProgramName ) { + // Install default VAO as required by GL 3.2 core! + GLuint vaoBuf = 0; + glGenVertexArrays(1, &vaoBuf); + glBindVertexArray(vaoBuf); + + // Set texture-unit 0 + GLint texUnitLoc = glGetUniformLocation (gl3ShaderProgramName, "mgl_Texture0"); + glUniform1i (texUnitLoc, 0); + } + glGenBuffers( 1, &vboBufVert ); + glBindBuffer( GL_ARRAY_BUFFER, vboBufVert ); + glBufferData( GL_ARRAY_BUFFER, 4 * 2 * sizeof(GLfloat), gl_verts, GL_STATIC_DRAW); + if( 0 != gl3ShaderProgramName ) { + vertAttrLoc = glGetAttribLocation( gl3ShaderProgramName, "mgl_Vertex" ); + glVertexAttribPointer( vertAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL ); + } else { + glVertexPointer(2, GL_FLOAT, 0, NULL); + } + + glGenBuffers( 1, &vboBufTexCoord ); + glBindBuffer( GL_ARRAY_BUFFER, vboBufTexCoord ); + glBufferData( GL_ARRAY_BUFFER, 4 * 2 * sizeof(GLfloat), gl_texCoords, GL_STATIC_DRAW); + if( 0 != gl3ShaderProgramName ) { + texCoordAttrLoc = glGetAttribLocation( gl3ShaderProgramName, "mgl_MultiTexCoord" ); + glVertexAttribPointer( texCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL ); + } else { + glTexCoordPointer(2, GL_FLOAT, 0, NULL); + } + } + if( texSizeChanged ) { + glBindBuffer( GL_ARRAY_BUFFER, vboBufTexCoord ); + glBufferSubData( GL_ARRAY_BUFFER, 0, 4 * 2 * sizeof(GLfloat), gl_texCoords); + if( 0 != gl3ShaderProgramName ) { + glVertexAttribPointer( texCoordAttrLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL ); + } else { + glTexCoordPointer(2, GL_FLOAT, 0, NULL); + } + } + if( 0 != gl3ShaderProgramName ) { + glEnableVertexAttribArray( vertAttrLoc ); + glEnableVertexAttribArray( texCoordAttrLoc ); + } else { + glEnable(textureTarget); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + if( 0 != gl3ShaderProgramName ) { + glDisableVertexAttribArray( vertAttrLoc ); + glDisableVertexAttribArray( texCoordAttrLoc ); + glUseProgram(0); + } else { + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glDisable(textureTarget); + } + glBindTexture(textureTarget, 0); [context clearDrawable]; @@ -664,13 +750,13 @@ static const GLfloat gl_verts[] = { @end -NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight) { +NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, int gl3ShaderProgramName, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight) { // This simply crashes after dealloc() has been called .. ie. ref-count -> 0 too early ? // However using alloc/init, actual dealloc happens at JAWT destruction, hence too later IMHO. // return [[MyNSOpenGLLayer layer] setupWithContext:ctx pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID // opaque: opaque texWidth: texWidth texHeight: texHeight]; - return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID + return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx gl3ShaderProgramName: (GLuint)gl3ShaderProgramName pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID opaque: opaque texWidth: texWidth texHeight: texHeight]; } @@ -688,7 +774,7 @@ void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros) { [pool release]; } -void setNSOpenGLLayerNeedsDisplayFBO(NSOpenGLLayer* layer, uint32_t texID, int texWidth, int texHeight) { +void setNSOpenGLLayerNeedsDisplayFBO(NSOpenGLLayer* layer, uint32_t texID) { MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; Bool shallDraw; @@ -698,7 +784,7 @@ void setNSOpenGLLayerNeedsDisplayFBO(NSOpenGLLayer* layer, uint32_t texID, int t shallDraw = [l isGLSourceValid]; l->shallDraw = shallDraw; - SYNC_PRINT("<! T%dx%d O%dx%d %d>", texWidth, texHeight, l->newTexWidth, l->newTexHeight, (int)shallDraw); + SYNC_PRINT("<! T %d>", (int)shallDraw); if(shallDraw) { if ( [NSThread isMainThread] == YES ) { [l setNeedsDisplay]; @@ -711,7 +797,7 @@ void setNSOpenGLLayerNeedsDisplayFBO(NSOpenGLLayer* layer, uint32_t texID, int t [pool release]; } -void setNSOpenGLLayerNeedsDisplayPBuffer(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p, int texWidth, int texHeight) { +void setNSOpenGLLayerNeedsDisplayPBuffer(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p) { MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; Bool shallDraw; @@ -724,7 +810,7 @@ void setNSOpenGLLayerNeedsDisplayPBuffer(NSOpenGLLayer* layer, NSOpenGLPixelBuff shallDraw = [l isGLSourceValid]; l->shallDraw = shallDraw; - SYNC_PRINT("<! T%dx%d O%dx%d %d>", texWidth, texHeight, l->newTexWidth, l->newTexHeight, (int)shallDraw); + SYNC_PRINT("<! T %d>", (int)shallDraw); if(shallDraw) { if ( [NSThread isMainThread] == YES ) { [l setNeedsDisplay]; |