From a06e40cce89615eb8c4b080842997c9c3ad1130b Mon Sep 17 00:00:00 2001
From: Sven Gothel ARB_create_context
related: flag debug. Not a cache key. */
public static final int CTX_OPTION_DEBUG = 1 << 5;
-
+
/** GL_ARB_ES2_compatibility
implementation related: Context is compatible w/ ES2. Not a cache key. */
protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8;
/** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. */
protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 15;
-
+
private static ThreadLocal
+ *
* If the context is in use by another thread at the time of the * call, then if isSynchronized() is true the call will * block. If isSynchronized() is false, an exception will be @@ -196,7 +196,7 @@ public abstract class GLContext { *
** The drawable's surface is being locked at entry - * and unlocked at {@link #release()} + * and unlocked at {@link #release()} *
* * @return CONTEXT_CURRENT if the context was successfully made current @@ -216,7 +216,7 @@ public abstract class GLContext { * Releases control of this GLContext from the current thread. ** The drawable's surface is being unlocked at exit, - * assumed to be locked by {@link #makeCurrent()}. + * assumed to be locked by {@link #makeCurrent()}. *
* * @throws GLException if the context had not previously been made @@ -284,18 +284,18 @@ public abstract class GLContext { * @return true if this GLContext is current on this thread */ public final boolean isCurrent() { - return getCurrent() == this ; + return getCurrent() == this ; } /** * @throws GLException if this GLContext is not current on this thread */ - public final void validateCurrent() throws GLException { + public final void validateCurrent() throws GLException { if(getCurrent() != this) { throw new GLException(getThreadName()+": This context is not current. Current context: "+getCurrent()+", this context "+this); } } - + /** * Sets the thread-local variable returned by {@link #getCurrent} * and has no other side-effects. For use by third parties adding @@ -307,14 +307,14 @@ public abstract class GLContext { } currentContext.set(cur); } - + /** * Destroys this OpenGL context and frees its associated * resources. *
* The context may be current w/o recursion when calling destroy()
,
* in which case this method destroys the context and releases the lock.
- *
* major.minor ([option]?[options,]*) - gl-version @@ -509,7 +510,7 @@ public abstract class GLContext { *row 2, cell 1 *row 2, cell 2 * - * + * * *
ES2 | 2.0 (ES profile, ES2 compatible, hardware) - 2.0 ES Profile | |
NV | GL3 | 3.3 (Core profile, arb, hardware) - 3.3.0 NVIDIA 195.36.07.03 |
NV | GL3bc | 3.3 (Compatibility profile, arb, hardware) - 3.3.0 NVIDIA 195.36.07.03 |
NV | GL2 | 3.0 (Compatibility profile, arb, ES2 compatible, hardware) - 3.0.0 NVIDIA 290.10 |
GL_ARB_ES2_compatibility
, otherwise false
+ * @return true if this context is an ES2 context or implements
+ * the extension GL_ARB_ES2_compatibility
, otherwise false
*/
public final boolean isGLES2Compatible() {
return 0 != ( ctxOptions & CTX_IMPL_ES2_COMPAT ) ;
}
-
+
public final boolean hasGLSL() {
return isGL2ES2() ;
}
-
+
/** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns true
. */
public boolean isNPOTTextureAvailable() {
return isGL3() || isGLES2Compatible() || isExtensionAvailable(GL_ARB_texture_non_power_of_two);
}
private static final String GL_ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
-
+
public boolean isTextureFormatBGRA8888Available() {
- return isGL2GL3() ||
- isExtensionAvailable("GL_EXT_texture_format_BGRA8888") ||
+ return isGL2GL3() ||
+ isExtensionAvailable("GL_EXT_texture_format_BGRA8888") ||
isExtensionAvailable("GL_IMG_texture_format_BGRA8888") ;
}
@@ -610,11 +611,11 @@ public abstract class GLContext {
/**
* Set the swap interval if the current context.
- * @param interval Should be ≥ 0. 0 Disables the vertical synchronisation,
+ * @param interval Should be ≥ 0. 0 Disables the vertical synchronisation,
* where ≥ 1 is the number of vertical refreshes before a swap buffer occurs.
* A value < 0 is ignored.
- * @return true if the operation was successful, otherwise false
- *
+ * @return true if the operation was successful, otherwise false
+ *
* @throws GLException if the context is not current.
*/
public final boolean setSwapInterval(int interval) throws GLException {
@@ -627,16 +628,16 @@ public abstract class GLContext {
}
return false;
}
- protected boolean setSwapIntervalImpl(int interval) {
- return false;
- }
- /** Return the current swap interval.
+ protected boolean setSwapIntervalImpl(int interval) {
+ return false;
+ }
+ /** Return the current swap interval.
*
* If the context has not been made current at all,
* the default value -1
is returned.
*
- * The default value for a valid context is 1
for
+ * The default value for a valid context is 1
for
* an EGL based profile (ES1 or ES2) and -1
(undefined)
* for desktop.
*
The default is true
, ie {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB}.
The default is true
, ie {@link GL2GL3#GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB}.
To enable the GLDebugOutput feature {@link #enableGLDebugMessage(boolean) enableGLDebugMessage(true)} * or {@link #setContextCreationFlags(int) setContextCreationFlags}({@link GLContext#CTX_OPTION_DEBUG}) * shall be called before context creation via {@link #makeCurrent()}!
- * - *In case {@link GLAutoDrawable} are being used, + * + *
In case {@link GLAutoDrawable} are being used, * {@link GLAutoDrawable#setContextCreationFlags(int) glAutoDrawable.setContextCreationFlags}({@link GLContext#CTX_OPTION_DEBUG}) * shall be issued before context creation via {@link #makeCurrent()}!
- * + * *After context creation, the GLDebugOutput feature may be enabled or disabled at any time using this method.
- * + * * @param enable If true enables, otherwise disables the GLDebugOutput feature. - * + * * @throws GLException if this context is not current or GLDebugOutput registration failed (enable) - * + * * @see #setContextCreationFlags(int) * @see #addGLDebugListener(GLDebugListener) * @see GLAutoDrawable#setContextCreationFlags(int) */ public abstract void enableGLDebugMessage(boolean enable) throws GLException; - + /** * Add {@link GLDebugListener}.- * This is currently being used and overridden by Mac OSX, + * This is currently being used and overridden by Mac OSX, * which issues the {@link jogamp.opengl.macosx.cgl.CGL#updateContext(long) NSOpenGLContext update()} call. *
- * + * * @throws GLException */ protected void drawableUpdatedNotify() throws GLException { } @@ -217,6 +222,7 @@ public abstract class GLContextImpl extends GLContext { public abstract Object getPlatformGLExtensions(); // Note: the surface is locked within [makeCurrent .. swap .. release] + @Override public void release() throws GLException { release(false); } @@ -228,7 +234,7 @@ public abstract class GLContextImpl extends GLContext { throw new GLException("Context not current on current thread "+Thread.currentThread().getName()+": "+this); } final boolean actualRelease = force || lock.getHoldCount() == 1 ; - try { + try { if( actualRelease ) { if (contextHandle != 0) { // allow dbl-release releaseImpl(); @@ -248,8 +254,9 @@ public abstract class GLContextImpl extends GLContext { } protected abstract void releaseImpl() throws GLException; + @Override public final void destroy() { - if (DEBUG || TRACE_SWITCH) { + if (DEBUG || TRACE_SWITCH) { System.err.println(getThreadName() + ": GLContextImpl.destroy.0: " + toHexString(contextHandle) + ", isShared "+GLContextShareSet.isShared(this)+" - "+lock); } @@ -268,7 +275,7 @@ public abstract class GLContextImpl extends GLContext { if ( lock.getHoldCount() > 2 ) { throw new GLException(getThreadName() + ": Lock was hold more than once - makeCurrent/release imbalance: "+lock); } - try { + try { // release current context if(null != glDebugHandler) { if(lock.getHoldCount() == 1) { @@ -279,7 +286,7 @@ public abstract class GLContextImpl extends GLContext { } if(lock.getHoldCount() > 1) { // pending release() after makeCurrent() - release(true); + release(true); } destroyImpl(); contextHandle = 0; @@ -303,6 +310,7 @@ public abstract class GLContextImpl extends GLContext { } protected abstract void destroyImpl() throws GLException; + @Override public final void copy(GLContext source, int mask) throws GLException { if (source.getHandle() == 0) { throw new GLException("Source OpenGL context has not been created"); @@ -364,6 +372,7 @@ public abstract class GLContextImpl extends GLContext { * @see #mapVersionAvailable * @see #destroyContextARBImpl */ + @Override public int makeCurrent() throws GLException { boolean unlockContextAndDrawable = false; int res = CONTEXT_NOT_CURRENT; @@ -377,9 +386,9 @@ public abstract class GLContextImpl extends GLContext { if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { drawable.updateHandle(); } - + lock.lock(); - try { + try { // One context can only be current by one thread, // and one thread can only have one context current! final GLContext current = getCurrent(); @@ -395,13 +404,13 @@ public abstract class GLContextImpl extends GLContext { } else { current.release(); } - } + } if (0 == drawable.getHandle()) { throw new GLException("drawable has invalid handle: "+drawable); } res = makeCurrentWithinLock(lockRes); unlockContextAndDrawable = CONTEXT_NOT_CURRENT == res; - + /** * FIXME: refactor dependence on Java 2D / JOGL bridge if ((tracker != null) && @@ -416,7 +425,7 @@ public abstract class GLContextImpl extends GLContext { } finally { if (unlockContextAndDrawable) { lock.unlock(); - } + } } } catch (RuntimeException e) { unlockContextAndDrawable = true; @@ -424,9 +433,9 @@ public abstract class GLContextImpl extends GLContext { } finally { if (unlockContextAndDrawable) { drawable.unlockSurface(); - } + } } - + if (res == CONTEXT_NOT_CURRENT) { if(TRACE_SWITCH) { System.err.println(getThreadName() +": GLContext.ContextSwitch: - switch - CONTEXT_NOT_CURRENT - "+lock); @@ -435,9 +444,9 @@ public abstract class GLContextImpl extends GLContext { setCurrent(this); if(res == CONTEXT_CURRENT_NEW) { // check if the drawable's and the GL's GLProfile are equal - // throws an GLException if not + // throws an GLException if not getGLDrawable().getGLProfile().verifyEquality(gl.getGLProfile()); - + glDebugHandler.init( isGL2GL3() && isGLDebugEnabled() ); if(DEBUG_GL) { @@ -448,7 +457,7 @@ public abstract class GLContextImpl extends GLContext { } if(TRACE_GL) { gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ); - } + } if(DEBUG || TRACE_SWITCH) { System.err.println(getThreadName() +": GLContext.ContextSwitch: - switch - CONTEXT_CURRENT_NEW - "+lock); } @@ -474,7 +483,7 @@ public abstract class GLContextImpl extends GLContext { // only impacts w/ createContextARB(..) additionalCtxCreationFlags |= GLContext.CTX_OPTION_DEBUG ; } - + final GLContextImpl shareWith = (GLContextImpl) GLContextShareSet.getShareContext(this); if (null != shareWith) { shareWith.getDrawableImpl().lockSurface(); @@ -485,7 +494,7 @@ public abstract class GLContextImpl extends GLContext { } finally { if (null != shareWith) { shareWith.getDrawableImpl().unlockSurface(); - } + } } if (DEBUG) { if(created) { @@ -493,16 +502,16 @@ public abstract class GLContextImpl extends GLContext { } else { System.err.println(getThreadName() + ": Create GL context FAILED for " + getClass().getName()); } - } + } if(!created) { return CONTEXT_NOT_CURRENT; } - + // finalize mapping the available GLVersions, in case it's not done yet - { + { final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice device = config.getScreen().getDevice(); - + if( !GLContext.getAvailableGLVersionsSet(device) ) { final int reqMajor; final int reqProfile; @@ -511,7 +520,7 @@ public abstract class GLContextImpl extends GLContext { reqMajor = ctxMajorVersion; reqProfile = GLContext.CTX_PROFILE_ES; } else { - if(ctxMajorVersion<3 || ctxMajorVersion==3 && ctxMinorVersion==0) { + if(ctxMajorVersion<3 || ctxMajorVersion==3 && ctxMinorVersion==0) { reqMajor = 2; } else { reqMajor = ctxMajorVersion; @@ -537,30 +546,30 @@ public abstract class GLContextImpl extends GLContext { return CONTEXT_CURRENT; } protected abstract void makeCurrentImpl() throws GLException; - - /** + + /** * Platform dependent entry point for context creation.MakeContextCurrent
call.ARB_create_context
* mechanism to create a context.MakeContextCurrent
call.ARB_create_context
related: created via ARB_create_context. Cache key value. */
+ /** ARB_create_context
related: created via ARB_create_context. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IS_ARB_CREATED = 1 << 0;
- /** ARB_create_context
related: compatibility profile. Cache key value. */
+ /** ARB_create_context
related: desktop compatibility profile. Cache key value. See {@link #isGLCompatibilityProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_PROFILE_COMPAT = 1 << 1;
- /** ARB_create_context
related: core profile. Cache key value. */
+ /** ARB_create_context
related: desktop core profile. Cache key value. See {@link #isGLCoreProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_PROFILE_CORE = 1 << 2;
- /** ARB_create_context
related: ES profile. Cache key value. */
+ /** ARB_create_context
related: ES profile. Cache key value. See {@link #isGLES()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_PROFILE_ES = 1 << 3;
- /** ARB_create_context
related: flag forward compatible. Cache key value. */
+ /** ARB_create_context
related: flag forward compatible. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_OPTION_FORWARD = 1 << 4;
- /** ARB_create_context
related: flag debug. Not a cache key. */
+ /** ARB_create_context
related: flag debug. Not a cache key. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
public static final int CTX_OPTION_DEBUG = 1 << 5;
- /** GL_ARB_ES2_compatibility
implementation related: Context is compatible w/ ES2. Not a cache key. */
+ /** GL_ARB_ES2_compatibility
implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8;
- /** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. */
- protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 15;
+ /** Context supports FBO, details see {@link #hasFBO()}.
+ * Not a cache key.
+ * @see #hasFBO()
+ * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
+ */
+ protected static final int CTX_IMPL_FBO = 1 << 9;
- private static ThreadLocal+ * If the context was current on this thread, it is being released before switching the drawable + * and made current afterwards. However the user shall take extra care that not other thread + * attempts to make this context current. Otherwise a race condition may happen. + *
+ *+ * Disclaimer: Even though the API may allows this functionality in theory, your mileage may vary + * switching the drawable of an already established GLContext, i.e. which is already made current once. + * FIXME: Validate functionality! + *
+ * @param readWrite the read/write drawable for framebuffer operations. + * @param setWriteOnly iftrue
and if the current read-drawable differs
+ * from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}),
+ * only change the write-drawable. Otherwise set both drawables.
+ * @return the replaced read/write drawable
+ *
+ * @throws GLException in case null
is being passed or
+ * this context is made current on another thread.
+ *
+ * @see #isGLReadDrawableAvailable()
+ * @see #getGLReadDrawable()
+ * @see #setGLReadDrawable()
+ * @see #getGLDrawable()
+ */
+ public abstract GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly);
+
+ /**
+ * Returns the write-drawable this context uses for framebuffer operations.
*/
public abstract GLDrawable getGLDrawable();
/**
- * Return availability of GL read drawable.
- * @return true if a GL read drawable is supported with your driver, otherwise false.
+ * Query whether using a distinguished read-drawable is supported.
+ * @return true if using a read-drawable is supported with your driver/OS, otherwise false.
*/
public abstract boolean isGLReadDrawableAvailable();
/**
- * Set the read GLDrawable for read framebuffer operations.+ * If the context was current on this thread, it is being released before switching the drawable + * and made current afterwards. However the user shall take extra care that not other thread + * attempts to make this context current. Otherwise a race condition may happen. + *
* - * @param read the read GLDrawable for read framebuffer operations. - * If null is passed, the default write drawable will be set. + * @param read the read-drawable for read framebuffer operations. + * If null is passed, the default write drawable will be set. + * @return the replaced read-drawable * - * @throws GLException in case a read drawable is not supported - * and the given drawable is not null and not equal to the internal write drawable. + * @throws GLException in case a read drawable is not supported or + * this context is made current on another thread. * * @see #isGLReadDrawableAvailable() * @see #getGLReadDrawable() */ - public abstract void setGLReadDrawable(GLDrawable read); + public abstract GLDrawable setGLReadDrawable(GLDrawable read); /** - * Returns the read GLDrawable this context uses for read framebuffer operations. + * Returns the read-Drawable this context uses for read framebuffer operations. + *+ * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)}, + * it equals to the write-drawable (default). + *
* @see #isGLReadDrawableAvailable() * @see #setGLReadDrawable(javax.media.opengl.GLDrawable) + * @see #getGLDrawable() */ public abstract GLDrawable getGLReadDrawable(); @@ -190,7 +245,7 @@ public abstract class GLContext { * ** This method is blocking, i.e. waits until another thread has - * released the context. + * released the context. *
*
* The drawable's surface is being locked at entry
@@ -547,6 +602,28 @@ public abstract class GLContext {
return 0 != ( ctxOptions & CTX_IMPL_ES2_COMPAT ) ;
}
+ /**
+ * @return true if impl. is a hardware rasterizer, otherwise false.
+ * @see GLProfile#isHardwareRasterizer()
+ */
+ public final boolean isHardwareRasterizer() {
+ return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ;
+ }
+
+ /** Returns whether the context supports FBO, hence is either GL-ES >= 2.0, >= core GL 3.0 or implements the extensions
+ *
+ * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
+ *
+ * FBO support is queried as described in {@link GLContext#hasFBO()}.
+ * Includes [ GLES1, GLES2 ]. Includes [ GL4bc, GL3bc, GL2, GLES1, GL2ES1 ].
+ * Can be turned off with property GL_ARB_ES2_compatibility
, ARB_framebuffer_object
or all of
+ * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
+ * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
+ * @see #CTX_IMPL_FBO
+ */
+ public final boolean hasFBO() {
+ return 0 != ( ctxOptions & CTX_IMPL_FBO ) ;
+ }
+
+ /**
+ * @return true if context supports GLSL
+ * @see GLProfile#hasGLSL()
+ */
public final boolean hasGLSL() {
return isGL2ES2() ;
}
@@ -555,60 +632,70 @@ public abstract class GLContext {
public boolean isNPOTTextureAvailable() {
return isGL3() || isGLES2Compatible() || isExtensionAvailable(GL_ARB_texture_non_power_of_two);
}
- private static final String GL_ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
public boolean isTextureFormatBGRA8888Available() {
return isGL2GL3() ||
- isExtensionAvailable("GL_EXT_texture_format_BGRA8888") ||
- isExtensionAvailable("GL_IMG_texture_format_BGRA8888") ;
+ isExtensionAvailable(GL_EXT_texture_format_BGRA8888) ||
+ isExtensionAvailable(GL_IMG_texture_format_BGRA8888) ;
}
+ /** @see GLProfile#isGL4bc() */
public final boolean isGL4bc() {
return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
&& 0 != (ctxOptions & CTX_PROFILE_COMPAT);
}
+ /** @see GLProfile#isGL4() */
public final boolean isGL4() {
return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
&& 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
}
+ /** @see GLProfile#isGL3bc() */
public final boolean isGL3bc() {
return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
&& 0 != (ctxOptions & CTX_IS_ARB_CREATED)
&& 0 != (ctxOptions & CTX_PROFILE_COMPAT);
}
+ /** @see GLProfile#isGL3() */
public final boolean isGL3() {
return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 )
&& 0 != (ctxOptions & CTX_IS_ARB_CREATED)
&& 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
}
-
+
+ /** @see GLProfile#isGL2() */
public final boolean isGL2() {
return ctxMajorVersion>=1 && 0!=(ctxOptions & CTX_PROFILE_COMPAT);
}
+ /** @see GLProfile#isGL2GL3() */
public final boolean isGL2GL3() {
return isGL2() || isGL3();
}
+ /** @see GLProfile#isGLES1() */
public final boolean isGLES1() {
return ctxMajorVersion==1 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
}
+ /** @see GLProfile#isGLES2() */
public final boolean isGLES2() {
return ctxMajorVersion==2 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ;
}
+ /** @see GLProfile#isGLES() */
public final boolean isGLES() {
return 0 != ( CTX_PROFILE_ES & ctxOptions ) ;
}
+ /** @see GLProfile#isGL2ES1() */
public final boolean isGL2ES1() {
return isGL2() || isGLES1() ;
}
+ /** @see GLProfile#isGL2ES2() */
public final boolean isGL2ES2() {
return isGL2GL3() || isGLES2() ;
}
@@ -846,8 +933,11 @@ public abstract class GLContext {
*/
private static /*final*/ HashSet0
+ */
+ protected static final int getAvailableContextProperties(final AbstractGraphicsDevice device, final GLProfile glp) {
+ final int[] reqMajorCTP = new int[] { 0, 0 };
+ getRequestMajorAndCompat(glp, reqMajorCTP);
+
+ int _major[] = { 0 };
+ int _minor[] = { 0 };
+ int _ctp[] = { 0 };
+ if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1],
+ _major, _minor, _ctp)) {
+ return _ctp[0];
+ }
+ return 0; // n/a
+ }
+
+ /**
+ * @param device the device the profile is being requested
* @param major Key Value either 1, 2, 3 or 4
* @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
- * @return the highest GLProfile string regarding the version and profile bits.
- * @throws GLException if version and context profile bits could not be mapped to a GLProfile
+ * @return the highest GLProfile regarding availability, version and profile bits.
*/
- public static String getAvailableGLProfile(AbstractGraphicsDevice device, int reqMajor, int reqProfile)
+ protected static GLProfile getAvailableGLProfile(AbstractGraphicsDevice device, int reqMajor, int reqProfile)
throws GLException {
int major[] = { 0 };
int minor[] = { 0 };
int ctp[] = { 0 };
if(GLContext.getAvailableGLVersion(device, reqMajor, reqProfile, major, minor, ctp)) {
- return GLContext.getGLProfile(major[0], minor[0], ctp[0]);
+ return GLProfile.get(GLContext.getGLProfile(major[0], minor[0], ctp[0]));
+ }
+ return null;
+ }
+
+ /**
+ * @param device the device the profile is being requested
+ * @param major Key Value either 1, 2, 3 or 4
+ * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
+ */
+ protected static String getAvailableGLVersionAsString(AbstractGraphicsDevice device, int major, int profile) {
+ int _major[] = { 0 };
+ int _minor[] = { 0 };
+ int _ctp[] = { 0 };
+ if(getAvailableGLVersion(device, major, profile, _major, _minor, _ctp)) {
+ return getGLVersion(_major[0], _minor[0], _ctp[0], null);
}
return null;
}
@@ -990,7 +1130,7 @@ public abstract class GLContext {
* @param isHardware return value of one boolean, whether the profile is a hardware rasterizer or not
* @return true if the requested GL version is available regardless of a software or hardware rasterizer, otherwise false.
*/
- public static boolean isGLVersionAvailable(AbstractGraphicsDevice device, int reqMajor, int reqProfile, boolean isHardware[]) {
+ protected static boolean isGLVersionAvailable(AbstractGraphicsDevice device, int reqMajor, int reqProfile, boolean isHardware[]) {
Integer valI = getAvailableGLVersion(device, reqMajor, reqProfile);
if(null==valI) {
return false;
@@ -1027,21 +1167,7 @@ public abstract class GLContext {
return isGLVersionAvailable(device, 2, CTX_PROFILE_COMPAT, isHardware);
}
- /**
- * @param major Key Value either 1, 2, 3 or 4
- * @param profile Key Value either {@link #CTX_PROFILE_COMPAT}, {@link #CTX_PROFILE_CORE} or {@link #CTX_PROFILE_ES}
- */
- public static String getAvailableGLVersionAsString(AbstractGraphicsDevice device, int major, int profile) {
- int _major[] = { 0 };
- int _minor[] = { 0 };
- int _ctp[] = { 0 };
- if(getAvailableGLVersion(device, major, profile, _major, _minor, _ctp)) {
- return getGLVersion(_major[0], _minor[0], _ctp[0], null);
- }
- return null;
- }
-
- public static String getGLVersion(int major, int minor, int ctp, String gl_version) {
+ protected static String getGLVersion(int major, int minor, int ctp, String gl_version) {
boolean needColon = false;
StringBuilder sb = new StringBuilder();
sb.append(major);
@@ -1055,6 +1181,7 @@ public abstract class GLContext {
needColon = appendString(sb, "arb", needColon, 0 != ( CTX_IS_ARB_CREATED & ctp ));
needColon = appendString(sb, "debug", needColon, 0 != ( CTX_OPTION_DEBUG & ctp ));
needColon = appendString(sb, "ES2 compatible", needColon, 0 != ( CTX_IMPL_ES2_COMPAT & ctp ));
+ needColon = appendString(sb, "FBO", needColon, 0 != ( CTX_IMPL_FBO & ctp ));
if( 0 != ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
needColon = appendString(sb, "software", needColon, true);
} else {
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index 1093685d6..d6480e7aa 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -492,6 +492,23 @@ public abstract class GLDrawableFactory {
GLContext shareWith)
throws GLException;
+ /**
+ * Returns true if it is possible to create an framebuffer object (FBO).
+ * null
for the platform's default device.
+ * @param glp {@link GLProfile} to check for FBO capabilities
+ * @see GLContext#hasFBO()
+ */
+ public final boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp) {
+ return 0 != ( GLContext.CTX_IMPL_FBO & GLContext.getAvailableContextProperties(device, glp) );
+ }
+
//----------------------------------------------------------------------
// Methods for interacting with third-party OpenGL libraries
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index ed457b0ea..cc4f6c517 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -113,9 +113,7 @@ public class GLProfile {
* @param firstUIActionOnProcess Should be true
if called before the first UI action of the running program,
* otherwise false
.
*
- * @deprecated This method shall not need to be called for other reasons than having a defined initialization sequence.
- * To ensure homogeneous behavior with application not calling this method, you shall pass firstUIActionOnProcess=false
.
- * This method is subject to be removed in future versions of JOGL.
+ * @deprecated Use {@link #initSingleton()}. This method is subject to be removed in future versions of JOGL.
*/
public static void initSingleton(final boolean firstUIActionOnProcess) {
initLock.lock();
@@ -1003,6 +1001,11 @@ public class GLProfile {
public final boolean isGLES2() {
return GLES2 == profile;
}
+
+ /** Indicates whether this profile is capable of GLES. true
(default), bootstrapping the available GL profiles
+ * will use the highest compatible GL context for each profile,
+ * hence skipping querying lower profiles if a compatible higher one is found:
+ *
+ *
+ * Otherwise the dedicated GL context would be queried and used:
+ *
+ *
+ * Using aliasing speeds up initialization about:
+ *
+ *
jogl.debug.GLContext.NoProfileAliasing
.
+ *
LPVOID glMapBuffer(GLenum target, GLenum access);
*/
-public java.nio.ByteBuffer glMapBuffer(int target, int access) {
+public final java.nio.ByteBuffer glMapBuffer(int target, int access) {
final long __addr_ = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer;
if (__addr_ == 0) {
throw new GLException("Method \"glMapBuffer\" not available");
@@ -230,7 +232,7 @@ public java.nio.ByteBuffer glMapBuffer(int target, int access) {
native private long dispatch_glMapBuffer(int target, int access, long glProcAddress);
/** Entry point to C language function: GLvoid * {@native glMapNamedBufferEXT}(GLuint buffer, GLenum access);
Part of GL_EXT_direct_state_access
*/
-public java.nio.ByteBuffer glMapNamedBufferEXT(int bufferName, int access) {
+public final java.nio.ByteBuffer glMapNamedBufferEXT(int bufferName, int access) {
final long __addr_ = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapNamedBufferEXT;
if (__addr_ == 0) {
throw new GLException("Method \"glMapNamedBufferEXT\" not available");
@@ -269,7 +271,8 @@ private native long dispatch_glMapNamedBufferEXT(int buffer, int access, long pr
native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
- public void glVertexPointer(GLArrayData array) {
+ @Override
+ public final void glVertexPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
@@ -277,7 +280,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer());
}
}
- public void glColorPointer(GLArrayData array) {
+ @Override
+ public final void glColorPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
@@ -286,7 +290,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
}
}
- public void glNormalPointer(GLArrayData array) {
+ @Override
+ public final void glNormalPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.getComponentCount()!=3) {
throw new GLException("Only 3 components per normal allowed");
@@ -297,7 +302,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
glNormalPointer(array.getComponentType(), array.getStride(), array.getBuffer());
}
}
- public void glTexCoordPointer(GLArrayData array) {
+ @Override
+ public final void glTexCoordPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java
index dff33cf81..68eadc683 100644
--- a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java
+++ b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java
@@ -12,98 +12,122 @@ public GLES1Impl(GLProfile glp, GLContextImpl context) {
this.glProfile = glp;
}
+@Override
public final boolean isGL4bc() {
return false;
}
+@Override
public final boolean isGL4() {
return false;
}
+@Override
public final boolean isGL3bc() {
return false;
}
+@Override
public final boolean isGL3() {
return false;
}
+@Override
public final boolean isGL2() {
return false;
}
+@Override
public final boolean isGLES1() {
return true;
}
+@Override
public final boolean isGLES2() {
return false;
}
+@Override
public final boolean isGLES() {
return true;
}
+@Override
public final boolean isGL2ES1() {
return true;
}
+@Override
public final boolean isGL2ES2() {
return false;
}
+@Override
public final boolean isGLES2Compatible() {
return false;
}
+@Override
public final boolean isGL2GL3() {
return false;
}
+@Override
public final boolean hasGLSL() {
return false;
}
+@Override
public boolean isNPOTTextureAvailable() {
return false;
}
+@Override
public final GL4bc getGL4bc() throws GLException {
throw new GLException("Not a GL4bc implementation");
}
+@Override
public final GL4 getGL4() throws GLException {
throw new GLException("Not a GL4 implementation");
}
+@Override
public final GL3bc getGL3bc() throws GLException {
throw new GLException("Not a GL3bc implementation");
}
+@Override
public final GL3 getGL3() throws GLException {
throw new GLException("Not a GL3 implementation");
}
+@Override
public final GL2 getGL2() throws GLException {
throw new GLException("Not a GL2 implementation");
}
+@Override
public final GLES1 getGLES1() throws GLException {
return this;
}
+@Override
public final GLES2 getGLES2() throws GLException {
throw new GLException("Not a GLES2 implementation");
}
+@Override
public final GL2ES1 getGL2ES1() throws GLException {
return this;
}
+@Override
public final GL2ES2 getGL2ES2() throws GLException {
throw new GLException("Not a GL2ES2 implementation");
}
+@Override
public final GL2GL3 getGL2GL3() throws GLException {
throw new GLException("Not a GL2GL3 implementation");
}
@@ -119,17 +143,17 @@ private final GLStateTracker glStateTracker;
private boolean bufferObjectExtensionsInitialized = false;
private boolean haveOESFramebufferObject;
-private void initBufferObjectExtensionChecks() {
+private final void initBufferObjectExtensionChecks() {
if (bufferObjectExtensionsInitialized)
return;
bufferObjectExtensionsInitialized = true;
haveOESFramebufferObject = isExtensionAvailable("GL_OES_framebuffer_object");
}
-private boolean checkBufferObject(boolean avail,
- boolean enabled,
- int state,
- String kind, boolean throwException) {
+private final boolean checkBufferObject(boolean avail,
+ boolean enabled,
+ int state,
+ String kind, boolean throwException) {
if (!avail) {
if (!enabled)
return true;
@@ -157,7 +181,7 @@ private boolean checkBufferObject(boolean avail,
return true;
}
-private boolean checkArrayVBODisabled(boolean throwException) {
+private final boolean checkArrayVBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
false,
@@ -165,7 +189,7 @@ private boolean checkArrayVBODisabled(boolean throwException) {
"array vertex_buffer_object", throwException);
}
-private boolean checkArrayVBOEnabled(boolean throwException) {
+private final boolean checkArrayVBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
true,
@@ -173,7 +197,7 @@ private boolean checkArrayVBOEnabled(boolean throwException) {
"array vertex_buffer_object", throwException);
}
-private boolean checkElementVBODisabled(boolean throwException) {
+private final boolean checkElementVBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
false,
@@ -181,7 +205,7 @@ private boolean checkElementVBODisabled(boolean throwException) {
"element vertex_buffer_object", throwException);
}
-private boolean checkElementVBOEnabled(boolean throwException) {
+private final boolean checkElementVBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
true,
@@ -189,30 +213,30 @@ private boolean checkElementVBOEnabled(boolean throwException) {
"element vertex_buffer_object", throwException);
}
-private boolean checkUnpackPBODisabled(boolean throwException) {
+private final boolean checkUnpackPBODisabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return true;
}
-private boolean checkUnpackPBOEnabled(boolean throwException) {
+private final boolean checkUnpackPBOEnabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return false;
}
-private boolean checkPackPBODisabled(boolean throwException) {
+private final boolean checkPackPBODisabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return true;
}
-private boolean checkPackPBOEnabled(boolean throwException) {
+private final boolean checkPackPBOEnabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return false;
}
-private HashMap
LPVOID glMapBuffer(GLenum target, GLenum access);
*/
-public java.nio.ByteBuffer glMapBuffer(int target, int access) {
+public final java.nio.ByteBuffer glMapBuffer(int target, int access) {
final long __addr_ = ((GLES1ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer;
if (__addr_ == 0) {
throw new GLException("Method \"glMapBuffer\" not available");
@@ -252,7 +276,8 @@ native private long dispatch_glMapBuffer(int target, int access, long glProcAddr
native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
-public void glVertexPointer(GLArrayData array) {
+@Override
+public final void glVertexPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
@@ -260,7 +285,8 @@ public void glVertexPointer(GLArrayData array) {
glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer());
}
}
-public void glColorPointer(GLArrayData array) {
+@Override
+public final void glColorPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
@@ -269,7 +295,8 @@ public void glColorPointer(GLArrayData array) {
}
}
-public void glNormalPointer(GLArrayData array) {
+@Override
+public final void glNormalPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.getComponentCount()!=3) {
throw new GLException("Only 3 components per normal allowed");
@@ -280,7 +307,8 @@ public void glNormalPointer(GLArrayData array) {
glNormalPointer(array.getComponentType(), array.getStride(), array.getBuffer());
}
}
-public void glTexCoordPointer(GLArrayData array) {
+@Override
+public final void glTexCoordPointer(GLArrayData array) {
if(array.getComponentCount()==0) return;
if(array.isVBO()) {
glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset());
diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles2.java b/make/config/jogl/gl-impl-CustomJavaCode-gles2.java
index a4976f5ea..760287364 100644
--- a/make/config/jogl/gl-impl-CustomJavaCode-gles2.java
+++ b/make/config/jogl/gl-impl-CustomJavaCode-gles2.java
@@ -1,6 +1,3 @@
-// Tracks glBegin/glEnd calls to determine whether it is legal to
-// query Vertex Buffer Object state
-private boolean inBeginEndPair;
public GLES2Impl(GLProfile glp, GLContextImpl context) {
this._context = context;
@@ -16,18 +13,22 @@ public GLES2Impl(GLProfile glp, GLContextImpl context) {
this.glProfile = glp;
}
+@Override
public final boolean isGL4bc() {
return false;
}
+@Override
public final boolean isGL4() {
return false;
}
+@Override
public final boolean isGL3bc() {
return false;
}
+@Override
public final boolean isGL3() {
return false;
}
@@ -36,78 +37,97 @@ public final boolean isGL2() {
return false;
}
+@Override
public final boolean isGLES1() {
return false;
}
+@Override
public final boolean isGLES2() {
return true;
}
+@Override
public final boolean isGLES() {
return true;
}
+@Override
public final boolean isGL2ES1() {
return false;
}
+@Override
public final boolean isGL2ES2() {
return true;
}
+@Override
public final boolean isGLES2Compatible() {
return true;
}
+@Override
public final boolean isGL2GL3() {
return false;
}
+@Override
public final boolean hasGLSL() {
return true;
}
+@Override
public boolean isNPOTTextureAvailable() {
return true;
}
+@Override
public final GL4bc getGL4bc() throws GLException {
throw new GLException("Not a GL4bc implementation");
}
+@Override
public final GL4 getGL4() throws GLException {
throw new GLException("Not a GL4 implementation");
}
+@Override
public final GL3bc getGL3bc() throws GLException {
throw new GLException("Not a GL3bc implementation");
}
+@Override
public final GL3 getGL3() throws GLException {
throw new GLException("Not a GL3 implementation");
}
+@Override
public final GL2 getGL2() throws GLException {
throw new GLException("Not a GL2 implementation");
}
+@Override
public final GLES1 getGLES1() throws GLException {
throw new GLException("Not a GLES1 implementation");
}
+@Override
public final GLES2 getGLES2() throws GLException {
return this;
}
+@Override
public final GL2ES1 getGL2ES1() throws GLException {
throw new GLException("Not a GL2ES1 implementation");
}
+@Override
public final GL2ES2 getGL2ES2() throws GLException {
return this;
}
+@Override
public final GL2GL3 getGL2GL3() throws GLException {
throw new GLException("Not a GL2GL3 implementation");
}
@@ -123,17 +143,17 @@ private final GLStateTracker glStateTracker;
private boolean bufferObjectExtensionsInitialized = false;
private boolean haveOESFramebufferObject;
-private void initBufferObjectExtensionChecks() {
+private final void initBufferObjectExtensionChecks() {
if (bufferObjectExtensionsInitialized)
return;
bufferObjectExtensionsInitialized = true;
haveOESFramebufferObject = isExtensionAvailable("GL_OES_framebuffer_object");
}
-private boolean checkBufferObject(boolean avail,
- boolean enabled,
- int state,
- String kind, boolean throwException) {
+private final boolean checkBufferObject(boolean avail,
+ boolean enabled,
+ int state,
+ String kind, boolean throwException) {
if (!avail) {
if (!enabled)
return true;
@@ -161,7 +181,7 @@ private boolean checkBufferObject(boolean avail,
return true;
}
-private boolean checkArrayVBODisabled(boolean throwException) {
+private final boolean checkArrayVBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
false,
@@ -169,7 +189,7 @@ private boolean checkArrayVBODisabled(boolean throwException) {
"array vertex_buffer_object", throwException);
}
-private boolean checkArrayVBOEnabled(boolean throwException) {
+private final boolean checkArrayVBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
true,
@@ -177,7 +197,7 @@ private boolean checkArrayVBOEnabled(boolean throwException) {
"array vertex_buffer_object", throwException);
}
-private boolean checkElementVBODisabled(boolean throwException) {
+private final boolean checkElementVBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
false,
@@ -185,7 +205,7 @@ private boolean checkElementVBODisabled(boolean throwException) {
"element vertex_buffer_object", throwException);
}
-private boolean checkElementVBOEnabled(boolean throwException) {
+private final boolean checkElementVBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
return checkBufferObject(true,
true,
@@ -193,30 +213,31 @@ private boolean checkElementVBOEnabled(boolean throwException) {
"element vertex_buffer_object", throwException);
}
-private boolean checkUnpackPBODisabled(boolean throwException) {
+private final boolean checkUnpackPBODisabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return true;
}
-private boolean checkUnpackPBOEnabled(boolean throwException) {
+private final boolean checkUnpackPBOEnabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return false;
}
-private boolean checkPackPBODisabled(boolean throwException) {
+private final boolean checkPackPBODisabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return true;
}
-private boolean checkPackPBOEnabled(boolean throwException) {
+private final boolean checkPackPBOEnabled(boolean throwException) {
// PBO n/a for ES 1.1 or ES 2.0
return false;
}
-private HashMap
LPVOID glMapBuffer(GLenum target, GLenum access);
*/
-public java.nio.ByteBuffer glMapBuffer(int target, int access) {
+@Override
+public final java.nio.ByteBuffer glMapBuffer(int target, int access) {
final long __addr_ = ((GLES2ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer;
if (__addr_ == 0) {
throw new GLException("Method \"glMapBuffer\" not available");
@@ -256,11 +277,13 @@ native private long dispatch_glMapBuffer(int target, int access, long glProcAddr
native private ByteBuffer newDirectByteBuffer(long addr, long capacity);
-public void glClearDepth(double depth) {
+@Override
+public final void glClearDepth(double depth) {
glClearDepthf((float)depth);
}
-public void glDepthRange(double zNear, double zFar) {
+@Override
+public final void glDepthRange(double zNear, double zFar) {
glDepthRangef((float)zNear, (float)zFar);
}
diff --git a/make/scripts/java-win32-dbg.bat b/make/scripts/java-win32-dbg.bat
index d1797bdbb..6f8206721 100755
--- a/make/scripts/java-win32-dbg.bat
+++ b/make/scripts/java-win32-dbg.bat
@@ -9,9 +9,9 @@ set BLD_DIR=..\%BLD_SUB%
set FFMPEG_LIB=%PROJECT_ROOT%\make\lib\ffmpeg\x32
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH%
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH%
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\angle\win32;%PATH%
+set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH%
REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj
set LIB_DIR=%FFMPEG_LIB%
@@ -20,11 +20,14 @@ set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluege
echo CP_ALL %CP_ALL%
-set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer"
+set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject"
+REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery"
+REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK"
+REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
+REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer"
REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.ProcAddressHelper=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true"
REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true"
REM set D_ARGS="-Djogamp.debug.JNILibLoader=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLProfile=true"
-REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
REM set D_ARGS="-Dnewt.debug.Window" "-Dnativewindow.debug.TraceLock"
REM set D_ARGS="-Dnativewindow.debug.TraceLock"
REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display"
diff --git a/make/scripts/java-win32.bat b/make/scripts/java-win32.bat
index 9d59c045e..1d8430280 100755
--- a/make/scripts/java-win32.bat
+++ b/make/scripts/java-win32.bat
@@ -8,8 +8,8 @@ set PROJECT_ROOT=D:\projects\jogamp\jogl
set BLD_DIR=..\%BLD_SUB%
REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH%
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH%
-REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH%
+set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH%
set BLD_DIR=..\%BLD_SUB%
REM set LIB_DIR=..\..\gluegen\%BLD_SUB%\obj;%BLD_DIR%\lib
diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/java-win64-dbg.bat
index d6b0435ea..109755d2e 100755
--- a/make/scripts/java-win64-dbg.bat
+++ b/make/scripts/java-win64-dbg.bat
@@ -9,7 +9,8 @@ set BLD_DIR=..\%BLD_SUB%
set FFMPEG_LIB=%PROJECT_ROOT%\make\lib\ffmpeg\x64
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH%
+set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_64;%PATH%
REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj
set LIB_DIR=%FFMPEG_LIB%
@@ -17,7 +18,13 @@ set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluege
echo CP_ALL %CP_ALL%
-set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer"
+set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject"
+REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery"
+REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK"
+REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all"
+REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug=all" "-Djogl.debug.EGLDrawableFactory.DontQuery"
+REM set D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser -Djogl.debug.GLProfile"
+REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer"
REM set D_ARGS="-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLSLCode"
REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.ProcAddressHelper=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true"
REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true"
@@ -33,7 +40,6 @@ REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLC
REM set D_ARGS="-Dnewt.debug.Window"
REM set D_ARGS="-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL"
REM set D_ARGS="-Djogl.debug.DebugGL" "-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.GLSLCode"
-REM set D_ARGS="-Djogl.debug.GraphicsConfiguration" "-Djogl.debug.CapabilitiesChooser"
REM set D_ARGS="-Djogl.debug.GLContext" "-Dnewt.debug=all"
REM set D_ARGS="-Dnewt.debug.Window" "-Dnativewindow.debug.TraceLock"
REM set D_ARGS="-Dnativewindow.debug.TraceLock"
diff --git a/make/scripts/java-win64.bat b/make/scripts/java-win64.bat
index b8f438aab..2c09feedc 100755
--- a/make/scripts/java-win64.bat
+++ b/make/scripts/java-win64.bat
@@ -4,7 +4,8 @@ set J2RE_HOME=c:\jre1.6.0_30_x64
set JAVA_HOME=c:\jdk1.6.0_30_x64
set ANT_PATH=C:\apache-ant-1.8.2
-set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH%
+REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH%
+set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_64;%PATH%
set BLD_DIR=..\%BLD_SUB%
REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj
diff --git a/make/scripts/tests-x32.bat b/make/scripts/tests-x32.bat
index c29dcef39..7947759a4 100755
--- a/make/scripts/tests-x32.bat
+++ b/make/scripts/tests-x32.bat
@@ -51,7 +51,7 @@ REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode0
REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT
REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple %*
-scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %*
+REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %*
REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.TexCubeES2 %*
REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT
@@ -94,6 +94,7 @@ REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMe
REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT
REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01
+scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %*
REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01
REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %*
diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat
index 32729d235..0b3711784 100755
--- a/make/scripts/tests-x64.bat
+++ b/make/scripts/tests-x64.bat
@@ -72,7 +72,7 @@ REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingPr
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT01GLn %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT02GLn %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAWT01GLn %*
-scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
+REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT -time 5000
@@ -96,7 +96,8 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMe
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01
-REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01
+scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %*
+REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %*
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 0258187fd..591f5f9d2 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -53,10 +53,17 @@ function jrun() {
swton=$1
shift
+ #D_ARGS="-Djogl.debug.FBObject -Djogl.debug.DebugGL"
+ #D_ARGS="-Djogl.debug.FBObject"
+ #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.FBObject"
#D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing"
#D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all"
#D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all"
+ #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock"
#D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all"
+ #D_ARGS="-Djogl.debug.EGLDrawableFactory.DontQuery -Djogl.debug.GLDrawable"
+ #D_ARGS="-Djogl.debug.EGLDrawableFactory.QueryNativeTK -Djogl.debug.GLDrawable"
+ #D_ARGS="-Djogl.debug.GLDrawable"
#D_ARGS="-Djogl.debug=all -Dnewt.debug=all"
#D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.TraceGL"
#D_ARGS="-Djogl.debug.GLDebugMessageHandler"
@@ -71,6 +78,7 @@ function jrun() {
#D_ARGS="-Djogamp.debug.IOUtil -Djogl.debug.GLSLCode -Djogl.debug.GLMediaPlayer"
#D_ARGS="-Djogl.debug.GLArrayData"
#D_ARGS="-Djogl.debug.EGL -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable"
+ #D_ARGS="-Djogl.debug.GLDrawable"
#D_ARGS="-Dnewt.test.Screen.disableScreenMode -Dnewt.debug.Screen"
#D_ARGS="-Djogl.debug.ExtensionAvailabilityCache -Djogl.debug=all -Dnativewindow.debug=all -Djogamp.debug.ProcAddressHelper=true -Djogamp.debug.NativeLibrary=true -Djogamp.debug.NativeLibrary.Lookup=true"
#D_ARGS="-Dnewt.debug.MainThread"
@@ -85,7 +93,7 @@ function jrun() {
#D_ARGS="-Dnativewindow.debug.NativeWindow"
#D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT"
#D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Window -Djogl.debug.GLContext"
- #D_ARGS="-Dnativewindow.debug.ToolkitLock.TraceLock -Dnativewindow.debug.X11Util.XErrorStackDump -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Dnativewindow.debug.X11Util"
+ #D_ARGS="-Dnativewindow.debug.X11Util.XErrorStackDump -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Dnativewindow.debug.X11Util"
#D_ARGS="-Dnativewindow.debug.X11Util -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnewt.debug=all"
#D_ARGS="-Dnativewindow.debug.X11Util -Dnativewindow.debug.X11Util.XSync"
#D_ARGS="-Dnativewindow.debug.X11Util.XSync -Dnewt.debug.Window"
@@ -100,9 +108,9 @@ function jrun() {
#D_ARGS="-Djogl.debug.Animator -Dnewt.debug=all"
#D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Display -Dnativewindow.debug.X11Util -Djogl.debug.GLDrawable -Djogl.debug.GLCanvas"
#D_ARGS="-Djogl.debug.GLContext"
- #D_ARGS="-Djogl.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser"
+ #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser"
#D_ARGS="-Dnewt.debug.Screen -Dnewt.debug.EDT -Djogamp.debug.Lock"
- #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GraphicsConfiguration"
+ #D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.GraphicsConfiguration"
#D_ARGS="-Dnewt.debug.EDT"
#D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.GLContext"
#D_ARGS="-Dnewt.debug.Window -Djogl.debug.Animator -Dnewt.debug.Screen"
@@ -115,8 +123,6 @@ function jrun() {
#D_ARGS="-Xprof"
#D_ARGS="-Djogl.debug.Animator"
#D_ARGS="-Dnativewindow.debug=all"
- #D_ARGS="-Djogl.debug.GraphicsConfiguration"
- #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GraphicsConfiguration"
#D_ARGS="-Djogl.debug.GLCanvas"
#D_ARGS="-Dnativewindow.debug.ToolkitLock.TraceLock"
#D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLCode -Djogl.debug.TraceGL"
@@ -162,20 +168,20 @@ function jrun() {
C_ARG="com.jogamp.newt.util.MainThread"
fi
fi
+ #export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_64:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_32:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=/usr/local/projects/Xorg.modular/build-x86_64/lib:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=/opt-linux-x86_64/x11lib-1.3:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=/usr/lib/mesa:/usr/lib32/mesa:$LD_LIBRARY_PATH
+ #export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/mesa:/usr/lib/i386-linux-gnu/mesa:$LD_LIBRARY_PATH
echo
echo "Test Start: $*"
echo
echo LD_LIBRARY_PATH $LD_LIBRARY_PATH
echo
echo $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $*
- #LD_LIBRARY_PATH=/usr/local/projects/Xorg.modular/build-x86_64/lib:$LD_LIBRARY_PATH \
- #LD_LIBRARY_PATH=/opt-linux-x86_64/x11lib-1.3:$LD_LIBRARY_PATH \
- #LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64:$LD_LIBRARY_PATH \
#LIBGL_DRIVERS_PATH=/usr/lib/mesa:/usr/lib32/mesa \
- #LD_LIBRARY_PATH=/usr/lib/mesa:/usr/lib32/mesa:$LD_LIBRARY_PATH \
- #LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/mesa:/usr/lib/i386-linux-gnu/mesa:$LD_LIBRARY_PATH \
- #LD_LIBRARY_PATH=$spath/../lib/PVRVFrame/OGLES-2.0/Linux_x86_64:$LD_LIBRARY_PATH \
- #LD_LIBRARY_PATH=$spath/../lib/PVRVFrame/OGLES-2.0/Linux_x86_32:$LD_LIBRARY_PATH \
#gdb --args $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $*
$javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $*
echo
@@ -228,6 +234,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT2 $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT $*
@@ -292,7 +299,7 @@ function testawtswt() {
# swt (testswt)
#
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $*
-testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
+#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor02GLn $*
@@ -322,7 +329,8 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testawt com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentParentingAWT $*
#testawt com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT
#testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES2NEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyNEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT
@@ -358,7 +366,9 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $*
+testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $*
#
# Graph
@@ -394,6 +404,7 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
#testawt com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot $*
#linux:
+#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES2NEWT $* # linux NV: cannot make ctx current ..
# osx:
#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $*
diff --git a/make/stub_includes/opengl/macosx-window-system.h b/make/stub_includes/opengl/macosx-window-system.h
index e7fe13553..47b51a509 100644
--- a/make/stub_includes/opengl/macosx-window-system.h
+++ b/make/stub_includes/opengl/macosx-window-system.h
@@ -31,7 +31,7 @@ NSView* getNSView(NSOpenGLContext* ctx);
NSOpenGLContext* createContext(NSOpenGLContext* shareContext,
NSView* nsView,
- Bool isBackingLayerView,
+ Bool allowIncompleteView,
NSOpenGLPixelFormat* pixelFormat,
Bool opaque,
int* viewNotReady);
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
index 87a734e1f..482d35cae 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java
@@ -293,9 +293,9 @@ public class BuildStaticGLInfo {
output.println(" public static String getFunctionAssociation(String glFunctionName)");
output.println(" {");
output.println(" String mappedName = null;");
- output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutationNumber(glFunctionName);");
+ output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutationNumber(glFunctionName);");
output.println(" for(int i = 0; null==mappedName && i < funcNamePermNum; i++) {");
- output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutation(glFunctionName, i);");
+ output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutation(glFunctionName, i);");
output.println(" try {");
output.println(" mappedName = (String)funcToAssocMap.get(tmp);");
output.println(" } catch (Exception e) { }");
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
index c1a4facd2..ba025e18c 100755
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java
@@ -43,7 +43,7 @@ import com.jogamp.gluegen.GlueEmitterControls;
import com.jogamp.gluegen.GlueGen;
import com.jogamp.gluegen.MethodBinding;
import com.jogamp.gluegen.procaddress.ProcAddressConfiguration;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -224,11 +224,11 @@ public class GLConfiguration extends ProcAddressConfiguration {
}
}
}
- boolean isGLEnum = GLExtensionNames.isGLEnumeration(symbol);
- boolean isGLFunc = GLExtensionNames.isGLFunction(symbol);
+ boolean isGLEnum = GLNameResolver.isGLEnumeration(symbol);
+ boolean isGLFunc = GLNameResolver.isGLFunction(symbol);
if (isGLFunc || isGLEnum) {
- if (GLExtensionNames.isExtensionVEN(symbol, isGLFunc)) {
- String extSuffix = GLExtensionNames.getExtensionSuffix(symbol, isGLFunc);
+ if (GLNameResolver.isExtensionVEN(symbol, isGLFunc)) {
+ String extSuffix = GLNameResolver.getExtensionSuffix(symbol, isGLFunc);
if (getDropUniqVendorExtensions(extSuffix)) {
if (DEBUG_IGNORES) {
System.err.println("Ignore UniqVendorEXT: " + symbol + ", vendor " + extSuffix);
diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
index f4658ad7b..809c6783d 100644
--- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
+++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java
@@ -51,7 +51,7 @@ import com.jogamp.gluegen.SymbolFilter;
import com.jogamp.gluegen.cgram.types.FunctionSymbol;
import com.jogamp.gluegen.procaddress.ProcAddressEmitter;
import com.jogamp.gluegen.procaddress.ProcAddressJavaMethodBindingEmitter;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import java.io.IOException;
import java.io.PrintWriter;
@@ -110,13 +110,13 @@ public class GLEmitter extends ProcAddressEmitter {
if (declarations != null) {
for (Iterator
+ * Integrates default read/write framebuffers via {@link GLContext#getDefaultReadFramebuffer()} and {@link GLContext#getDefaultReadFramebuffer()},
+ * which is being hooked at {@link GL#glBindFramebuffer(int, int)} when the default (zero
) framebuffer is selected.
+ *
FIXME: Implement support for {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} .
+ */ +public class FBObject { + protected static final boolean DEBUG = Debug.debug("FBObject"); + + /** + * Returnstrue
if basic FBO support is available, otherwise false
.
+ *
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
+ * ARB_ES2_compatibility
, ARB_framebuffer_object
, EXT_framebuffer_object
or OES_framebuffer_object
.
+ *
+ * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *
+ * @see GLContext#hasFBO() + */ + public static final boolean supportsBasicFBO(GL gl) { + return gl.getContext().hasFBO(); + } + + /** + * Returnstrue
if full FBO support is available, otherwise false
.
+ *
+ * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
+ * ARB_framebuffer_object
, or all of
+ * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
+ * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
+ *
+ * Full FBO support includes multiple color attachments and multisampling. + *
+ */ + public static final boolean supportsFullFBO(GL gl) { + return gl.isGL3() || // GL >= 3.0 + + gl.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object + + ( gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object* + gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) && + gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) && + gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) ) ; + } + + public static final int getMaxSamples(GL gl) { + if( supportsFullFBO(gl) ) { + int[] val = new int[] { 0 } ; + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + return val[0]; + } else { + return 0; + } + } + + /** Common super class of all attachments */ + public static abstract class Attachment { + public enum Type { + NONE, DEPTH, STENCIL, DEPTH_STENCIL, COLOR, COLOR_TEXTURE, DEPTH_TEXTURE, STENCIL_TEXTURE; + + /** + * Returns {@link #COLOR}, {@link #DEPTH}, {@link #STENCIL} or {@link #DEPTH_STENCIL} + * @throws IllegalArgumentException ifformat
cannot be handled.
+ */
+ public static Type determine(int format) throws IllegalArgumentException {
+ switch(format) {
+ case GL.GL_RGBA4:
+ case GL.GL_RGB5_A1:
+ case GL.GL_RGB565:
+ case GL.GL_RGB8:
+ case GL.GL_RGBA8:
+ return Type.COLOR;
+ case GL.GL_DEPTH_COMPONENT16:
+ case GL.GL_DEPTH_COMPONENT24:
+ case GL.GL_DEPTH_COMPONENT32:
+ return Type.DEPTH;
+ case GL.GL_STENCIL_INDEX1:
+ case GL.GL_STENCIL_INDEX4:
+ case GL.GL_STENCIL_INDEX8:
+ return Type.STENCIL;
+ case GL.GL_DEPTH24_STENCIL8:
+ return Type.DEPTH_STENCIL;
+ default:
+ throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format));
+ }
+ }
+ };
+
+ /** immutable type [{@link #COLOR}, {@link #DEPTH}, {@link #STENCIL}, {@link #COLOR_TEXTURE}, {@link #DEPTH_TEXTURE}, {@link #STENCIL_TEXTURE} ] */
+ public final Type type;
+
+ /** immutable the internal format */
+ public final int format;
+
+ private int width, height;
+
+ private int name;
+
+ /** true
if resource is initialized by {@link #initialize(GL)}, hence {@link #free(GL)} is allowed to free the GL resources. */
+ protected boolean resourceOwner;
+
+ private int initCounter;
+
+ protected Attachment(Type type, int iFormat, int width, int height, int name) {
+ this.type = type;
+ this.format = iFormat;
+ this.width = width;
+ this.height = height;
+ this.name = name;
+ this.resourceOwner = false;
+ this.initCounter = 0;
+ }
+
+ /** width of attachment */
+ public final int getWidth() { return width; }
+ /** height of attachment */
+ public final int getHeight() { return height; }
+ /* pp */ final void setSize(int w, int h) { width = w; height = h; }
+
+ /** buffer name [1..max], maybe a texture or renderbuffer name, depending on type. */
+ public final int getName() { return name; }
+ /* pp */ final void setName(int n) { name = n; }
+
+ public final int getInitCounter() { return initCounter; }
+
+ /**
+ * Initializes the attachment buffer and set it's parameter, if uninitialized, i.e. name is zero
.
+ * Implementation employs an initialization counter, hence it can be paired recursively with {@link #free(GL)}.
+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. + */ + public void initialize(GL gl) throws GLException { + initCounter++; + /* + super.initialize(gl); + if(1 == getInitCounter() && 0 == getName() ) { + do init .. + freeResources = true; // if all OK + } + */ + } + + /** + * Releases the attachment buffer if initialized, i.e. name iszero
.
+ * Implementation employs an initialization counter, hence it can be paired recursively with {@link #initialize(GL)}.
+ * @throws GLException if buffer release fails. + */ + public void free(GL gl) throws GLException { + /* + if(1 == getInitCounter() && freeResources && .. ) { + do free .. + } + super.free(gl); + */ + initCounter--; + if(0 == initCounter) { + resourceOwner = false; + name = 0; + } + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } + } + + /** + *+ * Comparison by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}. + *
+ * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if( this == o ) return true; + if( ! ( o instanceof Attachment ) ) return false; + final Attachment a = (Attachment)o; + return type == a.type && + format == a.format || + width == a.width || + height== a.height || + name == a.name ; + } + + /** + *+ * Hashed by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}. + *
+ * {@inheritDoc} + */ + @Override + public int hashCode() { + // 31 * x == (x << 5) - x + int hash = 31 + type.ordinal(); + hash = ((hash << 5) - hash) + format; + hash = ((hash << 5) - hash) + width; + hash = ((hash << 5) - hash) + height; + hash = ((hash << 5) - hash) + name; + return hash; + } + + int objectHashCode() { return super.hashCode(); } + + public String toString() { + return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", "+width+"x"+height+ + ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+ + ", resOwner "+resourceOwner+", initCount "+initCounter+"]"; + } + + public static Type getType(int attachmentPoint, int maxColorAttachments) { + if( GL.GL_COLOR_ATTACHMENT0 <= attachmentPoint && attachmentPoint < GL.GL_COLOR_ATTACHMENT0+maxColorAttachments ) { + return Type.COLOR; + } + switch(attachmentPoint) { + case GL.GL_DEPTH_ATTACHMENT: + return Type.DEPTH; + case GL.GL_STENCIL_ATTACHMENT: + return Type.STENCIL; + default: + throw new IllegalArgumentException("Invalid attachment point 0x"+Integer.toHexString(attachmentPoint)); + } + } + } + + /** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */ + public static class RenderAttachment extends Attachment { + private int samples; + + /** + * @param type allowed types are {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#COLOR} + * @param iFormat + * @param samples + * @param width + * @param height + * @param name + */ + public RenderAttachment(Type type, int iFormat, int samples, int width, int height, int name) { + super(validateType(type), iFormat, width, height, name); + this.samples = samples; + } + + /** number of samples, or zero for no multisampling */ + public final int getSamples() { return samples; } + /* pp */ final void setSamples(int s) { samples = s; } + + private static Type validateType(Type type) { + switch(type) { + case DEPTH: + case STENCIL: + case COLOR: + return type; + default: + throw new IllegalArgumentException("Invalid type: "+type); + } + } + + /** + *+ * Comparison by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}. + *
+ * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if( this == o ) return true; + if( ! ( o instanceof RenderAttachment ) ) return false; + return super.equals(o) && + samples == ((RenderAttachment)o).samples; + } + + /** + *+ * Hashed by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}. + *
+ * {@inheritDoc} + */ + @Override + public int hashCode() { + // 31 * x == (x << 5) - x + int hash = super.hashCode(); + hash = ((hash << 5) - hash) + samples; + return hash; + } + + @Override + public void initialize(GL gl) throws GLException { + super.initialize(gl); + if( 1 == getInitCounter() && 0 == getName() ) { + final int[] name = new int[] { -1 }; + gl.glGenRenderbuffers(1, name, 0); + if( 0 == name[0] ) { + throw new GLException("null renderbuffer, "+this); + } + setName(name[0]); + + gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName()); + if( samples > 0 ) { + ((GL2GL3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight()); + } else { + gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight()); + } + int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR != glerr) { + gl.glDeleteRenderbuffers(1, name, 0); + setName(0); + throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); + } + resourceOwner = true; + if(DEBUG) { + System.err.println("Attachment.init: "+this); + } + } + } + + @Override + public void free(GL gl) { + if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { + final int[] name = new int[] { getName() }; + gl.glDeleteRenderbuffers(1, name, 0); + } + super.free(gl); + } + + public String toString() { + return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+ + ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+ + ", resOwner "+resourceOwner+", initCount "+getInitCounter()+"]"; + } + } + + /** + * Marker interface, denotes a color buffer attachment. + *Always an instance of {@link Attachment}.
+ *Either an instance of {@link ColorAttachment} or {@link TextureAttachment}.
+ */
+ public static interface Colorbuffer {
+ }
+
+ /** Color render buffer attachment */
+ public static class ColorAttachment extends RenderAttachment implements Colorbuffer {
+ public ColorAttachment(int iFormat, int samples, int width, int height, int name) {
+ super(Type.COLOR, iFormat, samples, width, height, name);
+ }
+ }
+
+ /** Texture attachment */
+ public static class TextureAttachment extends Attachment implements Colorbuffer {
+ /** details of the texture setup */
+ public final int dataFormat, dataType, magFilter, minFilter, wrapS, wrapT;
+
+ /**
+ * @param type allowed types are [ {@link Type#COLOR_TEXTURE}, {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} ]
+ * @param iFormat
+ * @param width
+ * @param height
+ * @param dataFormat
+ * @param dataType
+ * @param magFilter
+ * @param minFilter
+ * @param wrapS
+ * @param wrapT
+ * @param name
+ */
+ public TextureAttachment(Type type, int iFormat, int width, int height, int dataFormat, int dataType,
+ int magFilter, int minFilter, int wrapS, int wrapT, int name) {
+ super(validateType(type), iFormat, width, height, name);
+ this.dataFormat = dataFormat;
+ this.dataType = dataType;
+ this.magFilter = magFilter;
+ this.minFilter = minFilter;
+ this.wrapS = wrapS;
+ this.wrapT = wrapT;
+ }
+
+ private static Type validateType(Type type) {
+ switch(type) {
+ case COLOR_TEXTURE:
+ case DEPTH_TEXTURE:
+ case STENCIL_TEXTURE:
+ return type;
+ default:
+ throw new IllegalArgumentException("Invalid type: "+type);
+ }
+ }
+
+ /**
+ * Initializes the texture and set it's parameter, if uninitialized, i.e. name is zero
.
+ * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case.
+ */
+ @Override
+ public void initialize(GL gl) throws GLException {
+ super.initialize(gl);
+ if( 1 == getInitCounter() && 0 == getName() ) {
+ final int[] name = new int[] { -1 };
+ gl.glGenTextures(1, name, 0);
+ if(0 == name[0]) {
+ throw new GLException("null texture, "+this);
+ }
+ setName(name[0]);
+
+ gl.glBindTexture(GL.GL_TEXTURE_2D, name[0]);
+ gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null);
+ if( 0 < magFilter ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter);
+ }
+ if( 0 < minFilter ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter);
+ }
+ if( 0 < wrapS ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS);
+ }
+ if( 0 < wrapT ) {
+ gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT);
+ }
+ int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR != glerr) {
+ gl.glDeleteTextures(1, name, 0);
+ setName(0);
+ throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this);
+ }
+ resourceOwner = true;
+ }
+ if(DEBUG) {
+ System.err.println("Attachment.init: "+this);
+ }
+ }
+
+ @Override
+ public void free(GL gl) {
+ if(1 == getInitCounter() && resourceOwner && 0 != getName() ) {
+ final int[] name = new int[] { getName() };
+ gl.glDeleteTextures(1, name, 0);
+ }
+ super.free(gl);
+ }
+ }
+
+ private boolean initialized;
+ private boolean basicFBOSupport;
+ private boolean fullFBOSupport;
+ private boolean rgba8Avail;
+ private boolean depth24Avail;
+ private boolean depth32Avail;
+ private boolean stencil01Avail;
+ private boolean stencil04Avail;
+ private boolean stencil08Avail;
+ private boolean stencil16Avail;
+ private boolean packedDepthStencilAvail;
+ private int maxColorAttachments, maxSamples, maxTextureSize, maxRenderbufferSize;
+
+ private int width, height, samples;
+ private int vStatus;
+ private int fbName;
+ private boolean bound;
+
+ private int colorAttachmentCount;
+ private Colorbuffer[] colorAttachmentPoints; // colorbuffer attachment points
+ private RenderAttachment depth, stencil; // depth and stencil maybe equal in case of packed-depth-stencil
+
+ private final FBObject samplesSink; // MSAA sink
+ private TextureAttachment samplesSinkTexture;
+ private boolean samplesSinkDirty;
+
+ //
+ // ColorAttachment helper ..
+ //
+
+ private final void validateColorAttachmentPointRange(int point) {
+ if(maxColorAttachments != colorAttachmentPoints.length) {
+ throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints);
+ }
+ if(0 > point || point >= maxColorAttachments) {
+ throw new IllegalArgumentException("attachment point out of range: "+point+", should be within [0.."+(maxColorAttachments-1)+"]");
+ }
+ }
+
+ private final void validateAddColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ if( null != colorAttachmentPoints[point] ) {
+ throw new IllegalArgumentException("Cannot attach "+ca+", attachment point already in use by "+colorAttachmentPoints[point]);
+ }
+ }
+
+ private final void addColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ final Colorbuffer c = colorAttachmentPoints[point];
+ if( null != c && c != ca ) {
+ throw new IllegalArgumentException("Add failed: requested to add "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+ }
+ colorAttachmentPoints[point] = ca;
+ colorAttachmentCount++;
+ }
+
+ private final void removeColorAttachment(int point, Colorbuffer ca) {
+ validateColorAttachmentPointRange(point);
+ final Colorbuffer c = colorAttachmentPoints[point];
+ if( null != c && c != ca ) {
+ throw new IllegalArgumentException("Remove failed: requested to removed "+ca+" at "+point+", but slot is holding "+c+"; "+this);
+ }
+ colorAttachmentPoints[point] = null;
+ colorAttachmentCount--;
+ }
+
+ /**
+ * Return the {@link Colorbuffer} attachment at attachmentPoint
if it is attached to this FBO, otherwise null.
+ *
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachColorbuffer(GL, boolean)
+ * @see #attachTexture2D(GL, int, boolean, int, int, int, int)
+ * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int)
+ */
+ public final Colorbuffer getColorbuffer(int attachmentPoint) {
+ validateColorAttachmentPointRange(attachmentPoint);
+ return colorAttachmentPoints[attachmentPoint];
+ }
+
+ /**
+ * Finds the passed {@link Colorbuffer} within the valid range of attachment points
+ * using reference comparison only.
+ *
+ * Note: Slow. Implementation uses a logN array search to save resources, i.e. not using a HashMap. + *
+ * @param ca the {@link Colorbuffer} to look for. + * @return -1 if the {@link Colorbuffer} could not be found, otherwise [0..{@link #getMaxColorAttachments()}-1] + */ + public final int getColorbufferAttachmentPoint(Colorbuffer ca) { + for(int i=0; i+ * Note: Slow. Uses {@link #getColorbufferAttachmentPoint(Colorbuffer)} to determine it's attachment point + * to be used for {@link #getColorbuffer(int)} + *
+ * + * @see #attachColorbuffer(GL, boolean) + * @see #attachColorbuffer(GL, boolean) + * @see #attachTexture2D(GL, int, boolean, int, int, int, int) + * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int) + */ + public final Colorbuffer getColorbuffer(Colorbuffer ca) { + final int p = getColorbufferAttachmentPoint(ca); + return p>=0 ? getColorbuffer(p) : null; + } + + /** + * Creates an uninitialized FBObject instance. + *+ * Call {@link #init(GL, int, int, int)} .. etc to use it. + *
+ */ + public FBObject() { + this(false); + } + /* pp */ FBObject(boolean isSampleSink) { + this.initialized = false; + + // TBD @ init + this.basicFBOSupport = false; + this.fullFBOSupport = false; + this.rgba8Avail = false; + this.depth24Avail = false; + this.depth32Avail = false; + this.stencil01Avail = false; + this.stencil04Avail = false; + this.stencil08Avail = false; + this.stencil16Avail = false; + this.packedDepthStencilAvail = false; + this.maxColorAttachments=-1; + this.maxSamples=-1; + this.maxTextureSize = 0; + this.maxRenderbufferSize = 0; + + this.width = 0; + this.height = 0; + this.samples = 0; + this.vStatus = -1; + this.fbName = 0; + this.bound = false; + + this.colorAttachmentPoints = null; // at init .. + this.colorAttachmentCount = 0; + this.depth = null; + this.stencil = null; + + this.samplesSink = isSampleSink ? null : new FBObject(true); + this.samplesSinkTexture = null; + this.samplesSinkDirty = true; + } + + private void init(GL gl, int width, int height, int samples) throws GLException { + if(initialized) { + throw new GLException("FBO already initialized"); + } + fullFBOSupport = supportsFullFBO(gl); + + if( !fullFBOSupport && !supportsBasicFBO(gl) ) { + throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this); + } + + basicFBOSupport = true; + + rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8); + depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24); + depth32Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth32); + stencil01Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil1); + stencil04Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil4); + stencil08Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil8); + stencil16Avail = fullFBOSupport; + + packedDepthStencilAvail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_packed_depth_stencil); + + final boolean NV_fbo_color_attachments = gl.isExtensionAvailable(GLExtensions.NV_fbo_color_attachments); + + int val[] = new int[1]; + + int glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("FBObject.init-preexisting.0 GL Error 0x"+Integer.toHexString(glerr)); + } + + int realMaxColorAttachments = 1; + maxColorAttachments = 1; + if( null != samplesSink && fullFBOSupport || NV_fbo_color_attachments ) { + try { + gl.glGetIntegerv(GL2GL3.GL_MAX_COLOR_ATTACHMENTS, val, 0); + glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1 + } else if(DEBUG) { + System.err.println("FBObject.init-GL_MAX_COLOR_ATTACHMENTS query GL Error 0x"+Integer.toHexString(glerr)); + } + } catch (GLException gle) {} + } + maxColorAttachments = realMaxColorAttachments <= 8 ? realMaxColorAttachments : 8; // cap to limit array size + + colorAttachmentPoints = new Colorbuffer[maxColorAttachments]; + colorAttachmentCount = 0; + + maxSamples = 0; + if(fullFBOSupport) { + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + maxSamples = val[0]; + } else if(DEBUG) { + System.err.println("FBObject.init-GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr)); + } + } + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0); + maxTextureSize = val[0]; + gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0); + this.maxRenderbufferSize = val[0]; + + glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("FBObject.init-preexisting.1 GL Error 0x"+Integer.toHexString(glerr)); + } + + this.width = width; + this.height = height; + this.samples = samples <= maxSamples ? samples : maxSamples; + + if(DEBUG) { + System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+samples+" samples"); + System.err.println("basicFBOSupport: "+basicFBOSupport); + System.err.println("fullFBOSupport: "+fullFBOSupport); + System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments); + System.err.println("maxSamples: "+maxSamples); + System.err.println("maxTextureSize: "+maxTextureSize); + System.err.println("maxRenderbufferSize: "+maxRenderbufferSize); + System.err.println("rgba8: "+rgba8Avail); + System.err.println("depth24: "+depth24Avail); + System.err.println("depth32: "+depth32Avail); + System.err.println("stencil01: "+stencil01Avail); + System.err.println("stencil04: "+stencil04Avail); + System.err.println("stencil08: "+stencil08Avail); + System.err.println("stencil16: "+stencil16Avail); + System.err.println("packedDepthStencil: "+packedDepthStencilAvail); + System.err.println("NV_fbo_color_attachments: "+NV_fbo_color_attachments); + System.err.println(gl.getContext().getGLVersion()); + System.err.println(JoglVersion.getGLStrings(gl, null).toString()); + System.err.println(gl.getContext()); + } + + checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error + + if(width > 2 + maxTextureSize || height> 2 + maxTextureSize || + width > maxRenderbufferSize || height> maxRenderbufferSize ) { + throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); + } + + if(null != samplesSink) { + // init sampling sink + samplesSink.reset(gl, width, height); + resetMSAATexture2DSink(gl); + } + + // generate fbo .. + gl.glGenFramebuffers(1, val, 0); + fbName = val[0]; + if(0 == fbName) { + throw new GLException("null framebuffer"); + } + + // bind fbo .. + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbName); + checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error + if(!gl.glIsFramebuffer(fbName)) { + checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException + } + bound = true; + initialized = true; + + updateStatus(gl); + if(DEBUG) { + System.err.println("FBObject.init(): "+this); + } + } + + /** + * Initializes or resets this FBO's instance. + *+ * In case the new parameters are compatible with the current ones + * no action will be performed. Otherwise all attachments will be recreated + * to match the new given parameters. + *
+ *+ * Currently incompatibility and hence recreation is given if + * the size or sample count doesn't match for subsequent calls. + *
+ * + *Leaves the FBO bound state untouched
+ * + * @param gl the current GL context + * @param newWidth + * @param newHeight + * @throws GLException in case of an error + */ + public final void reset(GL gl, int newWidth, int newHeight) { + reset(gl, newWidth, newHeight, 0); + } + + /** + * Initializes or resets this FBO's instance. + *+ * In case the new parameters are compatible with the current ones + * no action will be performed. Otherwise all attachments will be recreated + * to match the new given parameters. + *
+ *+ * Currently incompatibility and hence recreation is given if + * the size or sample count doesn't match for subsequent calls. + *
+ * + *Leaves the FBO bound state untouched
+ * + * @param gl the current GL context + * @param newWidth + * @param newHeight + * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}. + * @throws GLException in case of an error + */ + public final void reset(GL gl, int newWidth, int newHeight, int newSamples) { + if(!initialized) { + init(gl, newWidth, newHeight, newSamples); + return; + } + newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp + + if( newWidth != width || newHeight != height || newSamples != samples ) { + if(DEBUG) { + System.err.println("FBObject.reset - START - "+this); + } + + final boolean wasBound = isBound(); + + width = newWidth; + height = newHeight; + samples = newSamples; + detachAllImpl(gl, true , true); + resetMSAATexture2DSink(gl); + + if(wasBound) { + bind(gl); + } else { + unbind(gl); + } + + if(DEBUG) { + System.err.println("FBObject.reset - END - "+this); + } + } + } + + /** + * Note that the status may reflect an incomplete state during transition of attachments. + * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 + * @see #validateStatus() + */ + public final int getStatus() { + return vStatus; + } + + /** return the {@link #getStatus()} as a string. */ + public final String getStatusString() { + return getStatusString(vStatus); + } + + public static final String getStatusString(int fbStatus) { + switch(fbStatus) { + case -1: + return "NOT A FBO"; + + case GL.GL_FRAMEBUFFER_COMPLETE: + return "OK"; + + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + return("GL FBO: incomplete, incomplete attachment\n"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + return("GL FBO: incomplete, missing attachment"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + return("GL FBO: incomplete, attached images must have same dimensions"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: + return("GL FBO: incomplete, attached images must have same format"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + return("GL FBO: incomplete, missing draw buffer"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + return("GL FBO: incomplete, missing read buffer"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + return("GL FBO: incomplete, missing multisample buffer"); + case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + return("GL FBO: incomplete, layer targets"); + + case GL.GL_FRAMEBUFFER_UNSUPPORTED: + return("GL FBO: Unsupported framebuffer format"); + case GL2GL3.GL_FRAMEBUFFER_UNDEFINED: + return("GL FBO: framebuffer undefined"); + + case 0: + return("GL FBO: incomplete, implementation fault"); + default: + return("GL FBO: incomplete, implementation ERROR 0x"+Integer.toHexString(fbStatus)); + } + } + + /** + * The status may even be valid if incomplete during transition of attachments. + * @see #getStatus() + */ + public final boolean isStatusValid() { + switch(vStatus) { + case GL.GL_FRAMEBUFFER_COMPLETE: + return true; + + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + if(0 == colorAttachmentCount || null == depth) { + // we are in transition + return true; + } + + case GL.GL_FRAMEBUFFER_UNSUPPORTED: + case GL2GL3.GL_FRAMEBUFFER_UNDEFINED: + + case 0: + default: + System.out.println("Framebuffer " + fbName + " is incomplete: status = 0x" + Integer.toHexString(vStatus) + + " : " + getStatusString(vStatus)); + return false; + } + } + + private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException { + if(GL.GL_NO_ERROR != err) { + if(null != gl) { + destroy(gl); + } + if(null != exceptionMessage) { + throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err)); + } + return false; + } + return true; + } + + private final void checkInitialized() throws GLException { + if(!initialized) { + throw new GLException("FBO not initialized, call init(GL) first."); + } + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * selecting the texture data type and format automatically. + * + *Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.
+ * + *Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set totrue
if you request alpha channel, otherwise false
;
+ * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException {
+ return attachTexture2D(gl, attachmentPoint, alpha, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point,
+ * selecting the texture data type and format automatically.
+ *
+ * Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set totrue
if you request alpha channel, otherwise false
;
+ * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
+ * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
+ * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException {
+ final int textureInternalFormat, textureDataFormat, textureDataType;
+ if(gl.isGLES()) {
+ textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataType = GL.GL_UNSIGNED_BYTE;
+ } else {
+ textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
+ textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
+ }
+ return attachTexture2D(gl, attachmentPoint, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT);
+ }
+
+ /**
+ * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + */ + public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, + int internalFormat, int dataFormat, int dataType, + int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { + return attachTexture2D(gl, attachmentPoint, + new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, + magFilter, minFilter, wrapS, wrapT, 0 /* name */)); + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * + *
+ * In case the passed TextureAttachment texA
is uninitialized, i.e. it's texture name is zero
,
+ * a new texture name is generated and setup w/ the texture parameter.
+ * Otherwise, i.e. texture name is not zero
, the passed TextureAttachment texA
is
+ * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue.
+ *
Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param texA the to be attached {@link TextureAttachment}. Maybe complete or uninitialized, see above. + * @return the passed TextureAttachmenttexA
instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ */
+ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, TextureAttachment texA) throws GLException {
+ validateAddColorAttachment(attachmentPoint, texA);
+
+ if(samples>0) {
+ removeColorAttachment(attachmentPoint, texA);
+ throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl).");
+ }
+
+ texA.initialize(gl);
+ addColorAttachment(attachmentPoint, texA);
+
+ bind(gl);
+
+ // Set up the color buffer for use as a renderable texture:
+ gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
+ GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
+ GL.GL_TEXTURE_2D, texA.getName(), 0);
+ updateStatus(gl);
+
+ if(!isStatusValid()) {
+ detachColorbuffer(gl, attachmentPoint);
+ throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this);
+ }
+ if(DEBUG) {
+ System.err.println("FBObject.attachTexture2D: "+this);
+ }
+ return texA;
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point,
+ * selecting the format automatically.
+ *
+ * Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set totrue
if you request alpha channel, otherwise false
;
+ * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown
+ * @throws GLException in case the colorbuffer couldn't be allocated
+ */
+ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException {
+ final int internalFormat;
+ if( rgba8Avail ) {
+ internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ;
+ } else {
+ internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565;
+ }
+ return attachColorbuffer(gl, attachmentPoint, internalFormat);
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param internalFormat usually {@link GL#GL_RGBA4}, {@link GL#GL_RGB5_A1}, {@link GL#GL_RGB565}, {@link GL#GL_RGB8} or {@link GL#GL_RGBA8} + * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated + * @throws IllegalArgumentException ifinternalFormat
doesn't reflect a colorbuffer
+ */
+ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, int internalFormat) throws GLException, IllegalArgumentException {
+ final Attachment.Type atype = Attachment.Type.determine(internalFormat);
+ if( Attachment.Type.COLOR != atype ) {
+ throw new IllegalArgumentException("colorformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this);
+ }
+
+ return attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0));
+ }
+
+ /**
+ * Attaches a Color Buffer to this FBO's instance at the given attachment point.
+ *
+ * Leaves the FBO bound.
+ * + * @param gl + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param colA the template for the new {@link ColorAttachment} + * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated + */ + public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, ColorAttachment colA) throws GLException { + validateAddColorAttachment(attachmentPoint, colA); + + colA.initialize(gl); + addColorAttachment(attachmentPoint, colA); + + bind(gl); + + // Attach the color buffer + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_RENDERBUFFER, colA.getName()); + + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint); + throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } + if(DEBUG) { + System.err.println("FBObject.attachColorbuffer: "+this); + } + return colA; + } + + + /** + * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, + * selecting the internalFormat automatically. + *+ * Stencil and depth buffer can be attached only once. + *
+ *+ * In case the desired type or bit-number is not supported, the next available one is chosen. + *
+ *+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details + * about the attached buffer. The details cannot be returned, since it's possible 2 buffers + * are being created, depth and stencil. + *
+ * + *Leaves the FBO bound.
+ * + * @param gl + * @param atype either {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#DEPTH_STENCIL} + * @param reqBits desired bits for depth or -1 for default (24 bits) + * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached. + * @throws IllegalArgumentException + * @see #getDepthAttachment() + * @see #getStencilAttachment() + */ + public final void attachRenderbuffer(GL gl, Attachment.Type atype, int reqBits) throws GLException, IllegalArgumentException { + if( 0 > reqBits ) { + reqBits = 24; + } + final int internalFormat; + int internalStencilFormat = -1; + + switch ( atype ) { + case DEPTH: + if( 32 <= reqBits && depth32Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT32; + } else if( 24 <= reqBits && depth24Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT24; + } else { + internalFormat = GL.GL_DEPTH_COMPONENT16; + } + break; + + case STENCIL: + if( 16 <= reqBits && stencil16Avail ) { + internalFormat = GL2GL3.GL_STENCIL_INDEX16; + } else if( 8 <= reqBits && stencil08Avail ) { + internalFormat = GL.GL_STENCIL_INDEX8; + } else if( 4 <= reqBits && stencil04Avail ) { + internalFormat = GL.GL_STENCIL_INDEX4; + } else if( 1 <= reqBits && stencil01Avail ) { + internalFormat = GL.GL_STENCIL_INDEX1; + } else { + throw new GLException("stencil buffer n/a"); + } + break; + + case DEPTH_STENCIL: + if( packedDepthStencilAvail ) { + internalFormat = GL.GL_DEPTH24_STENCIL8; + } else { + if( 24 <= reqBits && depth24Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT24; + } else { + internalFormat = GL.GL_DEPTH_COMPONENT16; + } + if( stencil08Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX8; + } else if( stencil04Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX4; + } else if( stencil01Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX1; + } else { + throw new GLException("stencil buffer n/a"); + } + } + break; + default: + throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this); + } + + attachRenderbufferImpl(gl, atype, internalFormat); + + if(0<=internalStencilFormat) { + attachRenderbufferImpl(gl, Attachment.Type.STENCIL, internalStencilFormat); + } + } + + /** + * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, + * depending on theinternalFormat
.
+ * + * Stencil and depth buffer can be attached only once. + *
+ *+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details + * about the attached buffer. The details cannot be returned, since it's possible 2 buffers + * are being created, depth and stencil. + *
+ * + *Leaves the FBO bound.
+ * + * @param gl the current GL context + * @param internalFormat {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24}, {@link GL#GL_DEPTH_COMPONENT32}, + * {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} + * or {@link GL#GL_DEPTH24_STENCIL8} + * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached. + * @throws IllegalArgumentException + * @see #getDepthAttachment() + * @see #getStencilAttachment() + */ + public final void attachRenderbuffer(GL gl, int internalFormat) throws GLException, IllegalArgumentException { + final Attachment.Type atype = Attachment.Type.determine(internalFormat); + if( Attachment.Type.DEPTH != atype && Attachment.Type.STENCIL != atype && Attachment.Type.DEPTH_STENCIL != atype ) { + throw new IllegalArgumentException("renderformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this); + } + attachRenderbufferImpl(gl, atype, internalFormat); + } + + protected final void attachRenderbufferImpl(GL gl, Attachment.Type atype, int internalFormat) throws GLException { + if( null != depth && ( Attachment.Type.DEPTH == atype || Attachment.Type.DEPTH_STENCIL == atype ) ) { + throw new GLException("FBO depth buffer already attached (rb "+depth+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this); + } + if( null != stencil && ( Attachment.Type.STENCIL== atype || Attachment.Type.DEPTH_STENCIL == atype ) ) { + throw new GLException("FBO stencil buffer already attached (rb "+stencil+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this); + } + attachRenderbufferImpl2(gl, atype, internalFormat); + } + + private final void attachRenderbufferImpl2(GL gl, Attachment.Type atype, int internalFormat) throws GLException { + if( Attachment.Type.DEPTH == atype ) { + if(null == depth) { + depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0); + } else { + depth.setSize(width, height); + depth.setSamples(samples); + } + depth.initialize(gl); + } else if( Attachment.Type.STENCIL == atype ) { + if(null == stencil) { + stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, 0); + } else { + stencil.setSize(width, height); + stencil.setSamples(samples); + } + stencil.initialize(gl); + } else if( Attachment.Type.DEPTH_STENCIL == atype ) { + if(null == depth) { + depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0); + } else { + depth.setSize(width, height); + depth.setSamples(samples); + } + depth.initialize(gl); + if(null == stencil) { + stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, depth.getName()); + } else { + stencil.setName(depth.getName()); + stencil.setSize(width, height); + stencil.setSamples(samples); + } + stencil.initialize(gl); + } + + bind(gl); + + // Attach the buffer + if( Attachment.Type.DEPTH == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName()); + } else if( Attachment.Type.STENCIL == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName()); + } else if( Attachment.Type.DEPTH_STENCIL == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName()); + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName()); + } + + updateStatus(gl); + if( !isStatusValid() ) { + detachRenderbuffer(gl, atype); + throw new GLException("renderbuffer attachment failed: "+this.getStatusString()); + } + + if(DEBUG) { + System.err.println("FBObject.attachRenderbuffer: "+this); + } + } + + /** + *Leaves the FBO bound!
+ * @param gl + * @param ca + * @throws IllegalArgumentException + */ + public final void detachColorbuffer(GL gl, int attachmentPoint) throws IllegalArgumentException { + if(null == detachColorbufferImpl(gl, attachmentPoint, false)) { + throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this); + } + if(DEBUG) { + System.err.println("FBObject.detachAll: "+this); + } + } + + private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, boolean recreate) { + final Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here + + if(null == colbuf) { + return null; + } + + bind(gl); + + if(colbuf instanceof TextureAttachment) { + final TextureAttachment texA = (TextureAttachment) colbuf; + if( 0 != texA.getName() ) { + gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_TEXTURE_2D, 0, 0); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); + } + texA.free(gl); + removeColorAttachment(attachmentPoint, texA); + if(recreate) { + texA.setSize(width, height); + attachTexture2D(gl, attachmentPoint, texA); + } + } else if(colbuf instanceof ColorAttachment) { + final ColorAttachment colA = (ColorAttachment) colbuf; + if( 0 != colA.getName() ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0+attachmentPoint, + GL.GL_RENDERBUFFER, 0); + } + colA.free(gl); + removeColorAttachment(attachmentPoint, colbuf); + if(recreate) { + colA.setSize(width, height); + colA.setSamples(samples); + attachColorbuffer(gl, attachmentPoint, colA); + } + } + return colbuf; + } + + /** + * + * @param gl + * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL} + */ + public final void detachRenderbuffer(GL gl, Attachment.Type atype) throws IllegalArgumentException { + detachRenderbufferImpl(gl, atype, false); + } + + public final boolean isDepthStencilPackedFormat() { + final boolean res = null != depth && null != stencil && + depth.format == stencil.format ; + if(res && depth.getName() != stencil.getName() ) { + throw new InternalError("depth/stencil packed format not sharing: depth "+depth+", stencil "+stencil); + } + return res; + } + + private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, boolean recreate) throws IllegalArgumentException { + switch ( atype ) { + case DEPTH: + case STENCIL: + case DEPTH_STENCIL: + break; + default: + throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this); + } + if( null == depth && null == stencil ) { + return ; // nop + } + // reduction of possible combinations, create unique atype command(s) + final ArrayListLeaves the FBO bound!
+ *+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *
+ * @param gl the current GL context + */ + public final void detachAll(GL gl) { + if(null != samplesSink) { + samplesSink.detachAll(gl); + } + detachAllImpl(gl, true/* detachNonColorbuffer */, false /* recreate */); + } + + /** + * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s. + *Leaves the FBO bound!
+ *+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *
+ * @param gl the current GL context + */ + public final void detachAllColorbuffer(GL gl) { + if(null != samplesSink) { + samplesSink.detachAllColorbuffer(gl); + } + detachAllImpl(gl, false/* detachNonColorbuffer */, false /* recreate */); + } + + /** + * Detaches all {@link TextureAttachment}s + *Leaves the FBO bound!
+ *+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *
+ * @param gl the current GL context + */ + public final void detachAllTexturebuffer(GL gl) { + if(null != samplesSink) { + samplesSink.detachAllTexturebuffer(gl); + } + for(int i=0; iIf multisampling is used, it sets the read framebuffer to the sampling sink {@link #getWriteFramebuffer()}, + * if full FBO is supported.
+ * + *+ * In case you have attached more than one color buffer, + * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}. + *
+ * @param gl the current GL context + * @throws GLException + */ + public final void bind(GL gl) throws GLException { + if(!bound || fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER)) { + checkInitialized(); + if(samples > 0 && fullFBOSupport) { + // draw to multisampling - read from samplesSink + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, getWriteFramebuffer()); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, getReadFramebuffer()); + } else { + // one for all + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, getWriteFramebuffer()); + } + + checkNoError(null, gl.glGetError(), "FBObject post-bind"); // throws GLException if error + bound = true; + samplesSinkDirty = true; + } + } + + /** + * Unbind this FBO, i.e. bind read and write framebuffer to default, see {@link GLBase#getDefaultDrawFramebuffer()}. + * + *If full FBO is supported, sets the read and write framebuffer individually to default, hence not disturbing + * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}
+ * + * @param gl the current GL context + * @throws GLException + */ + public final void unbind(GL gl) throws GLException { + if(bound) { + if(fullFBOSupport) { + // default read/draw buffers, may utilize GLContext/GLDrawable override of + // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); + } else { + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer + } + checkNoError(null, gl.glGetError(), "FBObject post-unbind"); // throws GLException if error + bound = false; + } + } + + /** + * Returnstrue
if framebuffer object is bound via {@link #bind(GL)}, otherwise false
.
+ * + * Method verifies the bound state via {@link GL#getBoundFramebuffer(int)}. + *
+ * @param gl the current GL context + */ + public final boolean isBound(GL gl) { + bound = bound && fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER) ; + return bound; + } + + /** Returnstrue
if framebuffer object is bound via {@link #bind(GL)}, otherwise false
. */
+ public final boolean isBound() { return bound; }
+
+ /**
+ * Samples the multisampling colorbuffer (msaa-buffer) to it's sink {@link #getSamplingSink()}.
+ *
+ * The operation is skipped, if no multisampling is used or + * the msaa-buffer has not been flagged dirty by a previous call of {@link #bind(GL)}, + * see {@link #isSamplingBufferDirty()}
+ * + *If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing + * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}
+ * + *In case you intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)} + * you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()}); + *
+ * + *Leaves the FBO unbound.
+ * + * @param gl the current GL context + * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)} + * @throws IllegalArgumentException + */ + public final void syncSamplingBuffer(GL gl) { + unbind(gl); + if(samples>0 && samplesSinkDirty) { + samplesSinkDirty = false; + resetMSAATexture2DSink(gl); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbName); + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, samplesSink.getWriteFramebuffer()); + ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, ugly cast is OK + GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST); + if(fullFBOSupport) { + // default read/draw buffers, may utilize GLContext/GLDrawable override of + // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); + } else { + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer + } + } + } + + /** + * Bind the given texture colorbuffer. + * + *If multisampling is being used, {@link #syncSamplingBuffer(GL)} is being called.
+ * + *Leaves the FBO unbound!
+ * + * @param gl the current GL context + * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)} + * @throws IllegalArgumentException + */ + public final void use(GL gl, TextureAttachment ta) throws IllegalArgumentException { + if(null == ta) { throw new IllegalArgumentException("null TextureAttachment"); } + if(samples > 0 && samplesSinkTexture == ta) { + syncSamplingBuffer(gl); + } else { + unbind(gl); + } + gl.glBindTexture(GL.GL_TEXTURE_2D, ta.getName()); // use it .. + } + + /** + * Unbind texture, ie bind 'non' texture 0 + * + *Leaves the FBO unbound.
+ */ + public final void unuse(GL gl) { + unbind(gl); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it + } + + /** + * Returnstrue
if basic or full FBO is supported, otherwise false
.
+ * @param full true
for full FBO supported query, otherwise false
for basic FBO support query.
+ * @see #supportsFullFBO(GL)
+ * @see #supportsBasicFBO(GL)
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsFBO(boolean full) throws GLException { checkInitialized(); return full ? fullFBOSupport : basicFBOSupport; }
+
+ /**
+ * Returns true
if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise false
.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsRGBA8() throws GLException { checkInitialized(); return rgba8Avail; }
+
+ /**
+ * Returns true
if {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} is supported, otherwise false
.
+ * @param bits 16, 24 or 32 bits
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsDepth(int bits) throws GLException {
+ checkInitialized();
+ switch(bits) {
+ case 16: return basicFBOSupport;
+ case 24: return depth24Avail;
+ case 32: return depth32Avail;
+ default: return false;
+ }
+ }
+
+ /**
+ * Returns true
if {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} or {@link GL2GL3#GL_STENCIL_INDEX16} is supported, otherwise false
.
+ * @param bits 1, 4, 8 or 16 bits
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsStencil(int bits) throws GLException {
+ checkInitialized();
+ switch(bits) {
+ case 1: return stencil01Avail;
+ case 4: return stencil04Avail;
+ case 8: return stencil08Avail;
+ case 16: return stencil16Avail;
+ default: return false;
+ }
+ }
+
+ /**
+ * Returns true
if {@link GL#GL_DEPTH24_STENCIL8} is supported, otherwise false
.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final boolean supportsPackedDepthStencil() throws GLException { checkInitialized(); return packedDepthStencilAvail; }
+
+ /**
+ * Returns the maximum number of colorbuffer attachments.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; }
+
+ /**
+ * Returns the maximum number of samples for multisampling. Maybe zero if multisampling is not supported.
+ * @throws GLException if {@link #init(GL)} hasn't been called.
+ */
+ public final int getMaxSamples() throws GLException { checkInitialized(); return maxSamples; }
+
+ /**
+ * Returns true
if this instance has been initialized with {@link #reset(GL, int, int)}
+ * or {@link #reset(GL, int, int, int)}, otherwise false
+ */
+ public final boolean isInitialized() { return initialized; }
+ /** Returns the width */
+ public final int getWidth() { return width; }
+ /** Returns the height */
+ public final int getHeight() { return height; }
+ /** Returns the number of samples for multisampling (MSAA). zero if no multisampling is used. */
+ public final int getNumSamples() { return samples; }
+ /** Returns the framebuffer name to render to. */
+ public final int getWriteFramebuffer() { return fbName; }
+ /** Returns the framebuffer name to read from. Depending on multisampling, this may be a different framebuffer. */
+ public final int getReadFramebuffer() { return ( samples > 0 ) ? samplesSink.getReadFramebuffer() : fbName; }
+ /** Return the number of color/texture attachments */
+ public final int getColorAttachmentCount() { return colorAttachmentCount; }
+ /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */
+ public final RenderAttachment getStencilAttachment() { return stencil; }
+ /** Return the depth {@link RenderAttachment} attachment. Maybe share the same {@link Attachment#getName()} as {@link #getStencilAttachment()}, if packed depth-stencil is being used. */
+ public final RenderAttachment getDepthAttachment() { return depth; }
+
+ /** Return the complete multisampling {@link FBObject} sink, if using multisampling. */
+ public final FBObject getSamplingSinkFBO() { return samplesSink; }
+
+ /** Return the multisampling {@link TextureAttachment} sink, if using multisampling. */
+ public final TextureAttachment getSamplingSink() { return samplesSinkTexture; }
+ /**
+ * Returns true
if the multisampling colorbuffer (msaa-buffer)
+ * has been flagged dirty by a previous call of {@link #bind(GL)},
+ * otherwise false
.
+ */
+ public final boolean isSamplingBufferDirty() { return samplesSinkDirty; }
+
+ int objectHashCode() { return super.hashCode(); }
+
+ public final String toString() {
+ final String caps = null != colorAttachmentPoints ? Arrays.asList(colorAttachmentPoints).toString() : null ;
+ return "FBO[name r/w "+fbName+"/"+getReadFramebuffer()+", init "+initialized+", bound "+bound+", size "+width+"x"+height+", samples "+samples+"/"+maxSamples+
+ ", depth "+depth+", stencil "+stencil+", color attachments: "+colorAttachmentCount+"/"+maxColorAttachments+
+ ": "+caps+", msaa-sink "+samplesSinkTexture+", isSamplesSink "+(null == samplesSink)+
+ ", obj 0x"+Integer.toHexString(objectHashCode())+"]";
+ }
+
+ private final void updateStatus(GL gl) {
+ if( 0 == fbName ) {
+ vStatus = -1;
+ } else {
+ vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
new file mode 100644
index 000000000..f7e25fa01
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java
@@ -0,0 +1,81 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl;
+
+/**
+ * Class holding OpenGL extension strings, commonly used by JOGL's implementation.
+ */
+public class GLExtensions {
+ public static final String VERSION_1_2 = "GL_VERSION_1_2";
+ public static final String VERSION_1_4 = "GL_VERSION_1_4";
+ public static final String VERSION_1_5 = "GL_VERSION_1_5";
+ public static final String VERSION_2_0 = "GL_VERSION_2_0";
+
+ public static final String ARB_debug_output = "GL_ARB_debug_output";
+ public static final String AMD_debug_output = "GL_AMD_debug_output";
+
+ public static final String ARB_framebuffer_object = "GL_ARB_framebuffer_object";
+ public static final String OES_framebuffer_object = "GL_OES_framebuffer_object";
+ public static final String EXT_framebuffer_object = "GL_EXT_framebuffer_object";
+ public static final String EXT_framebuffer_blit = "GL_EXT_framebuffer_blit";
+ public static final String EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample";
+ public static final String EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil";
+ public static final String OES_depth24 = "GL_OES_depth24";
+ public static final String OES_depth32 = "GL_OES_depth32";
+ public static final String OES_packed_depth_stencil = "GL_OES_packed_depth_stencil";
+ public static final String NV_fbo_color_attachments = "GL_NV_fbo_color_attachments";
+
+ public static final String ARB_ES2_compatibility = "GL_ARB_ES2_compatibility";
+
+ public static final String EXT_abgr = "GL_EXT_abgr";
+ public static final String OES_rgb8_rgba8 = "GL_OES_rgb8_rgba8";
+ public static final String OES_stencil1 = "GL_OES_stencil1";
+ public static final String OES_stencil4 = "GL_OES_stencil4";
+ public static final String OES_stencil8 = "GL_OES_stencil8";
+ public static final String APPLE_float_pixels = "GL_APPLE_float_pixels";
+
+ public static final String ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
+ public static final String ARB_texture_rectangle = "GL_ARB_texture_rectangle";
+ public static final String EXT_texture_rectangle = "GL_EXT_texture_rectangle";
+ public static final String NV_texture_rectangle = "GL_NV_texture_rectangle";
+ public static final String EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888";
+ public static final String IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888";
+ public static final String EXT_texture_compression_s3tc = "GL_EXT_texture_compression_s3tc";
+ public static final String NV_texture_compression_vtc = "GL_NV_texture_compression_vtc";
+ public static final String SGIS_generate_mipmap = "GL_SGIS_generate_mipmap";
+ public static final String OES_read_format = "GL_OES_read_format";
+
+ public static final String OES_EGL_image_external = "GL_OES_EGL_image_external";
+
+ //
+ // Aliased GLX/WGL/.. extensions
+ //
+
+ public static final String ARB_pixel_format = "GL_ARB_pixel_format";
+ public static final String ARB_pbuffer = "GL_ARB_pbuffer";
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
index 75785fd86..cdb4b82bb 100644
--- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
+++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
@@ -93,11 +93,13 @@ public class JoglVersion extends JogampVersion {
return sb;
}
- public static StringBuilder getDefaultOpenGLInfo(StringBuilder sb, boolean withCapabilitiesInfo) {
+ public static StringBuilder getDefaultOpenGLInfo(AbstractGraphicsDevice device, StringBuilder sb, boolean withCapabilitiesInfo) {
if(null==sb) {
sb = new StringBuilder();
}
- final AbstractGraphicsDevice device = GLProfile.getDefaultDevice();
+ if(null == device) {
+ device = GLProfile.getDefaultDevice();
+ }
sb.append("Default Profiles on device ").append(device).append(Platform.getNewline());
if(null!=device) {
GLProfile.glAvailabilityToString(device, sb, "\t", 1);
@@ -120,13 +122,21 @@ public class JoglVersion extends JogampVersion {
if(null==sb) {
sb = new StringBuilder();
}
- GLContext ctx = gl.getContext();
-
+
sb.append(VersionUtil.SEPERATOR).append(Platform.getNewline());
sb.append(device.getClass().getSimpleName()).append("[type ")
.append(device.getType()).append(", connection ").append(device.getConnection()).append("]: ").append(Platform.getNewline());
GLProfile.glAvailabilityToString(device, sb, "\t", 1);
sb.append(Platform.getNewline());
+
+ return getGLStrings(gl, sb);
+ }
+
+ public static StringBuilder getGLStrings(GL gl, StringBuilder sb) {
+ if(null==sb) {
+ sb = new StringBuilder();
+ }
+ final GLContext ctx = gl.getContext();
sb.append("Swap Interval ").append(gl.getSwapInterval());
sb.append(Platform.getNewline());
sb.append("GL Profile ").append(gl.getGLProfile());
diff --git a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java
new file mode 100644
index 000000000..1ea8595c6
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+import javax.media.opengl.GLAutoDrawableDelegate;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLException;
+
+import jogamp.opengl.GLFBODrawableImpl;
+
+/**
+ * Platform-independent class exposing FBO offscreen functionality to
+ * applications.
+ * + * This class distinguishes itself from {@link GLAutoDrawableDelegate} + * with it's {@link #setSize(int, int)} functionality. + *
+ */ +public class OffscreenAutoDrawable extends GLAutoDrawableDelegate { + + public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, Object upstreamWidget) { + super(drawable, context, upstreamWidget); + } + + /** + * Attempts to resize this offscreen auto drawable, if supported + * by the underlying {@link GLDrawable). + * @param newWidth + * @param newHeight + * @returntrue
if resize was executed, otherwise false
.
+ * @throws GLException in case of an error during the resize operation
+ */
+ public boolean setSize(int newWidth, int newHeight) throws GLException {
+ boolean done = false;
+ if(drawable instanceof GLFBODrawableImpl) {
+ context.makeCurrent();
+ try {
+ ((GLFBODrawableImpl)drawable).setSize(context.getGL(), newWidth, newHeight);
+ done = true;
+ } finally {
+ context.release();
+ }
+ }
+ if(done) {
+ this.defaultWindowResizedOp();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * If the underlying {@link GLDrawable} is an FBO implementation
+ * and contains an {#link FBObject}, the same is returned.
+ * Otherwise returns null
.
+ */
+ public FBObject getFBObject() {
+ if(drawable instanceof GLFBODrawableImpl) {
+ return ((GLFBODrawableImpl)drawable).getFBObject();
+ }
+ return null;
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 5ee58b78d..0d9d3ddf5 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -231,6 +231,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
/* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite) */
device = SWTAccessor.getDevice(this);
+ /* Since we have no means of querying the screen index yet, assume 0. Good choice due to Xinerama alike settings anyways. */
+ final int screenIdx = 0;
/* Native handle for the control, used to associate with GLContext */
nativeWindowHandle = SWTAccessor.getWindowHandle(this);
@@ -243,7 +245,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile());
/* Create a NativeWindow proxy for the SWT canvas */
- proxySurface = glFactory.createProxySurface(device, nativeWindowHandle, caps, chooser);
+ proxySurface = glFactory.createProxySurface(device, screenIdx, nativeWindowHandle, caps, chooser, swtCanvasUpStreamHook);
/* Associate a GL surface with the proxy */
drawable = glFactory.createGLDrawable(proxySurface);
@@ -265,12 +267,58 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
addControlListener(new ControlAdapter() {
@Override
public void controlResized(final ControlEvent arg0) {
- clientArea = GLCanvas.this.getClientArea();
- /* Mark for OpenGL reshape next time the control is painted */
- sendReshape = true;
+ updateSizeCheck();
}
});
}
+ private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() {
+ @Override
+ public final void create(ProxySurface s) { /* nop */ }
+
+ @Override
+ public final void destroy(ProxySurface s) { /* nop */ }
+
+ @Override
+ public final int getWidth(ProxySurface s) {
+ return clientArea.width;
+ }
+
+ @Override
+ public final int getHeight(ProxySurface s) {
+ return clientArea.height;
+ }
+
+ @Override
+ public String toString() {
+ return "SETUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+"]";
+ }
+
+ };
+
+ protected final void updateSizeCheck() {
+ clientArea = GLCanvas.this.getClientArea();
+ if (clientArea != null &&
+ proxySurface.getWidth() != clientArea.width &&
+ proxySurface.getHeight() != clientArea.height) {
+ sendReshape = true; // Mark for OpenGL reshape next time the control is painted
+ }
+ sendReshape = false;
+ }
+
+ @Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
+ @Override
+ public int getWidth() {
+ return clientArea.width;
+ }
+
+ @Override
+ public int getHeight() {
+ return clientArea.height;
+ }
@Override
public void addGLEventListener(final GLEventListener arg0) {
@@ -417,25 +465,11 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
return (drawable != null) ? drawable.getHandle() : 0;
}
- @Override
- public int getHeight() {
- final Rectangle clientArea = this.clientArea;
- if (clientArea == null) return 0;
- return clientArea.height;
- }
-
@Override
public NativeSurface getNativeSurface() {
return (drawable != null) ? drawable.getNativeSurface() : null;
}
- @Override
- public int getWidth() {
- final Rectangle clientArea = this.clientArea;
- if (clientArea == null) return 0;
- return clientArea.width;
- }
-
@Override
public boolean isRealized() {
return (drawable != null) ? drawable.isRealized() : false;
@@ -515,7 +549,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
// System.err.println(NativeWindowVersion.getInstance());
System.err.println(JoglVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString());
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) );
final Display display = new Display();
diff --git a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java b/src/jogl/classes/com/jogamp/opengl/util/FBObject.java
deleted file mode 100644
index 3e049a334..000000000
--- a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2011 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- */
-
-package com.jogamp.opengl.util;
-
-import javax.media.opengl.*;
-
-public class FBObject {
- static final int MAX_FBO_TEXTURES = 32; // just for our impl .. not the real 'max' FBO color attachments
- private int[] fbo_tex_names;
- private int[] fbo_tex_units;
- private int fbo_tex_num;
- private int colorattachment_num;
-
- private boolean initialized;
- private int width, height;
- private int fb, depth_rb, stencil_rb, vStatus;
- private boolean bound;
-
- public FBObject(int width, int height) {
- this.fbo_tex_names = new int[MAX_FBO_TEXTURES];
- this.fbo_tex_units = new int[MAX_FBO_TEXTURES];
- this.fbo_tex_num = 0;
- this.colorattachment_num = 0;
- this.initialized = false;
- this.width = width;
- this.height = height;
- this.fb = 0;
- this.depth_rb = 0;
- this.stencil_rb = 0;
- this.bound = false;
- }
-
- /**
- * @return true if the FB status is valid, otherwise false
- * @see #getStatus()
- */
- public boolean isStatusValid() {
- switch(vStatus) {
- case GL.GL_FRAMEBUFFER_COMPLETE:
- return true;
- case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT:
- case 0:
- default:
- System.out.println("Framebuffer " + fb + " is incomplete: status = 0x" + Integer.toHexString(vStatus) +
- " : " + getStatusString(vStatus));
- return false;
- }
- }
-
- /**
- * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1
- * @see #validateStatus()
- */
- public int getStatus() {
- return vStatus;
- }
-
- public String getStatusString() {
- return getStatusString(vStatus);
- }
-
- public static final String getStatusString(int fbStatus) {
- switch(fbStatus) {
- case -1:
- return "NOT A FBO";
- case GL.GL_FRAMEBUFFER_COMPLETE:
- return "OK";
- case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- return("GL FBO: Unsupported framebuffer format");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- return("GL FBO: incomplete, incomplete attachment\n");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- return("GL FBO: incomplete, missing attachment");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- return("GL FBO: incomplete, attached images must have same dimensions");
- case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
- return("GL FBO: incomplete, attached images must have same format");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- return("GL FBO: incomplete, missing draw buffer");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- return("GL FBO: incomplete, missing read buffer");
- case GL2.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
- return("GL FBO: incomplete, missing multisample buffer");
- case 0:
- return("GL FBO: incomplete, implementation fault");
- default:
- return("GL FBO: incomplete, implementation ERROR");
- }
- }
-
- private boolean checkNoError(GL gl, int err, String exceptionMessage) {
- if(GL.GL_NO_ERROR != err) {
- if(null != gl) {
- destroy(gl);
- }
- if(null != exceptionMessage) {
- throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err));
- }
- return false;
- }
- return true;
- }
-
- private final void checkInitialized() {
- if(!initialized) {
- throw new GLException("FBO not initialized, call init(GL) first.");
- }
- }
-
- private final void checkBound(GL gl, boolean shallBeBound) {
- checkInitialized();
- if(bound != shallBeBound) {
- final String s0 = shallBeBound ? "not" : "already" ;
- throw new GLException("FBO "+s0+" bound "+toString());
- }
- checkNoError(null, gl.glGetError(), "FBObject pre"); // throws GLException if error
- }
-
- /**
- * Initializes this FBO's instance with it's texture.
- *
- * Leaves the FBO bound!
- * - * @param gl the current GL context - * @throws GLException in case of an error - */ - public void init(GL gl) throws GLException { - if(initialized) { - throw new GLException("FBO already initialized"); - } - checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error - - // generate fbo .. - int name[] = new int[1]; - - gl.glGenFramebuffers(1, name, 0); - fb = name[0]; - if(fb==0) { - throw new GLException("null generated framebuffer"); - } - - // bind fbo .. - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); - checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error - if(!gl.glIsFramebuffer(fb)) { - checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException - } - bound = true; - initialized = true; - - updateStatus(gl); - } - - /** - * Attaches a[nother] Texture2D Color Buffer to this FBO's instance, - * selecting the texture data type and format automatically. - *This may be done as many times as many color attachments are supported, - * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.
- * - *Assumes a bound FBO
- *Leaves the FBO bound!
- * - * @param gl the current GL context - * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)} - * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} - * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} - * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} - * @return idx of the new attached texture, otherwise -1 - * @throws GLException in case of an error - */ - public int attachTexture2D(GL gl, int texUnit, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - final int textureInternalFormat, textureDataFormat, textureDataType; - if(gl.isGLES()) { - textureInternalFormat=GL.GL_RGBA; - textureDataFormat=GL.GL_RGBA; - textureDataType=GL.GL_UNSIGNED_BYTE; - } else { - textureInternalFormat=GL.GL_RGBA8; - textureDataFormat=GL.GL_BGRA; - textureDataType=GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV; - } - return attachTexture2D(gl, texUnit, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); - } - - /** - * Attaches a[nother] Texture2D Color Buffer to this FBO's instance, - * selecting the texture data type and format automatically. - *This may be done as many times as many color attachments are supported, - * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.
- * - *Assumes a bound FBO
- *Leaves the FBO bound!
- * - * @param gl the current GL context - * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)} - * @param textureInternalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param textureDataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param textureDataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} - * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} - * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} - * @return index of the texture colorbuffer if bound and configured successfully, otherwise -1 - * @throws GLException in case the texture colorbuffer couldn't be allocated - */ - public int attachTexture2D(GL gl, int texUnit, - int textureInternalFormat, int textureDataFormat, int textureDataType, - int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - checkBound(gl, true); - final int fbo_tex_idx = fbo_tex_num; - gl.glGenTextures(1, fbo_tex_names, fbo_tex_num); - if(fbo_tex_names[fbo_tex_idx]==0) { - throw new GLException("null generated texture"); - } - fbo_tex_units[fbo_tex_idx] = texUnit; - fbo_tex_num++; - if(0<=texUnit) { - gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit); - } - gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx]); - checkNoError(gl, gl.glGetError(), "FBObject Init.bindTex"); // throws GLException if error - gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, textureInternalFormat, width, height, 0, - textureDataFormat, textureDataType, null); - int glerr = gl.glGetError(); - if(GL.GL_NO_ERROR != glerr) { - int[] sz = new int[1]; - gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, sz, 0); - // throws GLException if error - checkNoError(gl, glerr, "FBObject Init.texImage2D: "+ - " int-fmt 0x"+Integer.toHexString(textureInternalFormat)+ - ", "+width+"x"+height+ - ", data-fmt 0x"+Integer.toHexString(textureDataFormat)+ - ", data-type 0x"+Integer.toHexString(textureDataType)+ - ", max tex-sz "+sz[0]); - } - if( 0 < magFilter ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter); - } - if( 0 < minFilter ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter); - } - if( 0 < wrapS ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS); - } - if( 0 < wrapT ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); - } - - // Set up the color buffer for use as a renderable texture: - gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + colorattachment_num++, - GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx], 0); - - updateStatus(gl); - return isStatusValid() ? fbo_tex_idx : -1; - } - - /** - * Attaches one Depth Buffer to this FBO's instance. - *This may be done only one time.
- * - *Assumes a bound FBO
- *Leaves the FBO bound!
- * @param gl the current GL context - * @param depthComponentType {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} - * @return true if the depth renderbuffer could be bound and configured, otherwise false - * @throws GLException in case the depth renderbuffer couldn't be allocated or one is already attached. - */ - public boolean attachDepthBuffer(GL gl, int depthComponentType) throws GLException { - checkBound(gl, true); - if(depth_rb != 0) { - throw new GLException("FBO depth buffer already attached (rb "+depth_rb+")"); - } - int name[] = new int[1]; - gl.glGenRenderbuffers(1, name, 0); - depth_rb = name[0]; - if(depth_rb==0) { - throw new GLException("null generated renderbuffer"); - } - // Initialize the depth buffer: - gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, depth_rb); - if(!gl.glIsRenderbuffer(depth_rb)) { - System.err.println("not a depthbuffer: "+ depth_rb); - name[0] = depth_rb; - gl.glDeleteRenderbuffers(1, name, 0); - depth_rb=0; - return false; - } - - gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, depthComponentType, width, height); - // Set up the depth buffer attachment: - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_DEPTH_ATTACHMENT, - GL.GL_RENDERBUFFER, depth_rb); - updateStatus(gl); - return isStatusValid(); - } - - /** - * Attaches one Stencil Buffer to this FBO's instance. - *This may be done only one time.
- * - *Assumes a bound FBO
- *Leaves the FBO bound!
- * @param gl the current GL context - * @param stencilComponentType {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4} or {@link GL#GL_STENCIL_INDEX8} - * @return true if the stencil renderbuffer could be bound and configured, otherwise false - * @throws GLException in case the stencil renderbuffer couldn't be allocated or one is already attached. - */ - public boolean attachStencilBuffer(GL gl, int stencilComponentType) throws GLException { - checkBound(gl, true); - if(stencil_rb != 0) { - throw new GLException("FBO stencil buffer already attached (rb "+stencil_rb+")"); - } - int name[] = new int[1]; - gl.glGenRenderbuffers(1, name, 0); - stencil_rb = name[0]; - if(stencil_rb==0) { - throw new GLException("null generated stencilbuffer"); - } - // Initialize the stencil buffer: - gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, stencil_rb); - if(!gl.glIsRenderbuffer(stencil_rb)) { - System.err.println("not a stencilbuffer: "+ stencil_rb); - name[0] = stencil_rb; - gl.glDeleteRenderbuffers(1, name, 0); - stencil_rb=0; - return false; - } - gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, stencilComponentType, width, height); - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_STENCIL_ATTACHMENT, - GL.GL_RENDERBUFFER, stencil_rb); - updateStatus(gl); - return isStatusValid(); - } - - /** - * @param gl the current GL context - */ - public void destroy(GL gl) { - if(bound) { - unbind(gl); - } - - int name[] = new int[1]; - - if(0!=stencil_rb) { - name[0] = stencil_rb; - gl.glDeleteRenderbuffers(1, name, 0); - stencil_rb = 0; - } - if(0!=depth_rb) { - name[0] = depth_rb; - gl.glDeleteRenderbuffers(1, name, 0); - depth_rb=0; - } - if(null!=fbo_tex_names && fbo_tex_num>0) { - gl.glDeleteTextures(1, fbo_tex_names, fbo_tex_num); - fbo_tex_names = new int[MAX_FBO_TEXTURES]; - fbo_tex_units = new int[MAX_FBO_TEXTURES]; - fbo_tex_num = 0; - } - colorattachment_num = 0; - if(0!=fb) { - name[0] = fb; - gl.glDeleteFramebuffers(1, name, 0); - fb = 0; - } - initialized = false; - } - - /** - * Bind this FBO - *In case you have attached more than one color buffer, - * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}.
- * @param gl the current GL context - */ - public void bind(GL gl) { - checkBound(gl, false); - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); - bound = true; - } - - /** - * Unbind FBO, ie bind 'non' FBO 0 - * @param gl the current GL context - */ - public void unbind(GL gl) { - checkBound(gl, true); - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); - bound = false; - } - - /** - * Bind the texture with given index. - * - *If a valid texture unit was named via {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)}, - * the unit is activated via {@link GL#glActiveTexture(int) glActiveTexture(GL.GL_TEXTURE0 + unit)}.
- * @param gl the current GL context - * @param texIdx index of the texture to use, prev. attached w/ {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)} - */ - public void use(GL gl, int texIdx) { - checkBound(gl, false); - if(texIdx >= fbo_tex_num) { - throw new GLException("Invalid texId, only "+fbo_tex_num+" textures are attached"); - } - if(0<=fbo_tex_units[texIdx]) { - gl.glActiveTexture(GL.GL_TEXTURE0 + fbo_tex_units[texIdx]); - } - gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[texIdx]); // use it .. - } - - /** Unbind texture, ie bind 'non' texture 0 */ - public void unuse(GL gl) { - checkBound(gl, false); - gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it - } - - public final boolean isBound() { return bound; } - public final int getWidth() { return width; } - public final int getHeight() { return height; } - public final int getFBName() { return fb; } - public final int getTextureNumber() { return fbo_tex_num; } - public final int getTextureName(int idx) { return fbo_tex_names[idx]; } - - /** @return the named texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit was desired. */ - public final int getTextureUnit(int idx) { return fbo_tex_units[idx]; } - public final int getColorAttachmentNumber() { return colorattachment_num; } - public final int getStencilBuffer() { return stencil_rb; } - public final int getDepthBuffer() { return depth_rb; } - public final String toString() { - return "FBO[name "+fb+", size "+width+"x"+height+", color num "+colorattachment_num+", tex num "+fbo_tex_num+", depth "+depth_rb+", stencil "+stencil_rb+"]"; - } - - private void updateStatus(GL gl) { - if(!gl.glIsFramebuffer(fb)) { - vStatus = -1; - } else { - vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER); - } - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java index 8401b9cd2..331d6fa4e 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java @@ -39,6 +39,7 @@ package com.jogamp.opengl.util; import com.jogamp.common.nio.Buffers; + import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.GL2ES2; @@ -56,22 +57,32 @@ import java.nio.*; public class GLBuffers extends Buffers { /** - * @param glType shall be one of - * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, - * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, - * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, - * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, - * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, - * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, - * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, - * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV - * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, - * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, - * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27) + * @param glType shall be one of (29)- + based rendering mechanism as well by end users directly. +
The implementation shall initialize itself as soon as possible, ie if the attached {@link javax.media.nativewindow.NativeSurface NativeSurface} becomes visible/realized. The following protocol shall be satisfied: @@ -64,18 +64,18 @@ import jogamp.opengl.Debug; registered {@link GLEventListener}s. This can be done immediatly, or with the followup {@link #display display(..)} call.
- +
+
Another implementation detail is the drawable reconfiguration. One use case is where a window is being
dragged to another screen with a different pixel configuration, ie {@link GLCapabilities}. The implementation
- shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeSurface NativeSurface}.
+ shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeSurface NativeSurface}.
For example, AWT's {@link java.awt.Canvas} 's {@link java.awt.Canvas#getGraphicsConfiguration getGraphicsConfiguration()}
is capable to determine a display device change. This is demonstrated within {@link javax.media.opengl.awt.GLCanvas}'s
and NEWT's AWTCanvas
{@link javax.media.opengl.awt.GLCanvas#getGraphicsConfiguration getGraphicsConfiguration()}
specialization. Another demonstration is NEWT's {@link javax.media.nativewindow.NativeWindow NativeWindow}
- implementation on the Windows platform, which utilizes the native platform's MonitorFromWindow(HWND) function.
+ implementation on the Windows platform, which utilizes the native platform's MonitorFromWindow(HWND) function.
All OpenGL resources shall be regenerated, while the drawable's {@link GLCapabilities} has
- to be choosen again. The following protocol shall be satisfied.
+ to be chosen again. The following protocol shall be satisfied.
- - However, to not introduce to much breakage with older applications and because of the situation + and make your application comply with the above protocol. +
+ Avoiding breakage with older applications and because of the situation
mentioned above, the boolean
system property jogl.screenchange.action
will control the
- screen change action as follows:
-
+ screen change action as follows:
-Djogl.screenchange.action=false Disable the drawable reconfiguration (the default) -Djogl.screenchange.action=true Enable the drawable reconfiguration+ */ public interface GLAutoDrawable extends GLDrawable { /** Flag reflecting wheather the drawable reconfiguration will be issued in @@ -362,5 +362,29 @@ public interface GLAutoDrawable extends GLDrawable { demos for examples. @return the set GL pipeline or null if not successful */ public GL setGL(GL gl); + + /** + * Method may return the upstream UI toolkit object + * holding this {@link GLAutoDrawable} instance, if exist. + *
+ * Currently known Java UI toolkits and it's known return types are: + * + *
Toolkit | GLAutoDrawable Implementation | ~ | Return Type of getUpstreamWidget() | + *
NEWT | {@link com.jogamp.newt.opengl.GLWindow} | has a | {@link com.jogamp.newt.Window} | + *
SWT | {@link com.jogamp.opengl.swt.GLCanvas} | is a | {@link org.eclipse.swt.widgets.Canvas} | + *
AWT | {@link javax.media.opengl.awt.GLCanvas} | is a | {@link java.awt.Canvas} | + *
AWT | {@link javax.media.opengl.awt.GLJPanel} | is a | {@link javax.swing.JPanel} | + *
+ * This method may also return null
if no UI toolkit is being used,
+ * as common for offscreen rendering.
+ *
diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java
index bd24b15bc..f5831a72d 100644
--- a/src/jogl/classes/javax/media/opengl/GLBase.java
+++ b/src/jogl/classes/javax/media/opengl/GLBase.java
@@ -340,5 +340,60 @@ public interface GLBase {
* completeness.
*/
public Object getExtension(String extensionName);
+
+ /** Aliased entrypoint of void {@native glClearDepth}(GLclampd depth);
and void {@native glClearDepthf}(GLclampf depth);
. */
+ public void glClearDepth( double depth );
+
+ /** Aliased entrypoint of void {@native glDepthRange}(GLclampd depth);
and void {@native glDepthRangef}(GLclampf depth);
. */
+ public void glDepthRange(double zNear, double zFar);
+
+ /**
+ * @param target a GL buffer (VBO) target as used in {@link GL#glBindBuffer(int, int)}, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}, {@link GL#GL_ARRAY_BUFFER}, ..
+ * @return the GL buffer (VBO) name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound.
+ */
+ public int glGetBoundBuffer(int target);
+
+ /**
+ * @param buffer a GL buffer name, generated with {@link GL#glGenBuffers(int, int[], int)} and used in {@link GL#glBindBuffer(int, int)}, {@link GL#glBufferData(int, long, java.nio.Buffer, int)} or {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} for example.
+ * @return the size of the given GL buffer
+ */
+ public long glGetBufferSize(int buffer);
+
+ /**
+ * @return true if a VBO is bound to {@link GL.GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ */
+ public boolean glIsVBOArrayEnabled();
+
+ /**
+ * @return true if a VBO is bound to {@link GL.GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false
+ */
+ public boolean glIsVBOElementArrayEnabled();
+
+ /**
+ * Return the framebuffer name bound to this context,
+ * see {@link GL#glBindFramebuffer(int, int)}.
+ */
+ public int getBoundFramebuffer(int target);
+
+ /**
+ * Return the default draw framebuffer name.
+ *
+ * May differ from it's default zero
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ *
+ * May differ from it's default zero
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ *
- * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}
- * and {@link #setFBO(int) setFBO(false)}
+ * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}.
*
- * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}
- * and {@link #setPBuffer(int) setPBuffer(false)}
+ * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}.
*
true
(default), bootstrapping the available GL profiles
* will use the highest compatible GL context for each profile,
@@ -120,13 +122,13 @@ public abstract class GLContext {
protected static final int CTX_PROFILE_ES = 1 << 3;
/** ARB_create_context
related: flag forward compatible. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_OPTION_FORWARD = 1 << 4;
- /** ARB_create_context
related: flag debug. Not a cache key. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
+ /** ARB_create_context
related: flag debug. Cache key value. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
public static final int CTX_OPTION_DEBUG = 1 << 5;
/** GL_ARB_ES2_compatibility
implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8;
- /** Context supports FBO, details see {@link #hasFBO()}.
+ /** Context supports basic FBO, details see {@link #hasFBO()}.
* Not a cache key.
* @see #hasFBO()
* @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
@@ -136,16 +138,6 @@ public abstract class GLContext {
/** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. See {@link #isHardwareRasterizer()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 15;
- protected static final String GL_ARB_ES2_compatibility = "GL_ARB_ES2_compatibility";
- protected static final String GL_ARB_framebuffer_object = "GL_ARB_framebuffer_object";
- protected static final String GL_EXT_framebuffer_object = "GL_EXT_framebuffer_object";
- protected static final String GL_EXT_framebuffer_blit = "GL_EXT_framebuffer_blit";
- protected static final String GL_EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample";
- protected static final String GL_EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil";
- protected static final String GL_ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two";
- protected static final String GL_EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888";
- protected static final String GL_IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888";
-
private static final ThreadLocalGL_ARB_ES2_compatibility
, ARB_framebuffer_object
or all of
- * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
- * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
+ /**
+ * Returns true
if basic FBO support is available, otherwise false
.
+ *
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
+ * GL_ARB_ES2_compatibility
, GL_ARB_framebuffer_object
, GL_EXT_framebuffer_object
or GL_OES_framebuffer_object
.
+ *
+ * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *
* @see #CTX_IMPL_FBO + * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL) + * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL) */ public final boolean hasFBO() { return 0 != ( ctxOptions & CTX_IMPL_FBO ) ; @@ -659,13 +659,13 @@ public abstract class GLContext { /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returnstrue
. */
public boolean isNPOTTextureAvailable() {
- return isGL3() || isGLES2Compatible() || isExtensionAvailable(GL_ARB_texture_non_power_of_two);
+ return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
}
public boolean isTextureFormatBGRA8888Available() {
return isGL2GL3() ||
- isExtensionAvailable(GL_EXT_texture_format_BGRA8888) ||
- isExtensionAvailable(GL_IMG_texture_format_BGRA8888) ;
+ isExtensionAvailable(GLExtensions.EXT_texture_format_BGRA8888) ||
+ isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ;
}
/** @see GLProfile#isGL4bc() */
@@ -798,7 +798,32 @@ public abstract class GLContext {
}
protected boolean bindSwapBarrierImpl(int group, int barrier) { /** nop per default .. **/ return false; }
-
+ /**
+ * Return the framebuffer name bound to this context,
+ * see {@link GL#glBindFramebuffer(int, int)}.
+ */
+ public abstract int getBoundFramebuffer(int target);
+
+ /**
+ * Return the default draw framebuffer name.
+ *
+ * May differ from it's default zero
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ *
+ * May differ from it's default zero
+ * in case an framebuffer object ({@link FBObject}) based drawable
+ * is being used.
+ *
+ * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. + *
+ *+ * FBO support is queried as described in {@link #hasFBO()}. + *
+ * + * @param device the device to request whether FBO is available for + * @param glp {@link GLProfile} to check for FBO capabilities + * @see GLContext#hasFBO() + */ + public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) { + return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) ); + } + /** * @param device the device to request whether the profile is available for * @param reqMajor Key Value either 1, 2, 3 or 4 diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index d6480e7aa..612a02f14 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -50,9 +50,11 @@ import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; import javax.media.opengl.GLProfile.ShutdownType; import jogamp.opengl.Debug; @@ -398,9 +400,18 @@ public abstract class GLDrawableFactory { /** * Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. *
- * A Pbuffer drawable/surface is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()}
- * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
- * Otherwise a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.
+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below.
+ *
+ * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *
+ *+ * A Pbuffer drawable is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *
+ *+ * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. *
* * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may benull
for the platform's default device.
@@ -421,42 +432,31 @@ public abstract class GLDrawableFactory {
throws GLException;
/**
- * Creates an offscreen NativeSurface.null
for the platform's default device.
- * @param caps the requested GLCapabilties
- * @param chooser the custom chooser, may be null for default
- * @param width the requested offscreen width
- * @param height the requested offscreen height
- * @return the created offscreen native surface
- *
- * @throws GLException if any window system-specific errors caused
- * the creation of the GLDrawable to fail.
- */
- public abstract NativeSurface createOffscreenSurface(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable caps,
- GLCapabilitiesChooser chooser,
- int width, int height);
-
- /**
- * Highly experimental API entry, allowing developer of new windowing system bindings
- * to leverage the native window handle to produce a NativeSurface implementation (ProxySurface), having the required GLCapabilities.+ * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}. + *
+ *+ * Lifecycle (destruction) of the given surface handle shall be handled by the caller. + *
+ *+ * Such surface can be used to instantiate a GLDrawable. With the help of {@link GLAutoDrawableDelegate} + * you will be able to implement a new native windowing system binding almost on-the-fly, see {@link com.jogamp.opengl.swt.GLCanvas}. + *
* - * @param device the platform's target device, shall not benull
+ * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null
for the platform's default device.
+ * Caller has to ensure it is compatible w/ the given windowHandle
+ * @param screenIdx matching screen index of given windowHandle
* @param windowHandle the native window handle
* @param caps the requested GLCapabilties
* @param chooser the custom chooser, may be null for default
- * @return The proxy surface wrapping the windowHandle on the device
+ * @param upstream optional {@link ProxySurface.UpstreamSurfaceHook} allowing control of the {@link ProxySurface}'s lifecycle and data it presents.
+ * @return the created {@link ProxySurface} instance w/ defined surface handle.
*/
- public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device,
+ public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device,
+ int screenIdx,
long windowHandle,
- GLCapabilitiesImmutable caps,
- GLCapabilitiesChooser chooser);
+ GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
/**
* Returns true if it is possible to create a GLPbuffer. Some older
@@ -492,23 +492,7 @@ public abstract class GLDrawableFactory {
GLContext shareWith)
throws GLException;
- /**
- * Returns true if it is possible to create an framebuffer object (FBO).
- * - * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. - *
- *- * FBO support is queried as described in {@link GLContext#hasFBO()}. - *
- * - * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may benull
for the platform's default device.
- * @param glp {@link GLProfile} to check for FBO capabilities
- * @see GLContext#hasFBO()
- */
- public final boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp) {
- return 0 != ( GLContext.CTX_IMPL_FBO & GLContext.getAvailableContextProperties(device, glp) );
- }
-
+
//----------------------------------------------------------------------
// Methods for interacting with third-party OpenGL libraries
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index a7200b560..73d13a387 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -117,10 +117,12 @@ public class GLProfile {
* @deprecated Use {@link #initSingleton()}. This method is subject to be removed in future versions of JOGL.
*/
public static void initSingleton(final boolean firstUIActionOnProcess) {
+ final boolean justInitialized;
initLock.lock();
try {
if(!initialized) { // volatile: ok
initialized = true;
+ justInitialized = true;
if(DEBUG) {
System.err.println("GLProfile.initSingleton(firstUIActionOnProcess: "+firstUIActionOnProcess+") - thread "+Thread.currentThread().getName());
Thread.dumpStack();
@@ -166,10 +168,17 @@ public class GLProfile {
return null;
}
});
+ } else {
+ justInitialized = false;
}
} finally {
initLock.unlock();
}
+ if(DEBUG) {
+ if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES2Impl ) ) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true));
+ }
+ }
}
/**
@@ -1532,18 +1541,17 @@ public class GLProfile {
if(DEBUG) {
// System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
- System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile);
- System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable);
- System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory);
- System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl);
- System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory);
- System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl);
- System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl);
- System.err.println("GLProfile.init defaultDevice "+defaultDevice);
- System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL));
- if(hasGL234Impl || hasGLES1Impl || hasGLES2Impl) { // avoid deadlock
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true));
- }
+ System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile);
+ System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable);
+ System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory);
+ System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl);
+ System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory);
+ System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl);
+ System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl);
+ System.err.println("GLProfile.init defaultDevice "+defaultDevice);
+ System.err.println("GLProfile.init defaultDevice Desktop "+defaultDesktopDevice);
+ System.err.println("GLProfile.init defaultDevice EGL "+defaultEGLDevice);
+ System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL));
}
}
@@ -1642,24 +1650,6 @@ public class GLProfile {
if (DEBUG) {
System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail);
}
- if( hasGLES2Impl ) {
- // The native ES2 impl. overwrites a previous mapping using 'ES2 compatibility' by a desktop profile
- GLContext.mapAvailableGLVersion(device,
- 2, GLContext.CTX_PROFILE_ES,
- 2, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_IMPL_ES2_COMPAT);
- if (DEBUG) {
- System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES2 -> ES 2.0");
- }
- }
- if( hasGLES1Impl ) {
- // Always favor the native ES1 impl.
- GLContext.mapAvailableGLVersion(device,
- 1, GLContext.CTX_PROFILE_ES,
- 1, 0, GLContext.CTX_PROFILE_ES);
- if (DEBUG) {
- System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES1 -> ES 1.0");
- }
- }
addedEGLProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */);
}
@@ -1767,7 +1757,7 @@ public class GLProfile {
}
_mappedProfiles.put(profile, glProfile);
if (DEBUG) {
- System.err.println("GLProfile.init map "+glProfile+" on devide "+device.getConnection());
+ System.err.println("GLProfile.init map "+glProfile+" on device "+device.getConnection());
}
if(null==defaultGLProfileHW && isHardwareRasterizer[0]) {
defaultGLProfileHW=glProfile;
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index 48f7ea24a..c2e36ef9b 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -261,6 +261,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
this.device = device;
}
+ @Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
@Override
public void setShallUseOffscreenLayer(boolean v) {
shallUseOffscreenLayer = v;
@@ -1070,7 +1075,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
// System.err.println(NativeWindowVersion.getInstance());
System.err.println(JoglVersion.getInstance());
- System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString());
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) );
final Frame frame = new Frame("JOGL AWT Test");
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index cd18c5098..acb8f2183 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -87,7 +87,7 @@ import jogamp.opengl.awt.Java2D;
import jogamp.opengl.awt.Java2DGLContext;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
-import com.jogamp.opengl.util.FBObject;
+import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.util.GLBuffers;
// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
@@ -250,6 +250,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
this.shareWith = shareWith;
}
+ @Override
+ public final Object getUpstreamWidget() {
+ return this;
+ }
+
@Override
public void display() {
if (EventQueue.isDispatchThread()) {
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
index 804e9ee14..aabef29b0 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java
@@ -32,7 +32,6 @@ import java.nio.FloatBuffer;
import javax.media.opengl.GL2ES2;
// FIXME: Subsume GL2GL3.GL_DRAW_FRAMEBUFFER -> GL2ES2.GL_DRAW_FRAMEBUFFER !
import javax.media.opengl.GL;
-import javax.media.opengl.GLException;
import javax.media.opengl.GLUniformData;
import javax.media.opengl.fixedfunc.GLMatrixFunc;
@@ -45,7 +44,9 @@ import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RenderState;
-import com.jogamp.opengl.util.FBObject;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.FBObject.Attachment;
+import com.jogamp.opengl.FBObject.TextureAttachment;
import com.jogamp.opengl.util.GLArrayDataServer;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.glsl.ShaderState;
@@ -60,6 +61,7 @@ public class VBORegion2PES2 extends GLRegion {
private FBObject fbo;
+ private TextureAttachment texA;
private PMVMatrix fboPMVMatrix;
GLUniformData mgl_fboPMVMatrix;
@@ -72,7 +74,7 @@ public class VBORegion2PES2 extends GLRegion {
super(renderModes);
fboPMVMatrix = new PMVMatrix();
mgl_fboPMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, fboPMVMatrix.glGetPMvMatrixf());
- mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine);
+ mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine);
}
public void update(GL2ES2 gl, RenderState rs) {
@@ -214,8 +216,9 @@ public class VBORegion2PES2 extends GLRegion {
final ShaderState st = rs.getShaderState();
gl.glViewport(0, 0, width, hight);
- st.uniform(gl, mgl_ActiveTexture);
- fbo.use(gl, 0);
+ st.uniform(gl, mgl_ActiveTexture);
+ gl.glActiveTexture(GL.GL_TEXTURE0 + mgl_ActiveTexture.intValue());
+ fbo.use(gl, texA);
verticeFboAttr.enableBuffer(gl, true);
texCoordFboAttr.enableBuffer(gl, true);
indicesFbo.enableBuffer(gl, true);
@@ -244,20 +247,16 @@ public class VBORegion2PES2 extends GLRegion {
// System.out.println("FBO Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5));
if(null != fbo && fbo.getWidth() != tex_width_c && fbo.getHeight() != tex_height_c ) {
- fbo.destroy(gl);
- fbo = null;
+ fbo.reset(gl, tex_width_c, tex_height_c);
}
- if(null == fbo) {
- fbo = new FBObject(tex_width_c, tex_height_c);
- fbo.init(gl);
+ if(null == fbo) {
+ fbo = new FBObject();
+ fbo.reset(gl, tex_width_c, tex_height_c);
// FIXME: shall not use bilinear, due to own AA ? However, w/o bilinear result is not smooth
- fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- // fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
- fbo.attachDepthBuffer(gl, GL.GL_DEPTH_COMPONENT16); // FIXME: or shall we use 24 or 32 bit depth ?
- if(!fbo.isStatusValid()) {
- throw new GLException("FBO invalid: "+fbo);
- }
+ texA = fbo.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
+ // texA = fbo.attachTexture2D(gl, 0, GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
+ fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
} else {
fbo.bind(gl);
}
@@ -305,6 +304,7 @@ public class VBORegion2PES2 extends GLRegion {
if(null != fbo) {
fbo.destroy(gl);
fbo = null;
+ texA = null;
}
if(null != verticeTxtAttr) {
st.ownAttribute(verticeTxtAttr, false);
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 4dd8806fa..e730bc62e 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -49,8 +49,9 @@ import com.jogamp.common.os.DynamicLookupHelper;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.gluegen.runtime.FunctionAddressResolver;
import com.jogamp.gluegen.runtime.ProcAddressTable;
-import com.jogamp.gluegen.runtime.opengl.GLExtensionNames;
+import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.opengl.GLExtensions;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -88,13 +89,14 @@ public abstract class GLContextImpl extends GLContext {
// Tracks creation and initialization of buffer objects to avoid
// repeated glGet calls upon glMapBuffer operations
private GLBufferSizeTracker bufferSizeTracker; // Singleton - Set by GLContextShareSet
- private GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker();
- private GLStateTracker glStateTracker = new GLStateTracker();
+ private final GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker();
+ private final GLStateTracker glStateTracker = new GLStateTracker();
private GLDebugMessageHandler glDebugHandler = null;
+ private final int[] boundFBOTarget = new int[] { 0, 0 }; // { draw, read }
protected GLDrawableImpl drawable;
protected GLDrawableImpl drawableRead;
-
+
protected GL gl;
protected static final Object mappedContextTypeObjectLock;
@@ -140,11 +142,11 @@ public abstract class GLContextImpl extends GLContext {
bufferSizeTracker.clearCachedBufferSizes();
}
- if (bufferStateTracker != null) {
+ if (bufferStateTracker != null) { // Invoked by {@link GL#glBindFramebuffer(int, int)}.
+ * + *Assumes valid framebufferName
range of [0..{@link Integer#MAX_VALUE}]
Does not throw an exception if target
is unknown or framebufferName
invalid.
device
{@link AbstractGraphicsDevice#getConnection()},
* either a preexisting or newly created, or null
if creation failed or not supported.1
refers to ES1 and 2
to ES2,
* otherwise the profile is ignored.
@@ -125,6 +126,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
// Dispatching GLDrawable construction in respect to the NativeSurface Capabilities
//
+ @Override
public GLDrawable createGLDrawable(NativeSurface target) {
if (target == null) {
throw new IllegalArgumentException("Null target");
@@ -132,23 +134,37 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration();
final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
final AbstractGraphicsDevice adevice = config.getScreen().getDevice();
+ final boolean isFBOAvailable = GLContext.isFBOAvailable(adevice, chosenCaps.getGLProfile());
GLDrawable result = null;
adevice.lock();
try {
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true);
if(null != ols) {
- // layered surface -> Offscreen/PBuffer
+ // layered surface -> Offscreen/[FBO|PBuffer]
final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable();
chosenCapsMod.setOnscreen(false);
- chosenCapsMod.setPBuffer(canCreateGLPbuffer(adevice));
+ if( isFBOAvailable ) {
+ chosenCapsMod.setFBO(true);
+ } else if(canCreateGLPbuffer(adevice)) {
+ chosenCapsMod.setPBuffer(true);
+ } else {
+ chosenCapsMod.setFBO(false);
+ chosenCapsMod.setPBuffer(false);
+ }
config.setChosenCapabilities(chosenCapsMod);
if(DEBUG) {
System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer: "+target);
}
- if( ! ( target instanceof SurfaceChangeable ) ) {
+ if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target);
+ }
+ if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) {
+ // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO ..
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target);
+ result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */);
+ } else {
+ result = createOffscreenDrawableImpl(target);
}
- result = createOffscreenDrawableImpl(target);
} else if(chosenCaps.isOnscreen()) {
// onscreen
if(DEBUG) {
@@ -158,12 +174,18 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
} else {
// offscreen
if(DEBUG) {
- System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable (PBuffer: "+chosenCaps.isPBuffer()+"): "+target);
+ System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO-chosen(-avail)/PBuffer: "+chosenCaps.isFBO()+"("+isFBOAvailable+")/"+chosenCaps.isPBuffer()+": "+target);
}
- if( ! ( target instanceof SurfaceChangeable ) ) {
+ if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen: "+target);
}
- result = createOffscreenDrawableImpl(target);
+ if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) {
+ // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO ..
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target);
+ result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */);
+ } else {
+ result = createOffscreenDrawableImpl(target);
+ }
}
} finally {
adevice.unlock();
@@ -176,43 +198,42 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
//
- // Onscreen GLDrawable construction
+ // Onscreen GLDrawable construction
//
protected abstract GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target);
//---------------------------------------------------------------------------
//
- // PBuffer Offscreen GLDrawable construction
+ // PBuffer Offscreen GLDrawable construction
//
-
+
+ @Override
public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
+ @Override
public GLPbuffer createGLPbuffer(AbstractGraphicsDevice deviceReq,
GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
int width,
int height,
GLContext shareWith) {
- if(height<=0 || height<=0) {
- throw new GLException("Width and height of pbuffer must be positive (were (" +
- width + ", " + height + "))");
+ if(width<=0 || height<=0) {
+ throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
}
-
AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
-
- if (!canCreateGLPbuffer(device)) {
- throw new GLException("Pbuffer support not available with device: "+device);
+ if ( !canCreateGLPbuffer(device) ) {
+ throw new GLException("Pbuffer not available with device: "+device);
}
-
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested);
+
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested);
GLDrawableImpl drawable = null;
device.lock();
try {
- drawable = (GLDrawableImpl) createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) );
+ drawable = (GLDrawableImpl) createGLDrawable( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) );
if(null != drawable) {
drawable.setRealized(true);
}
@@ -228,75 +249,155 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
//---------------------------------------------------------------------------
//
- // Offscreen GLDrawable construction
+ // Offscreen GLDrawable construction
//
- protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
-
+ @Override
public GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq,
GLCapabilitiesImmutable capsRequested,
GLCapabilitiesChooser chooser,
- int width,
- int height) {
+ int width, int height) {
if(width<=0 || height<=0) {
- throw new GLException("Width and height of pbuffer must be positive (were (" +
- width + ", " + height + "))");
+ throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
}
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq));
-
+
+ if( capsRequested.isFBO() && GLContext.isFBOAvailable(device, capsRequested.getGLProfile()) ) {
+ device.lock();
+ try {
+ return createFBODrawableImpl(device, capsRequested, chooser, width, height);
+ } finally {
+ device.unlock();
+ }
+ }
+
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, false, canCreateGLPbuffer(device));
device.lock();
try {
- return createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) );
+ return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) );
} finally {
device.unlock();
}
}
- public NativeSurface createOffscreenSurface(AbstractGraphicsDevice deviceReq,
- GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height) {
- AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
+ /** Creates a platform independent offscreen FBO GLDrawable implementation */
+ protected GLDrawable createFBODrawableImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
+ int initialWidth, int initialHeight) {
+ final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps);
+ final NativeSurface dummySurface = createDummySurfaceImpl(device, true, dummyCaps, null, 64, 64);
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface);
+
+ return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, initialWidth, initialHeight, 0 /* textureUnit */);
+ }
+
+ /** Creates a platform dependent offscreen pbuffer/pixmap GLDrawable implementation */
+ protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ;
+
+ /**
+ * Creates a mutable {@link ProxySurface} w/o defined surface handle.
+ * + * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}. + *
+ *+ * Lifecycle (destruction) of the TBD surface handle shall be handled by the caller. + *
+ * @param device a valid platform dependent target device. + * @param createNewDevice iftrue
a new device instance is created using device
details,
+ * otherwise device
instance is used as-is.
+ * @param capsChosen
+ * @param capsRequested
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ * @param lifecycleHook optional control of the surface's lifecycle
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
+ */
+ protected abstract ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
+ GLCapabilitiesImmutable capsChosen,
+ GLCapabilitiesImmutable capsRequested,
+ GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook);
+
+ /**
+ * A dummy surface is not visible on screen and will not be used to render directly to,
+ * it maybe on- or offscreen.
+ * + * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. + * It also allows creation of framebuffer objects which are used for rendering. + *
+ * @param deviceReq which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may benull
for the platform's default device.
+ * @param requestedCaps
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ *
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
+ */
+ public NativeSurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser,
+ int width, int height) {
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
throw new GLException("No shared device for requested: "+deviceReq);
}
- GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq));
-
device.lock();
try {
- return createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height);
+ return createDummySurfaceImpl(device, true, requestedCaps, chooser, width, height);
} finally {
device.unlock();
}
}
-
+
/**
- * creates an offscreen NativeSurface, which must implement SurfaceChangeable as well,
- * so the windowing system related implementation is able to set the surface handle.
+ * A dummy surface is not visible on screen and will not be used to render directly to,
+ * it maybe on- or offscreen.
+ * + * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. + * It also allows creation of framebuffer objects which are used for rendering. + *
+ * @param device a valid platform dependent target device. + * @param createNewDevice iftrue
a new device instance is created using device
details,
+ * otherwise device
instance is used as-is.
+ * @param requestedCaps
+ * @param chooser the custom chooser, may be null for default
+ * @param width the initial width
+ * @param height the initial height
+ * @return the created {@link MutableSurface} instance w/o defined surface handle
*/
- protected abstract NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable capabilities, GLCapabilitiesImmutable capsRequested,
- GLCapabilitiesChooser chooser,
- int width, int height);
+ public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
+ GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height);
- public ProxySurface createProxySurface(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) {
+ //---------------------------------------------------------------------------
+ //
+ // ProxySurface (Wrapped pre-existing native surface) construction
+ //
+
+ @Override
+ public ProxySurface createProxySurface(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle,
+ GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) {
+ final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq);
if(null == device) {
- throw new GLException("No shared device for requested: "+device);
+ throw new GLException("No shared device for requested: "+deviceReq);
}
device.lock();
try {
- return createProxySurfaceImpl(device, windowHandle, capsRequested, chooser);
+ return createProxySurfaceImpl(device, screenIdx, windowHandle, capsRequested, chooser, upstream);
} finally {
device.unlock();
}
- }
-
- protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser);
+ }
+
+ /**
+ * Creates a {@link ProxySurface} with a set surface handle.
+ * + * Implementation is also required to allocate it's own {@link AbstractGraphicsDevice} instance. + *
+ * @param upstream TODO + */ + protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, + GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream); //--------------------------------------------------------------------------- // @@ -304,7 +405,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // protected abstract GLContext createExternalGLContextImpl(); - + + @Override public GLContext createExternalGLContext() { NativeWindowFactory.getDefaultToolkitLock().lock(); try { @@ -316,6 +418,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { protected abstract GLDrawable createExternalGLDrawableImpl(); + @Override public GLDrawable createExternalGLDrawable() { NativeWindowFactory.getDefaultToolkitLock().lock(); try { @@ -398,7 +501,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * normal ahead of time, use resetDisplayGamma(). Throws * IllegalArgumentException if any of the parameters were * out-of-bounds. - * + * * @param gamma The gamma value, typically > 1.0 (default value is * 1.0) * @param brightness The brightness value between -1.0 and 1.0, @@ -484,7 +587,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { return; if (gammaShutdownHook == null) { gammaShutdownHook = new Thread(new Runnable() { - public void run() { + @Override + public void run() { synchronized (GLDrawableFactoryImpl.this) { resetGammaRamp(originalGammaRamp); } diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index 58a4ac6b4..abf2bf557 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -42,6 +42,7 @@ package jogamp.opengl; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -75,7 +76,7 @@ public abstract class GLDrawableImpl implements GLDrawable { if( !realized ) { return; // destroyed already } - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); if ( caps.getDoubleBuffered() ) { if(!surface.surfaceSwap()) { int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] @@ -149,6 +150,9 @@ public abstract class GLDrawableImpl implements GLDrawable { realized = realizedArg; AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice(); if(realizedArg) { + if(surface instanceof ProxySurface) { + ((ProxySurface)surface).createNotify(); + } if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) { throw new GLException("GLDrawableImpl.setRealized(true): Surface not ready (lockSurface)"); } @@ -156,17 +160,21 @@ public abstract class GLDrawableImpl implements GLDrawable { aDevice.lock(); } try { - setRealizedImpl(); if(realizedArg) { + setRealizedImpl(); updateHandle(); } else { destroyHandle(); + setRealizedImpl(); } } finally { if(realizedArg) { unlockSurface(); } else { aDevice.unlock(); + if(surface instanceof ProxySurface) { + ((ProxySurface)surface).destroyNotify(); + } } } } else if(DEBUG) { @@ -175,6 +183,39 @@ public abstract class GLDrawableImpl implements GLDrawable { } protected abstract void setRealizedImpl(); + /** + * Callback for special implementations, allowing GLContext to trigger GL related lifecycle:construct
, destroy
.
+ *
+ * If realized
is true
, the context has just been created and made current.
+ *
+ * If realized
is false
, the context is still current and will be release and destroyed after this method returns.
+ *
+ * @see #contextMadeCurrent(GLContext, boolean)
+ */
+ protected void contextRealized(GLContext glc, boolean realized) {}
+
+ /**
+ * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: makeCurrent
, release
.
+ *
+ * Will not be called if {@link #contextRealized(GLContext, boolean)} has been triggered. + *
+ *
+ * If current
is true
, the context has just been made current.
+ *
+ * If current
is false
, the context is still current and will be release after this method returns.
+ *
+ * We intentionally override a non native EGL device ES profile mapping, + * i.e. this will override/modify an already 'set' X11/WGL/.. mapping. + *
+ * + * @param device + */ + protected void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) { + mapCurrentAvailableGLVersionImpl(device, ctxMajorVersion, ctxMinorVersion, ctxOptions); + } + + protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) { + int ctp = ( 2 == major ) ? ( GLContext.CTX_PROFILE_ES | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) : ( GLContext.CTX_PROFILE_ES ); + mapCurrentAvailableGLVersionImpl(device, major, 0, ctp); + } + private static void mapCurrentAvailableGLVersionImpl(AbstractGraphicsDevice device, int major, int minor, int ctp) { + if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) { + // ES1 or ES2 + final int reqMajor = major; + final int reqProfile = GLContext.CTX_PROFILE_ES; + GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, + major, minor, ctp); + } + } + + protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) { + return GLContext.getAvailableGLVersionsSet(device); + } + protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) { + GLContext.setAvailableGLVersionsSet(device); + } + protected static String toHexString(int hex) { return GLContext.toHexString(hex); } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java index 7f10d3bd9..432010f49 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java @@ -136,7 +136,17 @@ public class EGLDisplayUtil { return res; } - public static final EGLGraphicsDevice.EGLTerminateCallback eglTerminateCallback = new EGLGraphicsDevice.EGLTerminateCallback() { + public static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() { + public long eglGetAndInitDisplay(long nativeDisplayID) { + long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { + throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + return eglDisplay; + } public void eglTerminate(long eglDisplayHandle) { EGLDisplayUtil.eglTerminate(eglDisplayHandle); } @@ -148,17 +158,12 @@ public class EGLDisplayUtil { * @param unitID * @return an initialized EGLGraphicsDevice * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails - * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLTerminateCallback) + * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLDisplayLifecycleCallback) */ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(long nativeDisplayID, String connection, int unitID) { - long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } - if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { - throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } - return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, connection, unitID, eglTerminateCallback); + final EGLGraphicsDevice eglDisplay = new EGLGraphicsDevice(nativeDisplayID, 0, connection, unitID, eglLifecycleCallback); + eglDisplay.open(); + return eglDisplay; } /** @@ -189,6 +194,6 @@ public class EGLDisplayUtil { throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); } final AbstractGraphicsDevice adevice = surface.getGraphicsConfiguration().getScreen().getDevice(); - return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglTerminateCallback); + return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglLifecycleCallback); } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index d777c4f04..383b61f88 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -36,82 +36,65 @@ package jogamp.opengl.egl; -import jogamp.opengl.GLDynamicLookupHelper; -import jogamp.opengl.GLDrawableImpl; +import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; -import javax.media.nativewindow.*; -import javax.media.nativewindow.VisualIDHolder.VIDType; -import javax.media.opengl.*; +import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLDynamicLookupHelper; -import com.jogamp.nativewindow.egl.*; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public abstract class EGLDrawable extends GLDrawableImpl { - private boolean ownEGLDisplay = false; // for destruction private boolean ownEGLSurface = false; // for destruction - private EGLGraphicsConfiguration eglConfig; - private EGLGraphicsDevice eglDevice; - private long eglSurface; - protected EGLDrawable(EGLDrawableFactory factory, - NativeSurface component) throws GLException { + protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException { super(factory, component, false); - eglSurface=EGL.EGL_NO_SURFACE; - eglDevice=null; - } - - public final long getDisplay() { - return null != eglDevice ? eglDevice.getHandle() : 0; - } - - @Override - public final long getHandle() { - return eglSurface; - } - - public final EGLGraphicsConfiguration getGraphicsConfiguration() { - return eglConfig; - } - - @Override - public final GLCapabilitiesImmutable getChosenGLCapabilities() { - return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilitiesImmutable)eglConfig.getChosenCapabilities(); } @Override public abstract GLContext createContext(GLContext shareWith); - protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle); + protected abstract long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle); private final void recreateSurface() { - // create a new EGLSurface .. - if(EGL.EGL_NO_SURFACE!=eglSurface) { - EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface); - } - + final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice(); if(DEBUG) { - System.err.println(getThreadName() + ": createSurface using "+eglDevice+", "+eglConfig); + System.err.println(getThreadName() + ": createSurface using "+eglConfig); + } + if( EGL.EGL_NO_SURFACE != surface.getSurfaceHandle() ) { + EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle()); } - - eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surface.getSurfaceHandle()); - int eglError0 = EGL.EGL_SUCCESS; + + final EGLUpstreamSurfaceHook upstreamHook = (EGLUpstreamSurfaceHook) ((ProxySurface)surface).getUpstreamSurfaceHook(); + final NativeSurface upstreamSurface = upstreamHook.getUpstreamSurface(); + long eglSurface = createSurface(eglConfig, upstreamSurface.getSurfaceHandle()); + + int eglError0; if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); if(EGL.EGL_BAD_NATIVE_WINDOW == eglError0) { // Try window handle if available and differs (Windows HDC / HWND). // ANGLE impl. required HWND on Windows. - if(surface instanceof NativeWindow) { - final NativeWindow nw = (NativeWindow) surface; + if(upstreamSurface instanceof NativeWindow) { + final NativeWindow nw = (NativeWindow) upstreamSurface; if(nw.getWindowHandle() != nw.getSurfaceHandle()) { if(DEBUG) { System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle"); } - eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), nw.getWindowHandle()); + eglSurface = createSurface(eglConfig, nw.getWindowHandle()); if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); } } } } + } else { + eglError0 = EGL.EGL_SUCCESS; } if (EGL.EGL_NO_SURFACE == eglSurface) { throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0)); @@ -120,6 +103,8 @@ public abstract class EGLDrawable extends GLDrawableImpl { if(DEBUG) { System.err.println(getThreadName() + ": setSurface using component: handle "+toHexString(surface.getSurfaceHandle())+" -> "+toHexString(eglSurface)); } + + ((MutableSurface)surface).setSurfaceHandle(eglSurface); } @Override @@ -131,123 +116,71 @@ public abstract class EGLDrawable extends GLDrawableImpl { @Override protected final void setRealizedImpl() { + final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice(); if (realized) { - AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); - AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); - if(aDevice instanceof EGLGraphicsDevice) { + final long eglDisplayHandle = eglDevice.getHandle(); + if (EGL.EGL_NO_DISPLAY == eglDisplayHandle) { + throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice); + } + int[] tmp = new int[1]; + boolean eglSurfaceValid = 0 != surface.getSurfaceHandle(); + if(eglSurfaceValid) { + eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0); + if(!eglSurfaceValid) { + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl eglQuerySuface failed: "+toHexString(EGL.eglGetError())+", "+surface); + } + } + } + if(eglSurfaceValid) { + // surface holds valid EGLSurface if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): using existing EGL config - START"); + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl re-using component's EGLSurface: handle "+toHexString(surface.getSurfaceHandle())); + } + ownEGLSurface=false; + } else { + // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface(); + // However .. let's validate the surface object first + if( ! (surface instanceof ProxySurface) ) { + throw new InternalError("surface not ProxySurface: "+surface.getClass().getName()+", "+surface); } - // just fetch the data .. trust but verify .. - ownEGLDisplay = false; - eglDevice = (EGLGraphicsDevice) aDevice; - if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) { - throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice); + final ProxySurface.UpstreamSurfaceHook upstreamHook = ((ProxySurface)surface).getUpstreamSurfaceHook(); + if( null == upstreamHook ) { + throw new InternalError("null upstreamHook of: "+surface); } - if(aConfig instanceof EGLGraphicsConfiguration) { - eglConfig = (EGLGraphicsConfiguration) aConfig; // done .. - if (null == eglConfig) { - throw new GLException("Null EGLGraphicsConfiguration from "+aConfig); - } - - int[] tmp = new int[1]; - if ( 0 != surface.getSurfaceHandle() && - EGL.eglQuerySurface(eglDevice.getHandle(), surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) { - // surface holds static EGLSurface - eglSurface = surface.getSurfaceHandle(); - if(DEBUG) { - System.err.println(getThreadName() + ": setSurface re-using component's EGLSurface: handle "+toHexString(eglSurface)); - } - ownEGLSurface=false; - } else { - // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface(); - ownEGLSurface=true; - } - } else { - throw new GLException("EGLGraphicsDevice hold by non EGLGraphicsConfiguration: "+aConfig); + if( ! (upstreamHook instanceof EGLUpstreamSurfaceHook) ) { + throw new InternalError("upstreamHook not EGLUpstreamSurfaceHook: Surface: "+surface.getClass().getName()+", "+surface+"; UpstreamHook: "+upstreamHook.getClass().getName()+", "+upstreamHook); } - } else { - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): creating new EGL config - START"); + if( null == ((EGLUpstreamSurfaceHook)upstreamHook).getUpstreamSurface() ) { + throw new InternalError("null upstream surface"); } - // create a new EGL config .. - ownEGLDisplay=true; - // EGLSurface is ours .. ownEGLSurface=true; - - eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); - AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); - final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); - if(aConfig instanceof EGLGraphicsConfiguration) { - final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); - if(0 == capsChosen.getEGLConfig()) { - // 'refresh' the native EGLConfig handle - capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); - if(0 == capsChosen.getEGLConfig()) { - throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig); - } - } - eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); - if(DEBUG) { - System.err.println(getThreadName() + ": Reusing chosenCaps: "+eglConfig); - } - } else { - eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( - capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false); - - if (null == eglConfig) { - throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); - } else if(DEBUG) { - System.err.println(getThreadName() + ": Chosen eglConfig: "+eglConfig); - } + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl owning EGLSurface"); } - // subsequent updateHandle() will issue recreateSurface(); - } - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): END: ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface); } - } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) { + } else if (ownEGLSurface && surface.getSurfaceHandle() != EGL.EGL_NO_SURFACE) { if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(eglSurface)); + System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(surface.getSurfaceHandle())); } // Destroy the window surface - if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) { + if (!EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle())) { throw new GLException("Error destroying window surface (eglDestroySurface)"); } - eglSurface = EGL.EGL_NO_SURFACE; - eglConfig=null; - eglDevice.close(); - eglDevice=null; + ((MutableSurface)surface).setSurfaceHandle(EGL.EGL_NO_SURFACE); } } @Override protected final void swapBuffersImpl() { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - if(!EGL.eglSwapBuffers(eglDevice.getHandle(), eglSurface)) { + if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) { throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this); } } - /** - * Surface not realizes yet (onscreen) .. Quering EGL surface size only makes sense for external drawable. - * Leave it here for later impl. of an EGLExternalDrawable. - public int getWidth() { - int[] tmp = new int[1]; - if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) { - throw new GLException("Error querying surface width, eglError "+toHexString(EGL.eglGetError())); - } - return tmp[0]; - } - - public int getHeight() { - int[] tmp = new int[1]; - if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, tmp, 0)) { - throw new GLException("Error querying surface height, eglError "+toHexString(EGL.eglGetError())); - } - return tmp[0]; - } */ - @Override public GLDynamicLookupHelper getGLDynamicLookupHelper() { if (getGLProfile().usesNativeGLES2()) { @@ -263,10 +196,9 @@ public abstract class EGLDrawable extends GLDrawableImpl { public String toString() { return getClass().getName()+"[realized "+isRealized()+ ",\n\tfactory "+getFactory()+ - ",\n\tdevice "+eglDevice+ ",\n\tsurface "+getNativeSurface()+ - ",\n\teglSurface "+toHexString(eglSurface)+ - ",\n\teglConfig "+eglConfig+ + ",\n\teglSurface "+toHexString(surface.getSurfaceHandle())+ + ",\n\teglConfig "+surface.getGraphicsConfiguration()+ ",\n\trequested "+getRequestedGLCapabilities()+ ",\n\tchosen "+getChosenGLCapabilities()+"]"; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index f4fa1f13f..c848e3e5c 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -46,21 +46,29 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.VisualIDHolder.VIDType; import javax.media.nativewindow.VisualIDHolder; +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import javax.media.opengl.GLProfile.ShutdownType; +import jogamp.opengl.Debug; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; +import jogamp.opengl.GLGraphicsConfigurationUtil; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.os.Platform; @@ -69,6 +77,9 @@ import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public class EGLDrawableFactory extends GLDrawableFactoryImpl { + /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true); + /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true); + private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null; private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null; private static boolean isANGLE = false; @@ -231,7 +242,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { // final EGLContext getContextES1() { return contextES1; } // final EGLContext getContextES2() { return contextES2; } final boolean wasES1ContextAvailable() { return wasES1ContextCreated; } - final boolean wasES2ContextAvailable() { return wasES2ContextCreated; } + final boolean wasES2ContextAvailable() { return wasES2ContextCreated; } } @Override @@ -245,35 +256,98 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper; } - /** - private boolean isEGLContextAvailable(EGLGraphicsDevice sharedDevice, String profile) { - boolean madeCurrent = false; - final GLCapabilities caps = new GLCapabilities(GLProfile.get(profile)); - caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); - caps.setDoubleBuffered(false); - caps.setOnscreen(false); - caps.setPBuffer(true); - final EGLDrawable drawable = (EGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) ); - if(null!=drawable) { + private boolean isEGLContextAvailable(AbstractGraphicsDevice adevice, EGLGraphicsDevice sharedEGLDevice, String profileString) { + if( !GLProfile.isAvailable(adevice, profileString) ) { + return false; + } + final GLProfile glp = GLProfile.get(adevice, profileString) ; + final GLDrawableFactoryImpl desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory(); + EGLGraphicsDevice eglDevice = null; + NativeSurface surface = null; + ProxySurface upstreamSurface = null; // X11, GLX, .. + boolean success = false; + boolean deviceFromUpstreamSurface = false; + try { + final GLCapabilities caps = new GLCapabilities(glp); + caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); + if(adevice instanceof EGLGraphicsDevice || null == desktopFactory || !QUERY_EGL_ES_NATIVE_TK) { + eglDevice = sharedEGLDevice; // reuse + surface = createDummySurfaceImpl(eglDevice, false, caps, null, 64, 64); // egl pbuffer offscreen + upstreamSurface = (ProxySurface)surface; + upstreamSurface.createNotify(); + deviceFromUpstreamSurface = false; + } else { + surface = desktopFactory.createDummySurface(adevice, caps, null, 64, 64); // X11, WGL, .. dummy window + upstreamSurface = ( surface instanceof ProxySurface ) ? (ProxySurface)surface : null ; + if(null != upstreamSurface) { + upstreamSurface.createNotify(); + } + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); + deviceFromUpstreamSurface = true; + } + + final EGLDrawable drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface ); + drawable.setRealized(true); final EGLContext context = (EGLContext) drawable.createContext(null); if (null != context) { - context.setSynchronized(true); try { context.makeCurrent(); // could cause exception - madeCurrent = context.isCurrent(); + success = context.isCurrent(); + if(success) { + final String glVersion = context.getGL().glGetString(GL.GL_VERSION); + if(null == glVersion) { + // Oops .. something is wrong + if(DEBUG) { + System.err.println("EGLDrawableFactory.isEGLContextAvailable: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!"); + } + success = false; + } + } + if(success) { + context.mapCurrentAvailableGLVersion(eglDevice); + if(eglDevice != adevice) { + context.mapCurrentAvailableGLVersion(adevice); + } + } } catch (GLException gle) { if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared: INFO: makeCurrent failed"); + System.err.println("EGLDrawableFactory.createShared: INFO: context create/makeCurrent failed"); gle.printStackTrace(); } } finally { context.destroy(); } } - drawable.destroy(); + drawable.setRealized(false); + } catch (Throwable t) { + if(DEBUG) { + System.err.println("Catched Exception:"); + t.printStackTrace(); + } + success = false; + } finally { + if(eglDevice == sharedEGLDevice) { + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + } else if( deviceFromUpstreamSurface ) { + if(null != eglDevice) { + eglDevice.close(); + } + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + } else { + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + if(null != eglDevice) { + eglDevice.close(); + } + } } - return madeCurrent; - } */ + return success; + } /* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) { if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) { @@ -285,18 +359,41 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { sr = sharedMap.get(connection); } if(null==sr) { - final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, connection, adevice.getUnitID()); + final boolean madeCurrentES1; + final boolean madeCurrentES2; + final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); - // final boolean madeCurrentES1 = isEGLContextAvailable(sharedDevice, GLProfile.GLES1); - // final boolean madeCurrentES2 = isEGLContextAvailable(sharedDevice, GLProfile.GLES2); - final boolean madeCurrentES1 = true; // FIXME - final boolean madeCurrentES2 = true; // FIXME + if(QUERY_EGL_ES) { + madeCurrentES1 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES1); + madeCurrentES2 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES2); + } else { + madeCurrentES1 = true; + madeCurrentES2 = true; + EGLContext.mapStaticGLESVersion(sharedDevice, 1); + if(sharedDevice != adevice) { + EGLContext.mapStaticGLESVersion(adevice, 1); + } + EGLContext.mapStaticGLESVersion(sharedDevice, 2); + if(sharedDevice != adevice) { + EGLContext.mapStaticGLESVersion(adevice, 2); + } + } + + if( !EGLContext.getAvailableGLVersionsSet(adevice) ) { + // Even though we override the non EGL native mapping intentionally, + // avoid exception due to double 'set' - carefull exception of the rule. + EGLContext.setAvailableGLVersionsSet(adevice); + } sr = new SharedResource(sharedDevice, madeCurrentES1, madeCurrentES2); + synchronized(sharedMap) { sharedMap.put(connection, sr); + if(adevice != sharedDevice) { + sharedMap.put(sharedDevice.getConnection(), sr); + } } if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared: device: " + sharedDevice); + System.err.println("EGLDrawableFactory.createShared: devices: queried " + QUERY_EGL_ES + "[nativeTK "+QUERY_EGL_ES_NATIVE_TK+"], " + adevice + ", " + sharedDevice); System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1); System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2); } @@ -367,8 +464,51 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - return new EGLOnscreenDrawable(this, target); + return new EGLOnscreenDrawable(this, getEGLSurface(target)); + } + + protected static NativeSurface getEGLSurface(NativeSurface surface) { + AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); + AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); + if( aDevice instanceof EGLGraphicsDevice && aConfig instanceof EGLGraphicsConfiguration ) { + // already in native EGL format + if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - already in EGL format - use as-is: "+aConfig); + } + return surface; + } + // create EGL instance out of platform native types + final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); + final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); + final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); + final EGLGraphicsConfiguration eglConfig; + if( aConfig instanceof EGLGraphicsConfiguration ) { + // Config is already in EGL type - reuse .. + final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); + if( 0 == capsChosen.getEGLConfig() ) { + // 'refresh' the native EGLConfig handle + capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); + if( 0 == capsChosen.getEGLConfig() ) { + throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig); + } + } + eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); + if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - Reusing chosenCaps: "+eglConfig); + } + } else { + eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false); + + if (null == eglConfig) { + throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); + } else if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - Chosen eglConfig: "+eglConfig); + } + } + return new WrappedSurface(eglConfig, EGL.EGL_NO_SURFACE, surface.getWidth(), surface.getHeight(), new EGLUpstreamSurfaceHook(surface)); } + static String getThreadName() { return Thread.currentThread().getName(); } @Override protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) { @@ -390,22 +530,115 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { - final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; - final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); - WrappedSurface ns = new WrappedSurface(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(device, capsChosen, capsRequested, chooser)); - ns.surfaceSizeChanged(width, height); - return ns; + protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + final EGLGraphicsDevice device; + if(createNewDevice) { + final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; + device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); + } else { + device = (EGLGraphicsDevice) deviceReq; + } + final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); + final EGLGraphicsConfiguration config = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); + if(null == config) { + throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); + } + return new WrappedSurface(config, 0, width, height, lifecycleHook); + } + + @Override + public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { + final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq)); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook); + } + private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() { + @Override + public final void create(ProxySurface s) { + if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if(0 == eglDevice.getHandle()) { + eglDevice.open(); + s.setImplBitfield(ProxySurface.OWN_DEVICE); + } + createPBufferSurfaceImpl(s, false); + if(DEBUG) { + System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); + } + } + } + @Override + public final void destroy(ProxySurface s) { + if( EGL.EGL_NO_SURFACE != s.getSurfaceHandle() ) { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) s.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); + EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle()); + s.setSurfaceHandle(EGL.EGL_NO_SURFACE); + if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) { + eglDevice.close(); + } + if(DEBUG) { + System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); + } + } + } + @Override + public final int getWidth(ProxySurface s) { + return s.initialWidth; + } + @Override + public final int getHeight(ProxySurface s) { + return s.initialHeight; + } + @Override + public String toString() { + return "EGLSurfaceLifecycleHook[]"; + } + + }; + + /** + * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface. + * It will also hold the resulting pbuffer surface handle. + * @param useTexture + * @return the passed {@link MutableSurface} which now has the EGL pbuffer surface set as it's handle + */ + protected static MutableSurface createPBufferSurfaceImpl(MutableSurface ms, boolean useTexture) { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) ms.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final int texFormat; + + if(useTexture) { + texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ; + } else { + texFormat = EGL.EGL_NO_TEXTURE; + } + + if (DEBUG) { + System.out.println("Pbuffer config: " + config); + } + + final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(ms.getWidth(), ms.getHeight(), texFormat); + final long surf = EGL.eglCreatePbufferSurface(eglDevice.getHandle(), config.getNativeConfig(), attrs, 0); + if (EGL.EGL_NO_SURFACE==surf) { + throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+ms.getWidth()+"x"+ms.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } else if(DEBUG) { + System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf)); + } + ms.setSurfaceHandle(surf); + return ms; } @Override - protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { - // FIXME device/windowHandle -> screen ?! - EGLGraphicsDevice device = (EGLGraphicsDevice) adevice; - DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); - EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); - WrappedSurface ns = new WrappedSurface(cfg, windowHandle); - return ns; + protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { + final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; + final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); + final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); + final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); + return new WrappedSurface(cfg, windowHandle, 0, 0, upstream); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 56e7a4d22..214b36493 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -151,7 +151,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple public static EGLGLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config, boolean relaxed, boolean onscreen, boolean usePBuffer, boolean forceTransparentFlag) { ListEGL.eglGetDisplay(nativeDisplayID)
+ * inclusive EGL.eglInitialize(eglDisplayHandle, ..)
call.
+ * @param eglDisplayHandle
+ */
+ public long eglGetAndInitDisplay(long nativeDisplayID);
+
/**
* Implementation should issue an EGL.eglTerminate(eglDisplayHandle)
call.
* @param eglDisplayHandle
@@ -61,28 +68,45 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
*/
public EGLGraphicsDevice(String connection, int unitID) {
super(NativeWindowFactory.TYPE_EGL, connection, unitID);
- this.nativeDisplayID = 0;
- this.eglTerminateCallback = null;
+ this.nativeDisplayID = 0 ; // EGL.EGL_DEFAULT_DISPLAY
+ this.eglLifecycleCallback = null;
}
- public EGLGraphicsDevice(long nativeDisplayID, long eglDisplay, String connection, int unitID, EGLTerminateCallback eglTerminateCallback) {
+ public EGLGraphicsDevice(long nativeDisplayID, long eglDisplay, String connection, int unitID, EGLDisplayLifecycleCallback eglLifecycleCallback) {
super(NativeWindowFactory.TYPE_EGL, connection, unitID, eglDisplay);
this.nativeDisplayID = nativeDisplayID;
- this.eglTerminateCallback = eglTerminateCallback;
+ this.eglLifecycleCallback = eglLifecycleCallback;
}
public long getNativeDisplayID() { return nativeDisplayID; }
+ @Override
public Object clone() {
return super.clone();
}
+
+ @Override
+ public boolean open() {
+ if(null != eglLifecycleCallback && 0 == handle) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.open(): "+this);
+ }
+ handle = eglLifecycleCallback.eglGetAndInitDisplay(nativeDisplayID);
+ if(0 == handle) {
+ throw new NativeWindowException("EGLGraphicsDevice.open() failed: "+this);
+ }
+ return true;
+ }
+ return false;
+ }
+ @Override
public boolean close() {
- if(null != eglTerminateCallback) {
+ if(null != eglLifecycleCallback && 0 != handle) {
if(DEBUG) {
- System.err.println(Thread.currentThread().getName() + " - eglTerminate: "+this);
+ System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.close(): "+this);
}
- eglTerminateCallback.eglTerminate(handle);
+ eglLifecycleCallback.eglTerminate(handle);
}
return super.close();
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
index 735d85fb1..0494bb408 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java
@@ -43,7 +43,6 @@ import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
-import jogamp.common.awt.AWTEDTExecutor;
import jogamp.nativewindow.macosx.OSXUtil;
public class SWTAccessor {
@@ -204,8 +203,6 @@ public class SWTAccessor {
if( null != OS_gtk_class ) {
long widgedHandle = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle);
long displayHandle = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, widgedHandle);
- // FIXME: May think about creating a private non-shared X11 Display handle, like we use to for AWT
- // to avoid locking problems !
return new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, false);
}
if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ) {
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
index a02332413..7a98e3c25 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
@@ -33,7 +33,6 @@
package com.jogamp.nativewindow.x11;
-import jogamp.nativewindow.Debug;
import jogamp.nativewindow.x11.X11Lib;
import jogamp.nativewindow.x11.X11Util;
@@ -46,7 +45,7 @@ import javax.media.nativewindow.ToolkitLock;
*/
public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
- final boolean closeDisplay;
+ final boolean handleOwner;
/** Constructs a new X11GraphicsDevice corresponding to the given connection and default
* {@link javax.media.nativewindow.ToolkitLock} via {@link NativeWindowFactory#getDefaultToolkitLock(String)}.null
.
+ *
+ * The default implementation is a NOP
.
+ *
+ * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
+ * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
+ * issue the native open operation in case handle is null
.
+ *
null
and opening was successful, otherwise false.
+ */
+ public boolean open();
+
/**
- * Optionally closing the device.
+ * Optionally closing the device if handle is not null
.
*
* The default implementation is a NOP
, just setting the handle to null
.
*
+ * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice} + * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice} + * issue the native close operation or skip it depending on the handles's ownership. + *
* - * @return true if the handle was notnull
, otherwise false.
+ * @return true if the handle was not null
and closing was successful, otherwise false.
*/
public boolean close();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
index 187959a67..583fde07f 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
@@ -97,22 +97,27 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
}
}
+ @Override
public final String getType() {
return type;
}
+ @Override
public final String getConnection() {
return connection;
}
+ @Override
public final int getUnitID() {
return unitID;
}
+ @Override
public final String getUniqueID() {
return uniqueID;
}
+ @Override
public final long getHandle() {
return handle;
}
@@ -124,6 +129,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long)
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock)
*/
+ @Override
public final void lock() {
toolkitLock.lock();
}
@@ -135,10 +141,17 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long)
* @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock)
*/
+ @Override
public final void unlock() {
toolkitLock.unlock();
}
+
+ @Override
+ public boolean open() {
+ return false;
+ }
+ @Override
public boolean close() {
if(0 != handle) {
handle = 0;
diff --git a/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java
new file mode 100644
index 000000000..ff53c8109
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.nativewindow;
+
+/**
+ * Provides a {@link NativeSurface} with a mutable surfaceHandle
+ * via {@link #setSurfaceHandle(long)}.
+ *
+ * @see NativeSurface
+ */
+public interface MutableSurface extends NativeSurface {
+
+ /**
+ * Sets the surface handle which is created outside of this implementation.
+ */
+ public void setSurfaceHandle(long surfaceHandle);
+}
+
diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
index 1dabc3dcd..7fc9789c2 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java
@@ -28,38 +28,108 @@
package javax.media.nativewindow;
-
import jogamp.nativewindow.Debug;
import jogamp.nativewindow.SurfaceUpdatedHelper;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
-public abstract class ProxySurface implements NativeSurface {
+public abstract class ProxySurface implements NativeSurface, MutableSurface {
public static final boolean DEBUG = Debug.debug("ProxySurface");
+
+ /**
+ * Implementation specific bitvalue stating the upstream's {@link AbstractGraphicsDevice} is owned by this {@link ProxySurface}.
+ * @see #setImplBitfield(int)
+ * @see #getImplBitfield()
+ */
+ public static final int OWN_DEVICE = 1 << 7;
+
+ /**
+ * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete.
+ * @see #setImplBitfield(int)
+ * @see #getImplBitfield()
+ */
+ public static final int INVISIBLE_WINDOW = 1 << 8;
- private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
- private AbstractGraphicsConfiguration config; // control access due to delegation
- protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
+ /** Interface allowing upstream caller to pass lifecycle actions and size info to a {@link ProxySurface} instance. */
+ public interface UpstreamSurfaceHook {
+ /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */
+ public void create(ProxySurface s);
+ /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */
+ public void destroy(ProxySurface s);
+
+ /** Returns the width of the upstream surface */
+ public int getWidth(ProxySurface s);
+ /** Returns the height of the upstream surface */
+ public int getHeight(ProxySurface s);
+ }
+
+ private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
+ private final AbstractGraphicsConfiguration config; // control access due to delegation
+ private final UpstreamSurfaceHook upstream;
+ public final int initialWidth;
+ public final int initialHeight;
private long surfaceHandle_old;
+ protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
protected long displayHandle;
- protected int height;
protected int scrnIndex;
- protected int width;
+ protected int implBitfield;
- public ProxySurface(AbstractGraphicsConfiguration cfg) {
- invalidate();
- config = cfg;
- displayHandle=cfg.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
- surfaceHandle_old = 0;
+ /**
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param initialWidth the initial width
+ * @param initialHeight the initial height
+ */
+ protected ProxySurface(AbstractGraphicsConfiguration cfg, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) {
+ if(null == cfg) {
+ throw new IllegalArgumentException("null config");
+ }
+ this.config = cfg;
+ this.upstream = upstream;
+ this.initialWidth = initialWidth;
+ this.initialHeight = initialHeight;
+ this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ this.surfaceHandle_old = 0;
+ this.implBitfield = 0;
}
- void invalidate() {
- displayHandle = 0;
- invalidateImpl();
+ public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; }
+
+ /**
+ * If a valid {@link UpstreamSurfaceHook} instance is passed in the
+ * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor},
+ * {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set.
+ */
+ public void createNotify() {
+ if(null != upstream) {
+ upstream.create(this);
+ }
+ this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ this.surfaceHandle_old = 0;
}
- protected abstract void invalidateImpl();
-
+
+ /**
+ * If a valid {@link UpstreamSurfaceHook} instance is passed in the
+ * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor},
+ * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all fields are cleared.
+ */
+ public void destroyNotify() {
+ if(null != upstream) {
+ upstream.destroy(this);
+ invalidateImpl();
+ }
+ this.displayHandle = 0;
+ this.surfaceHandle_old = 0;
+ }
+
+ /**
+ * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed.
+ * @see #destroyNotify()
+ */
+ protected void invalidateImpl() {
+ throw new InternalError("UpstreamSurfaceHook given, but required method not implemented.");
+ }
+
@Override
public final long getDisplayHandle() {
return displayHandle;
@@ -82,19 +152,23 @@ public abstract class ProxySurface implements NativeSurface {
@Override
public abstract long getSurfaceHandle();
+ @Override
+ public abstract void setSurfaceHandle(long surfaceHandle);
+
@Override
public final int getWidth() {
- return width;
+ if(null != upstream) {
+ return upstream.getWidth(this);
+ }
+ return initialWidth;
}
@Override
public final int getHeight() {
- return height;
- }
-
- public void surfaceSizeChanged(int width, int height) {
- this.width = width;
- this.height = height;
+ if(null != upstream) {
+ return upstream.getHeight(this);
+ }
+ return initialHeight;
}
@Override
@@ -187,7 +261,10 @@ public abstract class ProxySurface implements NativeSurface {
public final Thread getSurfaceLockOwner() {
return surfaceLock.getOwner();
}
-
+
@Override
public abstract String toString();
+
+ public int getImplBitfield() { return implBitfield; }
+ public void setImplBitfield(int v) { implBitfield=v; }
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java b/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java
deleted file mode 100644
index 956e68e61..000000000
--- a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package javax.media.nativewindow;
-
-public interface SurfaceChangeable {
-
- /** Sets the surface handle which is created outside of this implementation */
- public void setSurfaceHandle(long surfaceHandle);
-
- /**
- * The surface's size has been determined or changed.
- * Implementation shall update the stored surface size with the given ones.
- */
- public void surfaceSizeChanged(int width, int height);
-
-}
-
diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
index 4877d5c4f..4f68c6945 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java
@@ -34,8 +34,8 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.SurfaceUpdatedListener;
public class SurfaceUpdatedHelper implements SurfaceUpdatedListener {
- private Object surfaceUpdatedListenersLock = new Object();
- private ArrayList+ * Actually the window handle (HWND), since the surfaceHandle (HDC) is derived + * from it at {@link #lockSurface()}. + *
+ */ + @Override + public final void setSurfaceHandle(long surfaceHandle) { + this.windowHandle = surfaceHandle; + } + + /** + * Sets the window handle (HWND). + */ + public final void setWindowHandle(long windowHandle) { + this.windowHandle = windowHandle; + } + + public final long getWindowHandle() { + return windowHandle; } @Override final protected int lockSurfaceImpl() { + if (0 == windowHandle) { + throw new NativeWindowException("null window handle: "+this); + } if (0 != surfaceHandle) { throw new InternalError("surface not released"); } @@ -89,12 +117,15 @@ public class GDISurface extends ProxySurface { @Override final public String toString() { - return "GDISurface[config "+getPrivateGraphicsConfiguration()+ + final UpstreamSurfaceHook ush = getUpstreamSurfaceHook(); + final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil"; + return getClass().getSimpleName()+"[config "+getPrivateGraphicsConfiguration()+ ", displayHandle 0x"+Long.toHexString(getDisplayHandle())+ ", windowHandle 0x"+Long.toHexString(windowHandle)+ ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+ ", size "+getWidth()+"x"+getHeight()+ - ", surfaceLock "+surfaceLock+"]"; + ", surfaceLock "+surfaceLock+ + ", upstreamSurfaceHook "+ush_s+"]"; } } diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index e010fc440..ebfefe345 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -148,37 +148,6 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS return res; } -/* - * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: CreateNSView0 - * Signature: (IIIIZ)J - */ -JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSView0 - (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSRect rect = NSMakeRect(x, y, width, height); - NSView * view = [[NSView alloc] initWithFrame: rect] ; - [view setCanDrawConcurrently: YES]; - [pool release]; - - return (jlong) (intptr_t) view; -} - -/* - * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: DestroyNSView0 - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSView0 - (JNIEnv *env, jclass unused, jlong nsView) -{ - NSView* view = (NSView*) (intptr_t) nsView; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [view release]; - [pool release]; -} - /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: CreateNSWindow0 @@ -222,6 +191,27 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSWindow0 [pool release]; } +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: GetNSView0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSView0 + (JNIEnv *env, jclass unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + + DBG_PRINT( "contentView0 - window: %p (START)\n", win); + + jlong res = (jlong) ((intptr_t) [win contentView]); + + DBG_PRINT( "contentView0 - window: %p (END)\n", win); + + [pool release]; + return res; +} + /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: CreateCALayer0 diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 71e86d520..e8537fec5 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -40,8 +40,20 @@ import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.WindowClosingProtocol; /** - * Specifying the public Window functionality for the - * using a Window and for shadowing one like {@link com.jogamp.newt.opengl.GLWindow}. + * Specifying NEWT's Window functionality: + *+ * One use case is {@link com.jogamp.newt.opengl.GLWindow}, which delegates + * window operation to an instance of this interface while providing OpenGL + * functionality. + *
*/ public interface Window extends NativeWindow, WindowClosingProtocol { public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent"); diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java index 44fcea49c..4db661eeb 100644 --- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java @@ -43,7 +43,7 @@ public class KeyEvent extends InputEvent this.keyChar=keyChar; } - /** Only valid if delivered via {@link KeyListener#keyPressed(KeyEvent)} */ + /** Only valid on all platforms at {@link KeyListener#keyTyped(KeyEvent)} */ public char getKeyChar() { return keyChar; } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index f08fbc8fa..c50ab77c4 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -124,6 +124,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind this.window.setLifecycleHook(new GLLifecycleHook()); } + @Override + public final Object getUpstreamWidget() { + return window; + } + /** * Creates a new GLWindow attaching a new Window referencing a * new default Screen and default Display with the given GLCapabilities. @@ -762,7 +767,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind System.err.println(GlueGenVersion.getInstance()); System.err.println(JoglVersion.getInstance()); - System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString()); + System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString()); final GLProfile glp = GLProfile.getDefault(); final GLCapabilitiesImmutable caps = new GLCapabilities( glp ); diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index 050e24b6c..be543aba9 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -34,15 +34,24 @@ package jogamp.newt; -import javax.media.nativewindow.*; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; -public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { +public class OffscreenWindow extends WindowImpl implements MutableSurface { long surfaceHandle = 0; - + ProxySurface.UpstreamSurfaceHook upstreamHook; + ProxySurface dummySurface; + public OffscreenWindow() { + upstreamHook = null; + dummySurface = null; } static long nextWindowHandle = 0x100; // start here - a marker @@ -52,6 +61,17 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { throw new NativeWindowException("Capabilities is onscreen"); } final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); + /** Cannot use OpenGL here .. + if(capsRequested instanceof GLCapabilitiesImmutable) { + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) capsRequested; + if(caps.isFBO() && GLContext.isFBOAvailable(aScreen.getDevice(), caps.getGLProfile()) ) { + final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(caps); + final ProxySurface dummySurface = factory.createDummySurfaceImpl(aScreen.getDevice(), false, dummyCaps, null, 64, 64); + upstreamHook = dummySurface.getUpstreamSurfaceHook(); + dummySurface.createNotify(); + } + } */ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice()).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, aScreen); if (null == cfg) { @@ -68,13 +88,14 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { // nop } - public void surfaceSizeChanged(int width, int height) { - sizeChanged(false, width, height, false); - } - @Override public synchronized void destroy() { super.destroy(); + if(null != dummySurface) { + dummySurface.destroyNotify(); + dummySurface = null; + upstreamHook = null; + } surfaceHandle = 0; } @@ -84,8 +105,12 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { @Override public long getSurfaceHandle() { + if(null != dummySurface) { + return dummySurface.getSurfaceHandle(); + // return upstreamHook.getWidth(); + } return surfaceHandle; - } + } protected void requestFocusImpl(boolean reparented) { } diff --git a/src/newt/classes/jogamp/newt/driver/android/MD.java b/src/newt/classes/jogamp/newt/driver/android/MD.java index 403eae383..f2f30937b 100644 --- a/src/newt/classes/jogamp/newt/driver/android/MD.java +++ b/src/newt/classes/jogamp/newt/driver/android/MD.java @@ -43,7 +43,7 @@ public class MD { .append(JoglVersion.getInstance()).append(Platform.NEWLINE) .append(Platform.NEWLINE); - JoglVersion.getDefaultOpenGLInfo(sb, true); + JoglVersion.getDefaultOpenGLInfo(null, sb, true); return sb.toString(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index 942994c13..fcca5c843 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -38,7 +38,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; @@ -50,7 +50,7 @@ import jogamp.newt.driver.DriverUpdatePosition; import com.jogamp.newt.event.KeyEvent; -public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverClearFocus, DriverUpdatePosition { +public class MacWindow extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition { static { MacDisplay.initSingleton(); @@ -131,10 +131,6 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl } } - public void surfaceSizeChanged(int width, int height) { - sizeChanged(false, width, height, false); - } - @Override protected void setTitleImpl(final String title) { setTitle0(getWindowHandle(), title); diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index f914467af..b58b99e38 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -972,7 +972,7 @@ static jint mods2JavaMods(NSUInteger mods) NSView* nsview = [self contentView]; if( ! [nsview isMemberOfClass:[NewtView class]] ) { - return; + return NO; } NewtView* view = (NewtView *) nsview; @@ -981,14 +981,14 @@ static jint mods2JavaMods(NSUInteger mods) DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject); if (javaWindowObject == NULL) { DBG_PRINT("windowWillClose: null javaWindowObject\n"); - return; + return NO; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { DBG_PRINT("windowWillClose: null JNIEnv\n"); - return; + return NO; } [view setDestroyNotifySent: true]; // earmark assumption of being closed diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java index a09cc76ac..b22be0a93 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java @@ -194,7 +194,7 @@ public class TestTextRendererNEWT00 extends UITestCase { pw.printf("%s-%03dx%03d-T%04d", objName, drawable.getWidth(), drawable.getHeight(), texSize[0]); final String filename = dir + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java index a3182a30f..6378c1ee3 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java @@ -194,7 +194,7 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), texSize[0], objName); final String filename = dir + tech + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java index d0093ad0c..15daf70cd 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java @@ -180,7 +180,7 @@ public abstract class UIListenerBase01 implements GLEventListener { pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), 0, objName); final String filename = dir + tech + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java new file mode 100644 index 000000000..1a33845b3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java @@ -0,0 +1,272 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLFBODrawableImpl; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.OffscreenAutoDrawable; +import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +public class TestFBODrawableNEWT extends UITestCase { + + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + @Test + public void testGL2ES2_Demo1Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo1MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo2Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(false)); + } + + @Test + public void testGL2ES2_Demo2MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); + } + + @Test + public void testGL2ES2_FBODemoNormal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testEGLES2_Demo0Normal() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + @Test + public void testEGLES2_Demo0MSAA4() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + boolean skipShot = false; + + void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + caps.setFBO(true); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLDrawable fboDrawable = factory.createOffscreenDrawable(null, caps, null, widthStep*szStep, heightStep*szStep); + Assert.assertNotNull(fboDrawable); + Assert.assertTrue("Not an FBO Drawable", fboDrawable instanceof GLFBODrawableImpl); + + fboDrawable.setRealized(true); + Assert.assertTrue(fboDrawable.isRealized()); + + final FBObject fbo = ((GLFBODrawableImpl)fboDrawable).getFBObject(); + + System.out.println("Realized: "+fboDrawable); + System.out.println("Realized: "+fboDrawable.getChosenGLCapabilities()); + System.out.println("Realized: "+fbo); + + final GLContext context = fboDrawable.createContext(null); + Assert.assertNotNull(context); + + int res = context.makeCurrent(); + Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); + context.release(); + + System.out.println("Post Create-Ctx: "+fbo); + final FBObject.Colorbuffer colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(colorA); + final FBObject.RenderAttachment depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(depthA); + + final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, null); + + glad.addGLEventListener(demo); + glad.addGLEventListener(new GLEventListener() { + volatile int displayCount=0; + volatile int reshapeCount=0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + // System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": step "+szStep+" "+drawable.getWidth()+"x"+drawable.getHeight()); + // System.err.println(Thread.currentThread().getName()+": ** FBO-THIS: "+fbo); + // System.err.println(Thread.currentThread().getName()+": ** FBO-SINK: "+fbo.getSamplingSinkFBO()); + // System.err.println(Thread.currentThread().getName()+": ** drawable-read: "+gl.getDefaultReadFramebuffer()); + if(skipShot) { + skipShot=false; + } else { + snapshot(getSimpleTestName("."), displayCount, "msaa"+fbo.getNumSamples(), gl, screenshot, TextureIO.PNG, null); + } + Assert.assertEquals(drawable.getWidth(), widthStep*szStep); + Assert.assertEquals(drawable.getHeight(), heightStep*szStep); + displayCount++; + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": step "+szStep+" "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight()); + Assert.assertEquals(drawable.getWidth(), widthStep*szStep); + Assert.assertEquals(drawable.getHeight(), heightStep*szStep); + reshapeCount++; + } + }); + + // 0 - szStep = 2 + glad.display(); + + // 1, 2 (resize + display) + szStep = 1; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + { + // Check whether the attachment reference are still valid! + FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + Assert.assertTrue(colorA.equals(_colorA)); + FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(_depthA); + Assert.assertTrue(depthA == _depthA); + Assert.assertTrue(depthA.equals(_depthA)); + + _colorA = fbo.getColorbuffer(colorA); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + Assert.assertTrue(colorA.equals(_colorA)); + } + + // 3, 4 (resize + display) + szStep = 4; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + { + // Check whether the attachment reference are still valid! + FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + final FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(_depthA); + Assert.assertTrue(depthA == _depthA); + + _colorA = fbo.getColorbuffer(colorA); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + } + + // 5 + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + + // 6, 7 (resize + display) + szStep = 3; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + + glad.destroy(); + System.out.println("Fin: "+fboDrawable); + + // final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(fboDrawable, context); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestFBODrawableNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java new file mode 100644 index 000000000..f7c83a03b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java @@ -0,0 +1,266 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.acore; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.FBObject.Attachment.Type; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NEWTGLContext; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import java.io.IOException; + +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLPipelineFactory; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLUniformData; + +import org.junit.Assert; +import org.junit.Test; + +public class TestFBOMRTNEWT01 extends UITestCase { + static long durationPerTest = 10*40*2; // ms + + @Test + public void test01() throws InterruptedException { + final int step = 4; + final int width = 800; + final int height = 600; + // preset .. + if(!GLProfile.isAvailable(GLProfile.GL2GL3)) { + System.err.println("Test requires GL2/GL3 profile."); + return; + } + final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow( + new GLCapabilities(GLProfile.getGL2GL3()), width/step, height/step, true); + final GLDrawable drawable = winctx.context.getGLDrawable(); + GL2GL3 gl = winctx.context.getGL().getGL2GL3(); + gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2GL3(); + System.err.println(winctx.context); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + // test code .. + final ShaderState st = new ShaderState(); + // st.setVerbose(true); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-1", false); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-1", false); + final ShaderProgram sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + Assert.assertTrue(0<=sp0.program()); + Assert.assertTrue(!sp0.inUse()); + Assert.assertTrue(!sp0.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.attachShaderProgram(gl, sp0, false); + + final ShaderCode vp1 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-2", false); + final ShaderCode fp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-2", false); + final ShaderProgram sp1 = new ShaderProgram(); + sp1.add(gl, vp1, System.err); + sp1.add(gl, fp1, System.err); + Assert.assertTrue(0<=sp1.program()); + Assert.assertTrue(!sp1.inUse()); + Assert.assertTrue(!sp1.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.attachShaderProgram(gl, sp1, true); + + final PMVMatrix pmvMatrix = new PMVMatrix(); + final GLUniformData pmvMatrixUniform = new GLUniformData("gcu_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("gca_Vertices", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 0, vertices0); + vertices0.putf(0); vertices0.putf(1); vertices0.putf(0); + vertices0.putf(1); vertices0.putf(1); vertices0.putf(0); + vertices0.putf(0); vertices0.putf(0); vertices0.putf(0); + vertices0.putf(1); vertices0.putf(0); vertices0.putf(0); + vertices0.seal(gl, true); + st.ownAttribute(vertices0, true); + vertices0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLArrayDataServer colors0 = GLArrayDataServer.createGLSL("gca_Colors", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 1, colors0); + colors0.putf(1); colors0.putf(0); colors0.putf(1); colors0.putf(1); + colors0.putf(0); colors0.putf(0); colors0.putf(1); colors0.putf(1); + colors0.putf(0); colors0.putf(0); colors0.putf(0); colors0.putf(1); + colors0.putf(0); colors0.putf(1); colors0.putf(1); colors0.putf(1); + colors0.seal(gl, true); + st.ownAttribute(colors0, true); + colors0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLUniformData texUnit0 = new GLUniformData("gcs_TexUnit0", 0); + st.ownUniform(texUnit0); + st.uniform(gl, texUnit0); + final GLUniformData texUnit1 = new GLUniformData("gcs_TexUnit1", 1); + st.ownUniform(texUnit1); + st.uniform(gl, texUnit1); + + final GLArrayDataServer texCoords0 = GLArrayDataServer.createGLSL("gca_TexCoords", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 2, texCoords0); + texCoords0.putf(0f); texCoords0.putf(1f); + texCoords0.putf(1f); texCoords0.putf(1f); + texCoords0.putf(0f); texCoords0.putf(0f); + texCoords0.putf(1f); texCoords0.putf(0f); + texCoords0.seal(gl, true); + st.ownAttribute(texCoords0, true); + texCoords0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final int texA0Point = 0; // attachment point for texA0 + final int texA1Point = 1; // attachment point for texA1 + + // FBO w/ 2 texture2D color buffers + final FBObject fbo_mrt = new FBObject(); + fbo_mrt.reset(gl, drawable.getWidth(), drawable.getHeight()); + final TextureAttachment texA0 = fbo_mrt.attachTexture2D(gl, texA0Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + final TextureAttachment texA1 = fbo_mrt.attachTexture2D(gl, texA1Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + fbo_mrt.attachRenderbuffer(gl, Type.DEPTH, 24); + Assert.assertTrue( fbo_mrt.isStatusValid() ) ; + fbo_mrt.unbind(gl); + + // misc GL setup + gl.glClearColor(1, 1, 1, 1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // reshape + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(0f, 1f, 0f, 1f, -10f, 10f); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + st.uniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final int[] two_buffers = new int[] { GL.GL_COLOR_ATTACHMENT0+texA0Point, GL.GL_COLOR_ATTACHMENT0+texA1Point }; + final int[] bck_buffers = new int[] { GL2GL3.GL_BACK_LEFT }; + + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + int step_i = 0; + int[] last_snap_size = new int[] { 0, 0 }; + + for(int i=0; i+ * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0004-0800x0600.png + * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0005-0800x0600.png + *+ * + * @param simpleTestName will be used as the filename prefix + * @param sn sequential number + * @param postSNDetail optional detail to be added to the filename after
sn
+ * @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename.
+ * @param readBufferUtil the {@link GLReadBufferUtil} to be used to read the pixels for the screenshot.
+ * @param fileSuffix Optional file suffix without a dot defining the file type, i.e. "png"
.
+ * If null
the "png"
as defined in {@link TextureIO#PNG} is being used.
+ * @param destPath Optional platform dependent file path. It shall use {@link File#separatorChar} as is directory separator.
+ * It shall not end with a directory separator, {@link File#separatorChar}.
+ * If null
the current working directory is being used.
+ */
+ public static void snapshot(String simpleTestName, int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) {
+ if(null == fileSuffix) {
+ fileSuffix = TextureIO.PNG;
+ }
+ final StringWriter filenameSW = new StringWriter();
+ {
+ final GLDrawable drawable = gl.getContext().getGLReadDrawable();
+ final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
+ final String F_pfmt = readBufferUtil.hasAlpha() ? "rgba" : "rgb_";
+ final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_";
+ final String aaext = caps.getSampleExtension();
+ final int samples = caps.getNumSamples() ;
+ postSNDetail = null != postSNDetail ? "-"+postSNDetail : "";
+ final PrintWriter pw = new PrintWriter(filenameSW);
+ pw.printf("%s-n%04d%s-F_%s-I_%s-S%d_%s-%s-%04dx%04d.%s",
+ simpleTestName, sn, postSNDetail, F_pfmt, pfmt, samples, aaext, drawable.getGLProfile().getName(),
+ drawable.getWidth(), drawable.getHeight(), fileSuffix);
+ }
+ final String filename = null != destPath ? destPath + File.separator + filenameSW.toString() : filenameSW.toString();
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename);
+ gl.glFinish(); // just make sure rendering finished ..
+ if(readBufferUtil.readPixels(gl, false)) {
+ readBufferUtil.write(new File(filename));
+ }
+ }
}
--
cgit v1.2.3
From 7bb5885fc3a904f49e22f0c8cbf747d9b189a7ba Mon Sep 17 00:00:00 2001
From: Sven Gothel Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used instead.
+ * */ public class GLCanvas extends Canvas implements GLAutoDrawable { + private static final boolean DEBUG = Debug.debug("GLCanvas"); /* * Flag for whether the SWT thread should be used for OpenGL calls when in single-threaded mode. This is controlled @@ -87,18 +92,20 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { /* GL Stuff */ private final RecursiveLock lock = LockFactory.createRecursiveLock(); private final GLDrawableHelper helper = new GLDrawableHelper(); + + private final GLContext shareWith; + private final GLCapabilitiesImmutable capsRequested; + private final GLCapabilitiesChooser capsChooser; + private volatile GLDrawable drawable; // volatile: avoid locking for read-only access private GLContext context; /* Native window surface */ private AbstractGraphicsDevice device; - private final long nativeWindowHandle; - private final ProxySurface proxySurface; /* Construction parameters stored for GLAutoDrawable accessor methods */ private int additionalCtxCreationFlags = 0; - private final GLCapabilitiesImmutable glCapsRequested; /* Flag indicating whether an unprocessed reshape is pending. */ private volatile boolean sendReshape; // volatile: maybe written by WindowManager thread w/o locking @@ -218,6 +225,37 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { */ private volatile Rectangle clientArea; + /** + * Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser, GLContext)} + * on the SWT thread. + * + * @param parent + * Required (non-null) parent Composite. + * @param style + * Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the + * Canvas constructor, so OpenGL handles the background. + * @param caps + * Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the + * graphics device determined by the parent Composite are used. Note that the GLCapabilities that are + * actually used may differ based on the capabilities of the graphics device. + * @param chooser + * Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the + * requested GLCapabilities, and the available capabilities of the graphics device. + * @param shareWith + * Optional GLContext to share state (textures, vbos, shaders, etc.) with. + * @return a new instance + */ + public static GLCanvas create(final Composite parent, final int style, final GLCapabilitiesImmutable caps, + final GLCapabilitiesChooser chooser, final GLContext shareWith) { + final GLCanvas[] res = new GLCanvas[] { null }; + parent.getDisplay().syncExec(new Runnable() { + public void run() { + res[0] = new GLCanvas( parent, style, caps, chooser, shareWith ); + } + }); + return res[0]; + } + /** * Creates a new SWT GLCanvas. * @@ -250,35 +288,26 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */ device = SWTAccessor.getDevice(this); - /* Since we have no means of querying the screen index yet, assume 0. Good choice due to Xinerama alike settings anyways. */ - final int screenIdx = 0; - /* Native handle for the control, used to associate with GLContext */ - nativeWindowHandle = SWTAccessor.getWindowHandle(this); /* Select default GLCapabilities if none was provided, otherwise clone provided caps to ensure safety */ if(null == caps) { caps = new GLCapabilities(GLProfile.getDefault(device)); } - glCapsRequested = caps; - - final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile()); - - /* Create a NativeWindow proxy for the SWT canvas */ - proxySurface = glFactory.createProxySurface(device, screenIdx, nativeWindowHandle, caps, chooser, swtCanvasUpStreamHook); - - /* Associate a GL surface with the proxy */ - drawable = glFactory.createGLDrawable(proxySurface); - drawable.setRealized(true); - - context = drawable.createContext(shareWith); - + this.capsRequested = caps; + this.capsChooser = chooser; + this.shareWith = shareWith; + + // post create .. when ready + drawable = null; + context = null; + /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */ /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */ addPaintListener(new PaintListener() { @Override public void paintControl(final PaintEvent arg0) { - if (!helper.isExternalAnimatorAnimating()) { - display(); + if ( !helper.isExternalAnimatorAnimating() ) { + display(); // checks: null != drawable } } }); @@ -291,39 +320,93 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { }); } private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() { - @Override - public final void create(ProxySurface s) { /* nop */ } - - @Override - public final void destroy(ProxySurface s) { /* nop */ } - - @Override - public final int getWidth(ProxySurface s) { - return clientArea.width; - } - - @Override - public final int getHeight(ProxySurface s) { - return clientArea.height; - } - - @Override - public String toString() { - return "SETUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+"]"; - } - + @Override + public final void create(ProxySurface s) { /* nop */ } + + @Override + public final void destroy(ProxySurface s) { /* nop */ } + + @Override + public final int getWidth(ProxySurface s) { + return clientArea.width; + } + + @Override + public final int getHeight(ProxySurface s) { + return clientArea.height; + } + + @Override + public String toString() { + return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientArea.width+"x"+clientArea.height+"]"; + } }; protected final void updateSizeCheck() { - clientArea = GLCanvas.this.getClientArea(); - if (clientArea != null && - proxySurface.getWidth() != clientArea.width && - proxySurface.getHeight() != clientArea.height) { + final Rectangle oClientArea = clientArea; + final Rectangle nClientArea = GLCanvas.this.getClientArea(); + if ( nClientArea != null && + ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height ) + ) { + clientArea = nClientArea; // write back new value sendReshape = true; // Mark for OpenGL reshape next time the control is painted } - sendReshape = false; + } + + @Override + public void display() { + if( null != drawable || validateDrawableAndContext() ) { + runInGLThread(makeCurrentAndDisplayOnEDTAction); + } } + + /** assumes drawable == null ! */ + protected final boolean validateDrawableAndContext() { + if( GLCanvas.this.isDisposed() ) { + return false; + } + final Rectangle nClientArea = clientArea; + if(0 == nClientArea.width * nClientArea.height) { + return false; + } + + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile()); + + /* Native handle for the control, used to associate with GLContext */ + final long nativeWindowHandle = SWTAccessor.getWindowHandle(this); + + /* Create a NativeWindow proxy for the SWT canvas */ + ProxySurface proxySurface = null; + try { + proxySurface = glFactory.createProxySurface(device, 0 /* screenIdx */, nativeWindowHandle, + capsRequested, capsChooser, swtCanvasUpStreamHook); + } catch (GLException gle) { + // not ready yet .. + if(DEBUG) { System.err.println(gle.getMessage()); } + } + + if(null != proxySurface) { + /* Associate a GL surface with the proxy */ + drawable = glFactory.createGLDrawable(proxySurface); + drawable.setRealized(true); + + context = drawable.createContext(shareWith); + } + } finally { + _lock.unlock(); + } + final boolean res = null != drawable; + if(DEBUG && res) { + System.err.println("SWT GLCanvas realized! "+this+", "+drawable); + Thread.dumpStack(); + } + return res; + } + @Override public final Object getUpstreamWidget() { return this; @@ -362,11 +445,6 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { dispose(); } - @Override - public void display() { - runInGLThread(makeCurrentAndDisplayOnEDTAction); - } - @Override public GLAnimatorControl getAnimator() { return helper.getAnimator(); @@ -379,7 +457,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLContext getContext() { - return context; + return null != drawable ? context : null; } @Override @@ -472,7 +550,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLCapabilitiesImmutable getChosenGLCapabilities() { - return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getChosenCapabilities(); + final GLDrawable _drawable = drawable; + return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getChosenGLCapabilities() : null; } /** @@ -481,7 +560,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { * @return Non-null GLCapabilities. */ public GLCapabilitiesImmutable getRequestedGLCapabilities() { - return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getRequestedCapabilities(); + final GLDrawable _drawable = drawable; + return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities() : null; } @Override @@ -492,7 +572,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { @Override public GLProfile getGLProfile() { - return glCapsRequested.getGLProfile(); + return capsRequested.getGLProfile(); } @Override @@ -523,10 +603,9 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { runInGLThread(makeCurrentAndSwapBuffersOnEDTAction); } - // FIXME: API of update() method ? @Override public void update() { - // FIXME: display(); ? + // don't paint background etc .. nop avoids flickering } @Override @@ -551,7 +630,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { * @see Platform#AWT_AVAILABLE * @see Platform#getOSType() */ - private void runInGLThread(final Runnable action) { + private static void runInGLThread(final Runnable action) { if(Platform.OSType.MACOS == Platform.OS_TYPE) { SWTAccessor.invoke(true, action); } else { diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index e730bc62e..bf6a0ee6e 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -338,7 +338,6 @@ public abstract class GLContextImpl extends GLContext { if (TRACE_SWITCH) { System.err.println(getThreadName() + ": GLContextImpl.destroy.X: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) + ", isShared "+GLContextShareSet.isShared(this)+" - "+lock); - Thread.dumpStack(); // JAU } } } finally { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java index 0494bb408..ba07d97dc 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java @@ -34,16 +34,21 @@ import java.lang.reflect.Method; import org.eclipse.swt.graphics.GCData; import org.eclipse.swt.widgets.Control; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowFactory; +import javax.media.nativewindow.VisualIDHolder; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsDevice; +import com.jogamp.nativewindow.x11.X11GraphicsScreen; import jogamp.nativewindow.macosx.OSXUtil; +import jogamp.nativewindow.x11.X11Lib; public class SWTAccessor { static final Field swt_control_handle; @@ -213,6 +218,26 @@ public class SWTAccessor { } throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); } + public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) { + if( null != OS_gtk_class ) { + return new X11GraphicsScreen((X11GraphicsDevice)device, screen); + } + if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) || + NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) { + return new DefaultGraphicsScreen(device, screen); + } + throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); + } + public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) { + if( null != OS_gtk_class ) { + return X11Lib.GetVisualIDFromWindow(device.getHandle(), windowHandle); + } + if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) || + NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false) ) { + return VisualIDHolder.VID_UNDEFINED; + } + throw new UnsupportedOperationException("n/a for this windowing system: "+NativeWindowFactory.getNativeWindowType(false)); + } public static long getWindowHandle(Control swtControl) { long handle = getHandle(swtControl); diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java index b85ad47f2..6faa9890c 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java @@ -561,4 +561,21 @@ public abstract class NativeWindowFactory { } return null; } + + /** + * Returns true if the given visualID is valid for further processing, i.e. OpenGL usage, + * otherwise return false. + *+ * On certain platforms, i.e. X11, a valid visualID is required at window creation. + * Other platforms may determine it later on, e.g. OSX and Windows.
+ *+ * If the visualID is {@link VisualIDHolder#VID_UNDEFINED} and the platform requires it + * at creation time (see above), it is not valid for further processing. + *
+ */ + public static boolean isNativeVisualIDValidForProcessing(int visualID) { + return NativeWindowFactory.TYPE_X11 != NativeWindowFactory.getNativeWindowType(false) || + VisualIDHolder.VID_UNDEFINED != visualID ; + } + } diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index 4767dff18..894084fce 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -28,6 +28,7 @@ package jogamp.nativewindow.macosx; import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; import jogamp.nativewindow.Debug; @@ -63,8 +64,37 @@ public class OSXUtil { return isNSView0(object); } - public static Point GetLocationOnScreen(long windowOrView, int src_x, int src_y) { - return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); + /** + * In case thewindowOrView
is top-level,
+ * you shall set topLevel
to true where
+ * insets gets into account to compute the client position as follows:
+ * + if(topLevel) { + // top-level position -> client window position + final Insets insets = GetInsets(windowOrView); + los.setX(los.getX() + insets.getLeftWidth()); + los.setY(los.getY() + insets.getTopHeight()); + } + *+ * @param windowOrView + * @param topLevel + * @param src_x + * @param src_y + * @return the client position + */ + public static Point GetLocationOnScreen(long windowOrView, boolean topLevel, int src_x, int src_y) { + final Point los = (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); + if(topLevel) { + // top-level position -> client window position + final Insets insets = GetInsets(windowOrView); + los.setX(los.getX() + insets.getLeftWidth()); + los.setY(los.getY() + insets.getTopHeight()); + } + return los; + } + + public static Insets GetInsets(long windowOrView) { + return (Insets) GetInsets0(windowOrView); } public static long CreateNSWindow(int x, int y, int width, int height) { @@ -135,6 +165,7 @@ public class OSXUtil { private static native boolean initIDs0(); private static native boolean isNSView0(long object); private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); + private static native Object GetInsets0(long windowOrView); private static native long CreateNSWindow0(int x, int y, int width, int height); private static native void DestroyNSWindow0(long nsWindow); private static native long GetNSView0(long nsWindow); diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index 37fa4c88f..2c853a43d 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -52,12 +52,18 @@ static const char * const ClazzNameRunnable = "java/lang/Runnable"; static jmethodID runnableRunID = NULL; -static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point"; static const char * const ClazzAnyCstrName = "
+ * If newEDTUtil
is null
,
+ * the device's default EDTUtil is created and used.
+ *
+ * If a previous one exists and it differs from the new one, + * it's being stopped, wait-until-idle and reset to allow restart. + *
+ *
+ * If newEDTUtil
is not null and equals the previous one,
+ * null
is returned and no change is being made.
+ *
+ * A previously detached newChild
will be released to top-level status
+ * and made invisible.
+ *
+ * Note: When switching NEWT child's, detaching the previous first via setNEWTChild(null)
+ * produced much cleaner visual results.
+ *
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation + * via {@link Display#setEDTUtil(EDTUtil)}. + *
+ * + * @param parent the SWT composite + * @param style additional styles to SWT#NO_BACKGROUND + * @param child optional preassigned {@link #Window}, maybe null + * @return a new instance + */ + public static NewtCanvasSWT create(final Composite parent, final int style, final Window child) { + final NewtCanvasSWT[] res = new NewtCanvasSWT[] { null }; + parent.getDisplay().syncExec( new Runnable() { + public void run() { + res[0] = new NewtCanvasSWT( parent, style, child); + } + }); + return res[0]; + } + + /** + * Instantiates a NewtCanvas with a NEWT child. + * + *+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation + * via {@link Display#setEDTUtil(EDTUtil)}. + *
+ * + * @param parent the SWT composite + * @param style additional styles to SWT#NO_BACKGROUND + * @param child optional preassigned {@link #Window}, maybe null + */ + public NewtCanvasSWT(final Composite parent, final int style, Window child) { + super(parent, style | SWT.NO_BACKGROUND); + + swtEDTUtil = new SWTEDTUtil(parent.getDisplay()); + + SWTAccessor.setRealized(this, true); + + clientArea = getClientArea(); + + final AbstractGraphicsDevice device = SWTAccessor.getDevice(this); + screen = SWTAccessor.getScreen(device, 0); + nativeWindow = null; + + if(null != child) { + setNEWTChild(child); + } + + /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */ + /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */ + addPaintListener(new PaintListener() { + @Override + public void paintControl(final PaintEvent arg0) { + if( null != nativeWindow || validateNative() ) { + if( null !=newtChild ) { + newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height); + } + } + } + }); + + addControlListener(new ControlAdapter() { + @Override + public void controlResized(final ControlEvent arg0) { + updateSizeCheck(); + } + }); + } + + /** assumes nativeWindow == null ! */ + protected final boolean validateNative() { + if( isDisposed() ) { + return false; + } + updateSizeCheck(); + final Rectangle nClientArea = clientArea; + if(0 == nClientArea.width * nClientArea.height) { + return false; + } + + /* Native handle for the control, used to associate with GLContext */ + final long nativeWindowHandle = SWTAccessor.getWindowHandle(this); + final int visualID = SWTAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle); + final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID); + if(DEBUG) { + System.err.println("NewtCanvasSWT.validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", valid "+visualIDValid); + } + if( visualIDValid ) { + /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite). + * Note: SWT is owner of the native handle, hence no closing operation will be a NOP. */ + final CapabilitiesImmutable caps = new Capabilities(); + final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.getDevice(), caps); + final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration( caps, caps, null, screen, visualID ); + if(DEBUG) { + System.err.println("NewtCanvasSWT.validateNative() factory: "+factory+", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", chosen config: "+config); + // Thread.dumpStack(); + } + if (null == config) { + throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); + } + + nativeWindow = new SWTNativeWindow(config, nativeWindowHandle); + reparentWindow( true ); + } + + return null != nativeWindow; + } + + protected final void updateSizeCheck() { + final Rectangle oClientArea = clientArea; + final Rectangle nClientArea = getClientArea(); + if ( nClientArea != null && + ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height ) + ) { + clientArea = nClientArea; // write back new value + if( null != newtChild ) { + newtChild.setSize(clientArea.width, clientArea.height); + } + } + } + + @Override + public void update() { + // don't paint background etc .. nop avoids flickering + } + + /** + * Destroys this resource: + *destroy()
on the NEWT Child
+ * A previously detached newChild
will be released to top-level status
+ * and made invisible.
+ *
+ * Note: When switching NEWT child's, detaching the previous first via setNEWTChild(null)
+ * produced much cleaner visual results.
+ *
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an SWT conform implementation + * via {@link Display#setEDTUtil(EDTUtil)}. + *
+ * @return the previous attached newt child. + */ + public Window setNEWTChild(final Window newChild) { + final Window prevChild = newtChild; + if(DEBUG) { + System.err.println("NewtCanvasSWT.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild)); + } + // remove old one + if(null != newtChild) { + reparentWindow( false ); + newtChild = null; + } + // add new one, reparent only if ready + newtChild = newChild; + if(null != nativeWindow && null != newChild) { + reparentWindow( true ); + } + return prevChild; + } + + /** @return the current NEWT child */ + public Window getNEWTChild() { + return newtChild; + } + + @Override + public boolean setParent(Composite parent) { + return super.setParent(parent); + } + + /* package */ void configureNewtChild(boolean attach) { + + if( null != newtChild ) { + newtChild.setKeyboardFocusHandler(null); + if(attach) { + newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE); + } else { + newtChild.setFocusAction(null); + newtChild.setDefaultCloseOperation(newtChildCloseOp); + } + } + } + + void reparentWindow(boolean add) { + if( null == newtChild ) { + return; // nop + } + if(DEBUG) { + System.err.println("NewtCanvasSWT.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()); + } + + newtChild.setFocusAction(null); // no AWT focus traversal .. + if(add) { + updateSizeCheck(); + final int w = clientArea.width; + final int h = clientArea.height; + + newtChild.getScreen().getDisplay().setEDTUtil(swtEDTUtil); + + newtChild.setSize(w, h); + newtChild.reparentWindow(nativeWindow); + newtChild.setVisible(true); + configureNewtChild(true); + newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener + + // force this SWT Canvas to be focus-able, + // since this it is completely covered by the newtChild (z-order). + setEnabled(true); + } else { + configureNewtChild(false); + newtChild.setVisible(false); + newtChild.reparentWindow(null); + } + if(DEBUG) { + System.err.println("NewtCanvasSWT.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()); + } + } + + private final void requestFocusNEWTChild() { + if( null != newtChild ) { + newtChild.setFocusAction(null); + newtChild.requestFocus(); + } + } + + @Override + public boolean forceFocus() { + final boolean res = NewtCanvasSWT.super.forceFocus(); + requestFocusNEWTChild(); + return res; + } + + private class SWTNativeWindow implements NativeWindow { + private final AbstractGraphicsConfiguration config; + private final long nativeWindowHandle; + private final InsetsImmutable insets; // only required to allow proper client position calculation on OSX + + public SWTNativeWindow(AbstractGraphicsConfiguration config, long nativeWindowHandle) { + this.config = config; + this.nativeWindowHandle = nativeWindowHandle; + if(isOSX) { + this.insets = OSXUtil.GetInsets(nativeWindowHandle); + } else { + this.insets = new Insets(0, 0, 0, 0); + } + } + + @Override + public int lockSurface() throws NativeWindowException, RuntimeException { + return NativeSurface.LOCK_SUCCESS; + } + + @Override + public void unlockSurface() { } + + @Override + public boolean isSurfaceLockedByOtherThread() { + return false; + } + + @Override + public Thread getSurfaceLockOwner() { + return null; + } + + @Override + public boolean surfaceSwap() { + return false; + } + + @Override + public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { } + + @Override + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException { + } + + @Override + public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { } + + @Override + public long getSurfaceHandle() { + return 0; + } + + @Override + public int getWidth() { + return clientArea.width; + } + + @Override + public int getHeight() { + return clientArea.height; + } + + @Override + public AbstractGraphicsConfiguration getGraphicsConfiguration() { + return config; + } + + @Override + public long getDisplayHandle() { + return config.getScreen().getDevice().getHandle(); + } + + @Override + public int getScreenIndex() { + return config.getScreen().getIndex(); + } + + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { } + + @Override + public void destroy() { } + + @Override + public NativeWindow getParent() { + return null; + } + + @Override + public long getWindowHandle() { + return nativeWindowHandle; + } + + @Override + public InsetsImmutable getInsets() { + return insets; + } + + @Override + public int getX() { + return 0; + } + + @Override + public int getY() { + return 0; + } + + @Override + public Point getLocationOnScreen(Point point) { + if( isOSX ) { + final Point los = OSXUtil.GetLocationOnScreen(nativeWindowHandle, false, 0, 0); + // top-level position -> client window position + los.setX(los.getX() + insets.getLeftWidth()); + los.setY(los.getY() + insets.getTopHeight()); + if(null!=point) { + return point.translate(los); + } else { + return los; + } + } else { + // client position on 'normal' windowing systems is 0/0 + if(null == point) { + point = new Point(0, 0); + } + return point; + } + } + + @Override + public boolean hasFocus() { + return isFocusControl(); + } + }; + + static String newtWinHandleToHexString(Window w) { + return null != w ? toHexString(w.getWindowHandle()) : "nil"; + } + static String toHexString(long l) { + return "0x"+Long.toHexString(l); + } +} + diff --git a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java new file mode 100644 index 000000000..3538caad2 --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java @@ -0,0 +1,99 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.newt.swt; + +import org.eclipse.swt.widgets.Display; + +import com.jogamp.newt.util.EDTUtil; + +/** + * Simple {@link EDTUtil} implementation utilizing the SWT UI thread + * of the given {@link Display}. + */ +public class SWTEDTUtil implements EDTUtil { + private final Display swtDisplay; + + public SWTEDTUtil(Display swtDisplay) { + this.swtDisplay = swtDisplay; + } + + public final Display getDisplay() { + return swtDisplay; + } + + @Override + public long getPollPeriod() { + return 0; + } + + @Override + public void setPollPeriod(long ms) { + } + + @Override + public void reset() { + } + + @Override + public void start() { + } + + @Override + public boolean isCurrentThreadEDT() { + return swtDisplay.getThread() == Thread.currentThread(); + } + + @Override + public boolean isRunning() { + return true; + } + + @Override + public void invokeStop(Runnable finalTask) { + swtDisplay.syncExec(finalTask); + } + + @Override + public void invoke(boolean wait, Runnable task) { + if(wait) { + swtDisplay.syncExec(task); + } else { + swtDisplay.asyncExec(task); + } + } + + @Override + public void waitUntilIdle() { + // all sync .. + } + + @Override + public void waitUntilStopped() { + // all sync .. + } +} diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index b10561c5b..b178bb5d3 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -101,7 +101,9 @@ public abstract class DisplayImpl extends Display { display.hashCode = display.fqname.hashCode(); displayList.add(display); } - display.createEDTUtil(); + if(null == display.edtUtil) { + display.setEDTUtil(null); // device's default if EDT is used, or null + } if(DEBUG) { System.err.println("Display.create() NEW: "+display+" "+getThreadName()); } @@ -168,15 +170,45 @@ public abstract class DisplayImpl extends Display { return true; } - protected void createEDTUtil() { + protected EDTUtil createEDTUtil() { + final EDTUtil def; if(NewtFactory.useEDT()) { - edtUtil = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable); + def = new DefaultEDTUtil(Thread.currentThread().getThreadGroup(), "Display-"+getFQName(), dispatchMessagesRunnable); if(DEBUG) { - System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName()); + System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); } + } else { + def = null; } + return def; } + @Override + public EDTUtil setEDTUtil(EDTUtil newEDTUtil) { + if(null == newEDTUtil) { + newEDTUtil = createEDTUtil(); + } + if( newEDTUtil == edtUtil ) { + if(DEBUG) { + System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!"); + } + return null; // no change + } + final EDTUtil oldEDTUtil = edtUtil; + if(DEBUG) { + System.err.println("Display.setEDTUtil: "+oldEDTUtil+" -> "+newEDTUtil); + } + if(null != oldEDTUtil) { + stopEDT( new Runnable() { public void run() {} } ); + // ready for restart .. + oldEDTUtil.waitUntilStopped(); + oldEDTUtil.reset(); + } + edtUtil = newEDTUtil; + return oldEDTUtil; + } + + @Override public final EDTUtil getEDTUtil() { return edtUtil; } diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index b12e42680..606101ade 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -445,9 +445,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer protected abstract void closeNativeImpl(); /** - * The native implementation must invoke {@link #focusChanged(boolean, boolean)} - * to change the focus state, ifforce == false
.
- * This may happen asynchronous within {@link #TIMEOUT_NATIVEWINDOW}.
+ * Async request which shall be performed within {@link #TIMEOUT_NATIVEWINDOW}.
+ *
+ * If if force == false
the native implementation
+ * may only request focus if not yet owner.
+ * {@link #focusChanged(boolean, boolean)} should be called + * to notify about the focus traversal. + *
* * @param force if true, bypass {@link #focusChanged(boolean, boolean)} and force focus request */ diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java index ce8ed7c49..747e2368e 100644 --- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java +++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java @@ -34,6 +34,7 @@ import javax.media.nativewindow.NativeWindow; import jogamp.newt.driver.DriverUpdatePosition; +import com.jogamp.newt.Window; import com.jogamp.newt.event.awt.AWTAdapter; import com.jogamp.newt.event.awt.AWTWindowAdapter; @@ -92,19 +93,20 @@ public class AWTParentWindowAdapter if(DEBUG_IMPLEMENTATION) { System.err.println("AWT: componentResized: "+comp); } - getNewtWindow().runOnEDTIfAvail(false, new Runnable() { + final Window newtWindow = getNewtWindow(); + newtWindow.runOnEDTIfAvail(false, new Runnable() { public void run() { int cw = comp.getWidth(); int ch = comp.getHeight(); if( 0 < cw * ch ) { - if( getNewtWindow().getWidth() != cw || getNewtWindow().getHeight() != ch ) { - getNewtWindow().setSize(cw, ch); - if(comp.isVisible() != getNewtWindow().isVisible()) { - getNewtWindow().setVisible(comp.isVisible()); + if( newtWindow.getWidth() != cw || newtWindow.getHeight() != ch ) { + newtWindow.setSize(cw, ch); + if(comp.isVisible() != newtWindow.isVisible()) { + newtWindow.setVisible(comp.isVisible()); } } - } else if(getNewtWindow().isVisible()) { - getNewtWindow().setVisible(false); + } else if(newtWindow.isVisible()) { + newtWindow.setVisible(false); } }}); } @@ -113,8 +115,9 @@ public class AWTParentWindowAdapter if(DEBUG_IMPLEMENTATION) { System.err.println("AWT: componentMoved: "+e); } - if(getNewtWindow().getDelegatedWindow() instanceof DriverUpdatePosition) { - ((DriverUpdatePosition)getNewtWindow().getDelegatedWindow()).updatePosition(); + final Window newtWindow = getNewtWindow(); + if(newtWindow.getDelegatedWindow() instanceof DriverUpdatePosition) { + ((DriverUpdatePosition)newtWindow.getDelegatedWindow()).updatePosition(); } } diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java index 166da5c1c..65f8b4715 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTDisplay.java @@ -36,6 +36,7 @@ package jogamp.newt.driver.awt; import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.util.EDTUtil; import jogamp.newt.DisplayImpl; @@ -54,13 +55,17 @@ public class AWTDisplay extends DisplayImpl { protected void closeNativeImpl() { } @Override - protected void createEDTUtil() { + protected EDTUtil createEDTUtil() { + final EDTUtil def; if(NewtFactory.useEDT()) { - edtUtil = AWTEDTUtil.getSingleton(); + def = AWTEDTUtil.getSingleton(); if(DEBUG) { - System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+edtUtil.getClass().getName()); + System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); } + } else { + def = null; } + return def; } protected void dispatchMessagesNative() { /* nop */ } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index 720d4ee4c..27d7a1679 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -150,7 +150,7 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear System.err.println("MacWindow: clearFocus() - requestFocusParent, isOffscreenInstance "+isOffscreenInstance); } if(!isOffscreenInstance) { - requestFocusParent0(getWindowHandle()); + resignFocus0(getWindowHandle()); } else { focusChanged(false, false); } @@ -360,7 +360,6 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear if(recreate && 0==surfaceHandle) { throw new NativeWindowException("Internal Error - recreate, window but no view"); } - orderOut0(getWindowHandle()); close0(getWindowHandle()); setWindowHandle(0); } else { @@ -397,7 +396,7 @@ public class MacWindow extends WindowImpl implements MutableSurface, DriverClear private native boolean lockSurface0(long window); private native void unlockSurface0(long window); private native void requestFocus0(long window, boolean force); - private native void requestFocusParent0(long window); + private native void resignFocus0(long window); /** in case of a child window, it actually only issues orderBack(..) */ private native void orderOut0(long window); private native void orderFront0(long window); diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java index 34d76a148..6a8c81f3d 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java @@ -151,8 +151,8 @@ public class WindowsWindow extends WindowImpl { } protected void closeNativeImpl() { - if (hdc != 0) { - if(windowHandleClose != 0) { + if(windowHandleClose != 0) { + if (hdc != 0) { try { GDI.ReleaseDC(windowHandleClose, hdc); } catch (Throwable t) { @@ -162,11 +162,8 @@ public class WindowsWindow extends WindowImpl { } } } - hdc = 0; - hdc_old = 0; - } - if(windowHandleClose != 0) { try { + GDI.SetParent(windowHandleClose, 0); // detach first, experience hang w/ SWT parent GDI.DestroyWindow(windowHandleClose); } catch (Throwable t) { if(DEBUG_IMPLEMENTATION) { @@ -177,6 +174,8 @@ public class WindowsWindow extends WindowImpl { windowHandleClose = 0; } } + hdc = 0; + hdc_old = 0; } protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 01cbd80ec..bbadc9dd0 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -599,6 +599,15 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0 } DBG_PRINT( "createWindow0 - is visible.1: %d\n", [myWindow isVisible]); + // Remove animations for child windows + if(NULL != parentWindow) { +NS_DURING + // Available >= 10.7 - Removes default animations + [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; +NS_HANDLER +NS_ENDHANDLER + } + #ifdef VERBOSE_ON int dbgIdx = 1; #endif @@ -734,7 +743,7 @@ NS_ENDHANDLER if(NULL!=pWin) { [mWin detachFromParent: pWin]; } - [mWin orderOut: mWin]; + [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; DBG_PRINT( "windowClose.1 - %p,%d view %p,%d, parent %p\n", mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin); @@ -742,11 +751,6 @@ NS_ENDHANDLER // Only release window, if release is not yet in process. // E.g. destroyNotifySent:=true set by NewtMacWindow::windowWillClose(), i.e. window-close was clicked. if(!destroyNotifySent) { - // '[mWin close]' causes a crash at exit. - // This probably happens b/c it sends events to the main loop - // but our resources are gone ?! - // However, issuing a simple release seems to work quite well. - // [mWin release]; [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO]; } @@ -806,11 +810,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus); [mWin makeFirstResponder: nil]; - [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; - [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderFrontRegardless]; - // [mWin makeKeyWindow]; + [mWin performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO]; + [mWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO]; DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force); @@ -819,26 +820,27 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocus0 /* * Class: jogamp_newt_driver_macosx_MacWindow - * Method: requestFocusParent0 + * Method: resignFocus0 * Signature: (J)V */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_requestFocusParent0 +JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_resignFocus0 (JNIEnv *env, jobject window, jlong w) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* mWin = (NSWindow*) ((intptr_t) w); NSWindow* pWin = [mWin parentWindow]; -#ifdef VERBOSE_ON BOOL hasFocus = [mWin isKeyWindow]; -#endif - DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); - if(NULL != pWin) { - [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [pWin makeKeyWindow]; + DBG_PRINT( "requestFocusParent0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus ); + if( hasFocus ) { + if(NULL != pWin) { + // [mWin performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:pWin waitUntilDone:NO]; + [pWin performSelectorOnMainThread:@selector(makeKeyWindow) withObject:nil waitUntilDone:NO]; + } else { + [mWin performSelectorOnMainThread:@selector(resignKeyWindow) withObject:nil waitUntilDone:NO]; + } } - DBG_PRINT( "requestFocusParent0 - window: %p, parent: %p (END)\n", mWin, pWin); + DBG_PRINT( "requestFocusParent0 - window: %p (END)\n", mWin); [pool release]; } @@ -856,9 +858,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderFront0 DBG_PRINT( "orderFront0 - window: %p (START)\n", win); - [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [win orderFrontRegardless]; + [win performSelectorOnMainThread:@selector(orderFrontRegardless) withObject:nil waitUntilDone:NO]; DBG_PRINT( "orderFront0 - window: %p (END)\n", win); @@ -880,13 +880,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_orderOut0 DBG_PRINT( "orderOut0 - window: (parent %p) %p (START)\n", pWin, mWin); if(NULL == pWin) { - [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderOut: mWin]; + [mWin performSelectorOnMainThread:@selector(orderOut:) withObject:mWin waitUntilDone:NO]; } else { - [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:YES]; - // This will occasionally cause a free of non allocated object crash: - // [mWin orderBack: mWin]; + [mWin performSelectorOnMainThread:@selector(orderBack:) withObject:mWin waitUntilDone:NO]; } DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java new file mode 100644 index 000000000..6a27e6f27 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/swt/TestNewtCanvasSWTGLn.java @@ -0,0 +1,233 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.swt; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.After; +import org.junit.Test; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +/** + * Tests that a basic SWT app can open without crashing under different GL profiles + * _and_ custom GLCapabilities. + *
+ * Uses JOGL's NewtCanvasSWT, which allows to be a native container of a NEWT Window.
+ * This method allows utilizing custom GLCapability settings,
+ * independent from the already instantiated SWT visual.
+ *
+ * Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/ + * SWT running on Mac OSX, i.e. to enforce UI action on the main thread. + *
+ */ +public class TestNewtCanvasSWTGLn extends UITestCase { + + static int duration = 250; + + static final int iwidth = 640; + static final int iheight = 480; + + Display display = null; + Shell shell = null; + Composite composite = null; + + @BeforeClass + public static void startup() { + System.out.println( "GLProfile " + GLProfile.glAvailabilityToString() ); + } + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite = new Composite( shell, SWT.NONE ); + composite.setLayout( new FillLayout() ); + Assert.assertNotNull( composite ); + }}); + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite ); + try { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + composite.dispose(); + shell.dispose(); + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + display = null; + shell = null; + composite = null; + } + + protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo, + boolean postAttach, boolean useAnimator ) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + + final GLWindow glWindow1 = GLWindow.create(caps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + glWindow1.addGLEventListener(demo); + glWindow1.addGLEventListener(new GLEventListener() { + int displayCount = 0; + public void init(final GLAutoDrawable drawable) { } + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } + public void display(final GLAutoDrawable drawable) { + if(displayCount < 3) { + snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + } + public void dispose(final GLAutoDrawable drawable) { } + }); + + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite, 0, postAttach ? null : glWindow1 ); + Assert.assertNotNull( canvas1 ); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } + }); + + if(postAttach) { + canvas1.setNEWTChild(glWindow1); + } + + // canvas1.update(); + + Animator anim; + if(useAnimator) { + anim = new Animator(glWindow1); + anim.start(); + } else { + anim = null; + } + + long lStartTime = System.currentTimeMillis(); + long lEndTime = lStartTime + duration; + try { + while( (System.currentTimeMillis() < lEndTime) && !canvas1.isDisposed() ) { + if( !display.readAndDispatch() ) { + // blocks on linux .. display.sleep(); + Thread.sleep(10); + } + } + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + if(null != anim) { + anim.stop(); + } + + canvas1.dispose(); + } + + @Test + public void preAttach_WithAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, true /* animator */); + } + + @Test + public void preAttach_NoAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), false /* postAttach */, false /* animator */); + } + + @Test + public void postAttach_WithAnimator() throws InterruptedException { + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2(), true /* postAttach */, true /* animator */); + } + + @Test + public void test_MultisampleAndAlpha() throws InterruptedException { + GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); + caps.setSampleBuffers(true); + caps.setNumSamples(2); + runTestAGL( caps, new MultisampleDemoES2(true), false /* postAttach */, false /* animator */); + } + + static int atoi(String a) { + int i=0; + try { + i = Integer.parseInt(a); + } catch (Exception ex) { ex.printStackTrace(); } + return i; + } + + public static void main(String args[]) { + for(int i=0; i+ * Note: To employ custom GLCapabilities, NewtCanvasSWT shall be used. + *
+ ** Note that {@link SWTAccessor#invoke(boolean, Runnable)} is still used to comply w/ * SWT running on Mac OSX, i.e. to enforce UI action on the main thread. *
@@ -116,34 +121,32 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase { composite = null; } - protected void runTestAGL( GLProfile glprofile ) throws InterruptedException { - // need SWT.NO_BACKGROUND to prevent SWT from clearing the window - // at the wrong times (we use glClear for this instead) - final GLCapabilitiesImmutable caps = new GLCapabilities( glprofile ); + protected void runTestAGL( GLCapabilitiesImmutable caps, GLEventListener demo ) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); - final GLCanvas canvas = new GLCanvas( composite, 0, caps, null, null); + final GLCanvas canvas = GLCanvas.create( composite, 0, caps, null, null); Assert.assertNotNull( canvas ); + canvas.addGLEventListener( demo ); canvas.addGLEventListener(new GLEventListener() { - public void init(final GLAutoDrawable drawable) { - System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - init()"); - } - public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { - System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - reshape()"); - OneTriangle.setup( drawable.getGL().getGL2(), width, height ); - } + int displayCount = 0; + public void init(final GLAutoDrawable drawable) { } + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { } public void display(final GLAutoDrawable drawable) { - OneTriangle.render( drawable.getGL().getGL2(), drawable.getWidth(), drawable.getHeight()); + if(displayCount < 3) { + snapshot(getSimpleTestName("."), displayCount++, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } } - public void dispose(final GLAutoDrawable drawable) { - System.err.println(Thread.currentThread().getName()+" - SWT Canvas - GLEventListener - dispose()"); - } - }); + public void dispose(final GLAutoDrawable drawable) { } + }); - shell.setText( getClass().getName() ); - shell.setSize( 640, 480 ); - shell.open(); - + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } } ); + long lStartTime = System.currentTimeMillis(); long lEndTime = lStartTime + duration; try { @@ -157,13 +160,15 @@ public class TestSWTJOGLGLCanvas01GLn extends UITestCase { throwable.printStackTrace(); Assume.assumeNoException( throwable ); } - canvas.dispose(); + SWTAccessor.invoke(true, new Runnable() { + public void run() { + canvas.dispose(); + } } ); } @Test public void test() throws InterruptedException { - GLProfile glprofile = GLProfile.getGL2ES1(); - runTestAGL( glprofile ); + runTestAGL( new GLCapabilities(GLProfile.getGL2ES2()), new GearsES2() ); } static int atoi(String a) { diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java new file mode 100644 index 000000000..11aef7c24 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParenting01aSWT.java @@ -0,0 +1,210 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.newt.parenting; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.nativewindow.swt.SWTAccessor; +import com.jogamp.newt.Window; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.newt.swt.NewtCanvasSWT; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Simple visibility test .. + */ +public class TestParenting01aSWT extends UITestCase { + static int width, height; + static long durationPerTest = 800; + static GLCapabilities glCaps; + + Display display = null; + Shell shell = null; + Composite composite1 = null; + + @BeforeClass + public static void initClass() { + width = 640; + height = 480; + glCaps = new GLCapabilities(null); + } + + @Before + public void init() { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + display = new Display(); + Assert.assertNotNull( display ); + shell = new Shell( display ); + Assert.assertNotNull( shell ); + shell.setLayout( new FillLayout() ); + composite1 = new Composite( shell, SWT.NONE ); + composite1.setLayout( new FillLayout() ); + Assert.assertNotNull( composite1 ); + }}); + } + + @After + public void release() { + Assert.assertNotNull( display ); + Assert.assertNotNull( shell ); + Assert.assertNotNull( composite1 ); + try { + SWTAccessor.invoke(true, new Runnable() { + public void run() { + composite1.dispose(); + shell.dispose(); + display.dispose(); + }}); + } + catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + display = null; + shell = null; + composite1 = null; + } + + @Test + public void testWindowParenting01CreateVisibleDestroy1() throws InterruptedException, InvocationTargetException { + + GLWindow glWindow1 = GLWindow.create(glCaps); + Assert.assertNotNull(glWindow1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); + GLEventListener demo1 = new RedSquareES2(); + setDemoFields(demo1, glWindow1, false); + glWindow1.addGLEventListener(demo1); + + final NewtCanvasSWT canvas1 = NewtCanvasSWT.create( composite1, 0, glWindow1 ); + Assert.assertNotNull(canvas1); + Assert.assertEquals(false, glWindow1.isVisible()); + Assert.assertEquals(false, glWindow1.isNativeValid()); + Assert.assertNull(glWindow1.getParent()); + + SWTAccessor.invoke(true, new Runnable() { + public void run() { + shell.setText( getSimpleTestName(".") ); + shell.setSize( 640, 480 ); + shell.open(); + } + }); + + // visible test + Assert.assertEquals(canvas1.getNativeWindow(),glWindow1.getParent()); + + for(int i=0; i*10true
if basic FBO support is available, otherwise false
.
- *
- * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
- * ARB_ES2_compatibility
, ARB_framebuffer_object
, EXT_framebuffer_object
or OES_framebuffer_object
.
- *
- * Basic FBO support may only include one color attachment and no multisampling, - * as well as limited internal formats for renderbuffer. - *
- * @see GLContext#hasFBO() - */ - public static final boolean supportsBasicFBO(GL gl) { - return gl.getContext().hasFBO(); - } - - /** - * Returnstrue
if full FBO support is available, otherwise false
.
- *
- * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
- * ARB_framebuffer_object
, or all of
- * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
- * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
- *
- * Full FBO support includes multiple color attachments and multisampling. - *
+ * Marker interface, denotes a color buffer attachment. + *Always an instance of {@link Attachment}.
+ *Either an instance of {@link ColorAttachment} or {@link TextureAttachment}.
*/
- public static final boolean supportsFullFBO(GL gl) {
- return !forceMinimumFBOSupport &&
- ( gl.isGL3() || // GL >= 3.0
- gl.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object
-
- ( gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object*
- gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) &&
- gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) &&
- gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil)
- )
- ) ;
- }
-
- public static final int getMaxSamples(GL gl) {
- if( supportsFullFBO(gl) ) {
- int[] val = new int[] { 0 } ;
- gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
- return val[0];
- } else {
- return 0;
- }
+ public static interface Colorbuffer {
+ /**
+ * Initializes the color buffer and set it's parameter, if uninitialized, i.e. name is zero
.
+ * @return true
if newly initialized, otherwise false
.
+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case.
+ */
+ public boolean initialize(GL gl) throws GLException;
+
+ /**
+ * Releases the color buffer if initialized, i.e. name is not zero
.
+ * @throws GLException if buffer release fails.
+ */
+ public void free(GL gl) throws GLException;
+
+ /**
+ * Writes the internal format to the given GLCapabilities object.
+ * @param caps the destination for format bits
+ * @param rgba8Avail whether rgba8 is available
+ */
+ public void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail);
}
/** Common super class of all attachments */
@@ -155,21 +134,89 @@ public class FBObject {
private int name;
- /** true
if resource is initialized by {@link #initialize(GL)}, hence {@link #free(GL)} is allowed to free the GL resources. */
- protected boolean resourceOwner;
-
- private int initCounter;
-
protected Attachment(Type type, int iFormat, int width, int height, int name) {
this.type = type;
this.format = iFormat;
this.width = width;
this.height = height;
this.name = name;
- this.resourceOwner = false;
- this.initCounter = 0;
}
+ /**
+ * Writes the internal format to the given GLCapabilities object.
+ * @param caps the destination for format bits
+ * @param rgba8Avail whether rgba8 is available
+ */
+ public final void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail) {
+ final int _format;
+ switch(format) {
+ case GL.GL_RGBA:
+ _format = rgba8Avail ? GL.GL_RGBA8 : GL.GL_RGBA4;
+ break;
+ case GL.GL_RGB:
+ _format = rgba8Avail ? GL.GL_RGB8 : GL.GL_RGB565;
+ break;
+ default:
+ _format = format;
+ }
+ switch(_format) {
+ case GL.GL_RGBA4:
+ caps.setRedBits(4);
+ caps.setGreenBits(4);
+ caps.setBlueBits(4);
+ caps.setAlphaBits(4);
+ break;
+ case GL.GL_RGB5_A1:
+ caps.setRedBits(5);
+ caps.setGreenBits(5);
+ caps.setBlueBits(5);
+ caps.setAlphaBits(1);
+ break;
+ case GL.GL_RGB565:
+ caps.setRedBits(5);
+ caps.setGreenBits(6);
+ caps.setBlueBits(5);
+ caps.setAlphaBits(0);
+ break;
+ case GL.GL_RGB8:
+ caps.setRedBits(8);
+ caps.setGreenBits(8);
+ caps.setBlueBits(8);
+ caps.setAlphaBits(0);
+ break;
+ case GL.GL_RGBA8:
+ caps.setRedBits(8);
+ caps.setGreenBits(8);
+ caps.setBlueBits(8);
+ caps.setAlphaBits(8);
+ break;
+ case GL.GL_DEPTH_COMPONENT16:
+ caps.setDepthBits(16);
+ break;
+ case GL.GL_DEPTH_COMPONENT24:
+ caps.setDepthBits(24);
+ break;
+ case GL.GL_DEPTH_COMPONENT32:
+ caps.setDepthBits(32);
+ break;
+ case GL.GL_STENCIL_INDEX1:
+ caps.setStencilBits(1);
+ break;
+ case GL.GL_STENCIL_INDEX4:
+ caps.setStencilBits(4);
+ break;
+ case GL.GL_STENCIL_INDEX8:
+ caps.setStencilBits(8);
+ break;
+ case GL.GL_DEPTH24_STENCIL8:
+ caps.setDepthBits(24);
+ caps.setStencilBits(8);
+ break;
+ default:
+ throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format));
+ }
+ }
+
/** width of attachment */
public final int getWidth() { return width; }
/** height of attachment */
@@ -180,45 +227,31 @@ public class FBObject {
public final int getName() { return name; }
/* pp */ final void setName(int n) { name = n; }
- public final int getInitCounter() { return initCounter; }
-
/**
- * Initializes the attachment buffer and set it's parameter, if uninitialized, i.e. name is zero
.
- *
Implementation employs an initialization counter, hence it can be paired recursively with {@link #free(GL)}.
- * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. - */ - public void initialize(GL gl) throws GLException { - initCounter++; - /* - super.initialize(gl); - if(1 == getInitCounter() && 0 == getName() ) { + * Initializes the attachment and set it's parameter, if uninitialized, i.e. name iszero
.
+ * + final boolean init = 0 == name; + if( init ) { do init .. - freeResources = true; // if all OK } - */ - } + return init; + *+ * @return
true
if newly initialized, otherwise false
.
+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case.
+ */
+ public abstract boolean initialize(GL gl) throws GLException;
/**
- * Releases the attachment buffer if initialized, i.e. name is zero
.
- * Implementation employs an initialization counter, hence it can be paired recursively with {@link #initialize(GL)}.
- * @throws GLException if buffer release fails. - */ - public void free(GL gl) throws GLException { - /* - if(1 == getInitCounter() && freeResources && .. ) { + * Releases the attachment if initialized, i.e. name is notzero
.
+ * + if(0 != name) { do free .. - } - super.free(gl); - */ - initCounter--; - if(0 == initCounter) { - resourceOwner = false; name = 0; } - if(DEBUG) { - System.err.println("Attachment.free: "+this); - } - } + *+ * @throws GLException if buffer release fails. + */ + public abstract void free(GL gl) throws GLException; /** *
@@ -232,9 +265,9 @@ public class FBObject { if( ! ( o instanceof Attachment ) ) return false; final Attachment a = (Attachment)o; return type == a.type && - format == a.format || - width == a.width || - height== a.height || + format == a.format && + width == a.width && + height== a.height && name == a.name ; } @@ -259,8 +292,7 @@ public class FBObject { public String toString() { return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", "+width+"x"+height+ - ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+ - ", resOwner "+resourceOwner+", initCount "+initCounter+"]"; + ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+"]"; } public static Type getType(int attachmentPoint, int maxColorAttachments) { @@ -277,7 +309,7 @@ public class FBObject { } } } - + /** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */ public static class RenderAttachment extends Attachment { private int samples; @@ -339,14 +371,13 @@ public class FBObject { } @Override - public void initialize(GL gl) throws GLException { - super.initialize(gl); - if( 1 == getInitCounter() && 0 == getName() ) { + public boolean initialize(GL gl) throws GLException { + final boolean init = 0 == getName(); + if( init ) { + int glerr = checkPreGLError(gl); + final int[] name = new int[] { -1 }; gl.glGenRenderbuffers(1, name, 0); - if( 0 == name[0] ) { - throw new GLException("null renderbuffer, "+this); - } setName(name[0]); gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName()); @@ -355,43 +386,37 @@ public class FBObject { } else { gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight()); } - int glerr = gl.glGetError(); + glerr = gl.glGetError(); if(GL.GL_NO_ERROR != glerr) { gl.glDeleteRenderbuffers(1, name, 0); setName(0); throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); } - resourceOwner = true; if(DEBUG) { System.err.println("Attachment.init: "+this); } } + return init; } @Override public void free(GL gl) { - if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { - final int[] name = new int[] { getName() }; + final int[] name = new int[] { getName() }; + if( 0 != name[0] ) { gl.glDeleteRenderbuffers(1, name, 0); + setName(0); + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } } - super.free(gl); } public String toString() { return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+ - ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+ - ", resOwner "+resourceOwner+", initCount "+getInitCounter()+"]"; + ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+"]"; } } - /** - * Marker interface, denotes a color buffer attachment. - *
Always an instance of {@link Attachment}.
- *Either an instance of {@link ColorAttachment} or {@link TextureAttachment}. - */ - public static interface Colorbuffer { - } - /** Color render buffer attachment */ public static class ColorAttachment extends RenderAttachment implements Colorbuffer { public ColorAttachment(int iFormat, int samples, int width, int height, int name) { @@ -444,9 +469,11 @@ public class FBObject { * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case. */ @Override - public void initialize(GL gl) throws GLException { - super.initialize(gl); - if( 1 == getInitCounter() && 0 == getName() ) { + public boolean initialize(GL gl) throws GLException { + final boolean init = 0 == getName(); + if( init ) { + int glerr = checkPreGLError(gl); + final int[] name = new int[] { -1 }; gl.glGenTextures(1, name, 0); if(0 == name[0]) { @@ -468,31 +495,111 @@ public class FBObject { if( 0 < wrapT ) { gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); } - int glerr = gl.glGetError(); + glerr = gl.glGetError(); if(GL.GL_NO_ERROR != glerr) { gl.glDeleteTextures(1, name, 0); setName(0); throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); } - resourceOwner = true; - } - if(DEBUG) { - System.err.println("Attachment.init: "+this); + if(DEBUG) { + System.err.println("Attachment.init: "+this); + } } + return init; } @Override public void free(GL gl) { - if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { - final int[] name = new int[] { getName() }; + final int[] name = new int[] { getName() }; + if( 0 != name[0] ) { gl.glDeleteTextures(1, name, 0); + setName(0); + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } } - super.free(gl); + } + } + + /** + * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}, + * selecting the texture data type and format automatically. + * + *
Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.
+ * + * @param glp the chosen {@link GLProfile} + * @param alpha set totrue
if you request alpha channel, otherwise false
;
+ * @param width texture width
+ * @param height texture height
+ * @return the created and uninitialized color {@link TextureAttachment}
+ */
+ public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height) {
+ return createColorTextureAttachment(glp, alpha, width, height, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ }
+
+ /**
+ * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE},
+ * selecting the texture data type and format automatically.
+ *
+ * @param glp the chosen {@link GLProfile}
+ * @param alpha set to true
if you request alpha channel, otherwise false
;
+ * @param width texture width
+ * @param height texture height
+ * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
+ * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
+ * @return the created and uninitialized color {@link TextureAttachment}
+ */
+ public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height,
+ int magFilter, int minFilter, int wrapS, int wrapT) {
+ final int textureInternalFormat, textureDataFormat, textureDataType;
+ if(glp.isGLES()) {
+ textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB;
+ textureDataType = GL.GL_UNSIGNED_BYTE;
+ } else {
+ textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8;
+ textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB;
+ textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE;
+ }
+ return createColorTextureAttachment(textureInternalFormat, width, height, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT);
+ }
+
+ /**
+ * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}.
+ *
+ * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param width texture width
+ * @param height texture height
+ * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)}
+ * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER}
+ * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER}
+ * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S}
+ * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T}
+ * @return the created and uninitialized color {@link TextureAttachment}
+ */
+ public static final TextureAttachment createColorTextureAttachment(int internalFormat, int width, int height, int dataFormat, int dataType,
+ int magFilter, int minFilter, int wrapS, int wrapT) {
+ return new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType,
+ magFilter, minFilter, wrapS, wrapT, 0 /* name */);
+ }
+
+ private static boolean hasAlpha(int format) {
+ switch(format) {
+ case GL.GL_RGBA8:
+ case GL.GL_RGBA4:
+ case GL.GL_RGBA:
+ case GL.GL_BGRA:
+ case 4:
+ return true;
+ default:
+ return false;
}
}
private boolean initialized;
- private boolean basicFBOSupport;
private boolean fullFBOSupport;
private boolean rgba8Avail;
private boolean depth24Avail;
@@ -523,6 +630,9 @@ public class FBObject {
//
private final void validateColorAttachmentPointRange(int point) {
+ if(!initialized) {
+ throw new GLException("FBO not initialized");
+ }
if(maxColorAttachments != colorAttachmentPoints.length) {
throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints);
}
@@ -621,7 +731,6 @@ public class FBObject {
this.initialized = false;
// TBD @ init
- this.basicFBOSupport = false;
this.fullFBOSupport = false;
this.rgba8Avail = false;
this.depth24Avail = false;
@@ -657,14 +766,11 @@ public class FBObject {
private void init(GL gl, int width, int height, int samples) throws GLException {
if(initialized) {
throw new GLException("FBO already initialized");
- }
- fullFBOSupport = supportsFullFBO(gl);
-
- if( !fullFBOSupport && !supportsBasicFBO(gl) ) {
+ }
+ if( !gl.hasBasicFBOSupport() ) {
throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this);
}
-
- basicFBOSupport = true;
+ fullFBOSupport = gl.hasFullFBOSupport();
rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8);
depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24);
@@ -680,10 +786,7 @@ public class FBObject {
int val[] = new int[1];
- int glerr = gl.glGetError();
- if(DEBUG && GL.GL_NO_ERROR != glerr) {
- System.err.println("FBObject.init-preexisting.0 GL Error 0x"+Integer.toHexString(glerr));
- }
+ int glerr = checkPreGLError(gl);
int realMaxColorAttachments = 1;
maxColorAttachments = 1;
@@ -703,16 +806,7 @@ public class FBObject {
colorAttachmentPoints = new Colorbuffer[maxColorAttachments];
colorAttachmentCount = 0;
- maxSamples = 0;
- if(fullFBOSupport) {
- gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
- glerr = gl.glGetError();
- if(GL.GL_NO_ERROR == glerr) {
- maxSamples = val[0];
- } else if(DEBUG) {
- System.err.println("FBObject.init-GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
- }
- }
+ maxSamples = gl.getMaxRenderbufferSamples();
if(!forceMinimumFBOSupport) {
gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0);
maxTextureSize = val[0];
@@ -733,10 +827,9 @@ public class FBObject {
this.samples = samples <= maxSamples ? samples : maxSamples;
if(DEBUG) {
- System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+samples+" samples");
- System.err.println("basicFBOSupport: "+basicFBOSupport);
+ System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+this.samples+" samples");
System.err.println("fullFBOSupport: "+fullFBOSupport);
- System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments);
+ System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments+" [capped/real]");
System.err.println("maxSamples: "+maxSamples);
System.err.println("maxTextureSize: "+maxTextureSize);
System.err.println("maxRenderbufferSize: "+maxRenderbufferSize);
@@ -761,12 +854,8 @@ public class FBObject {
throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]");
}
- if(null != samplesSink) {
- // init sampling sink
- samplesSink.reset(gl, width, height);
- resetMSAATexture2DSink(gl);
- }
-
+ resetMSAATexture2DSink(gl);
+
// generate fbo ..
gl.glGenFramebuffers(1, val, 0);
fbName = val[0];
@@ -780,7 +869,8 @@ public class FBObject {
if(!gl.glIsFramebuffer(fbName)) {
checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException
}
- bound = true;
+ bound = true;
+ samplesSinkDirty = true;
initialized = true;
updateStatus(gl);
@@ -797,7 +887,7 @@ public class FBObject {
* to match the new given parameters.
*
* - * Currently incompatibility and hence recreation is given if + * Incompatibility and hence recreation is forced if * the size or sample count doesn't match for subsequent calls. *
* @@ -820,17 +910,17 @@ public class FBObject { * to match the new given parameters. * *- * Currently incompatibility and hence recreation is given if - * the size or sample count doesn't match for subsequent calls. + * Currently incompatibility and hence recreation of the attachments will be performed + * if the size or sample count doesn't match for subsequent calls. *
* *Leaves the FBO bound state untouched
* * @param gl the current GL context - * @param newWidth - * @param newHeight + * @param newWidth the new width, it's minimum is capped to 1 + * @param newHeight the new height, it's minimum is capped to 1 * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}. - * @throws GLException in case of an error + * @throws GLException in case of an error, i.e. size too big, etc .. */ public final void reset(GL gl, int newWidth, int newHeight, int newSamples) { if(!initialized) { @@ -841,13 +931,15 @@ public class FBObject { newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp if( newWidth != width || newHeight != height || newSamples != samples ) { + if(0>=newWidth) { newWidth = 1; } + if(0>=newHeight) { newHeight = 1; } if(newWidth > 2 + maxTextureSize || newHeight> 2 + maxTextureSize || newWidth > maxRenderbufferSize || newHeight> maxRenderbufferSize ) { throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); } if(DEBUG) { - System.err.println("FBObject.reset - START - "+this); + System.err.println("FBObject.reset - START - "+width+"x"+height+", "+samples+" -> "+newWidth+"x"+newHeight+", "+newSamples+"; "+this); } final boolean wasBound = isBound(); @@ -856,11 +948,18 @@ public class FBObject { height = newHeight; samples = newSamples; detachAllImpl(gl, true , true); - resetMSAATexture2DSink(gl); - if(wasBound) { - bind(gl); - } else { + /** + * Postpone reset of samplesSink until syncFramebuffer, + * issued at use(..) method (swapBuffer usually initiates it). + * This allows another thread to still use the 'samplesSinkTexture' + * until swapBuffer happens and does not invalidate the GL_FRONT + * FBO (framebuffer & texture). + resetMSAATexture2DSink(gl); + */ + samplesSinkDirty = true; + + if(!wasBound) { unbind(gl); } @@ -870,6 +969,28 @@ public class FBObject { } } + /** + * Writes the internal format of the attachments to the given GLCapabilities object. + * @param caps the destination for format bits + */ + public final void formatToGLCapabilities(GLCapabilities caps) { + caps.setSampleBuffers(samples > 0); + caps.setNumSamples(samples); + caps.setDepthBits(0); + caps.setStencilBits(0); + + final Colorbuffer cb = samples > 0 ? getSamplingSink() : getColorbuffer(0); + if(null != cb) { + cb.formatToGLCapabilities(caps, rgba8Avail); + } + if(null != depth) { + depth.formatToGLCapabilities(caps, rgba8Avail); + } + if(null != stencil && stencil != depth) { + stencil.formatToGLCapabilities(caps, rgba8Avail); + } + } + /** * Note that the status may reflect an incomplete state during transition of attachments. * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 @@ -954,6 +1075,15 @@ public class FBObject { } } + private static int checkPreGLError(GL gl) { + int glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("Pre-existing GL error: 0x"+Integer.toHexString(glerr)); + Thread.dumpStack(); + } + return glerr; + } + private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException { if(GL.GL_NO_ERROR != err) { if(null != gl) { @@ -974,7 +1104,7 @@ public class FBObject { } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point, * selecting the texture data type and format automatically. * *Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.
@@ -986,13 +1116,15 @@ public class FBObject { * @param alpha set totrue
if you request alpha channel, otherwise false
;
* @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
* @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ * @see #createColorTextureAttachment(GLProfile, boolean, int, int)
*/
public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException {
- return attachTexture2D(gl, attachmentPoint, alpha, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE);
+ return (TextureAttachment)attachColorbuffer(gl, attachmentPoint,
+ createColorTextureAttachment(gl.getGLProfile(), alpha, width, height));
}
/**
- * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point,
+ * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point,
* selecting the texture data type and format automatically.
*
* Leaves the FBO bound.
@@ -1006,23 +1138,15 @@ public class FBObject { * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @see #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int) */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - final int textureInternalFormat, textureDataFormat, textureDataType; - if(gl.isGLES()) { - textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; - textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; - textureDataType = GL.GL_UNSIGNED_BYTE; - } else { - textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8; - textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB; - textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE; - } - return attachTexture2D(gl, attachmentPoint, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); + return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, + createColorTextureAttachment(gl.getGLProfile(), alpha, width, height, magFilter, minFilter, wrapS, wrapT)); } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point. * *Leaves the FBO bound.
* @@ -1037,66 +1161,33 @@ public class FBObject { * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @see #createColorTextureAttachment(int, int, int, int, int, int, int, int, int) */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, int internalFormat, int dataFormat, int dataType, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - return attachTexture2D(gl, attachmentPoint, - new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, - magFilter, minFilter, wrapS, wrapT, 0 /* name */)); + return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, + createColorTextureAttachment(internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT)); } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * Creates a {@link ColorAttachment}, selecting the format automatically. * - *
- * In case the passed TextureAttachment texA
is uninitialized, i.e. it's texture name is zero
,
- * a new texture name is generated and setup w/ the texture parameter.
- * Otherwise, i.e. texture name is not zero
, the passed TextureAttachment texA
is
- * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue.
- *
Leaves the FBO bound.
- * - * @param gl the current GL context - * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] - * @param texA the to be attached {@link TextureAttachment}. Maybe complete or uninitialized, see above. - * @return the passed TextureAttachmenttexA
instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown
- * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen
+ * @param alpha set to true
if you request alpha channel, otherwise false
;
+ * @return uninitialized ColorAttachment instance describing the new attached colorbuffer
*/
- public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, TextureAttachment texA) throws GLException {
- validateAddColorAttachment(attachmentPoint, texA);
-
- if(samples>0) {
- removeColorAttachment(attachmentPoint, texA);
- throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl).");
- }
-
- texA.initialize(gl);
- addColorAttachment(attachmentPoint, texA);
-
- bind(gl);
-
- // Set up the color buffer for use as a renderable texture:
- gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
- GL.GL_COLOR_ATTACHMENT0 + attachmentPoint,
- GL.GL_TEXTURE_2D, texA.getName(), 0);
-
- if(!ignoreStatus) {
- updateStatus(gl);
- if(!isStatusValid()) {
- detachColorbuffer(gl, attachmentPoint);
- throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this);
- }
- }
- if(DEBUG) {
- System.err.println("FBObject.attachTexture2D: "+this);
+ public final ColorAttachment createColorAttachment(boolean alpha) {
+ final int internalFormat;
+ if( rgba8Avail ) {
+ internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ;
+ } else {
+ internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565;
}
- return texA;
+ return new ColorAttachment(internalFormat, samples, width, height, 0);
}
-
+
/**
- * Attaches a Color Buffer to this FBO's instance at the given attachment point,
+ * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point,
* selecting the format automatically.
*
* Leaves the FBO bound.
@@ -1106,19 +1197,14 @@ public class FBObject { * @param alpha set totrue
if you request alpha channel, otherwise false
;
* @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown
* @throws GLException in case the colorbuffer couldn't be allocated
+ * @see #createColorAttachment(boolean)
*/
public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException {
- final int internalFormat;
- if( rgba8Avail ) {
- internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ;
- } else {
- internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565;
- }
- return attachColorbuffer(gl, attachmentPoint, internalFormat);
+ return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, createColorAttachment(alpha));
}
/**
- * Attaches a Color Buffer to this FBO's instance at the given attachment point.
+ * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point.
*
* Leaves the FBO bound.
* @@ -1135,46 +1221,80 @@ public class FBObject { throw new IllegalArgumentException("colorformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this); } - return attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0)); + return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0)); } /** - * Attaches a Color Buffer to this FBO's instance at the given attachment point. + * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}, + * to this FBO's instance at the given attachment point. * + *
+ * If {@link Colorbuffer} is a {@link TextureAttachment} and is uninitialized, i.e. it's texture name is zero
,
+ * a new texture name is generated and setup w/ the texture parameter.
+ * Otherwise, i.e. texture name is not zero
, the passed TextureAttachment texA
is
+ * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue.
+ *
Leaves the FBO bound.
* * @param gl * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] - * @param colA the template for the new {@link ColorAttachment} - * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown - * @throws GLException in case the colorbuffer couldn't be allocated + * @param colbuf the to be attached {@link Colorbuffer} + * @return newly attached {@link Colorbuffer} instance if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated or MSAA has been chosen in case of a {@link TextureAttachment} */ - public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, ColorAttachment colA) throws GLException { - validateAddColorAttachment(attachmentPoint, colA); - - colA.initialize(gl); - addColorAttachment(attachmentPoint, colA); + public final Colorbuffer attachColorbuffer(GL gl, int attachmentPoint, Colorbuffer colbuf) throws GLException { + validateAddColorAttachment(attachmentPoint, colbuf); - bind(gl); + final boolean initializedColorbuf = colbuf.initialize(gl); + addColorAttachment(attachmentPoint, colbuf); - // Attach the color buffer - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, - GL.GL_RENDERBUFFER, colA.getName()); + bind(gl); - if(!ignoreStatus) { - updateStatus(gl); - if(!isStatusValid()) { - detachColorbuffer(gl, attachmentPoint); - throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + if(colbuf instanceof TextureAttachment) { + final TextureAttachment texA = (TextureAttachment) colbuf; + + if(samples>0) { + removeColorAttachment(attachmentPoint, texA); + if(initializedColorbuf) { + texA.free(gl); + } + throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl)."); + } + + // Set up the color buffer for use as a renderable texture: + gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_TEXTURE_2D, texA.getName(), 0); + + if(!ignoreStatus) { + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint, true); + throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } + } + } else if(colbuf instanceof ColorAttachment) { + final ColorAttachment colA = (ColorAttachment) colbuf; + + // Attach the color buffer + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_RENDERBUFFER, colA.getName()); + + if(!ignoreStatus) { + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint, true); + throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } } } if(DEBUG) { - System.err.println("FBObject.attachColorbuffer: "+this); + System.err.println("FBObject.attachColorbuffer: [attachmentPoint "+attachmentPoint+", colbuf "+colbuf+"]: "+this); } - return colA; + return colbuf; } - /** * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, @@ -1355,33 +1475,39 @@ public class FBObject { if(!ignoreStatus) { updateStatus(gl); if( !isStatusValid() ) { - detachRenderbuffer(gl, atype); + detachRenderbuffer(gl, atype, true); throw new GLException("renderbuffer attachment failed: "+this.getStatusString()); } } if(DEBUG) { - System.err.println("FBObject.attachRenderbuffer: "+this); - } + System.err.println("FBObject.attachRenderbuffer: [attachmentType "+atype+"]: "+this); + } } /** + * Detaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}. *Leaves the FBO bound!
+ * * @param gl - * @param ca + * @param attachmentPoint + * @param dispose true if the Colorbuffer shall be disposed + * @return the detached Colorbuffer * @throws IllegalArgumentException */ - public final void detachColorbuffer(GL gl, int attachmentPoint) throws IllegalArgumentException { - if(null == detachColorbufferImpl(gl, attachmentPoint, false)) { + public final Colorbuffer detachColorbuffer(GL gl, int attachmentPoint, boolean dispose) throws IllegalArgumentException { + final Colorbuffer res = detachColorbufferImpl(gl, attachmentPoint, dispose ? DetachAction.DISPOSE : DetachAction.NONE); + if(null == res) { throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this); } if(DEBUG) { - System.err.println("FBObject.detachColorbuffer: [attachmentPoint "+attachmentPoint+"]: "+this); + System.err.println("FBObject.detachColorbuffer: [attachmentPoint "+attachmentPoint+", dispose "+dispose+"]: "+res+", "+this); } + return res; } - private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, boolean recreate) { - final Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here + private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, DetachAction detachAction) { + Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here if(null == colbuf) { return null; @@ -1389,6 +1515,8 @@ public class FBObject { bind(gl); + removeColorAttachment(attachmentPoint, colbuf); + if(colbuf instanceof TextureAttachment) { final TextureAttachment texA = (TextureAttachment) colbuf; if( 0 != texA.getName() ) { @@ -1397,11 +1525,22 @@ public class FBObject { GL.GL_TEXTURE_2D, 0, 0); gl.glBindTexture(GL.GL_TEXTURE_2D, 0); } - texA.free(gl); - removeColorAttachment(attachmentPoint, texA); - if(recreate) { - texA.setSize(width, height); - attachTexture2D(gl, attachmentPoint, texA); + switch(detachAction) { + case DISPOSE: + texA.free(gl); + break; + case RECREATE: + texA.free(gl); + if(samples == 0) { + // stay non MSAA + texA.setSize(width, height); + } else { + // switch to MSAA + colbuf = createColorAttachment(hasAlpha(texA.format)); + } + attachColorbuffer(gl, attachmentPoint, colbuf); + break; + default: } } else if(colbuf instanceof ColorAttachment) { final ColorAttachment colA = (ColorAttachment) colbuf; @@ -1410,12 +1549,30 @@ public class FBObject { GL.GL_COLOR_ATTACHMENT0+attachmentPoint, GL.GL_RENDERBUFFER, 0); } - colA.free(gl); - removeColorAttachment(attachmentPoint, colbuf); - if(recreate) { - colA.setSize(width, height); - colA.setSamples(samples); - attachColorbuffer(gl, attachmentPoint, colA); + switch(detachAction) { + case DISPOSE: + colA.free(gl); + break; + case RECREATE: + colA.free(gl); + if(samples > 0) { + // stay MSAA + colA.setSize(width, height); + colA.setSamples(samples); + } else { + // switch to non MSAA + if(null != samplesSinkTexture) { + colbuf = createColorTextureAttachment(samplesSinkTexture.format, width, height, + samplesSinkTexture.dataFormat, samplesSinkTexture.dataType, + samplesSinkTexture.magFilter, samplesSinkTexture.minFilter, + samplesSinkTexture.wrapS, samplesSinkTexture.wrapT); + } else { + colbuf = createColorTextureAttachment(gl.getGLProfile(), true, width, height); + } + } + attachColorbuffer(gl, attachmentPoint, colbuf); + break; + default: } } return colbuf; @@ -1424,10 +1581,14 @@ public class FBObject { /** * * @param gl + * @param dispose true if the Colorbuffer shall be disposed * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL} */ - public final void detachRenderbuffer(GL gl, Attachment.Type atype) throws IllegalArgumentException { - detachRenderbufferImpl(gl, atype, false); + public final void detachRenderbuffer(GL gl, Attachment.Type atype, boolean dispose) throws IllegalArgumentException { + detachRenderbufferImpl(gl, atype, dispose ? DetachAction.DISPOSE : DetachAction.NONE); + if(DEBUG) { + System.err.println("FBObject.detachRenderbuffer: [attachmentType "+atype+", dispose "+dispose+"]: "+this); + } } public final boolean isDepthStencilPackedFormat() { @@ -1439,7 +1600,7 @@ public class FBObject { return res; } - private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, boolean recreate) throws IllegalArgumentException { + private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, DetachAction detachAction) throws IllegalArgumentException { switch ( atype ) { case DEPTH: case STENCIL: @@ -1485,8 +1646,14 @@ public class FBObject { if( 0 != depth.getName() ) { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - depth.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + depth.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { depth = null; } break; @@ -1495,8 +1662,14 @@ public class FBObject { if(0 != stencil.getName()) { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - stencil.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + stencil.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { stencil = null; } break; @@ -1506,9 +1679,15 @@ public class FBObject { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0); gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - depth.free(gl); - stencil.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + depth.free(gl); + stencil.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { depth = null; stencil = null; } @@ -1516,14 +1695,15 @@ public class FBObject { default: throw new InternalError("XXX"); } - if(recreate) { + if(DetachAction.RECREATE == detachAction) { attachRenderbufferImpl2(gl, action, format); } } } /** - * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s. + * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s + * and disposes them. *Leaves the FBO bound!
** An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. @@ -1538,7 +1718,8 @@ public class FBObject { } /** - * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s. + * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s + * and disposes them. *
Leaves the FBO bound!
** An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. @@ -1553,7 +1734,7 @@ public class FBObject { } /** - * Detaches all {@link TextureAttachment}s + * Detaches all {@link TextureAttachment}s and disposes them. *
Leaves the FBO bound!
*
* An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}.
@@ -1566,30 +1747,33 @@ public class FBObject {
}
for(int i=0; i
+ * Only use this method if a subsequent {@link #unbind(GL)}, {@link #use(GL, TextureAttachment)} or {@link #bind(GL)}
+ * follows on any FBO.
+ * The operation is skipped, if no multisampling is used or
- * the msaa-buffer has not been flagged dirty by a previous call of {@link #bind(GL)},
- * see {@link #isSamplingBufferDirty()} If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing
- * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()} In case you intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
+ * If multisampling is being used and flagged dirty by a previous call of {@link #bind(GL)} or after initialization,
+ * the msaa-buffers are sampled to it's sink {@link #getSamplingSink()}.
+ *
+ * Method also updates the sampling sink configuration (if used). Hence it is recommended to call this
+ * method after your have initialized the FBO and attached renderbuffer etc for the 1st time.
+ * Method is called automatically by {@link #use(GL, TextureAttachment)}.
+ *
+ * Methos always resets the framebuffer binding to default in the end.
+ * If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing
+ * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}
+ *
+ * In case you use this FBO w/o the {@link GLFBODrawable} and intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}
* you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()});
* Leaves the FBO unbound. If multisampling is being used, {@link #syncSamplingBuffer(GL)} is being called. If using multiple texture units, ensure you call {@link GL#glActiveTexture(int)} first! {@link #syncFramebuffer(GL)} is being called Leaves the FBO unbound!
+ * Since no native windowing system events are being processed, it is recommended
+ * to handle at least:
+ * true
if framebuffer object is bound via {@link #bind(GL)}, otherwise false
.
@@ -1785,49 +1988,54 @@ public class FBObject {
public final boolean isBound() { return bound; }
/**
- * Samples the multisampling colorbuffer (msaa-buffer) to it's sink {@link #getSamplingSink()}.
- *
- * true
if basic or full FBO is supported, otherwise false
.
- * @param full true
for full FBO supported query, otherwise false
for basic FBO support query.
- * @see #supportsFullFBO(GL)
- * @see #supportsBasicFBO(GL)
- * @throws GLException if {@link #init(GL)} hasn't been called.
- */
- public final boolean supportsFBO(boolean full) throws GLException { checkInitialized(); return full ? fullFBOSupport : basicFBOSupport; }
+ /** @see GL#hasFullFBOSupport() */
+ public final boolean hasFullFBOSupport() throws GLException { checkInitialized(); return this.fullFBOSupport; }
/**
* Returns true
if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise false
.
@@ -1878,7 +2076,7 @@ public class FBObject {
public final boolean supportsDepth(int bits) throws GLException {
checkInitialized();
switch(bits) {
- case 16: return basicFBOSupport;
+ case 16: return true;
case 24: return depth24Avail;
case 32: return depth32Avail;
default: return false;
@@ -1913,11 +2111,11 @@ public class FBObject {
*/
public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; }
- /**
- * Returns the maximum number of samples for multisampling. Maybe zero if multisampling is not supported.
- * @throws GLException if {@link #init(GL)} hasn't been called.
- */
- public final int getMaxSamples() throws GLException { checkInitialized(); return maxSamples; }
+ public final int getMaxTextureSize() throws GLException { checkInitialized(); return this.maxTextureSize; }
+ public final int getMaxRenderbufferSize() throws GLException { checkInitialized(); return this.maxRenderbufferSize; }
+
+ /** @see GL#getMaxRenderbufferSamples() */
+ public final int getMaxSamples() throws GLException { checkInitialized(); return this.maxSamples; }
/**
* Returns true
if this instance has been initialized with {@link #reset(GL, int, int)}
diff --git a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
new file mode 100644
index 000000000..38a8deef8
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
@@ -0,0 +1,189 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLException;
+
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
+import jogamp.opengl.GLAutoDrawableBase;
+import jogamp.opengl.GLContextImpl;
+import jogamp.opengl.GLDrawableImpl;
+
+
+/**
+ * Fully functional {@link GLAutoDrawable} implementation
+ * utilizing already created created {@link GLDrawable} and {@link GLContext} instances.
+ *
+ *
+ *
+ * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}. + *
+ */ +public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAutoDrawable { + /** + * @param drawable a valid and already realized {@link GLDrawable} + * @param context a valid {@link GLContext}, may not be made current (created) yet. + * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. + * @param ownDevice passtrue
if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass false
. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
+ * @param lock optional custom {@link RecursiveLock}.
+ */
+ public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice, RecursiveLock lock) {
+ super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice);
+ if(null == drawable) {
+ throw new IllegalArgumentException("null drawable");
+ }
+ if(null == context) {
+ throw new IllegalArgumentException("null context");
+ }
+ if(!drawable.isRealized()) {
+ throw new IllegalArgumentException("drawable not realized");
+ }
+ this.upstreamWidget = upstreamWidget;
+ this.lock = ( null != lock ) ? lock : LockFactory.createRecursiveLock() ;
+ }
+
+ //
+ // expose default methods
+ //
+
+ /** Default implementation to handle repaint events from the windowing system */
+ public final void windowRepaintOp() {
+ super.defaultWindowRepaintOp();
+ }
+
+ /** Implementation to handle resize events from the windowing system. All required locks are being claimed. */
+ public final void windowResizedOp(int newWidth, int newHeight) {
+ super.defaultWindowResizedOp(newWidth, newHeight);
+ }
+
+ /**
+ * Implementation to handle destroy notifications from the windowing system.
+ *
+ * + * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol} + * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default), + * a thread safe destruction is being induced. + *
+ */ + public final void windowDestroyNotifyOp() { + super.defaultWindowDestroyNotifyOp(); + } + + // + // Complete GLAutoDrawable + // + + private Object upstreamWidget; + private final RecursiveLock lock; + + @Override + protected final RecursiveLock getLock() { return lock; } + + @Override + public final Object getUpstreamWidget() { + return upstreamWidget; + } + + /** + * Set the upstream UI toolkit object. + * @see #getUpstreamWidget() + */ + public final void setUpstreamWidget(Object newUpstreamWidget) { + upstreamWidget = newUpstreamWidget; + } + + /** + * {@inheritDoc} + *+ * This implementation calls {@link #defaultDestroy()}. + *
+ *+ * User still needs to destroy the upstream window, which details are hidden from this aspect. + * This can be performed by overriding {@link #destroyImplInLock()}. + *
+ */ + @Override + public final void destroy() { + defaultDestroy(); + } + + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); + } + + @Override + public void display() { + defaultDisplay(); + } + + // + // GLDrawable delegation + // + + @Override + public final GLDrawableFactory getFactory() { + return drawable.getFactory(); + } + + @Override + public final void setRealized(boolean realized) { + } + + @Override + public final void swapBuffers() throws GLException { + defaultSwapBuffers(); + } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + + ", \n\tContext: " + context + ", \n\tUpstreamWidget: "+upstreamWidget+ /** ", \n\tFactory: "+factory+ */ "]"; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java index f7e25fa01..cf81b85ee 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java +++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java @@ -72,6 +72,9 @@ public class GLExtensions { public static final String OES_EGL_image_external = "GL_OES_EGL_image_external"; + public static final String ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; + public static final String ARB_shader_objects = "GL_ARB_shader_objects"; + // // Aliased GLX/WGL/.. extensions // diff --git a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java deleted file mode 100644 index 4caea03b2..000000000 --- a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl; - -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.opengl.GLAutoDrawableDelegate; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLException; - -import jogamp.opengl.GLFBODrawableImpl; - -/** - * Platform-independent class exposing FBO offscreen functionality to - * applications. - *- * This class distinguishes itself from {@link GLAutoDrawableDelegate} - * with it's {@link #setSize(int, int)} functionality. - *
- */ -public class OffscreenAutoDrawable extends GLAutoDrawableDelegate { - - /** - * @param drawable a valid {@link GLDrawable}, may not be realized yet. - * @param context a valid {@link GLContext}, may not be made current (created) yet. - * @param ownDevice passtrue
if {@link AbstractGraphicsDevice#close()} shall be issued,
- * otherwise pass false
. Closing the device is required in case
- * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
- * and no further lifecycle handling is applied.
- */
- public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, boolean ownDevice) {
- super(drawable, context, null, ownDevice);
- }
-
- /**
- * Attempts to resize this offscreen auto drawable, if supported
- * by the underlying {@link GLDrawable).
- * @param newWidth
- * @param newHeight
- * @return true
if resize was executed, otherwise false
.
- * @throws GLException in case of an error during the resize operation
- */
- public boolean setSize(int newWidth, int newHeight) throws GLException {
- boolean done = false;
- if(drawable instanceof GLFBODrawableImpl) {
- Throwable tFBO = null;
- Throwable tGL = null;
- context.makeCurrent();
- try {
- ((GLFBODrawableImpl)drawable).setSize(context.getGL(), newWidth, newHeight);
- done = true;
- } catch (Throwable t) {
- tFBO = t;
- } finally {
- try {
- context.release();
- } catch (Throwable t) {
- tGL = t;
- }
- }
- if(null != tFBO) {
- throw new GLException("OffscreenAutoDrawable.setSize(..) GLFBODrawableImpl.setSize(..) exception", tFBO);
- }
- if(null != tGL) {
- throw new GLException("OffscreenAutoDrawable.setSize(..) GLContext.release() exception", tGL);
- }
- }
- if(done) {
- this.defaultWindowResizedOp();
- return true;
- }
- return false;
- }
-
- /**
- * If the underlying {@link GLDrawable} is an FBO implementation
- * and contains an {#link FBObject}, the same is returned.
- * Otherwise returns null
.
- */
- public FBObject getFBObject() {
- if(drawable instanceof GLFBODrawableImpl) {
- return ((GLFBODrawableImpl)drawable).getFBObject();
- }
- return null;
- }
-}
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 8d237162c..02f62daec 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -30,6 +30,7 @@ package com.jogamp.opengl.swt;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
import javax.media.opengl.GL;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
@@ -48,6 +49,7 @@ import javax.media.opengl.Threading;
import jogamp.opengl.Debug;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableHelper;
+import jogamp.opengl.GLDrawableImpl;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
@@ -97,8 +99,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
private final GLCapabilitiesImmutable capsRequested;
private final GLCapabilitiesChooser capsChooser;
- private volatile GLDrawable drawable; // volatile: avoid locking for read-only access
- private GLContext context;
+ private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
+ private GLContextImpl context;
/* Native window surface */
private AbstractGraphicsDevice device;
@@ -319,7 +321,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
});
}
- private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() {
+ private final UpstreamSurfaceHook swtCanvasUpStreamHook = new UpstreamSurfaceHook() {
@Override
public final void create(ProxySurface s) { /* nop */ }
@@ -349,7 +351,27 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height )
) {
clientArea = nClientArea; // write back new value
- sendReshape = true; // Mark for OpenGL reshape next time the control is painted
+
+ GLDrawableImpl _drawable = drawable;
+ if( null != _drawable ) {
+ if(DEBUG) {
+ System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+ }
+ if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, nClientArea.width, nClientArea.height);
+ if(_drawable != _drawableNew) {
+ // write back
+ drawable = _drawableNew;
+ }
+ } finally {
+ _lock.unlock();
+ }
+ sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
+ }
+ }
}
}
@@ -391,10 +413,10 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
if(null != proxySurface) {
/* Associate a GL surface with the proxy */
- drawable = glFactory.createGLDrawable(proxySurface);
+ drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface);
drawable.setRealized(true);
- context = drawable.createContext(shareWith);
+ context = (GLContextImpl) drawable.createContext(shareWith);
}
} finally {
_lock.unlock();
@@ -455,6 +477,11 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
return helper.getAutoSwapBufferMode();
}
+ @Override
+ public final GLDrawable getDelegatedDrawable() {
+ return drawable;
+ }
+
@Override
public GLContext getContext() {
return null != drawable ? context : null;
@@ -502,7 +529,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
_lock.lock();
try {
final GLContext oldCtx = context;
- final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
context=(GLContextImpl)newCtx;
if(newCtxCurrent) {
context.makeCurrent();
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
index 0b2c664fe..38f1746f9 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
@@ -114,6 +114,12 @@ public interface GLAutoDrawable extends GLDrawable {
* where you drag the window to another monitor. */
public static final boolean SCREEN_CHANGE_ACTION_ENABLED = Debug.getBooleanProperty("jogl.screenchange.action", true);
+ /**
+ * If the implementation uses delegation, return the delegated {@link GLDrawable} instance,
+ * otherwise return this
instance.
+ */
+ public GLDrawable getDelegatedDrawable();
+
/**
* Returns the context associated with this drawable. The returned
* context will be synchronized.
@@ -124,23 +130,31 @@ public interface GLAutoDrawable extends GLDrawable {
/**
* Associate a new context to this drawable and also propagates the context/drawable switch by
* calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
- * drawable
might be an inner GLDrawable instance if using such a delegation pattern,
- * or this GLAutoDrawable itself.
- * - * If the old context's drawable was an {@link GLAutoDrawable}, it's reference to the given drawable - * is being cleared by calling - * {@link GLAutoDrawable#setContext(GLContext) ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null)}. - *
+ *drawable
might be an inner GLDrawable instance if using a delegation pattern,
+ * or this GLAutoDrawable instance.
* * If the old or new context was current on this thread, it is being released before switching the drawable. * The new context will be made current afterwards, if it was current before. - * However the user shall take extra care that not other thread - * attempts to make this context current. Otherwise a race condition may happen. + * However the user shall take extra care that no other thread + * attempts to make this context current. + *
+ *+ * Be aware that the old context is still bound to the drawable, + * and that one context can only be bound to one drawable at one time! *
*- * Disclaimer: Even though the API may allows this functionality in theory, your mileage may vary - * switching the drawable of an already established GLContext, i.e. which is already made current once. - * FIXME: Validate functionality! + * In case you do not intend to use the old context anymore, i.e. + * not assigning it to another drawable, it shall be + * destroyed before setting the new context, i.e.: + *
+ GLContext oldCtx = glad.getContext(); + if(null != oldCtx) { + oldCtx.destroy(); + } + glad.setContext(newCtx); + *+ * This is required, since a context must have a valid drawable at all times + * and this API shall not restrict the user in any way. * * * @param newCtx the new context diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java deleted file mode 100644 index 67e81270d..000000000 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package javax.media.opengl; - -import javax.media.nativewindow.AbstractGraphicsDevice; - -import com.jogamp.common.util.locks.LockFactory; -import com.jogamp.common.util.locks.RecursiveLock; - -import jogamp.opengl.Debug; -import jogamp.opengl.GLAutoDrawableBase; -import jogamp.opengl.GLContextImpl; -import jogamp.opengl.GLDrawableImpl; - - -/** - * Fully functional {@link GLAutoDrawable} implementation - * utilizing already created created {@link GLDrawable} and {@link GLContext} instances. - *
- * Since no native windowing system events are being processed, it is recommended - * to handle at least: - *
- * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}. - *
- */ -public class GLAutoDrawableDelegate extends GLAutoDrawableBase { - public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate"); - - /** - * @param drawable a valid {@link GLDrawable}, may not be realized yet. - * @param context a valid {@link GLContext}, may not be made current (created) yet. - * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. - * @param ownDevice passtrue
if {@link AbstractGraphicsDevice#close()} shall be issued,
- * otherwise pass false
. Closing the device is required in case
- * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
- * and no further lifecycle handling is applied.
- */
- public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice) {
- super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice);
- this.upstreamWidget = null;
- }
-
- //
- // expose default methods
- //
-
- public final void windowRepaintOp() {
- super.defaultWindowRepaintOp();
- }
-
- public final void windowResizedOp() {
- super.defaultWindowResizedOp();
- }
-
- public final void windowDestroyNotifyOp() {
- super.defaultWindowDestroyNotifyOp();
- }
-
- //
- // Complete GLAutoDrawable
- //
-
- private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock
- private final Object upstreamWidget;
-
- @Override
- protected final RecursiveLock getLock() { return lock; }
-
- @Override
- public final Object getUpstreamWidget() {
- return upstreamWidget;
- }
-
- /**
- * {@inheritDoc}
- * - * This implementation calls {@link #defaultDestroy()}. - *
- *- * User still needs to destroy the upstream window, which details are hidden from this aspect. - * This can be performed by overriding {@link #destroyImplInLock()}. - *
- */ - @Override - public final void destroy() { - defaultDestroy(); - } - - @Override - public void display() { - defaultDisplay(); - } - - // - // GLDrawable delegation - // - - @Override - public final GLDrawableFactory getFactory() { - return drawable.getFactory(); - } - - @Override - public final void setRealized(boolean realized) { - } - - @Override - public final void swapBuffers() throws GLException { - defaultSwapBuffers(); - } - -} diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java index f5831a72d..9bcee819a 100644 --- a/src/jogl/classes/javax/media/opengl/GLBase.java +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -273,6 +273,42 @@ public interface GLBase { */ public boolean isExtensionAvailable(String glExtensionName); + /** + * Returnstrue
if basic FBO support is available, otherwise false
.
+ *
+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions
+ * GL_ARB_ES2_compatibility
, GL_ARB_framebuffer_object
, GL_EXT_framebuffer_object
or GL_OES_framebuffer_object
.
+ *
+ * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *
+ * @see GLContext#hasBasicFBOSupport() + */ + public boolean hasBasicFBOSupport(); + + /** + * Returnstrue
if full FBO support is available, otherwise false
.
+ *
+ * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
+ * ARB_framebuffer_object
, or all of
+ * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
+ * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
+ *
+ * Full FBO support includes multiple color attachments and multisampling. + *
+ * @see GLContext#hasFullFBOSupport() + */ + public boolean hasFullFBOSupport(); + + /** + * Returns the maximum number of FBO RENDERBUFFER samples + * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. + * @see GLContext#getMaxRenderbufferSamples() + */ + public int getMaxRenderbufferSamples(); + /** * Returns true if the GL context supports non power of two (NPOT) textures, * otherwise false. @@ -284,6 +320,8 @@ public interface GLBase { */ public boolean isNPOTTextureAvailable(); + public boolean isTextureFormatBGRA8888Available(); + /** Provides a platform-independent way to specify the minimum swap interval for buffer swaps. An argument of 0 disables sync-to-vertical-refresh completely, while an argument of 1 diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index c2f94b9af..a5e639c74 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -96,6 +96,9 @@ public abstract class GLContext { */ public static final boolean PROFILE_ALIASING = !Debug.isPropertyDefined("jogl.debug.GLContext.NoProfileAliasing", true); + protected static final boolean FORCE_NO_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.none", true); + protected static final boolean FORCE_MIN_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.min", true); + public static final boolean DEBUG = Debug.debug("GLContext"); public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true); @@ -127,9 +130,9 @@ public abstract class GLContext { /**GL_ARB_ES2_compatibility
implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8;
- /** Context supports basic FBO, details see {@link #hasFBO()}.
+ /** Context supports basic FBO, details see {@link #hasBasicFBOSupport()}.
* Not a cache key.
- * @see #hasFBO()
+ * @see #hasBasicFBOSupport()
* @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)
*/
protected static final int CTX_IMPL_FBO = 1 << 9;
@@ -178,11 +181,6 @@ public abstract class GLContext {
* and made current afterwards. However the user shall take extra care that not other thread
* attempts to make this context current. Otherwise a race condition may happen.
*
- * - * Disclaimer: Even though the API may allows this functionality in theory, your mileage may vary - * switching the drawable of an already established GLContext, i.e. which is already made current once. - * FIXME: Validate functionality! - *
* @param readWrite the read/write drawable for framebuffer operations. * @param setWriteOnly iftrue
and if the current read-drawable differs
* from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}),
@@ -603,12 +601,23 @@ public abstract class GLContext {
/**
* @return true if impl. is a hardware rasterizer, otherwise false.
+ * @see #isHardwareRasterizer(AbstractGraphicsDevice, GLProfile)
* @see GLProfile#isHardwareRasterizer()
*/
public final boolean isHardwareRasterizer() {
return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ;
}
+ /**
+ * @return true if context supports GLSL, i.e. is either {@link #isGLES2()}, {@link #isGL3()} or {@link #isGL2()} and major-version > 1.
+ * @see GLProfile#hasGLSL()
+ */
+ public final boolean hasGLSL() {
+ return isGLES2() ||
+ isGL3() ||
+ isGL2() && ctxMajorVersion>1 ;
+ }
+
/**
* Returns true
if basic FBO support is available, otherwise false
.
* @@ -620,21 +629,54 @@ public abstract class GLContext { * as well as limited internal formats for renderbuffer. *
* @see #CTX_IMPL_FBO - * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL) - * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL) */ - public final boolean hasFBO() { + public final boolean hasBasicFBOSupport() { return 0 != ( ctxOptions & CTX_IMPL_FBO ) ; } + /** + * Returnstrue
if full FBO support is available, otherwise false
.
+ *
+ * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions
+ * ARB_framebuffer_object
, or all of
+ * EXT_framebuffer_object
, EXT_framebuffer_multisample
,
+ * EXT_framebuffer_blit
, GL_EXT_packed_depth_stencil
.
+ *
+ * Full FBO support includes multiple color attachments and multisampling. + *
+ */ + public final boolean hasFullFBOSupport() { + return !FORCE_MIN_FBO_SUPPORT && hasBasicFBOSupport() && + ( isGL3() || // GL >= 3.0 + isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object + ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object* + isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) && + isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) && + isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) + ) + ) ; + } + /** - * @return true if context supports GLSL - * @see GLProfile#hasGLSL() + * Returns the maximum number of FBO RENDERBUFFER samples + * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. */ - public final boolean hasGLSL() { - return isGL2ES2() ; + public final int getMaxRenderbufferSamples() { + if( hasFullFBOSupport() ) { + final GL gl = getGL(); + final int[] val = new int[] { 0 } ; + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + final int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + return val[0]; + } else if(DEBUG) { + System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr)); + } + } + return 0; } - + /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returnstrue
. */
public boolean isNPOTTextureAvailable() {
return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two);
@@ -1014,6 +1056,9 @@ public abstract class GLContext {
validateProfileBits(profile, "profile");
validateProfileBits(resCtp, "resCtp");
+ if(FORCE_NO_FBO_SUPPORT) {
+ resCtp &= ~CTX_IMPL_FBO ;
+ }
if(DEBUG) {
System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null));
// Thread.dumpStack();
@@ -1197,17 +1242,35 @@ public abstract class GLContext {
* FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent.
*
* - * FBO support is queried as described in {@link #hasFBO()}. + * FBO support is queried as described in {@link #hasBasicFBOSupport()}. *
* * @param device the device to request whether FBO is available for * @param glp {@link GLProfile} to check for FBO capabilities - * @see GLContext#hasFBO() + * @see GLContext#hasBasicFBOSupport() */ public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) { return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) ); } + /** + * @return1
if using a hardware rasterizer, 0
if using a software rasterizer and -1
if not determined yet.
+ * @see GLContext#isHardwareRasterizer()
+ * @see GLProfile#isHardwareRasterizer()
+ */
+ public static final int isHardwareRasterizer(AbstractGraphicsDevice device, GLProfile glp) {
+ final int r;
+ final int ctp = getAvailableContextProperties(device, glp);
+ if(0 == ctp) {
+ r = -1;
+ } else if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctp ) ) {
+ r = 1;
+ } else {
+ r = 0;
+ }
+ return r;
+ }
+
/**
* @param device the device to request whether the profile is available for
* @param reqMajor Key Value either 1, 2, 3 or 4
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index 9fd895c1f..b6e7b0576 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -48,13 +48,16 @@ import java.util.List;
import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.opengl.GLAutoDrawableDelegate;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.ProxySurface;
-import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
+import javax.media.nativewindow.UpstreamSurfaceHook;
import jogamp.opengl.Debug;
@@ -373,44 +376,63 @@ public abstract class GLDrawableFactory {
// Methods to create high-level objects
/**
- * Returns a GLDrawable according to it's chosen Capabilities,- * The native platform's chosen Capabilties are referenced within the target - * NativeSurface's AbstractGraphicsConfiguration.
- *
- * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is true,
- * an onscreen GLDrawable will be realized.
+ * The chosen {@link GLCapabilitiesImmutable} are referenced within the target
+ * {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.
+ *
*
- * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is false,
- * either a Pbuffer drawable is created if target's {@link javax.media.opengl.GLCapabilities#isPBuffer()} is true,
- * or a simple pixmap/bitmap drawable is created. The latter is unlikely to be hardware accelerated.
+ * An onscreen GLDrawable is created if {@link CapabilitiesImmutable#isOnscreen() caps.isOnscreen()} is true.
+ *
- * + * A FBO drawable is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *
+ *+ * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *
+ *+ * If not onscreen and neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. + *
+ * * @throws IllegalArgumentException if the passed target is null * @throws GLException if any window system-specific errors caused * the creation of the GLDrawable to fail. * + * @see #canCreateGLPbuffer(AbstractGraphicsDevice) + * @see GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) + * @see javax.media.opengl.GLCapabilities#isOnscreen() + * @see javax.media.opengl.GLCapabilities#isFBO() + * @see javax.media.opengl.GLCapabilities#isPBuffer() * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen) */ public abstract GLDrawable createGLDrawable(NativeSurface target) throws IllegalArgumentException, GLException; - + /** - * Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. + * Creates an {@link GLOffscreenAutoDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. *- * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below. + * The {@link GLOffscreenAutoDrawable}'s {@link GLDrawable} is realized and it's {@link GLContext} assigned but not yet made current. *
*
- * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#isFBO() caps.isFBO()}
+ * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
+ * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} == true
,
+ * it is auto-configured. The latter will set offscreen and also FBO or Pbuffer, whichever is available in that order.
+ *
+ * A FBO based auto drawable, {@link GLOffscreenAutoDrawable.FBO}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. *
*- * A Pbuffer drawable is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} - * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + * A Pbuffer based auto drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. *
*- * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. + * If neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap auto drawable is created, which is unlikely to be hardware accelerated. *
* * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may benull
for the platform's default device.
@@ -418,17 +440,55 @@ public abstract class GLDrawableFactory {
* @param chooser the custom chooser, may be null for default
* @param width the requested offscreen width
* @param height the requested offscreen height
+ * @return the created and initialized offscreen {@link GLOffscreenAutoDrawable} instance
*
- * @return the created offscreen GLDrawable
+ * @throws GLException if any window system-specific errors caused
+ * the creation of the Offscreen to fail.
+ *
+ * @see #createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int)
+ */
+ public abstract GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice device,
+ GLCapabilitiesImmutable caps,
+ GLCapabilitiesChooser chooser,
+ int width, int height,
+ GLContext shareWith) throws GLException;
+ /**
+ * Creates a offscreen {@link GLDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions.
+ *
+ * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e.
+ * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} == true
,
+ * it is auto-configured. The latter will set offscreen and also FBO or Pbuffer, whichever is available in that order.
+ *
+ * A resizeable FBO drawable, {@link GLFBODrawable.Resizeable}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *
+ *+ * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *
+ *+ * If neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap drawable is created, which is unlikely to be hardware accelerated. + *
+ * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may benull
for the platform's default device.
+ * @param caps the requested GLCapabilties
+ * @param chooser the custom chooser, may be null for default
+ * @param width the requested offscreen width
+ * @param height the requested offscreen height
+ *
+ * @return the created offscreen {@link GLDrawable}
*
* @throws GLException if any window system-specific errors caused
* the creation of the Offscreen to fail.
+ *
+ * @see #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)
*/
public abstract GLDrawable createOffscreenDrawable(AbstractGraphicsDevice device,
- GLCapabilitiesImmutable capabilities,
+ GLCapabilitiesImmutable caps,
GLCapabilitiesChooser chooser,
- int width, int height)
- throws GLException;
+ int width, int height) throws GLException;
/**
* Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link GDISurface} instance.
@@ -458,6 +518,21 @@ public abstract class GLDrawableFactory {
long windowHandle,
GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream);
+ /**
+ * Returns true if it is possible to create an framebuffer object (FBO).
+ * + * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. + *
+ *+ * FBO support is queried as described in {@link GLContext#hasBasicFBOSupport()}. + *
+ * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may benull
for the platform's default device.
+ * @param glp {@link GLProfile} to check for FBO capabilities
+ * @see GLContext#hasBasicFBOSupport()
+ */
+ public abstract boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp);
+
/**
* Returns true if it is possible to create a GLPbuffer. Some older
* graphics cards do not have this capability.
@@ -467,7 +542,10 @@ public abstract class GLDrawableFactory {
public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device);
/**
- * Creates a GLPbuffer with the given capabilites and dimensions. + * Creates a GLPbuffer {@link GLAutoDrawable} with the given capabilites and dimensions. + *
+ * The GLPbuffer drawable is realized and initialized eagerly. + *
* * See the note in the overview documentation on * context sharing. @@ -479,10 +557,12 @@ public abstract class GLDrawableFactory { * @param initialHeight initial height of pbuffer * @param shareWith a shared GLContext this GLPbuffer shall use * - * @return the new {@link GLPbuffer} specific {@link GLAutoDrawable} + * @return the created and initialized {@link GLPbuffer} instance * * @throws GLException if any window system-specific errors caused * the creation of the GLPbuffer to fail. + * + * @deprecated {@link GLPbuffer} is deprecated, use {@link #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)} */ public abstract GLPbuffer createGLPbuffer(AbstractGraphicsDevice device, GLCapabilitiesImmutable capabilities, diff --git a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java new file mode 100644 index 000000000..45fd3b686 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java @@ -0,0 +1,173 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; + +/** + * Platform-independent {@link GLDrawable} specialization, + * exposing {@link FBObject} functionality. + * + *+ * A {@link GLFBODrawable} is uninitialized until a {@link GLContext} is bound + * and made current the first time. + *
+ * + *+ * MSAA is used if {@link GLCapabilitiesImmutable#getNumSamples() requested}. + *
+ *+ * Double buffering is used if {@link GLCapabilitiesImmutable#getDoubleBuffered() requested}. + *
+ *+ * In MSAA mode, it always uses the implicit 2nd {@link FBObject framebuffer} {@link FBObject#getSamplingSinkFBO() sink}. + * Hence double buffering is always the case w/ MSAA. + *
+ *+ * In non MSAA a second explicit {@link FBObject framebuffer} is being used. + * This method allows compliance w/ the spec, i.e. read and draw framebuffer selection + * and double buffer usage for e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}. + * This method also allows usage of both textures seperately. + *
+ *+ * It would be possible to implement double buffering simply using + * {@link FBObject.TextureAttachment texture attachment}s with one {@link FBObject framebuffer}. + * This would require mode selection and hence complicate the API. Besides, it would + * not support differentiation of read and write framebuffer and hence not be spec compliant. + *
+ *
+ * Actual swapping of the {@link FBObject.TextureAttachment texture}s or {@link FBObject framebuffer}
+ * is performed either in the {@link #contextMadeCurrent(boolean) context current hook}
+ * or when {@link #swapBuffersImpl(boolean) swapping buffers}, whatever comes first.
+ *
true
if initialized, i.e. a {@link GLContext} is bound and made current once, otherwise false
.
+ */
+ public boolean isInitialized();
+
+ /**
+ * Notify this instance about upstream size change
+ * to reconfigure the {@link FBObject}.
+ * @param gl GL context object bound to this drawable, will be made current during operation.
+ * A prev. current context will be make current after operation.
+ * @throws GLException if resize operation failed
+ */
+ void resetSize(GL gl) throws GLException;
+
+ /**
+ * @return the used texture unit
+ */
+ int getTextureUnit();
+
+ /**
+ *
+ * @param unit the texture unit to be used
+ */
+ void setTextureUnit(int unit);
+
+ /**
+ * Set a new sample size
+ * @param gl GL context object bound to this drawable, will be made current during operation.
+ * A prev. current context will be make current after operation.
+ * @param newSamples new sample size
+ * @throws GLException if resetting the FBO failed
+ */
+ void setNumSamples(GL gl, int newSamples) throws GLException;
+
+ /**
+ * @return the number of sample buffers if using MSAA, otherwise 0
+ */
+ int getNumSamples();
+
+ /**
+ * @return the used {@link DoubleBufferMode}
+ */
+ // DoubleBufferMode getDoubleBufferMode(); // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
+
+ /**
+ * Sets the {@link DoubleBufferMode}. Must be called before {@link #isInitialized() initialization},
+ * otherwise an exception is thrown.
+ * + * This call has no effect is MSAA is selected, since MSAA always forces the mode to {@link DoubleBufferMode#FBO FBO}. + * Also setting the mode to {@link DoubleBufferMode#NONE NONE} where double buffering is {@link GLCapabilitiesImmutable#getDoubleBuffered() requested} + * or setting a double buffering mode w/o {@link GLCapabilitiesImmutable#getDoubleBuffered() request} will be ignored. + *
+ *+ * Since {@link DoubleBufferMode#TEXTURE TEXTURE} mode is currently not implemented, this method has no effect. + *
+ * @throws GLException if already initialized, see {@link #isInitialized()}. + */ + // void setDoubleBufferMode(DoubleBufferMode mode) throws GLException; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + /** + * If MSAA is being used and {@link GL#GL_FRONT} is requested, + * the internal {@link FBObject} {@link FBObject#getSamplingSinkFBO() sample sink} is being returned. + * + * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names + * @return the named {@link FBObject} + * @throws IllegalArgumentException if an illegal buffer name is being used + */ + FBObject getFBObject(int bufferName) throws IllegalArgumentException; + + /** + * Returns the named texture buffer. + *+ * If MSAA is being used, only the {@link GL#GL_FRONT} buffer is accessible + * and an exception is being thrown if {@link GL#GL_BACK} is being requested. + *
+ * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names + * @return the named {@link TextureAttachment} + * @throws IllegalArgumentException if using MSAA and {@link GL#GL_BACK} is requested or an illegal buffer name is being used + */ + FBObject.TextureAttachment getTextureBuffer(int bufferName) throws IllegalArgumentException; + + /** Resizeable {@link GLFBODrawable} specialization */ + public interface Resizeable extends GLFBODrawable { + /** + * Resize this drawable. + *+ * This drawable is being locked during operation. + *
+ * @param context the {@link GLContext} bound to this drawable, will be made current during operation + * A prev. current context will be make current after operation. + * @param newWidth + * @param newHeight + * @throws NativeWindowException in case the surface could no be locked + * @throws GLException in case an error during the resize operation occurred + */ + void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException; + } +} diff --git a/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java new file mode 100644 index 000000000..6fe76a3f4 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java @@ -0,0 +1,63 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.opengl.FBObject; + +/** + * Platform-independent {@link GLAutoDrawable} specialization, + * exposing offscreen functionality. + *+ * This class distinguishes itself from {@link GLAutoDrawable} + * with it's {@link #setSize(int, int)} functionality. + *
+ */ +public interface GLOffscreenAutoDrawable extends GLAutoDrawable { + + /** + * Resize this auto drawable. + * @param newWidth + * @param newHeight + * @throws NativeWindowException in case the surface could no be locked + * @throws GLException in case of an error during the resize operation + */ + void setSize(int newWidth, int newHeight) throws NativeWindowException, GLException; + + /** + * Set the upstream UI toolkit object. + * @see #getUpstreamWidget() + */ + void setUpstreamWidget(Object newUpstreamWidget); + + /** {@link FBObject} based {@link GLOffscreenAutoDrawable} specialization */ + public interface FBO extends GLOffscreenAutoDrawable, GLFBODrawable { + } +} diff --git a/src/jogl/classes/javax/media/opengl/GLPbuffer.java b/src/jogl/classes/javax/media/opengl/GLPbuffer.java index 273a992cf..de7731a3b 100644 --- a/src/jogl/classes/javax/media/opengl/GLPbuffer.java +++ b/src/jogl/classes/javax/media/opengl/GLPbuffer.java @@ -45,7 +45,11 @@ package javax.media.opengl; contains experimental methods for accessing the pbuffer's contents as a texture map and enabling rendering to floating-point frame buffers. These methods are not guaranteed to be supported on all - platforms and may be deprecated in a future release. */ + platforms and may be deprecated in a future release. + + @deprecated Use {@link GLOffscreenAutoDrawable} w/ {@link GLCapabilities#setFBO(boolean)} + via {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) GLDrawableFactory.createOffscreenAutoDrawable(..)}. + */ public interface GLPbuffer extends GLAutoDrawable { /** Indicates the GL_APPLE_float_pixels extension is being used for this pbuffer. */ diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 033591fe3..329cf9e3f 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -98,6 +98,7 @@ import jogamp.common.awt.AWTEDTExecutor; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableHelper; +import jogamp.opengl.GLDrawableImpl; // FIXME: Subclasses need to call resetGLFunctionAvailability() on their // context whenever the displayChanged() function is called on our @@ -109,6 +110,16 @@ import jogamp.opengl.GLDrawableHelper; interfaces when adding a heavyweight doesn't work either because of Z-ordering or LayoutManager problems. * + *
+ * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
+ * is being called if {@link GLCapabilitiesImmutable#isOnscreen()} is false
.
+ *
- - Overrides: -
paint
in class java.awt.Component
Overridden to track when this component is removed from a @@ -620,22 +637,37 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @SuppressWarnings("deprecation") @Override public void reshape(int x, int y, int width, int height) { - super.reshape(x, y, width, height); - final GLDrawable _drawable = drawable; - if(null != _drawable && _drawable.isRealized() && !_drawable.getChosenGLCapabilities().isOnscreen()) { - dispose(true); - } else { - sendReshape = true; + synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape + super.reshape(x, y, width, height); + + GLDrawableImpl _drawable = drawable; + if( null != _drawable ) { + if(DEBUG) { + System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+width+"x"+height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, width, height); + if(_drawable != _drawableNew) { + // write back + drawable = _drawableNew; + } + } finally { + _lock.unlock(); + } + } + sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock + } } } - /** Overrides: -
update
in class java.awt.Component
reshape
in class java.awt.Component
true
if {@link AbstractGraphicsDevice#close()} shall be issued,
- * otherwise pass false
. Closing the device is required in case
- * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
- * and no further lifecycle handling is applied.
+ * @param drawable upstream {@link GLDrawableImpl} instance, may be null for lazy initialization
+ * @param context upstream {@link GLContextImpl} instance, may be null for lazy initialization
+ * @param ownsDevice pass true
if {@link AbstractGraphicsDevice#close()} shall be issued,
+ * otherwise pass false
. Closing the device is required in case
+ * the drawable is created w/ it's own new instance, e.g. offscreen drawables,
+ * and no further lifecycle handling is applied.
*/
- public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownDevice) {
+ public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownsDevice) {
this.drawable = drawable;
this.context = context;
- this.ownDevice = ownDevice;
+ this.ownsDevice = ownsDevice;
resetFPSCounter();
}
+ /** Returns the recursive lock object of the upstream implementation, which synchronizes multithreaded access. */
protected abstract RecursiveLock getLock();
- /** Returns the delegated GLDrawable */
- public final GLDrawable getDelegatedDrawable() { return drawable; }
-
/** Default implementation to handle repaint events from the windowing system */
protected final void defaultWindowRepaintOp() {
final GLDrawable _drawable = drawable;
@@ -103,29 +101,43 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
}
- /** Default implementation to handle resize events from the windowing system */
- protected final void defaultWindowResizedOp() {
- final GLDrawable _drawable = drawable;
+ /** Default implementation to handle resize events from the windowing system. All required locks are being claimed. */
+ protected final void defaultWindowResizedOp(int newWidth, int newHeight) throws NativeWindowException, GLException {
+ GLDrawableImpl _drawable = drawable;
if( null!=_drawable ) {
if(DEBUG) {
- System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+getWidth()+"x"+getHeight()+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+ System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle()));
+ }
+ if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
+ final RecursiveLock _lock = getLock();
+ _lock.lock();
+ try {
+ final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, newWidth, newHeight);
+ if(_drawable != _drawableNew) {
+ // write back
+ _drawable = _drawableNew;
+ drawable = _drawableNew;
+ }
+ } finally {
+ _lock.unlock();
+ }
}
sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
if( _drawable.isRealized() ) {
if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) {
display();
}
- }
+ }
}
}
-
+
/**
* Default implementation to handle destroy notifications from the windowing system.
*
* * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol} * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default), - * {@link #defaultDestroy()} is being called. + * a thread safe destruction is being induced. *
*/ protected final void defaultWindowDestroyNotifyOp() { @@ -174,7 +186,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { ctrl.resume(); } } else if (null != ns && ns.isSurfaceLockedByOtherThread()) { - // surface is locked by another thread + // Surface is locked by another thread. // Flag that destroy should be performed on the next // attempt to display. sendDestroy = true; // async, but avoiding deadlock @@ -225,7 +237,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { } _drawable.setRealized(false); } - if( ownDevice ) { + if( ownsDevice ) { _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close(); } } @@ -238,7 +250,6 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { _lock.lock(); try { if(drawable!=null && context != null) { - drawable.swapBuffers(); helper.invokeGL(drawable, context, defaultSwapAction, defaultInitAction); } } finally { @@ -276,7 +287,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { destroy(); return; } - final RecursiveLock _lock = getLock(); + final RecursiveLock _lock = getLock(); _lock.lock(); try { if( null != context ) { @@ -294,6 +305,11 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { drawable.swapBuffers(); } } ; + @Override + public final GLDrawable getDelegatedDrawable() { + return drawable; + } + @Override public final GLContext getContext() { return context; @@ -305,7 +321,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { lock.lock(); try { final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); context=(GLContextImpl)newCtx; if(newCtxCurrent) { context.makeCurrent(); @@ -529,4 +545,10 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { final GLDrawable _drawable = drawable; return null != _drawable ? _drawable.getHandle() : 0; } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + + ", \n\tContext: " + context + /** ", \n\tWindow: "+window+ ", \n\tFactory: "+factory+ */ "]"; + } } diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index e82756022..050c619fd 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -47,6 +47,7 @@ import java.util.Map; import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.common.util.VersionNumber; import com.jogamp.gluegen.runtime.FunctionAddressResolver; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLNameResolver; @@ -85,6 +86,7 @@ public abstract class GLContextImpl extends GLContext { private String glRenderer; private String glRendererLowerCase; + private String glVersion; // Tracks creation and initialization of buffer objects to avoid // repeated glGet calls upon glMapBuffer operations @@ -126,6 +128,9 @@ public abstract class GLContextImpl extends GLContext { GLContextShareSet.synchronizeBufferObjectSharing(shareWith, this); this.drawable = drawable; + if(null != drawable) { + drawable.associateContext(this, true); + } this.drawableRead = drawable; this.glDebugHandler = new GLDebugMessageHandler(this); @@ -205,8 +210,10 @@ public abstract class GLContextImpl extends GLContext { if(!setWriteOnly || drawableRead==drawable) { // if !setWriteOnly || !explicitReadDrawable drawableRead = (GLDrawableImpl) readWrite; } - final GLDrawable old = drawable; + final GLDrawableImpl old = drawable; + old.associateContext(this, false); drawable = (GLDrawableImpl) readWrite ; + drawable.associateContext(this, true); if(lockHeld) { makeCurrent(); } @@ -272,7 +279,7 @@ public abstract class GLContextImpl extends GLContext { if( actualRelease ) { if( !inDestruction ) { try { - drawable.contextMadeCurrent(this, false); + contextMadeCurrent(false); } catch (Throwable t) { drawableContextMadeCurrentException = t; } @@ -331,7 +338,8 @@ public abstract class GLContextImpl extends GLContext { makeCurrent(); } try { - drawable.contextRealized(this, false); + contextRealized(false); + drawable.associateContext(this, false); } catch (Throwable t) { drawableContextRealizedException = t; } @@ -514,19 +522,17 @@ public abstract class GLContextImpl extends GLContext { gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ); } - drawable.contextRealized(this, true); + contextRealized(true); if(DEBUG || TRACE_SWITCH) { System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT_NEW - "+lock); } - } else { - drawable.contextMadeCurrent(this, true); - - if(TRACE_SWITCH) { - System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock); - } + } else if(TRACE_SWITCH) { + System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock); } + contextMadeCurrent(true); + /* FIXME: refactor dependence on Java 2D / JOGL bridge // Try cleaning up any stale server-side OpenGL objects @@ -608,6 +614,20 @@ public abstract class GLContextImpl extends GLContext { } protected abstract void makeCurrentImpl() throws GLException; + /** + * @see GLDrawableImpl#contextRealized(GLContext, boolean) + */ + protected void contextRealized(boolean realized) { + drawable.contextRealized(this, realized); + } + + /** + * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean) + */ + protected void contextMadeCurrent(boolean current) { + drawable.contextMadeCurrent(this, current); + } + /** * Platform dependent entry point for context creation.device
instance is used as-is.
* @param requestedCaps
* @param chooser the custom chooser, may be null for default
- * @param width the initial width
- * @param height the initial height
- * @return the created {@link MutableSurface} instance w/o defined surface handle
+ * @param width the initial width as returned by {@link NativeSurface#getWidth()}, not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getHeight()}, not the actual dummy surface height,
+ * The latter is platform specific and small
+ * @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}.
*/
public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice,
GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height);
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index 090c5fe69..bdf0b6d74 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -43,12 +43,19 @@ package jogamp.opengl;
import java.util.ArrayList;
import java.util.HashSet;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLFBODrawable;
import javax.media.opengl.GLRunnable;
import com.jogamp.opengl.util.Animator;
@@ -108,24 +115,27 @@ public class GLDrawableHelper {
/**
* Associate a new context to the drawable and also propagates the context/drawable switch by
* calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
- * - * If the old context's drawable was an {@link GLAutoDrawable}, it's reference to the given drawable - * is being cleared by calling - * {@link GLAutoDrawable#setContext(GLContext) ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null)}. - *
** If the old or new context was current on this thread, it is being released before switching the drawable. *
+ *+ * Be aware that the old context is still bound to the drawable, + * and that one context can only bound to one drawable at one time! + *
+ *+ * No locking is being performed on the drawable, caller is required to take care of it. + *
* * @param drawable the drawable which context is changed - * @param newCtx the new context * @param oldCtx the old context - * @return true if the newt context was current, otherwise false + * @param newCtx the new context + * @param newCtxCreationFlags additional creation flags if newCtx is not null and not been created yet, see {@link GLContext#setContextCreationFlags(int)} + * @return true if the new context was current, otherwise false * * @see GLAutoDrawable#setContext(GLContext) */ - public final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int additionalCtxCreationFlags) { - if(null != oldCtx && oldCtx.isCurrent()) { + public static final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int newCtxCreationFlags) { + if( null != oldCtx && oldCtx.isCurrent() ) { oldCtx.release(); } final boolean newCtxCurrent; @@ -134,17 +144,135 @@ public class GLDrawableHelper { if(newCtxCurrent) { newCtx.release(); } - newCtx.setContextCreationFlags(additionalCtxCreationFlags); + newCtx.setContextCreationFlags(newCtxCreationFlags); newCtx.setGLDrawable(drawable, true); // propagate context/drawable switch } else { newCtxCurrent = false; } - if(null!=oldCtx && oldCtx.getGLDrawable() instanceof GLAutoDrawable) { - ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null); - } return newCtxCurrent; } + /** + * If the drawable is not realized, OP is a NOP. + *+ * No locking is being performed, caller is required to take care of it. + *
+ * + * @param drawable + * @param context maybe null + * @return the new drawable + */ + public static final GLDrawableImpl recreateGLDrawable(GLDrawableImpl drawable, GLContext context) { + if( ! drawable.isRealized() ) { + return drawable; + } + final boolean contextCurrent = null != context && context.isCurrent(); + final GLDrawableFactory factory = drawable.getFactory(); + final NativeSurface surface = drawable.getNativeSurface(); + final ProxySurface proxySurface = (surface instanceof ProxySurface) ? (ProxySurface)surface : null; + + if(contextCurrent) { + context.release(); + } + + if(null != proxySurface) { + proxySurface.enableUpstreamSurfaceHookLifecycle(false); + } + try { + drawable.setRealized(false); + drawable = (GLDrawableImpl) factory.createGLDrawable(surface); // [2] + drawable.setRealized(true); + } finally { + if(null != proxySurface) { + proxySurface.enableUpstreamSurfaceHookLifecycle(true); + } + } + + if(null != context) { + context.setGLDrawable(drawable, true); // re-association + } + + if(contextCurrent) { + context.makeCurrent(); + } + return drawable; + } + + /** + * Performs resize operation on the given drawable, assuming it is offscreen. + *+ * The {@link GLDrawableImpl}'s {@link NativeSurface} is being locked during operation. + * In case the holder is an auto drawable or similar, it's lock shall be claimed by the caller. + *
+ *+ * May recreate the drawable via {@link #recreateGLDrawable(GLDrawableImpl, GLContext)} + * in case of a a pbuffer- or pixmap-drawable. + *
+ *+ * FBO drawables are resized w/o drawable destruction. + *
+ *+ * Offscreen resize operation is validated w/ drawable size in the end. + * An exception is thrown if not successful. + *
+ * + * @param drawable + * @param context + * @param newWidth the new width, it's minimum is capped to 1 + * @param newHeight the new height, it's minimum is capped to 1 + * @return the new drawable in case of an pbuffer/pixmap drawable, otherwise the passed drawable is being returned. + * @throws NativeWindowException is drawable is not offscreen or it's surface lock couldn't be claimed + * @throws GLException may be thrown a resize operation + */ + public static final GLDrawableImpl resizeOffscreenDrawable(GLDrawableImpl drawable, GLContext context, int newWidth, int newHeight) + throws NativeWindowException, GLException + { + if(drawable.getChosenGLCapabilities().isOnscreen()) { + throw new NativeWindowException("Drawable is not offscreen: "+drawable); + } + final NativeSurface ns = drawable.getNativeSurface(); + final int lockRes = ns.lockSurface(); + if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { + throw new NativeWindowException("Could not lock surface of drawable: "+drawable); + } + try { + if(0>=newWidth) { newWidth = 1; } + if(0>=newHeight) { newHeight = 1; } + // propagate new size + if(ns instanceof ProxySurface) { + final ProxySurface ps = (ProxySurface) ns; + final UpstreamSurfaceHook ush = ps.getUpstreamSurfaceHook(); + if(ush instanceof UpstreamSurfaceHook.MutableSize) { + ((UpstreamSurfaceHook.MutableSize)ush).setSize(newWidth, newHeight); + } else if(DEBUG) { // we have to assume UpstreamSurfaceHook contains the new size already, hence size check @ bottom + System.err.println("GLDrawableHelper.resizeOffscreenDrawable: Drawable's offscreen ProxySurface n.a. UpstreamSurfaceHook.MutableSize, but "+ush.getClass().getName()+": "+ush); + } + } else if(DEBUG) { // we have to assume surface contains the new size already, hence size check @ bottom + System.err.println("GLDrawableHelper.resizeOffscreenDrawable: Drawable's offscreen surface n.a. ProxySurface, but "+ns.getClass().getName()+": "+ns); + } + if(drawable instanceof GLFBODrawable) { + if( null != context && context.isCreated() ) { + ((GLFBODrawable) drawable).resetSize(context.getGL()); + } + } else { + drawable = GLDrawableHelper.recreateGLDrawable(drawable, context); + } + } finally { + ns.unlockSurface(); + } + if(drawable.getWidth() != newWidth || drawable.getHeight() != newHeight) { + throw new InternalError("Incomplete resize operation: expected "+newWidth+"x"+newHeight+", has: "+drawable); + } + return drawable; + } + public final void addGLEventListener(GLEventListener listener) { addGLEventListener(-1, listener); } @@ -196,15 +324,11 @@ public class GLDrawableHelper { } } - private final boolean init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { - if(listenersToBeInit.remove(l)) { - l.init(drawable); - if(sendReshape) { - reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false /* checkInit */); - } - return true; + private final void init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { + l.init(drawable); + if(sendReshape) { + reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false /* checkInit */); } - return false; } /** The default init action to be called once after ctx is being created @ 1st makeCurrent(). */ @@ -214,14 +338,11 @@ public class GLDrawableHelper { for (int i=0; i < _listeners.size(); i++) { final GLEventListener listener = _listeners.get(i) ; - // If make current ctx, invoked by invokGL(..), results in a new ctx, init gets called. + // If make ctx current, invoked by invokGL(..), results in a new ctx, init gets called. // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window), - // hence the must always be initialized unconditional. - listenersToBeInit.add(listener); - - if ( ! init( listener, drawable, true /* sendReshape */) ) { - throw new GLException("GLEventListener "+listener+" already initialized: "+drawable); - } + // hence it must be called unconditional, always. + listenersToBeInit.remove(listener); // remove if exist, avoiding dbl init + init( listener, drawable, true /* sendReshape */); } } } @@ -239,7 +360,9 @@ public class GLDrawableHelper { final GLEventListener listener = _listeners.get(i) ; // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable - init( listener, drawable, true /* sendReshape */) ; + if( listenersToBeInit.remove(listener) ) { + init( listener, drawable, true /* sendReshape */) ; + } listener.display(drawable); } } @@ -251,7 +374,9 @@ public class GLDrawableHelper { // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable synchronized(listenersLock) { - init( listener, drawable, false /* sendReshape */) ; + if( listenersToBeInit.remove(listener) ) { + init( listener, drawable, false /* sendReshape */) ; + } } } if(setViewport) { diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index abf2bf557..311690f1d 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -43,6 +43,7 @@ package jogamp.opengl; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GL; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -76,31 +77,46 @@ public abstract class GLDrawableImpl implements GLDrawable { if( !realized ) { return; // destroyed already } - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); - if ( caps.getDoubleBuffered() ) { - if(!surface.surfaceSwap()) { - int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] - if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { - return; + int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] + if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { + return; + } + try { + if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { + updateHandle(); + } + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); + if ( caps.getDoubleBuffered() ) { + if(!surface.surfaceSwap()) { + swapBuffersImpl(true); } - try { - if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { - updateHandle(); - } - swapBuffersImpl(); - } finally { - unlockSurface(); + } else { + final GLContext ctx = GLContext.getCurrent(); + if(null!=ctx && ctx.getGLDrawable()==this) { + ctx.getGL().glFlush(); } + swapBuffersImpl(false); } - } else { - GLContext ctx = GLContext.getCurrent(); - if(null!=ctx && ctx.getGLDrawable()==this) { - ctx.getGL().glFinish(); - } - } + } finally { + unlockSurface(); + } surface.surfaceUpdated(this, surface, System.currentTimeMillis()); } - protected abstract void swapBuffersImpl(); + + /** + * Platform and implementation depending surface swap. + *The surface is locked.
+ *
+ * If doubleBuffered
is true
,
+ * an actual platform dependent surface swap shall be executed.
+ *
+ * If doubleBuffered
is false
,
+ * {@link GL#glFlush()} has been called already and
+ * the implementation may execute implementation specific code.
+ *
realized
is true
, the context has just been created and made current.
*
*
- * If realized
is false
, the context is still current and will be release and destroyed after this method returns.
+ * If realized
is false
, the context is still current and will be released and destroyed after this method returns.
*
* @see #contextMadeCurrent(GLContext, boolean)
@@ -199,18 +218,27 @@ public abstract class GLDrawableImpl implements GLDrawable {
/**
* Callback for special implementations, allowing GLContext to trigger GL related lifecycle: makeCurrent
, release
.
*
- * Will not be called if {@link #contextRealized(GLContext, boolean)} has been triggered. - *
- *
* If current
is true
, the context has just been made current.
*
* If current
is false
, the context is still current and will be release after this method returns.
*
+ * Note: Will also be called after {@link #contextRealized(GLContext, boolean) contextRealized(ctx, true)} + * but not at context destruction, i.e. {@link #contextRealized(GLContext, boolean) contextRealized(ctx, false)}. + *
* @see #contextRealized(GLContext, boolean) */ protected void contextMadeCurrent(GLContext glc, boolean current) { } + /** + * Callback for special implementations, allowing to associate bound context to this drawable (bound == true) + * or to remove such association (bound == false). + * @param ctx the just bounded or unbounded context + * @param bound iftrue
create an association, otherwise remove it
+ */
+ protected void associateContext(GLContext ctx, boolean bound) { }
+
/** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/
protected int getDefaultDrawFramebuffer() { return 0; }
/** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */
@@ -245,8 +273,8 @@ public abstract class GLDrawableImpl implements GLDrawable {
public String toString() {
return getClass().getSimpleName()+"[Realized "+isRealized()+
",\n\tFactory "+getFactory()+
- ",\n\thandle "+toHexString(getHandle())+
- ",\n\tWindow "+getNativeSurface()+"]";
+ ",\n\tHandle "+toHexString(getHandle())+
+ ",\n\tSurface "+getNativeSurface()+"]";
}
protected static String getThreadName() {
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index 03bc26cbc..de45466f3 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -1,142 +1,476 @@
package jogamp.opengl;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
import javax.media.opengl.GL;
-import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLFBODrawable;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.FBObject.Attachment;
+import com.jogamp.opengl.FBObject.Colorbuffer;
import com.jogamp.opengl.FBObject.TextureAttachment;
/**
- * Offscreen GLDrawable implementation using framebuffer object (FBO)
- * as it's offscreen rendering mechanism.
+ * {@link FBObject} offscreen GLDrawable implementation, i.e. {@link GLFBODrawable}.
+ * + * It utilizes the context lifecycle hook {@link #contextRealized(GLContext, boolean)} + * to initialize the {@link FBObject} instance. + *
+ *+ * It utilizes the context current hook {@link #contextMadeCurrent(GLContext, boolean) contextMadeCurrent(context, true)} + * to {@link FBObject#bind(GL) bind} the FBO. + *
+ * See {@link GLFBODrawable} for double buffering details. * * @see GLDrawableImpl#contextRealized(GLContext, boolean) * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean) * @see GLDrawableImpl#getDefaultDrawFramebuffer() * @see GLDrawableImpl#getDefaultReadFramebuffer() */ -public class GLFBODrawableImpl extends GLDrawableImpl { - final GLDrawableImpl parent; - final FBObject fbo; - int texUnit; - int samplesTexUnit = 0; - int width=0, height=0, samples=0; - - protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, - NativeSurface surface, int initialWidth, int initialHeight, int textureUnit) { +public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { + protected static final boolean DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject"); + + private final GLDrawableImpl parent; + + private boolean initialized; + private int texUnit; + private int samples; + + private FBObject[] fbos; + private int fboIBack; // points to GL_BACK buffer + private int fboIFront; // points to GL_FRONT buffer + private FBObject pendingFBOReset = null; + private boolean fboBound; + private static final int bufferCount = 2; // number of FBOs for double buffering. TODO: Possible to configure! + + // private DoubleBufferMode doubleBufferMode; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + private SwapBufferContext swapBufferContext; + + public static interface SwapBufferContext { + public void swapBuffers(boolean doubleBuffered); + } + + protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, NativeSurface surface, + GLCapabilitiesImmutable fboCaps, int textureUnit) { super(factory, surface, false); + this.initialized = false; + + // Replace the chosen caps of dummy-surface w/ it's clone and copied values of orig FBO caps request. + // The dummy-surface has already been configured, hence value replace is OK + // and due to cloning, the native GLCapability portion is being preserved. + final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration(); + final GLCapabilities fboCapsNative = (GLCapabilities) msConfig.getChosenCapabilities().cloneMutable(); + fboCapsNative.copyFrom(fboCaps); + msConfig.setChosenCapabilities(fboCapsNative); + this.parent = parent; this.texUnit = textureUnit; - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); - this.width = initialWidth; - this.height = initialHeight; - this.samples = caps.getNumSamples(); - this.fbo = new FBObject(); + this.samples = fboCaps.getNumSamples(); + + // default .. // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + // this.doubleBufferMode = ( samples > 0 || fboCaps.getDoubleBuffered() ) ? DoubleBufferMode.FBO : DoubleBufferMode.NONE ; + + this.swapBufferContext = null; } - @Override - protected void contextRealized(GLContext glc, boolean realized) { - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); - final GL gl = glc.getGL(); - if(realized) { - fbo.reset(gl, width, height, samples); - samples = fbo.getNumSamples(); // update, maybe capped + private final void initialize(boolean realize, GL gl) { + if(realize) { + final int maxSamples = gl.getMaxRenderbufferSamples(); + samples = samples <= maxSamples ? samples : maxSamples; + + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); + final int fbosN; if(samples > 0) { - fbo.attachColorbuffer(gl, 0, caps.getAlphaBits()>0); + fbosN = 1; + } else if( caps.getDoubleBuffered() ) { + fbosN = bufferCount; } else { - fbo.attachTexture2D(gl, 0, caps.getAlphaBits()>0); + fbosN = 1; } - if( caps.getStencilBits() > 0 ) { - fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24); - } else { - fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24); + + fbos = new FBObject[fbosN]; + fboIBack = 0; // head + fboIFront = fbos.length - 1; // tail + + for(int i=0; i+ * The implementation may itself apply the swapping, * in which case true shall be returned. + *
* * @return true if this method completed swapping the surface, * otherwise false, in which case eg the GLDrawable diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java index f7dbc6c27..f9800109c 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java @@ -50,4 +50,7 @@ public interface OffscreenLayerSurface { /** Returns true if a surface layer is attached, otherwise false. */ public boolean isSurfaceLayerAttached(); + /** Sets the capabilities of this instance, allowing upstream API's to refine it, i.e. OpenGL related settings. */ + public void setChosenCapabilities(CapabilitiesImmutable caps); + } diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java index 7fc9789c2..395fdc818 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java @@ -1,5 +1,5 @@ /** - * Copyright 2010 JogAmp Community. All rights reserved. + * Copyright 2012 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -29,242 +29,82 @@ package javax.media.nativewindow; import jogamp.nativewindow.Debug; -import jogamp.nativewindow.SurfaceUpdatedHelper; -import com.jogamp.common.util.locks.LockFactory; -import com.jogamp.common.util.locks.RecursiveLock; - -public abstract class ProxySurface implements NativeSurface, MutableSurface { +/** + * Provides a mutable {@link NativeSurface}, i.e. {@link MutableSurface}, while allowing an + * {@link UpstreamSurfaceHook} to influence the lifecycle and information. + * + * @see UpstreamSurfaceHook + * @see MutableSurface + * @see NativeSurface + */ +public interface ProxySurface extends MutableSurface { public static final boolean DEBUG = Debug.debug("ProxySurface"); /** - * Implementation specific bitvalue stating the upstream's {@link AbstractGraphicsDevice} is owned by this {@link ProxySurface}. - * @see #setImplBitfield(int) - * @see #getImplBitfield() + * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's surface handle + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() */ - public static final int OWN_DEVICE = 1 << 7; + public static final int OPT_PROXY_OWNS_UPSTREAM_SURFACE = 1 << 6; + + /** + * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's {@link AbstractGraphicsDevice}. + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() + */ + public static final int OPT_PROXY_OWNS_UPSTREAM_DEVICE = 1 << 7; /** * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete. - * @see #setImplBitfield(int) - * @see #getImplBitfield() + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() */ - public static final int INVISIBLE_WINDOW = 1 << 8; + public static final int OPT_UPSTREAM_WINDOW_INVISIBLE = 1 << 8; - /** Interface allowing upstream caller to pass lifecycle actions and size info to a {@link ProxySurface} instance. */ - public interface UpstreamSurfaceHook { - /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */ - public void create(ProxySurface s); - /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */ - public void destroy(ProxySurface s); + /** Allow redefining the AbstractGraphicsConfiguration */ + public void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg); - /** Returns the width of the upstream surface */ - public int getWidth(ProxySurface s); - /** Returns the height of the upstream surface */ - public int getHeight(ProxySurface s); - } + /** Returns the set {@link UpstreamSurfaceHook}, or null if not set. */ + public UpstreamSurfaceHook getUpstreamSurfaceHook(); - private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); - private final AbstractGraphicsConfiguration config; // control access due to delegation - private final UpstreamSurfaceHook upstream; - public final int initialWidth; - public final int initialHeight; - private long surfaceHandle_old; - protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); - protected long displayHandle; - protected int scrnIndex; - protected int implBitfield; - /** - * @param cfg the {@link AbstractGraphicsConfiguration} to be used - * @param initialWidth the initial width - * @param initialHeight the initial height + * Sets the {@link UpstreamSurfaceHook} and returns the previous value. */ - protected ProxySurface(AbstractGraphicsConfiguration cfg, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { - if(null == cfg) { - throw new IllegalArgumentException("null config"); - } - this.config = cfg; - this.upstream = upstream; - this.initialWidth = initialWidth; - this.initialHeight = initialHeight; - this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - this.surfaceHandle_old = 0; - this.implBitfield = 0; - } - - public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; } + public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook); + + /** + * Enables or disables the {@link UpstreamSurfaceHook} lifecycle functions + * {@link UpstreamSurfaceHook#create(ProxySurface)} and {@link UpstreamSurfaceHook#destroy(ProxySurface)}. + *+ * Use this for small code blocks where the native resources shall not change, + * i.e. resizing a derived (OpenGL) drawable. + *
+ */ + public void enableUpstreamSurfaceHookLifecycle(boolean enable); /** - * If a valid {@link UpstreamSurfaceHook} instance is passed in the - * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, * {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set. */ - public void createNotify() { - if(null != upstream) { - upstream.create(this); - } - this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - this.surfaceHandle_old = 0; - } + public void createNotify(); /** - * If a valid {@link UpstreamSurfaceHook} instance is passed in the - * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, - * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all fields are cleared. + * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all proxy surface/window handles shall be cleared. */ - public void destroyNotify() { - if(null != upstream) { - upstream.destroy(this); - invalidateImpl(); - } - this.displayHandle = 0; - this.surfaceHandle_old = 0; - } + public void destroyNotify(); - /** - * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed. - * @see #destroyNotify() - */ - protected void invalidateImpl() { - throw new InternalError("UpstreamSurfaceHook given, but required method not implemented."); - } + public StringBuilder getUpstreamOptionBits(StringBuilder sink); + public int getUpstreamOptionBits(); - @Override - public final long getDisplayHandle() { - return displayHandle; - } - - protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() { - return config; - } - - @Override - public final AbstractGraphicsConfiguration getGraphicsConfiguration() { - return config.getNativeGraphicsConfiguration(); - } - - @Override - public final int getScreenIndex() { - return getGraphicsConfiguration().getScreen().getIndex(); - } - - @Override - public abstract long getSurfaceHandle(); - - @Override - public abstract void setSurfaceHandle(long surfaceHandle); + /** Returnstrue
if the give bit-mask v
is set in this instance upstream-option-bits, otherwise false
.*/
+ public boolean containsUpstreamOptionBits(int v);
- @Override
- public final int getWidth() {
- if(null != upstream) {
- return upstream.getWidth(this);
- }
- return initialWidth;
- }
-
- @Override
- public final int getHeight() {
- if(null != upstream) {
- return upstream.getHeight(this);
- }
- return initialHeight;
- }
-
- @Override
- public boolean surfaceSwap() {
- return false;
- }
-
- @Override
- public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
- }
-
- @Override
- public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
- surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
- }
-
- @Override
- public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
- surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
- }
-
- @Override
- public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
- surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
- }
-
- @Override
- public int lockSurface() throws NativeWindowException, RuntimeException {
- surfaceLock.lock();
- int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
-
- if ( LOCK_SURFACE_NOT_READY == res ) {
- try {
- final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
- adevice.lock();
- try {
- res = lockSurfaceImpl();
- if(LOCK_SUCCESS == res && surfaceHandle_old != getSurfaceHandle()) {
- res = LOCK_SURFACE_CHANGED;
- if(DEBUG) {
- System.err.println("ProxySurface: surface change 0x"+Long.toHexString(surfaceHandle_old)+" -> 0x"+Long.toHexString(getSurfaceHandle()));
- // Thread.dumpStack();
- }
- }
- } finally {
- if (LOCK_SURFACE_NOT_READY >= res) {
- adevice.unlock();
- }
- }
- } finally {
- if (LOCK_SURFACE_NOT_READY >= res) {
- surfaceLock.unlock();
- }
- }
- }
- return res;
- }
-
- @Override
- public final void unlockSurface() {
- surfaceLock.validateLocked();
- surfaceHandle_old = getSurfaceHandle();
-
- if (surfaceLock.getHoldCount() == 1) {
- final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
- try {
- unlockSurfaceImpl();
- } finally {
- adevice.unlock();
- }
- }
- surfaceLock.unlock();
- }
-
- protected abstract int lockSurfaceImpl();
-
- protected abstract void unlockSurfaceImpl() ;
-
- public final void validateSurfaceLocked() {
- surfaceLock.validateLocked();
- }
-
- @Override
- public final boolean isSurfaceLockedByOtherThread() {
- return surfaceLock.isLockedByOtherThread();
- }
-
- @Override
- public final Thread getSurfaceLockOwner() {
- return surfaceLock.getOwner();
- }
+ /** Add the given bit-mask to this instance upstream-option-bits using bit-or w/ v
.*/
+ public void addUpstreamOptionBits(int v);
- @Override
- public abstract String toString();
+ /** Clear the given bit-mask from this instance upstream-option-bits using bit-and w/ ~v
*/
+ public void clearUpstreamOptionBits(int v);
- public int getImplBitfield() { return implBitfield; }
- public void setImplBitfield(int v) { implBitfield=v; }
+ public StringBuilder toString(StringBuilder sink);
+ public String toString();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java
new file mode 100644
index 000000000..6fe2e5364
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package javax.media.nativewindow;
+
+/**
+ * Interface allowing upstream caller to pass lifecycle actions and size info
+ * to a {@link ProxySurface} instance.
+ */
+public interface UpstreamSurfaceHook {
+ /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */
+ public void create(ProxySurface s);
+ /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */
+ public void destroy(ProxySurface s);
+
+ /** Returns the width of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */
+ public int getWidth(ProxySurface s);
+ /** Returns the height of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */
+ public int getHeight(ProxySurface s);
+
+ /**
+ * {@link UpstreamSurfaceHook} w/ mutable size, allowing it's {@link ProxySurface} user to resize.
+ */
+ public interface MutableSize extends UpstreamSurfaceHook {
+ public void setSize(int width, int height);
+ }
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
new file mode 100644
index 000000000..63f56cbae
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java
@@ -0,0 +1,326 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.SurfaceUpdatedListener;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
+public abstract class ProxySurfaceImpl implements ProxySurface {
+ private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper();
+ protected long displayHandle; // convenient ref of config.screen.device.handle
+ private AbstractGraphicsConfiguration config; // control access due to delegation
+ private UpstreamSurfaceHook upstream;
+ private long surfaceHandle_old;
+ private RecursiveLock surfaceLock = LockFactory.createRecursiveLock();
+ private int implBitfield;
+ private boolean upstreamSurfaceHookLifecycleEnabled;
+
+ /**
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param upstream the {@link UpstreamSurfaceHook} to be used
+ * @param ownsDevice true
if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise false
. Owning the device implies closing it at {@link #destroyNotify()}.
+ */
+ protected ProxySurfaceImpl(AbstractGraphicsConfiguration cfg, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ if(null == cfg) {
+ throw new IllegalArgumentException("null AbstractGraphicsConfiguration");
+ }
+ if(null == upstream) {
+ throw new IllegalArgumentException("null UpstreamSurfaceHook");
+ }
+ this.config = cfg;
+ this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ this.upstream = upstream;
+ this.surfaceHandle_old = 0;
+ this.implBitfield = 0;
+ this.upstreamSurfaceHookLifecycleEnabled = true;
+ if(ownsDevice) {
+ addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ }
+
+ @Override
+ public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; }
+
+ @Override
+ public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook) {
+ if(null == hook) {
+ throw new IllegalArgumentException("null UpstreamSurfaceHook");
+ }
+ upstream = hook;
+ }
+
+ @Override
+ public final void enableUpstreamSurfaceHookLifecycle(boolean enable) {
+ upstreamSurfaceHookLifecycleEnabled = enable;
+ }
+
+ @Override
+ public void createNotify() {
+ if(upstreamSurfaceHookLifecycleEnabled) {
+ upstream.create(this);
+ }
+ this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle();
+ this.surfaceHandle_old = 0;
+ }
+
+ @Override
+ public void destroyNotify() {
+ if(upstreamSurfaceHookLifecycleEnabled) {
+ upstream.destroy(this);
+ if( containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ) ) {
+ final AbstractGraphicsDevice aDevice = getGraphicsConfiguration().getScreen().getDevice();
+ aDevice.close();
+ clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ invalidateImpl();
+ }
+ this.displayHandle = 0;
+ this.surfaceHandle_old = 0;
+ }
+
+ /**
+ * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed.
+ * @see #destroyNotify()
+ */
+ protected void invalidateImpl() {
+ throw new InternalError("UpstreamSurfaceHook given, but required method not implemented.");
+ }
+
+ @Override
+ public final long getDisplayHandle() {
+ return displayHandle;
+ }
+
+ protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() {
+ return config;
+ }
+
+ @Override
+ public final AbstractGraphicsConfiguration getGraphicsConfiguration() {
+ return config.getNativeGraphicsConfiguration();
+ }
+
+ @Override
+ public final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) {
+ config = cfg;
+ }
+
+ @Override
+ public final int getScreenIndex() {
+ return getGraphicsConfiguration().getScreen().getIndex();
+ }
+
+ @Override
+ public abstract long getSurfaceHandle();
+
+ @Override
+ public abstract void setSurfaceHandle(long surfaceHandle);
+
+ @Override
+ public final int getWidth() {
+ return upstream.getWidth(this);
+ }
+
+ @Override
+ public final int getHeight() {
+ return upstream.getHeight(this);
+ }
+
+ @Override
+ public boolean surfaceSwap() {
+ return false;
+ }
+
+ @Override
+ public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l);
+ }
+
+ @Override
+ public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) {
+ surfaceUpdatedHelper.removeSurfaceUpdatedListener(l);
+ }
+
+ @Override
+ public void surfaceUpdated(Object updater, NativeSurface ns, long when) {
+ surfaceUpdatedHelper.surfaceUpdated(updater, ns, when);
+ }
+
+ @Override
+ public int lockSurface() throws NativeWindowException, RuntimeException {
+ surfaceLock.lock();
+ int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ?
+
+ if ( LOCK_SURFACE_NOT_READY == res ) {
+ try {
+ final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
+ adevice.lock();
+ try {
+ res = lockSurfaceImpl();
+ if(LOCK_SUCCESS == res && surfaceHandle_old != getSurfaceHandle()) {
+ res = LOCK_SURFACE_CHANGED;
+ if(DEBUG) {
+ System.err.println("ProxySurfaceImpl: surface change 0x"+Long.toHexString(surfaceHandle_old)+" -> 0x"+Long.toHexString(getSurfaceHandle()));
+ // Thread.dumpStack();
+ }
+ }
+ } finally {
+ if (LOCK_SURFACE_NOT_READY >= res) {
+ adevice.unlock();
+ }
+ }
+ } finally {
+ if (LOCK_SURFACE_NOT_READY >= res) {
+ surfaceLock.unlock();
+ }
+ }
+ }
+ return res;
+ }
+
+ @Override
+ public final void unlockSurface() {
+ surfaceLock.validateLocked();
+ surfaceHandle_old = getSurfaceHandle();
+
+ if (surfaceLock.getHoldCount() == 1) {
+ final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice();
+ try {
+ unlockSurfaceImpl();
+ } finally {
+ adevice.unlock();
+ }
+ }
+ surfaceLock.unlock();
+ }
+
+ protected abstract int lockSurfaceImpl();
+
+ protected abstract void unlockSurfaceImpl() ;
+
+ public final void validateSurfaceLocked() {
+ surfaceLock.validateLocked();
+ }
+
+ @Override
+ public final boolean isSurfaceLockedByOtherThread() {
+ return surfaceLock.isLockedByOtherThread();
+ }
+
+ @Override
+ public final Thread getSurfaceLockOwner() {
+ return surfaceLock.getOwner();
+ }
+
+ public final StringBuilder getUpstreamOptionBits(StringBuilder sink) {
+ if(null == sink) {
+ sink = new StringBuilder();
+ }
+ sink.append("UOB[ ");
+ if(0 == implBitfield) {
+ sink.append("]");
+ return sink;
+ }
+ boolean needsOr = false;
+ if( 0 != ( implBitfield & OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
+ sink.append("OWNS_SURFACE");
+ needsOr = true;
+ }
+ if( 0 != ( implBitfield & OPT_PROXY_OWNS_UPSTREAM_DEVICE ) ) {
+ if(needsOr) {
+ sink.append(" | ");
+ }
+ sink.append("OWNS_DEVICE");
+ needsOr = true;
+ }
+ if( 0 != ( implBitfield & OPT_UPSTREAM_WINDOW_INVISIBLE ) ) {
+ if(needsOr) {
+ sink.append(" | ");
+ }
+ sink.append("WINDOW_INVISIBLE");
+ needsOr = true;
+ }
+ sink.append(" ]");
+ return sink;
+ }
+
+ @Override
+ public final int getUpstreamOptionBits() { return implBitfield; }
+
+ @Override
+ public final boolean containsUpstreamOptionBits(int v) {
+ return v == ( implBitfield & v ) ;
+ }
+
+ @Override
+ public final void addUpstreamOptionBits(int v) { implBitfield |= v; }
+
+ @Override
+ public final void clearUpstreamOptionBits(int v) { implBitfield &= ~v; }
+
+ @Override
+ public StringBuilder toString(StringBuilder sink) {
+ if(null == sink) {
+ sink = new StringBuilder();
+ }
+ sink.append(getUpstreamSurfaceHook()).
+ append(", displayHandle 0x" + Long.toHexString(getDisplayHandle())).
+ append(", surfaceHandle 0x" + Long.toHexString(getSurfaceHandle())).
+ append(", size " + getWidth() + "x" + getHeight()).append(", ");
+ getUpstreamOptionBits(sink);
+ sink.append(", surfaceLock "+surfaceLock);
+ return sink;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder msg = new StringBuilder();
+ msg.append(getClass().getSimpleName()).append("[ ");
+ toString(msg);
+ msg.append(" ]");
+ return msg.toString();
+ }
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
new file mode 100644
index 000000000..e544bc61a
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.nativewindow;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
+
+public class WrappedSurface extends ProxySurfaceImpl {
+ protected long surfaceHandle;
+
+ /**
+ * Utilizes a {@link UpstreamSurfaceHook.MutableSize} to hold the size information,
+ * which is being passed to the {@link ProxySurface} instance.
+ *
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
+ * @param initialWidth
+ * @param initialHeight
+ * @param ownsDevice true
if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise false
. Owning the device implies closing it at {@link #destroyNotify()}.
+ */
+ public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, int initialWidth, int initialHeight, boolean ownsDevice) {
+ super(cfg, new UpstreamSurfaceHookMutableSize(initialWidth, initialHeight), ownsDevice);
+ surfaceHandle=handle;
+ }
+
+ /**
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined
+ * @param upstream the {@link UpstreamSurfaceHook} to be used
+ * @param ownsDevice true
if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise false
.
+ */
+ public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ super(cfg, upstream, ownsDevice);
+ surfaceHandle=handle;
+ }
+
+ @Override
+ protected void invalidateImpl() {
+ surfaceHandle = 0;
+ }
+
+ @Override
+ public final long getSurfaceHandle() {
+ return surfaceHandle;
+ }
+
+ @Override
+ public final void setSurfaceHandle(long surfaceHandle) {
+ this.surfaceHandle=surfaceHandle;
+ }
+
+ @Override
+ protected final int lockSurfaceImpl() {
+ return LOCK_SUCCESS;
+ }
+
+ @Override
+ protected final void unlockSurfaceImpl() {
+ }
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
index e81d61e0f..5fd242247 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
@@ -51,7 +51,6 @@ import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.MutableSurface;
import javax.media.nativewindow.util.Point;
-import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.nativewindow.awt.JAWTWindow;
import jogamp.nativewindow.jawt.JAWT;
@@ -71,17 +70,18 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
}
protected void invalidateNative() {
- surfaceHandle=0;
+ offscreenSurfaceHandle=0;
+ offscreenSurfaceHandleSet=false;
if(isOffscreenLayerSurfaceEnabled()) {
if(0 != rootSurfaceLayerHandle) {
OSXUtil.DestroyCALayer(rootSurfaceLayerHandle);
rootSurfaceLayerHandle = 0;
}
- if(0 != drawable) {
- OSXUtil.DestroyNSWindow(drawable);
- drawable = 0;
+ if(0 != windowHandle) {
+ OSXUtil.DestroyNSWindow(windowHandle);
}
}
+ windowHandle=0;
}
protected void attachSurfaceLayerImpl(final long layerHandle) {
@@ -92,8 +92,14 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
OSXUtil.RemoveCASublayer(rootSurfaceLayerHandle, layerHandle);
}
- public long getSurfaceHandle() {
- return isOffscreenLayerSurfaceEnabled() ? surfaceHandle : super.getSurfaceHandle() ;
+ @Override
+ public final long getWindowHandle() {
+ return windowHandle;
+ }
+
+ @Override
+ public final long getSurfaceHandle() {
+ return offscreenSurfaceHandleSet ? offscreenSurfaceHandle : drawable /* super.getSurfaceHandle() */ ;
}
public void setSurfaceHandle(long surfaceHandle) {
@@ -103,7 +109,8 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
if(DEBUG) {
System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
}
- this.surfaceHandle = surfaceHandle;
+ this.offscreenSurfaceHandle = surfaceHandle;
+ this.offscreenSurfaceHandleSet = true;
}
protected JAWT fetchJAWTImpl() throws NativeWindowException {
@@ -167,6 +174,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
unlockSurfaceImpl();
return NativeWindow.LOCK_SURFACE_NOT_READY;
} else {
+ windowHandle = OSXUtil.GetNSWindow(drawable);
ret = NativeWindow.LOCK_SUCCESS;
}
} else {
@@ -177,36 +185,46 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
* The actual surface/ca-layer shall be created/attached
* by the upper framework (JOGL) since they require more information.
*/
+ String errMsg = null;
if(0 == drawable) {
- drawable = OSXUtil.CreateNSWindow(0, 0, getBounds().getWidth(), getBounds().getHeight());
- if(0 == drawable) {
- unlockSurfaceImpl();
- throw new NativeWindowException("Unable to created dummy NSWindow (layered case)");
+ windowHandle = OSXUtil.CreateNSWindow(0, 0, 64, 64);
+ if(0 == windowHandle) {
+ errMsg = "Unable to create dummy NSWindow (layered case)";
+ } else {
+ drawable = OSXUtil.GetNSView(windowHandle);
+ if(0 == drawable) {
+ errMsg = "Null NSView of NSWindow 0x"+Long.toHexString(windowHandle);
+ }
+ }
+ if(null == errMsg) {
+ // fix caps reflecting offscreen! (no GL available here ..)
+ Capabilities caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable();
+ caps.setOnscreen(false);
+ setChosenCapabilities(caps);
}
- // fix caps reflecting offscreen!
- Capabilities caps = (Capabilities) getPrivateGraphicsConfiguration().getChosenCapabilities().cloneMutable();
- caps.setOnscreen(false);
- getPrivateGraphicsConfiguration().setChosenCapabilities(caps);
- caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable();
- caps.setOnscreen(false);
- ((MutableGraphicsConfiguration)getGraphicsConfiguration()).setChosenCapabilities(caps);
}
- if(0 == rootSurfaceLayerHandle) {
- rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
- if(0 == rootSurfaceLayerHandle) {
- OSXUtil.DestroyNSWindow(drawable);
- drawable = 0;
- unlockSurfaceImpl();
- throw new NativeWindowException("Could not create root CALayer: "+this);
+ if(null == errMsg) {
+ if(0 == rootSurfaceLayerHandle) {
+ rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
+ if(0 == rootSurfaceLayerHandle) {
+ errMsg = "Could not create root CALayer";
+ } else if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) {
+ errMsg = "Could not set JAWT rootSurfaceLayerHandle 0x"+Long.toHexString(rootSurfaceLayerHandle);
+ }
}
- if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) {
+ }
+ if(null != errMsg) {
+ if(0 != rootSurfaceLayerHandle) {
OSXUtil.DestroyCALayer(rootSurfaceLayerHandle);
rootSurfaceLayerHandle = 0;
- OSXUtil.DestroyNSWindow(drawable);
- drawable = 0;
- unlockSurfaceImpl();
- throw new NativeWindowException("Could not set JAWT rootSurfaceLayerHandle: "+this);
}
+ if(0 != windowHandle) {
+ OSXUtil.DestroyNSWindow(windowHandle);
+ windowHandle = 0;
+ }
+ drawable = 0;
+ unlockSurfaceImpl();
+ throw new NativeWindowException(errMsg+": "+this);
}
ret = NativeWindow.LOCK_SUCCESS;
}
@@ -264,7 +282,9 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
private long rootSurfaceLayerHandle = 0; // attached to the JAWT_SurfaceLayer
- private long surfaceHandle = 0;
+ private long windowHandle = 0;
+ private long offscreenSurfaceHandle = 0;
+ private boolean offscreenSurfaceHandleSet = false;
// Workaround for instance of 4796548
private boolean firstLock = true;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java
new file mode 100644
index 000000000..de3206c0c
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java
@@ -0,0 +1,56 @@
+package jogamp.nativewindow.macosx;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
+
+public class OSXDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
+ long nsWindow;
+
+ /**
+ * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
+ * not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * not the actual dummy surface height,
+ * The latter is platform specific and small
+ */
+ public OSXDummyUpstreamSurfaceHook(int width, int height) {
+ super(width, height);
+ nsWindow = 0;
+ }
+
+ @Override
+ public final void create(ProxySurface s) {
+ if(0 == nsWindow && 0 == s.getSurfaceHandle()) {
+ nsWindow = OSXUtil.CreateNSWindow(0, 0, 64, 64);
+ if(0 == nsWindow) {
+ throw new NativeWindowException("Error NS window 0");
+ }
+ long nsView = OSXUtil.GetNSView(nsWindow);
+ if(0 == nsView) {
+ throw new NativeWindowException("Error NS view 0");
+ }
+ s.setSurfaceHandle(nsView);
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
+ }
+
+ @Override
+ public final void destroy(ProxySurface s) {
+ if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
+ if( 0 == nsWindow || 0 == s.getSurfaceHandle() ) {
+ throw new InternalError("Owns upstream surface, but no OSX view/window: "+s+", nsWindow 0x"+Long.toHexString(nsWindow));
+ }
+ OSXUtil.DestroyNSWindow(nsWindow);
+ nsWindow = 0;
+ s.setSurfaceHandle(0);
+ s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ }
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index 149ebdf4a..b7a83e133 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -72,6 +72,10 @@ public class OSXUtil {
return isNSView0(object);
}
+ public static boolean isNSWindow(long object) {
+ return isNSWindow0(object);
+ }
+
/**
* In case the windowOrView
is top-level,
* you shall set topLevel
to true where
@@ -114,6 +118,9 @@ public class OSXUtil {
public static long GetNSView(long nsWindow) {
return GetNSView0(nsWindow);
}
+ public static long GetNSWindow(long nsView) {
+ return GetNSWindow0(nsView);
+ }
public static long CreateCALayer(int x, int y, int width, int height) {
return CreateCALayer0(x, y, width, height);
@@ -149,6 +156,11 @@ public class OSXUtil {
return IsMainThread0();
}
+ /** Returns the screen refresh rate in Hz. If unavailable, returns 60Hz. */
+ public static int GetScreenRefreshRate(int scrn_idx) {
+ return GetScreenRefreshRate0(scrn_idx);
+ }
+
/***
private static boolean isAWTEDTMainThreadInit = false;
private static boolean isAWTEDTMainThread;
@@ -172,15 +184,18 @@ public class OSXUtil {
private static native boolean initIDs0();
private static native boolean isNSView0(long object);
+ private static native boolean isNSWindow0(long object);
private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y);
private static native Object GetInsets0(long windowOrView);
private static native long CreateNSWindow0(int x, int y, int width, int height);
private static native void DestroyNSWindow0(long nsWindow);
private static native long GetNSView0(long nsWindow);
+ private static native long GetNSWindow0(long nsView);
private static native long CreateCALayer0(int x, int y, int width, int height);
private static native void AddCASublayer0(long rootCALayer, long subCALayer);
private static native void RemoveCASublayer0(long rootCALayer, long subCALayer);
private static native void DestroyCALayer0(long caLayer);
private static native void RunOnMainThread0(boolean waitUntilDone, Runnable runnable);
private static native boolean IsMainThread0();
+ private static native int GetScreenRefreshRate0(int scrn_idx);
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java
new file mode 100644
index 000000000..aa5f3dac5
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java
@@ -0,0 +1,50 @@
+package jogamp.nativewindow.windows;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
+
+public class GDIDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
+ /**
+ * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
+ * not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * not the actual dummy surface height,
+ * The latter is platform specific and small
+ */
+ public GDIDummyUpstreamSurfaceHook(int width, int height) {
+ super(width, height);
+ }
+
+ @Override
+ public final void create(ProxySurface s) {
+ final GDISurface ms = (GDISurface)s;
+ if(0 == ms.getWindowHandle()) {
+ final long windowHandle = GDIUtil.CreateDummyWindow(0, 0, 64, 64);
+ if(0 == windowHandle) {
+ throw new NativeWindowException("Error windowHandle 0, werr: "+GDI.GetLastError());
+ }
+ ms.setWindowHandle(windowHandle);
+ ms.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
+ }
+
+ @Override
+ public final void destroy(ProxySurface s) {
+ final GDISurface ms = (GDISurface)s;
+ if( ms.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
+ if( 0 == ms.getWindowHandle() ) {
+ throw new InternalError("Owns upstream surface, but no GDI window: "+ms);
+ }
+ GDI.ShowWindow(ms.getWindowHandle(), GDI.SW_HIDE);
+ GDIUtil.DestroyDummyWindow(ms.getWindowHandle());
+ ms.setWindowHandle(0);
+ ms.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ }
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
index e368aa6a1..3db2b5fc9 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java
@@ -29,9 +29,13 @@
package jogamp.nativewindow.windows;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.ProxySurface;
-import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+import jogamp.nativewindow.ProxySurfaceImpl;
+import jogamp.nativewindow.windows.GDI;
/**
@@ -40,12 +44,20 @@ import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook;
* The latter will get and release the HDC.
* The size via getWidth()/getHeight() is invalid.
*/
-public class GDISurface extends ProxySurface {
+public class GDISurface extends ProxySurfaceImpl {
protected long windowHandle;
protected long surfaceHandle;
- public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) {
- super(cfg, initialWidth, initialHeight, upstream);
+ /**
+ * @param cfg the {@link AbstractGraphicsConfiguration} to be used
+ * @param windowHandle the wrapped pre-existing native window handle, maybe 0 if not yet determined
+ * @param upstream the {@link UpstreamSurfaceHook} to be used
+ * @param ownsDevice true
if this {@link ProxySurface} instance
+ * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice},
+ * otherwise false
. Owning the device implies closing it at {@link #destroyNotify()}.
+ */
+ public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, UpstreamSurfaceHook upstream, boolean ownsDevice) {
+ super(cfg, upstream, ownsDevice);
this.windowHandle=windowHandle;
this.surfaceHandle=0;
}
@@ -114,18 +126,4 @@ public class GDISurface extends ProxySurface {
final public long getSurfaceHandle() {
return surfaceHandle;
}
-
- @Override
- final public String toString() {
- final UpstreamSurfaceHook ush = getUpstreamSurfaceHook();
- final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil";
- return getClass().getSimpleName()+"[config "+getPrivateGraphicsConfiguration()+
- ", displayHandle 0x"+Long.toHexString(getDisplayHandle())+
- ", windowHandle 0x"+Long.toHexString(windowHandle)+
- ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+
- ", size "+getWidth()+"x"+getHeight()+
- ", surfaceLock "+surfaceLock+
- ", upstreamSurfaceHook "+ush_s+"]";
- }
-
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
new file mode 100644
index 000000000..55a29dd5e
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java
@@ -0,0 +1,60 @@
+package jogamp.nativewindow.x11;
+
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.nativewindow.UpstreamSurfaceHook;
+
+import jogamp.nativewindow.x11.X11Lib;
+
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
+import com.jogamp.nativewindow.x11.X11GraphicsConfiguration;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+
+public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
+ /**
+ * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)},
+ * not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)},
+ * not the actual dummy surface height,
+ * The latter is platform specific and small
+ */
+ public X11DummyUpstreamSurfaceHook(int width, int height) {
+ super(width, height);
+ }
+
+ @Override
+ public final void create(ProxySurface s) {
+ final X11GraphicsConfiguration cfg = (X11GraphicsConfiguration) s.getGraphicsConfiguration();
+ final X11GraphicsScreen screen = (X11GraphicsScreen) cfg.getScreen();
+ final X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice();
+ if(0 == device.getHandle()) {
+ device.open();
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ if( 0 == s.getSurfaceHandle() ) {
+ final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64);
+ if(0 == windowHandle) {
+ throw new NativeWindowException("Creating dummy window failed w/ "+cfg);
+ }
+ s.setSurfaceHandle(windowHandle);
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
+ }
+
+ @Override
+ public final void destroy(ProxySurface s) {
+ if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
+ final X11GraphicsDevice device = (X11GraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice();
+ if( 0 == s.getSurfaceHandle() ) {
+ throw new InternalError("Owns upstream surface, but no X11 window: "+s);
+ }
+ X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle());
+ s.setSurfaceHandle(0);
+ s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ }
+}
diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m
index 2c853a43d..d6ae7ed31 100644
--- a/src/nativewindow/native/macosx/OSXmisc.m
+++ b/src/nativewindow/native/macosx/OSXmisc.m
@@ -119,6 +119,12 @@ Java_jogamp_nativewindow_macosx_OSXUtil_isNSView0(JNIEnv *env, jclass _unused, j
return [nsObj isMemberOfClass:[NSView class]];
}
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_macosx_OSXUtil_isNSWindow0(JNIEnv *env, jclass _unused, jlong object) {
+ NSObject *nsObj = (NSObject*) (intptr_t) object;
+ return [nsObj isMemberOfClass:[NSWindow class]];
+}
+
/*
* Class: Java_jogamp_nativewindow_macosx_OSXUtil
* Method: getLocationOnScreen0
@@ -238,8 +244,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0
[myWindow setPreservesContentDuringLiveResize: YES];
// Remove animations
NS_DURING
+ if ( [myWindow respondsToSelector:@selector(setAnimationBehavior:)] ) {
// Available >= 10.7 - Removes default animations
[myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone];
+ }
NS_HANDLER
NS_ENDHANDLER
@@ -278,11 +286,28 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSView0
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSWindow* win = (NSWindow*) ((intptr_t) window);
- DBG_PRINT( "contentView0 - window: %p (START)\n", win);
-
jlong res = (jlong) ((intptr_t) [win contentView]);
- DBG_PRINT( "contentView0 - window: %p (END)\n", win);
+ DBG_PRINT( "GetNSView(window: %p): %p\n", win, (void*) (intptr_t) res);
+
+ [pool release];
+ return res;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_macosx_OSXUtil
+ * Method: GetNSWindow0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSWindow0
+ (JNIEnv *env, jclass unused, jlong view)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSView* v = (NSView*) ((intptr_t) view);
+
+ jlong res = (jlong) ((intptr_t) [v window]);
+
+ DBG_PRINT( "GetNSWindow(view: %p): %p\n", v, (void*) (intptr_t) res);
[pool release];
return res;
@@ -314,6 +339,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0
// no animations for add/remove/swap sublayers etc
// doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
[layer removeAllAnimations];
+ [layer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+ [layer setNeedsDisplayOnBoundsChange: YES];
DBG_PRINT("CALayer::CreateCALayer.1: %p %lf/%lf %lfx%lf\n", layer, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height);
DBG_PRINT("CALayer::CreateCALayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]);
@@ -357,7 +384,11 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_AddCASublayer0
// no animations for add/remove/swap sublayers etc
// doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition]
[rootLayer removeAllAnimations];
+ [rootLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+ [rootLayer setNeedsDisplayOnBoundsChange: YES];
[subLayer removeAllAnimations];
+ [subLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)];
+ [subLayer setNeedsDisplayOnBoundsChange: YES];
}];
DBG_PRINT("CALayer::AddCASublayer0.X: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]);
JNF_COCOA_EXIT(env);
@@ -404,6 +435,63 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyCALayer0
JNF_COCOA_EXIT(env);
}
+/*
+ * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow
+ * Method: SetJAWTRootSurfaceLayer0
+ * Signature: (JJ)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0
+ (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer)
+{
+ JNF_COCOA_ENTER(env);
+ JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer);
+ if (NULL == dsi) {
+ NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer");
+ return JNI_FALSE;
+ }
+ CALayer* layer = (CALayer*) (intptr_t) caLayer;
+ [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
+ id + * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + *
+ *+ * Extensive FBO reconfiguration (size and sample buffer count) and validation are performed. + *
+ */ +public class TestFBOAutoDrawableFactoryNEWT extends UITestCase { + + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + @Test + public void testGL2ES2_Demo1_SingleBuffer_Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(false); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo1_DoubleBuffer_Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(true); // default + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo2MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); + } + + @Test + public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testEGLES2_Demo0Normal() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + @Test + public void testEGLES2_Demo0MSAA4() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { + caps.setFBO(true); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLOffscreenAutoDrawable.FBO glad = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, caps, null, widthStep*szStep, heightStep*szStep, null); + Assert.assertNotNull(glad); + + System.out.println("Realized GLAD: "+glad); + System.out.println("Realized GLAD: "+glad.getChosenGLCapabilities()); + Assert.assertTrue("FBO drawable is initialized before ctx creation", !glad.isInitialized()); + + glad.display(); // initial display incl. init! + { + final GLContext context = glad.getContext(); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + Assert.assertTrue("FBO drawable is not initialized after ctx creation", glad.isInitialized()); + + // + // FBO incl. MSAA is fully initialized now + // + + final GLCapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Init GLAD: "+glad); + System.out.println("Init GLAD: "+chosenCaps); + + final FBObject fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject fboBack = glad.getFBObject(GL.GL_BACK); + + System.out.println("Init front FBO: "+fboFront); + System.out.println("Init back FBO: "+fboBack); + + Assert.assertTrue("FBO drawable is not initialized before ctx creation", glad.isInitialized()); + Assert.assertTrue("FBO Front is not initialized before ctx creation", fboFront.isInitialized()); + Assert.assertTrue("FBO Back is not initialized before ctx creation", fboBack.isInitialized()); + + if( chosenCaps.getDoubleBuffered() ) { + Assert.assertTrue("FBO are equal: "+fboFront+" == "+fboBack, !fboFront.equals(fboBack)); + Assert.assertNotSame(fboFront, fboBack); + } else { + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+fboBack, fboFront.equals(fboBack)); + Assert.assertSame(fboFront, fboBack); + } + + final FBObject.TextureAttachment texAttachA, texAttachB; + + texAttachA = glad.getTextureBuffer(GL.GL_FRONT); + if(0==glad.getNumSamples()) { + texAttachB = glad.getTextureBuffer(GL.GL_BACK); + } else { + texAttachB = null; + } + + final FBObject.Colorbuffer colorA, colorB; + final FBObject.RenderAttachment depthA, depthB; + + colorA = fboFront.getColorbuffer(0); + Assert.assertNotNull(colorA); + colorB = fboBack.getColorbuffer(0); + Assert.assertNotNull(colorB); + + depthA = fboFront.getDepthAttachment(); + Assert.assertNotNull(depthA); + depthB = fboBack.getDepthAttachment(); + Assert.assertNotNull(depthB); + + glad.display(); // SWAP_ODD + + if( chosenCaps.getDoubleBuffered() ) { + // double buffer or MSAA + Assert.assertTrue("Color attachments are equal: "+colorB+" == "+colorA, !colorB.equals(colorA)); + Assert.assertNotSame(colorB, colorA); + Assert.assertTrue("Depth attachments are equal: "+depthB+" == "+depthA, !depthB.equals(depthA)); + Assert.assertNotSame(depthB, depthA); + } else { + // single buffer + Assert.assertEquals(colorA, colorB); + Assert.assertSame(colorA, colorB); + Assert.assertEquals(depthA, depthB); + Assert.assertSame(depthA, depthB); + } + + Assert.assertEquals(texAttachA, colorA); + Assert.assertSame(texAttachA, colorA); + if(0==glad.getNumSamples()) { + Assert.assertEquals(texAttachB, colorB); + Assert.assertSame(texAttachB, colorB); + } + + if( chosenCaps.getNumSamples() > 0 ) { + // MSAA + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront)); + Assert.assertSame(fboFront, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack)); + Assert.assertSame(fboBack, _fboBack); + } else if( chosenCaps.getDoubleBuffered() ) { + // real double buffer + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront)); + Assert.assertSame(fboBack, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack)); + Assert.assertSame(fboFront, _fboBack); + } else { + // single buffer + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront)); + Assert.assertSame(fboFront, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront)); + Assert.assertSame(fboBack, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack)); + Assert.assertSame(fboBack, _fboBack); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack)); + Assert.assertSame(fboFront, _fboBack); + } + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // - SWAP_EVEN + + // 1 - szStep = 2 + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_ODD + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_EVEN + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_ODD + glad.display(); // - SWAP_EVEN + { + // Check whether the attachment reference are still valid! + final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + System.out.println("Resize1.oldFront: "+fboFront); + System.out.println("Resize1.nowFront: "+_fboFront); + System.out.println("Resize1.oldBack : "+fboBack); + System.out.println("Resize1.nowBack : "+_fboBack); + Assert.assertEquals(fboFront, _fboFront); + Assert.assertSame(fboFront, _fboFront); + Assert.assertEquals(fboBack, _fboBack); + Assert.assertSame(fboBack, _fboBack); + + FBObject.Colorbuffer _color = _fboFront.getColorbuffer(0); + Assert.assertNotNull(_color); + Assert.assertEquals(colorA, _color); + Assert.assertSame(colorA, _color); + + FBObject.RenderAttachment _depth = _fboFront.getDepthAttachment(); + System.err.println("Resize1.oldDepth "+depthA); + System.err.println("Resize1.newDepth "+_depth); + Assert.assertNotNull(_depth); + + Assert.assertEquals(depthA, _depth); + Assert.assertSame(depthA, _depth); + _depth = _fboBack.getDepthAttachment(); + Assert.assertNotNull(_depth); + Assert.assertEquals(depthB, _depth); + Assert.assertSame(depthB, _depth); + + _color = _fboFront.getColorbuffer(colorA); + Assert.assertNotNull(_color); + Assert.assertEquals(colorA, _color); + Assert.assertSame(colorA, _color); + } + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_ODD + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_EVEN + glad.display(); // - SWAP_ODD + { + // Check whether the attachment reference are still valid! + final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + System.out.println("Resize2.oldFront: "+fboFront); + System.out.println("Resize2.nowFront: "+_fboFront); + System.out.println("Resize2.oldBack : "+fboBack); + System.out.println("Resize2.nowBack : "+_fboBack); + if(chosenCaps.getDoubleBuffered() && 0==chosenCaps.getNumSamples()) { + // real double buffer + Assert.assertEquals(fboBack, _fboFront); + Assert.assertEquals(fboFront, _fboBack); + } else { + // single or MSAA + Assert.assertEquals(fboFront, _fboFront); + Assert.assertEquals(fboBack, _fboBack); + } + + FBObject.Colorbuffer _color = fboBack.getColorbuffer(0); + Assert.assertNotNull(_color); + Assert.assertEquals(colorB, _color); + Assert.assertSame(colorB, _color); + + FBObject.RenderAttachment _depth = fboBack.getDepthAttachment(); + Assert.assertNotNull(_depth); // MSAA back w/ depth + Assert.assertEquals(depthB, _depth); + Assert.assertSame(depthB, _depth); + + _depth = fboFront.getDepthAttachment(); + Assert.assertNotNull(_depth); + Assert.assertEquals(depthA, _depth); + Assert.assertSame(depthA, _depth); + + _color = fboBack.getColorbuffer(colorB); + Assert.assertNotNull(_color); + Assert.assertEquals(colorB, _color); + Assert.assertSame(colorB, _color); + } + + // 6 + 7 (samples + display) + glad.setNumSamples(glad.getGL(), chosenCaps.getNumSamples() > 0 ? 0 : 4); // triggers repaint + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // actual screenshot + + // 8, 9 (resize + samples + display) + szStep = 3; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + glad.destroy(); + System.out.println("Fin: "+glad); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestFBOAutoDrawableFactoryNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java deleted file mode 100644 index 7977347a7..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java +++ /dev/null @@ -1,272 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.opengl.GL; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLProfile; - -import jogamp.opengl.GLFBODrawableImpl; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.opengl.FBObject; -import com.jogamp.opengl.OffscreenAutoDrawable; -import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.GLReadBufferUtil; -import com.jogamp.opengl.util.texture.TextureIO; - -public class TestFBODrawableNEWT extends UITestCase { - - static final int widthStep = 800/4; - static final int heightStep = 600/4; - volatile int szStep = 2; - - @Test - public void testGL2ES2_Demo1Normal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } - - @Test - public void testGL2ES2_Demo1MSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } - - @Test - public void testGL2ES2_Demo2Normal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new MultisampleDemoES2(false)); - } - - @Test - public void testGL2ES2_Demo2MSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); - } - - @Test - public void testGL2ES2_FBODemoNormal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); - demo.setDoRotation(false); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, demo); - } - - @Test - public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); - demo.setDoRotation(false); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, demo); - } - - @Test - public void testEGLES2_Demo0Normal() throws InterruptedException { - if( GLProfile.isAvailable(GLProfile.GLES2) ) { - final GLProfile glp = GLProfile.get(GLProfile.GLES2); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } else { - System.err.println("EGL ES2 n/a"); - } - } - - @Test - public void testEGLES2_Demo0MSAA4() throws InterruptedException { - if( GLProfile.isAvailable(GLProfile.GLES2) ) { - final GLProfile glp = GLProfile.get(GLProfile.GLES2); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } else { - System.err.println("EGL ES2 n/a"); - } - } - - boolean skipShot = false; - - void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { - final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); - caps.setFBO(true); - final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); - final GLDrawable fboDrawable = factory.createOffscreenDrawable(null, caps, null, widthStep*szStep, heightStep*szStep); - Assert.assertNotNull(fboDrawable); - Assert.assertTrue("Not an FBO Drawable", fboDrawable instanceof GLFBODrawableImpl); - - fboDrawable.setRealized(true); - Assert.assertTrue(fboDrawable.isRealized()); - - final FBObject fbo = ((GLFBODrawableImpl)fboDrawable).getFBObject(); - - System.out.println("Realized: "+fboDrawable); - System.out.println("Realized: "+fboDrawable.getChosenGLCapabilities()); - System.out.println("Realized: "+fbo); - - final GLContext context = fboDrawable.createContext(null); - Assert.assertNotNull(context); - - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - context.release(); - - System.out.println("Post Create-Ctx: "+fbo); - final FBObject.Colorbuffer colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(colorA); - final FBObject.RenderAttachment depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(depthA); - - final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, true); - - glad.addGLEventListener(demo); - glad.addGLEventListener(new GLEventListener() { - volatile int displayCount=0; - volatile int reshapeCount=0; - public void init(GLAutoDrawable drawable) {} - public void dispose(GLAutoDrawable drawable) {} - public void display(GLAutoDrawable drawable) { - final GL gl = drawable.getGL(); - // System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": step "+szStep+" "+drawable.getWidth()+"x"+drawable.getHeight()); - // System.err.println(Thread.currentThread().getName()+": ** FBO-THIS: "+fbo); - // System.err.println(Thread.currentThread().getName()+": ** FBO-SINK: "+fbo.getSamplingSinkFBO()); - // System.err.println(Thread.currentThread().getName()+": ** drawable-read: "+gl.getDefaultReadFramebuffer()); - if(skipShot) { - skipShot=false; - } else { - snapshot(getSimpleTestName("."), displayCount, "msaa"+fbo.getNumSamples(), gl, screenshot, TextureIO.PNG, null); - } - Assert.assertEquals(drawable.getWidth(), widthStep*szStep); - Assert.assertEquals(drawable.getHeight(), heightStep*szStep); - displayCount++; - } - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": step "+szStep+" "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight()); - Assert.assertEquals(drawable.getWidth(), widthStep*szStep); - Assert.assertEquals(drawable.getHeight(), heightStep*szStep); - reshapeCount++; - } - }); - - // 0 - szStep = 2 - glad.display(); - - // 1, 2 (resize + display) - szStep = 1; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - { - // Check whether the attachment reference are still valid! - FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - Assert.assertTrue(colorA.equals(_colorA)); - FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(_depthA); - Assert.assertTrue(depthA == _depthA); - Assert.assertTrue(depthA.equals(_depthA)); - - _colorA = fbo.getColorbuffer(colorA); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - Assert.assertTrue(colorA.equals(_colorA)); - } - - // 3, 4 (resize + display) - szStep = 4; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - { - // Check whether the attachment reference are still valid! - FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - final FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(_depthA); - Assert.assertTrue(depthA == _depthA); - - _colorA = fbo.getColorbuffer(colorA); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - } - - // 5 - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - - // 6, 7 (resize + display) - szStep = 3; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - - glad.destroy(); - System.out.println("Fin: "+fboDrawable); - - // final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(fboDrawable, context); - } - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestFBODrawableNEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java index f7c83a03b..077baad43 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java @@ -229,7 +229,7 @@ public class TestFBOMRTNEWT01 extends UITestCase { final NativeSurface ns = gl.getContext().getGLReadDrawable().getNativeSurface(); if(last_snap_size[0] != ns.getWidth() && last_snap_size[1] != ns.getHeight()) { gl.glFinish(); // sync .. no swap buffers yet! - snapshot(getSimpleTestName("."), step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok + snapshot(step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok last_snap_size[0] = ns.getWidth(); last_snap_size[1] = ns.getHeight(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java index b384c9327..b3c542c63 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java @@ -106,7 +106,7 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase { if(dw<800) { System.err.println("XXX: "+dw+"x"+dh+", c "+c); if(0 == c%3) { - snapshot(getSimpleTestName("."), i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null); + snapshot(i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null); } if( 3 == c ) { new Thread() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java new file mode 100644 index 000000000..3ecf89bfc --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java @@ -0,0 +1,298 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.QuitAdapter; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.Mix2TexturesES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.SurfaceUpdatedListener; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Test; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + *+ * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + *
+ *+ * This test simulates shared off-thread GL context / texture usage, + * where the producer use FBOs and delivers shared textures. + * The receiver blends the shared textures onscreen. + * In detail the test consist of: + *
+ * This test simulates shared on-thread GL context / texture usage, + * where the producer uses an FBO and delivers a shared texture. + * The receiver draws the shared texture onscreen. + * In detail the test consist of: + *
+ * Finally a {@link GLAutoDrawableDelegate} is created with the just created {@link GLDrawable} and {@link GLContext}. + * It is being used to run the {@link GLEventListener}. + *
+ */ +public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final Window window = NewtFactory.createWindow(reqGLCaps); + Assert.assertNotNull(window); + window.setSize(widthStep*szStep, heightStep*szStep); + window.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + System.out.println("Window: "+window.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLDrawable drawable = factory.createGLDrawable(window); + Assert.assertNotNull(drawable); + System.out.println("Drawable Pre-GL(0): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + // + drawable.setRealized(true); + Assert.assertTrue(drawable.isRealized()); + + System.out.println("Window Caps PostGL : "+window.getGraphicsConfiguration().getChosenCapabilities()); + System.out.println("Drawable Post-GL(1): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + GLContext context = drawable.createContext(null); + Assert.assertNotNull(context); + int res = context.makeCurrent(); + Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); + context.release(); + + System.out.println("Chosen GL Caps(2): "+drawable.getChosenGLCapabilities()); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + System.out.println("Drawable Post-GL(2): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) { + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); // destroys drawable/context + window.destroy(); // destroys the actual window, incl. the device + } + }; + + window.addWindowListener(new WindowAdapter() { + @Override + public void windowRepaint(WindowUpdateEvent e) { + glad.windowRepaintOp(); + } + + @Override + public void windowResized(WindowEvent e) { + glad.windowResizedOp(window.getWidth(), window.getHeight()); + } + + @Override + public void windowDestroyNotify(WindowEvent e) { + glad.windowDestroyNotifyOp(); + } + }); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + window.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + window.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+drawable); + System.out.println("Fin Window: "+window); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java new file mode 100644 index 000000000..544d74aa5 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java @@ -0,0 +1,317 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + *+ * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}. + *
+ */ +public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, reqGLCaps, null, widthStep*szStep, heightStep*szStep, null); + + Assert.assertNotNull(glad); + System.out.println("Drawable Pre-GL(0): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + Assert.assertTrue(glad.isRealized()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Drawable Caps Pre_GL : "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + System.out.println("Chosen GL CTX (1): "+glad.getContext().getGLVersion()); + + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java new file mode 100644 index 000000000..64a75716b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java @@ -0,0 +1,328 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import jogamp.nativewindow.jawt.JAWTUtil; +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *+ * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *
+ */ +public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + static void setGLCanvasSize(final Frame frame, final GLCanvas glc, final int width, final int height) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Dimension new_sz = new Dimension(width, height); + glc.setMinimumSize(new_sz); + glc.setPreferredSize(new_sz); + glc.setSize(new_sz); + frame.pack(); + frame.validate(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + if(reqGLCaps.isOnscreen() && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(!reqGLCaps.isOnscreen() && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final GLCanvas glad = new GLCanvas(reqGLCaps); // will implicit trigger offscreen layer - if !onscreen && supported + Assert.assertNotNull(glad); + Dimension glc_sz = new Dimension(widthStep*szStep, heightStep*szStep); + glad.setMinimumSize(glc_sz); + glad.setPreferredSize(glc_sz); + glad.setSize(glc_sz); + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(glad); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glad); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreen() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreen() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java new file mode 100644 index 000000000..37ec44566 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java @@ -0,0 +1,351 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *+ * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *
+ */ +public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final GLWindow glad = GLWindow.create(reqGLCaps); + Assert.assertNotNull(glad); + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getGraphicsConfiguration().getChosenCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getGraphicsConfiguration().getChosenCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.display(); + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java new file mode 100644 index 000000000..47fc99844 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java @@ -0,0 +1,300 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.jawt.JAWTUtil; +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *+ * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *
+ */ +public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + static void setComponentSize(final Frame frame, final Component comp, final int width, final int height) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Dimension new_sz = new Dimension(width, height); + comp.setMinimumSize(new_sz); + comp.setPreferredSize(new_sz); + comp.setSize(new_sz); + frame.pack(); + frame.validate(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + void doTest(boolean offscreenLayer, GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = offscreenLayer ? + GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable) : + GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + + final GLWindow glad = GLWindow.create(reqGLCaps); + Assert.assertNotNull(glad); + + + final NewtCanvasAWT nca = new NewtCanvasAWT(glad); + Assert.assertNotNull(nca); + Dimension size0 = new Dimension(widthStep*szStep, heightStep*szStep); + nca.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported + nca.setPreferredSize(size0); + nca.setMinimumSize(size0); + nca.setSize(size0); + + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(nca); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(nca); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + glad.destroy(); + System.out.println("Fin: "+nca); + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(false, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenLayerAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setFBO(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setPBuffer(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + doTest(true, reqGLCaps, new GearsES2(1)); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java deleted file mode 100644 index cd1107e25..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java +++ /dev/null @@ -1,266 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLProfile; - -import jogamp.opengl.GLGraphicsConfigurationUtil; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.newt.NewtFactory; -import com.jogamp.newt.Window; -import com.jogamp.opengl.JoglVersion; -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; - -public class TestGLCapabilities01NEWT extends UITestCase { - static final int width = 100; - static final int height = 100; - - boolean checkProfile(String profile) { - if( !GLProfile.isAvailable(profile) ) { - System.err.println("Profile "+profile+" n/a"); - return false; - } - return true; - } - - void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { - System.out.println("Requested GL Caps: "+reqGLCaps); - - final GLCapabilitiesImmutable expGLCaps; - if( GLGraphicsConfigurationUtil.isGLCapabilitiesOffscreenAutoSelection(reqGLCaps) ) { - final GLDrawableFactory f = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); - final boolean fboAvailable = true ; // f.canCreateFBO(null, reqGLCaps.getGLProfile()); - final boolean pbufferAvailable = f.canCreateGLPbuffer(null); - expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); - } else { - expGLCaps = reqGLCaps; - } - System.out.println("Expected GL Caps: "+expGLCaps); - // - // Create native windowing resources .. X11/Win/OSX - // - final Window window = NewtFactory.createWindow(reqGLCaps); - Assert.assertNotNull(window); - window.setSize(width, height); - window.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); - System.out.println("Window: "+window.getClass().getName()); - - // Check caps of NativeWindow config w/o GL - final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); - System.out.println("Window Caps Pre_GL: "+chosenCaps); - Assert.assertNotNull(chosenCaps); - Assert.assertTrue(chosenCaps.getGreenBits()>5); - Assert.assertTrue(chosenCaps.getBlueBits()>5); - Assert.assertTrue(chosenCaps.getRedBits()>5); - - // - // Create native OpenGL resources .. XGL/WGL/CGL .. - // equivalent to GLAutoDrawable methods: setVisible(true) - // - final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); - - final GLDrawable drawable = factory.createGLDrawable(window); - Assert.assertNotNull(drawable); - System.out.println("Drawable Pre-GL(0): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - // - drawable.setRealized(true); - Assert.assertTrue(drawable.isRealized()); - - System.out.println("Window Caps PostGL : "+window.getGraphicsConfiguration().getChosenCapabilities()); - System.out.println("Drawable Post-GL(1): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - // Check caps of GLDrawable after realization - final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); - System.out.println("Chosen GL Caps(1): "+chosenGLCaps); - Assert.assertNotNull(chosenGLCaps); - Assert.assertTrue(chosenGLCaps.getGreenBits()>5); - Assert.assertTrue(chosenGLCaps.getBlueBits()>5); - Assert.assertTrue(chosenGLCaps.getRedBits()>5); - Assert.assertTrue(chosenGLCaps.getDepthBits()>4); - Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); - Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); - Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); - Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); - if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { - // dbl buffer may be disabled w/ offscreen pbuffer and bitmap - Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); - } - - GLContext context = drawable.createContext(null); - Assert.assertNotNull(context); - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - context.release(); - - System.out.println("Chosen GL Caps(2): "+drawable.getChosenGLCapabilities()); - System.out.println("Drawable Post-GL(2): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - drawable.setRealized(false); - window.destroy(); - } - - @Test - public void testAvailableInfo() { - GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); - if(null != f) { - System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); - } - f = GLDrawableFactory.getEGLFactory(); - if(null != f) { - System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); - } - } - - @Test - public void testGL2OnScreenDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenAutoDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenFBODblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setFBO(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setPBuffer(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setBitmap(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OnScreenDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenAutoDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenFBODblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setFBO(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenPbufferDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setPBuffer(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - /** Not implemented ! - @Test - public void testES2OffScreenBitmapDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setBitmap(true); - doTest(reqGLCaps, new GearsES2(1)); - } */ - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestGLCapabilities01NEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java index cece4c6d5..4c1130498 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java @@ -39,13 +39,14 @@ import com.jogamp.newt.event.WindowUpdateEvent; import com.jogamp.newt.opengl.GLWindow; import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLAutoDrawableDelegate; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.GLAutoDrawableDelegate; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -81,14 +82,17 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); - GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); - GLDrawable drawable = factory.createGLDrawable(window); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLDrawable drawable = factory.createGLDrawable(window); Assert.assertNotNull(drawable); drawable.setRealized(true); Assert.assertTrue(drawable.isRealized()); - final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false) { + final GLContext context = drawable.createContext(null); + Assert.assertNotNull(context); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) { @Override protected void destroyImplInLock() { super.destroyImplInLock(); @@ -104,7 +108,7 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { } @Override public void windowResized(WindowEvent e) { - glad.windowResizedOp(); + glad.windowResizedOp(window.getWidth(), window.getHeight()); } @Override public void windowDestroyNotify(WindowEvent e) { @@ -123,9 +127,13 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter); // no GLContext! GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter); // no GLContext! - // create single context using glad1 and assign it to glad1 + // create single context using glad1 and assign it to glad1, + // after destroying the prev. context! { - GLContext singleCtx = glad1.createContext(null); + final GLContext oldCtx = glad1.getContext(); + Assert.assertNotNull(oldCtx); + oldCtx.destroy(); + final GLContext singleCtx = glad1.createContext(null); Assert.assertNotNull(singleCtx); int res = singleCtx.makeCurrent(); Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java deleted file mode 100644 index a6e9cfb07..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.opengl.GL; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLProfile; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.newt.NewtFactory; -import com.jogamp.newt.Window; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; - -public class TestGLDrawable01NEWT extends UITestCase { - static final int width = 200, height = 200; - - void doTest(String profile, boolean onscreen, boolean fbo, boolean pbuffer) throws InterruptedException { - if( !GLProfile.isAvailable(profile) ) { - System.err.println("Profile "+profile+" n/a"); - return; - } - - final GLProfile glp = GLProfile.get(profile); - final GLCapabilities reqGLCaps = new GLCapabilities(glp); - - reqGLCaps.setOnscreen(onscreen); - reqGLCaps.setPBuffer(!onscreen && pbuffer); - reqGLCaps.setFBO(!onscreen && fbo); - reqGLCaps.setDoubleBuffered(onscreen); - // System.out.println("Requested: "+caps); - - // - // Create native windowing resources .. X11/Win/OSX - // - Window window = NewtFactory.createWindow(reqGLCaps); - Assert.assertNotNull(window); - window.setSize(width, height); - window.setVisible(true); - AWTRobotUtil.waitForVisible(window, true); - AWTRobotUtil.waitForRealized(window, true); - // System.out.println("Created: "+window); - - // Check caps of NativeWindow config w/o GL - final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); - Assert.assertNotNull(chosenCaps); - Assert.assertTrue(chosenCaps.getGreenBits()>5); - Assert.assertTrue(chosenCaps.getBlueBits()>5); - Assert.assertTrue(chosenCaps.getRedBits()>5); - - // - // Create native OpenGL resources .. XGL/WGL/CGL .. - // equivalent to GLAutoDrawable methods: setVisible(true) - // - final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp); - - final GLDrawable drawable = factory.createGLDrawable(window); - Assert.assertNotNull(drawable); - // System.out.println("Pre: "+drawable); - // - drawable.setRealized(true); - Assert.assertTrue(drawable.isRealized()); - - // Check caps of GLDrawable after realization - final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); - Assert.assertNotNull(chosenGLCaps); - Assert.assertTrue(chosenGLCaps.getGreenBits()>5); - Assert.assertTrue(chosenGLCaps.getBlueBits()>5); - Assert.assertTrue(chosenGLCaps.getRedBits()>5); - Assert.assertTrue(chosenGLCaps.getDepthBits()>4); - Assert.assertEquals(reqGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); - Assert.assertEquals(reqGLCaps.isOnscreen(), chosenGLCaps.getDoubleBuffered()); // offscreen shall be !dbl-buffer - // System.out.println("Post: "+drawable); - - GLContext context = drawable.createContext(null); - Assert.assertNotNull(context); - // System.out.println(context); - - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - - // draw something .. - final GL gl = context.getGL(); - gl.glClearColor(1, 1, 1, 1); - gl.glEnable(GL.GL_DEPTH_TEST); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - gl.glViewport(0, 0, width, height); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - - drawable.swapBuffers(); - context.release(); - - Thread.sleep(50); - - context.destroy(); - drawable.setRealized(false); - window.destroy(); - // System.out.println("Final: "+window); - } - - @Test - public void testGL2OnScreen() throws InterruptedException { - doTest(GLProfile.GL2, true, false, false); - } - - @Test - public void testES2OnScreen() throws InterruptedException { - doTest(GLProfile.GLES2, true, false, false); - } - - @Test - public void testGL2PBuffer() throws InterruptedException { - doTest(GLProfile.GL2, false, false, true); - } - - @Test - public void testES2PBuffer() throws InterruptedException { - doTest(GLProfile.GLES2, false, false, true); - } - - // @Test // TODO: FBO-Drawable via createGLDrawable and pre-exisiting NativeSurface - public void testGL2FBO() throws InterruptedException { - doTest(GLProfile.GL2, false, true, false); - } - - // @Test // TODO: FBO-Drawable via createGLDrawable and pre-exisiting NativeSurface - public void testES2FBO() throws InterruptedException { - doTest(GLProfile.GLES2, false, true, false); - } - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestGLDrawable01NEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java index e4245ef11..d4f3fece5 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java @@ -32,14 +32,11 @@ import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GL; -import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLProfile; import jogamp.opengl.GLDrawableFactoryImpl; @@ -77,13 +74,11 @@ public class TestGLExtensionQueryOffscreen { @Test public void testJogl2ExtensionCheck2() { - GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); - GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory(); - GLCapabilitiesChooser glCapsChooser = new DefaultGLCapabilitiesChooser(); - AbstractGraphicsDevice agd = factory.getDefaultDevice(); + final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLOffscreenAutoDrawable drawable = factory.createOffscreenAutoDrawable(null, caps, null, 256, 256, null); - GLAutoDrawable drawable = factory.createGLPbuffer(agd, caps, glCapsChooser, 256, 256, null); - GLContext context = drawable.getContext(); + final GLContext context = drawable.getContext(); context.makeCurrent(); String extensions; try { @@ -94,8 +89,8 @@ public class TestGLExtensionQueryOffscreen { String[] tabExtensions = extensions.split(" "); SortedSet
+ * + Container is the JFrame's implicit root content pane
+ *
+ * {@link JFrame} . {@link JPanel}+ . {@link Container} . {@link NewtCanvasAWT} . {@link GLWindow} + *
+ *
+ * + JPanel is set as JFrame's root content pane
+ *
- * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0004-0800x0600.png - * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0005-0800x0600.png + * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgb_-S00_default-0400x0300.png + * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgb_-S00_default-0200x0150.png + * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgb_-S00_default-0200x0150.png *- * - * @param simpleTestName will be used as the filename prefix * @param sn sequential number * @param postSNDetail optional detail to be added to the filename after
sn
* @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename.
@@ -137,30 +156,80 @@ public abstract class UITestCase {
* It shall not end with a directory separator, {@link File#separatorChar}.
* If null
the current working directory is being used.
*/
- public static void snapshot(String simpleTestName, int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) {
+ public void snapshot(int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) {
if(null == fileSuffix) {
fileSuffix = TextureIO.PNG;
}
- final StringWriter filenameSW = new StringWriter();
- {
+ final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1;
+ final String simpleTestName = this.getSimpleTestName(".");
+ final String filenameBaseName;
+ {
final GLDrawable drawable = gl.getContext().getGLReadDrawable();
final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities();
+ final String accel = caps.getHardwareAccelerated() ? "hw" : "sw" ;
+ final String scrnm;
+ if(caps.isOnscreen()) {
+ scrnm = "onscreen";
+ } else if(caps.isFBO()) {
+ scrnm = "fbobject";
+ } else if(caps.isPBuffer()) {
+ scrnm = "pbuffer_";
+ } else if(caps.isBitmap()) {
+ scrnm = "bitmap__";
+ } else {
+ scrnm = "unknown_";
+ }
+ final String dblb = caps.getDoubleBuffered() ? "dbl" : "one";
final String F_pfmt = readBufferUtil.hasAlpha() ? "rgba" : "rgb_";
final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_";
- final String aaext = caps.getSampleExtension();
final int samples = caps.getNumSamples() ;
+ final String aaext = caps.getSampleExtension();
postSNDetail = null != postSNDetail ? "-"+postSNDetail : "";
- final PrintWriter pw = new PrintWriter(filenameSW);
- pw.printf("%s-n%04d%s-F_%s-I_%s-S%d_%s-%s-%04dx%04d.%s",
- simpleTestName, sn, postSNDetail, F_pfmt, pfmt, samples, aaext, drawable.getGLProfile().getName(),
- drawable.getWidth(), drawable.getHeight(), fileSuffix);
+
+ filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-S%02d_%s-%04dx%04d.%s",
+ simpleTestName, sn, postSNDetail, drawable.getGLProfile().getName(), accel,
+ scrnm, dblb, F_pfmt, pfmt, samples, aaext,
+ drawable.getWidth(), drawable.getHeight(), fileSuffix).replace(' ', '_');
}
- final String filename = null != destPath ? destPath + File.separator + filenameSW.toString() : filenameSW.toString();
- System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename);
+ final String filename = null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName;
+ System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename+", maxTestNameLen "+maxSimpleTestNameLen+", <"+simpleTestName+">");
gl.glFinish(); // just make sure rendering finished ..
if(readBufferUtil.readPixels(gl, false)) {
readBufferUtil.write(new File(filename));
}
- }
+ }
+
+ public class SnapshotGLEventListener implements GLEventListener {
+ private final GLReadBufferUtil screenshot;
+ private volatile boolean makeShot = false;
+ private volatile int displayCount=0;
+ private volatile int reshapeCount=0;
+ public SnapshotGLEventListener(GLReadBufferUtil screenshot) {
+ this.screenshot = screenshot;
+ }
+ public SnapshotGLEventListener() {
+ this.screenshot = new GLReadBufferUtil(false, false);
+ }
+
+ public void init(GLAutoDrawable drawable) {}
+ public void dispose(GLAutoDrawable drawable) {}
+ public void display(GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": "+drawable.getWidth()+"x"+drawable.getHeight()+", makeShot "+makeShot);
+ if(makeShot) {
+ makeShot=false;
+ snapshot(displayCount, null, gl, screenshot, TextureIO.PNG, null);
+ }
+ displayCount++;
+ }
+ public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
+ System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight());
+ reshapeCount++;
+ }
+ public void setMakeSnapshot() {
+ makeShot=true;
+ }
+ };
+
}
--
cgit v1.2.3
From 923d9dd7f1d40db72d35ca76a761ca14babf147f Mon Sep 17 00:00:00 2001
From: Sven Gothel + * Using centralized quirk identifier enables us to + * locate code dealing w/ it and hence eases it's maintenance. + *
+ */ +public class GLRendererQuirks { + /** Crashes XServer when using double buffered PBuffer with 'Mesa DRI Intel(R) Sandybridge Desktop' & 'Mesa DRI Intel(R) Ivybridge Mobile - 3.0 Mesa 8.0.4' */ + public static final int NoDoubleBufferedPBuffer = 0; + + /** On Windows no double buffered bitmaps are guaranteed to be available. */ + public static final int NoDoubleBufferedBitmap = 1; + + /** Crashes application when trying to set EGL swap interval on Android 4.0.3 / Pandaboard ES / PowerVR SGX 540 */ + public static final int NoSetSwapInterval = 2; + + /** No offscreen bitmap available, currently true for JOGL's OSX implementation. */ + public static final int NoOffscreenBitmap = 3; + + /** Number of quirks known. */ + public static final int COUNT = 4; + + private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval", + "NoOffscreenBitmap" + }; + + private final int _bitmask; + + /** + * @param quirks an array of valid quirks + * @param offset offset in quirks array to start reading + * @param len number of quirks to read from offset within quirks array + * @throws IllegalArgumentException if one of the quirks is out of range + */ + public GLRendererQuirks(int[] quirks, int offset, int len) throws IllegalArgumentException { + int bitmask = 0; + if( !( 0 <= offset + len && offset + len < quirks.length ) ) { + throw new IllegalArgumentException("offset and len out of bounds: offset "+offset+", len "+len+", array-len "+quirks.length); + } + for(int i=offset; iquirk
exist in {@link #getRendererQuirks()}, otherwise false.
+ * + * Convenience method for: + *
+ * final GLRendererQuirks glrq = ctx.getRendererQuirks(); + * boolean hasQuirk = null != glrq ? glrq.exist(quirk) : false ; + *+ * + * @param quirk the quirk to be tested, e.g. {@link GLRendererQuirks#NoDoubleBufferedPBuffer}. + * @throws IllegalArgumentException if the quirk is out of range + */ + public final boolean hasRendererQuirk(int quirk) throws IllegalArgumentException { + return null != glRendererQuirks ? glRendererQuirks.exist(quirk) : false ; + } + /** * Sets the read/write drawable for framebuffer operations. *
@@ -464,6 +489,12 @@ public abstract class GLContext {
sb.append(toHexString(contextHandle));
sb.append(", ");
sb.append(getGL());
+ sb.append(",\n\t quirks: ");
+ if(null != glRendererQuirks) {
+ glRendererQuirks.toString(sb);
+ } else {
+ sb.append("n/a");
+ }
if(getGLDrawable()!=getGLReadDrawable()) {
sb.append(",\n\tRead Drawable : ");
sb.append(getGLReadDrawable());
@@ -473,8 +504,6 @@ public abstract class GLContext {
sb.append(",\n\tDrawable: ");
sb.append(getGLDrawable());
}
- sb.append(", lock ");
- sb.append(lock.toString());
return sb;
}
@@ -666,13 +695,15 @@ public abstract class GLContext {
if( hasFullFBOSupport() ) {
final GL gl = getGL();
final int[] val = new int[] { 0 } ;
- gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
- final int glerr = gl.glGetError();
- if(GL.GL_NO_ERROR == glerr) {
- return val[0];
- } else if(DEBUG) {
- System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
- }
+ try {
+ gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0);
+ final int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR == glerr) {
+ return val[0];
+ } else if(DEBUG) {
+ System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr));
+ }
+ } catch (GLException gle) { gle.printStackTrace(); }
}
return 0;
}
@@ -1369,6 +1400,6 @@ public abstract class GLContext {
protected static String getThreadName() {
return Thread.currentThread().getName();
}
-
+
}
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index b6e7b0576..ae49eeeff 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -49,6 +49,7 @@ import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.opengl.GLAutoDrawableDelegate;
+import com.jogamp.opengl.GLRendererQuirks;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
@@ -307,6 +308,42 @@ public abstract class GLDrawableFactory {
*/
protected abstract boolean createSharedResource(AbstractGraphicsDevice device);
+ /**
+ * Returns true if the quirk
exist in the shared resource's context {@link GLRendererQuirks}.
+ *
+ * Convenience method for: + *
+ final GLRendererQuirks glrq = factory.getRendererQuirks(device); + return null != glrq ? glrq.exist(quirk) : false; + *+ * + * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be
null
for the platform's default device.
+ * @param quirk the quirk to be tested, e.g. {@link GLRendererQuirks#NoDoubleBufferedPBuffer}.
+ * @throws IllegalArgumentException if the quirk is out of range
+ * @see #getRendererQuirks()
+ * @see GLRendererQuirks
+ */
+ public final boolean hasRendererQuirk(AbstractGraphicsDevice device, int quirk) {
+ final GLRendererQuirks glrq = getRendererQuirks(device);
+ return null != glrq ? glrq.exist(quirk) : false;
+ }
+
+ /**
+ * Returns the shared resource's context {@link GLRendererQuirks}.
+ * + * Implementation calls {@link GLContext#getRendererQuirks()} on the shared resource context. + *
+ *
+ * In case no shared device exist yet or the implementation doesn't support tracking quirks,
+ * the result is always null
.
+ *
null
for the platform's default device.
+ * @see GLContext#getRendererQuirks()
+ * @see GLRendererQuirks
+ */
+ public abstract GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device);
+
/**
* Returns the sole GLDrawableFactory instance for the desktop (X11, WGL, ..) if exist or null
*/
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index 23d789afd..aabda465e 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -1445,10 +1445,6 @@ public class GLProfile {
}
} else {
defaultDesktopDevice = desktopFactory.getDefaultDevice();
- defaultDevice = defaultDesktopDevice;
- if(DEBUG) {
- System.err.println("Info: GLProfile.init - Default device is desktop derived: "+defaultDevice);
- }
}
if ( !disableOpenGLES && ReflectionUtil.isClassAvailable("jogamp.opengl.egl.EGLDrawableFactory", classloader) ) {
@@ -1490,7 +1486,7 @@ public class GLProfile {
}
}
- final AbstractGraphicsDevice defaultEGLDevice;
+ final AbstractGraphicsDevice defaultEGLDevice;
if(null == eglFactory) {
hasGLES2Impl = false;
hasGLES1Impl = false;
@@ -1499,25 +1495,33 @@ public class GLProfile {
System.err.println("Info: GLProfile.init - EGL GLDrawable factory not available");
}
} else {
- defaultEGLDevice = eglFactory.getDefaultDevice();
- if(null == defaultDevice) {
- defaultDevice = defaultEGLDevice;
- if(DEBUG) {
- System.err.println("Info: GLProfile.init - Default device is EGL derived: "+defaultDevice);
- }
- }
+ defaultEGLDevice = eglFactory.getDefaultDevice();
}
- /** Should not be required .. but keep it here if simple probe on defaultDevice ain't enough.
- final boolean addedDesktopProfile = initProfilesForDevice(defaultDesktopDevice);
- final boolean addedEGLProfile = initProfilesForDevice(defaultEGLDevice);
- final boolean addedAnyProfile = addedDesktopProfile || addedEGLProfile ;
- */
- final boolean addedAnyProfile = initProfilesForDevice(defaultDevice);
-
+ if( null != defaultDesktopDevice ) {
+ defaultDevice = defaultDesktopDevice;
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device is desktop derived: "+defaultDevice);
+ }
+ } else if ( null != defaultEGLDevice ) {
+ defaultDevice = defaultEGLDevice;
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device is EGL derived: "+defaultDevice);
+ }
+ } else {
+ if(DEBUG) {
+ System.err.println("Info: GLProfile.init - Default device not available");
+ }
+ defaultDevice = null;
+ }
+
+ // we require to initialize the EGL device 1st, if available
+ final boolean addedEGLProfile = null != defaultEGLDevice ? initProfilesForDevice(defaultEGLDevice) : false;
+ final boolean addedDesktopProfile = null != defaultDesktopDevice ? initProfilesForDevice(defaultDesktopDevice) : false;
+ final boolean addedAnyProfile = addedEGLProfile || addedDesktopProfile ;
+
if(DEBUG) {
- // System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
- System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile);
+ System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable);
System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory);
System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl);
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 050c619fd..e164dfe44 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -46,6 +46,7 @@ import java.util.HashMap;
import java.util.Map;
import com.jogamp.common.os.DynamicLookupHelper;
+import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.gluegen.runtime.FunctionAddressResolver;
@@ -53,6 +54,7 @@ import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLNameResolver;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -162,7 +164,7 @@ public abstract class GLContextImpl extends GLContext {
additionalCtxCreationFlags = 0;
glRenderer = "";
- glRendererLowerCase = glRenderer;
+ glRendererLowerCase = glRenderer;
if (boundFBOTarget != null) { // device
{@link AbstractGraphicsDevice#getConnection()},
* either a pre-existing or newly created, or null
if creation failed or not supported.null
for the platform's default device.
*/
protected final AbstractGraphicsDevice getOrCreateSharedDevice(AbstractGraphicsDevice device) {
- if(null==device) {
- device = getDefaultDevice();
- if(null==device) {
- throw new InternalError("no default device");
- }
- if (GLProfile.DEBUG) {
- System.err.println("Info: GLDrawableFactoryImpl.getOrCreateSharedContext: using default device : "+device);
- }
- } else if( !getIsDeviceCompatible(device) ) {
- if (GLProfile.DEBUG) {
- System.err.println("Info: GLDrawableFactoryImpl.getOrCreateSharedContext: device not compatible : "+device);
- }
- return null;
+ device = validateDevice(device);
+ if( null != device) {
+ return getOrCreateSharedDeviceImpl(device);
}
- return getOrCreateSharedDeviceImpl(device);
+ return null;
}
protected abstract AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device);
+
/**
* Returns the GLDynamicLookupHelper
* @param profile if EGL/ES, profile 1
refers to ES1 and 2
to ES2,
@@ -144,12 +145,11 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
try {
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true);
if(null != ols) {
+ final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, this, adevice);
// layered surface -> Offscreen/[FBO|PBuffer]
- final boolean isPbufferAvailable = canCreateGLPbuffer(adevice) ;
- if(!isPbufferAvailable && !isFBOAvailable) {
- throw new GLException("Neither FBO nor Pbuffer is available for "+target);
+ if( !chosenCapsMod.isFBO() && !chosenCapsMod.isPBuffer() ) {
+ throw new GLException("Neither FBO nor Pbuffer is available for "+chosenCapsMod+", "+target);
}
- final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, isFBOAvailable, isPbufferAvailable);
config.setChosenCapabilities(chosenCapsMod);
ols.setChosenCapabilities(chosenCapsMod);
if(DEBUG) {
@@ -163,7 +163,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
if( ! ( target instanceof MutableSurface ) ) {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target);
}
- if( chosenCapsMod.isFBO() && isFBOAvailable ) {
+ if( chosenCapsMod.isFBO() ) {
// target surface is already a native one
result = createFBODrawableImpl(target, chosenCapsMod, 0);
} else {
@@ -294,9 +294,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
throw new GLException("No shared device for requested: "+deviceReq);
}
- final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested,
- GLContext.isFBOAvailable(device, capsRequested.getGLProfile()),
- canCreateGLPbuffer(device));
+ final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, this, device);
if( capsChosen.isFBO() ) {
device.lock();
diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
index 13c95b0dd..31e52b86c 100644
--- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
+++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java
@@ -32,8 +32,9 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawableFactory;
-import com.jogamp.common.os.Platform;
+import com.jogamp.opengl.GLRendererQuirks;
public class GLGraphicsConfigurationUtil {
public static final String NV_coverage_sample = "NV_coverage_sample";
@@ -138,16 +139,25 @@ public class GLGraphicsConfigurationUtil {
return caps;
}
- public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable)
- {
+ /**
+ * Fixes the requested {@link GLCapabilitiesImmutable} according to on- and offscreen usage.
+ * + * No modification will be made for onscreen usage, for offscreen usage see + * {@link #fixOffscreenGLCapabilities(GLCapabilitiesImmutable, GLDrawableFactory, AbstractGraphicsDevice)}. + *
+ * @param capsRequested the requested {@link GLCapabilitiesImmutable} + * @param factory the {@link GLDrawableFactory} used to validate the requested capabilities and later used to create the drawable. + * @param device the device on which the drawable will be created, maybe null for the {@link GLDrawableFactory#getDefaultDevice() default device}. + * @return either the given requested {@link GLCapabilitiesImmutable} instance if no modifications were required, or a modified {@link GLCapabilitiesImmutable} instance. + */ + public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, + GLDrawableFactory factory, AbstractGraphicsDevice device) { if( !capsRequested.isOnscreen() ) { - return fixOffscreenGLCapabilities(capsRequested, fboAvailable, pbufferAvailable); - } /* we maintain the offscreen mode flags in onscreen mode - else { - return fixOnscreenGLCapabilities(capsRequested); - } */ + return fixOffscreenGLCapabilities(capsRequested, factory, device); + } return capsRequested; } - + public static GLCapabilitiesImmutable fixOnscreenGLCapabilities(GLCapabilitiesImmutable capsRequested) { if( !capsRequested.isOnscreen() || capsRequested.isFBO() || capsRequested.isPBuffer() || capsRequested.isBitmap() ) { @@ -162,25 +172,68 @@ public class GLGraphicsConfigurationUtil { return capsRequested; } - public static boolean isGLCapabilitiesOffscreenAutoSelection(GLCapabilitiesImmutable capsRequested) { - return !capsRequested.isOnscreen() && - !capsRequested.isFBO() && !capsRequested.isPBuffer() && !capsRequested.isBitmap() ; + public static GLCapabilitiesImmutable fixOffscreenBitOnly(GLCapabilitiesImmutable capsRequested) + { + if( capsRequested.isOnscreen() ) { + // fix caps .. + final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); + caps2.setOnscreen(false); + return caps2; + } + return capsRequested; } - - public static GLCapabilitiesImmutable fixOffscreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable) { - final boolean auto = !capsRequested.isFBO() && !capsRequested.isPBuffer() && !capsRequested.isBitmap() ; - - final boolean requestedPBuffer = capsRequested.isPBuffer() || Platform.getOSType() == Platform.OSType.MACOS ; // no native bitmap for OSX + + /** + * Fixes the requested {@link GLCapabilitiesImmutable} according to: + *- * We intentionally override a non native EGL device ES profile mapping, - * i.e. this will override/modify an already 'set' X11/WGL/.. mapping. - *
- * - * @param device - */ - protected void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) { - mapCurrentAvailableGLVersionImpl(device, ctxMajorVersion, ctxMinorVersion, ctxOptions); - } - protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, GLCapabilitiesImmutable caps) { + /* pp */ void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) { + mapStaticGLVersion(device, ctxMajorVersion, ctxMinorVersion, ctxOptions); + } + /* pp */ int getContextOptions() { return ctxOptions; } + /* pp */ static void mapStaticGLESVersion(AbstractGraphicsDevice device, GLCapabilitiesImmutable caps) { final GLProfile glp = caps.getGLProfile(); final int[] reqMajorCTP = new int[2]; GLContext.getRequestMajorAndCompat(glp, reqMajorCTP); @@ -309,21 +294,27 @@ public abstract class EGLContext extends GLContextImpl { if(!caps.getHardwareAccelerated()) { reqMajorCTP[1] |= GLContext.CTX_IMPL_ACCEL_SOFT; } - mapCurrentAvailableGLVersionImpl(device, reqMajorCTP[0], 0, reqMajorCTP[1]); - } - protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) { + mapStaticGLVersion(device, reqMajorCTP[0], 0, reqMajorCTP[1]); + } + /* pp */ static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) { int ctp = ( 2 == major ) ? ( GLContext.CTX_PROFILE_ES | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) : ( GLContext.CTX_PROFILE_ES ); - mapCurrentAvailableGLVersionImpl(device, major, 0, ctp); + mapStaticGLVersion(device, major, 0, ctp); } - private static void mapCurrentAvailableGLVersionImpl(AbstractGraphicsDevice device, int major, int minor, int ctp) { + /* pp */ static void mapStaticGLVersion(AbstractGraphicsDevice device, int major, int minor, int ctp) { if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) { // ES1 or ES2 final int reqMajor = major; final int reqProfile = GLContext.CTX_PROFILE_ES; - GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, - major, minor, ctp); + GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, major, minor, ctp); + if(! ( device instanceof EGLGraphicsDevice ) ) { + final EGLGraphicsDevice eglDevice = new EGLGraphicsDevice(device.getHandle(), EGL.EGL_NO_DISPLAY, device.getConnection(), device.getUnitID(), null); + GLContext.mapAvailableGLVersion(eglDevice, reqMajor, reqProfile, major, minor, ctp); + } } } + protected static String getGLVersion(int major, int minor, int ctp, String gl_version) { + return GLContext.getGLVersion(major, minor, ctp, gl_version); + } protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) { return GLContext.getAvailableGLVersionsSet(device); diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index e98d69140..a907c4aff 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -43,6 +43,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; @@ -77,11 +78,11 @@ import com.jogamp.common.nio.PointerBuffer; import com.jogamp.common.os.Platform; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; +import com.jogamp.opengl.GLRendererQuirks; public class EGLDrawableFactory extends GLDrawableFactoryImpl { protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG; - /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true); /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true); private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null; @@ -113,36 +114,11 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } catch (JogampRuntimeException jre) { /* n/a .. */ } } - defaultDevice = new EGLGraphicsDevice(); - // FIXME: Probably need to move EGL from a static model // to a dynamic one, where there can be 2 instances // for each ES profile with their own ProcAddressTable. synchronized(EGLDrawableFactory.class) { - /** - * Currently AMD's EGL impl. crashes at eglGetDisplay(EGL_DEFAULT_DISPLAY) - * - // Check Desktop ES2 Availability first (AMD, ..) - if(null==eglES2DynamicLookupHelper) { - GLDynamicLookupHelper tmp=null; - try { - tmp = new GLDynamicLookupHelper(new DesktopES2DynamicLibraryBundleInfo()); - } catch (GLException gle) { - if(DEBUG) { - gle.printStackTrace(); - } - } - if(null!=tmp && tmp.isLibComplete()) { - eglES2DynamicLookupHelper = tmp; - EGL.resetProcAddressTable(eglES2DynamicLookupHelper); - if (GLProfile.DEBUG) { - System.err.println("Info: EGLDrawableFactory: Desktop ES2 - OK"); - } - } else if (GLProfile.DEBUG) { - System.err.println("Info: EGLDrawableFactory: Desktop ES2 - NOPE"); - } - } */ final boolean hasDesktopES2 = null != eglES2DynamicLookupHelper; if(!hasDesktopES2 && null==eglES1DynamicLookupHelper) { @@ -188,8 +164,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } } if(null != eglES2DynamicLookupHelper || null != eglES1DynamicLookupHelper) { - sharedMap = new HashMap-1
is returned.
*
*
- * The default value for a valid context is 1
for
- * an EGL based profile (ES1 or ES2) and -1
(undefined)
- * for desktop.
+ * For a valid context the default value is 1
+ * in case of an EGL based profile (ES1 or ES2) and -1
+ * (undefined) for desktop.
*
+ * The context must have been current once, otherwise null
is returned.
+ *
+ * Examples w/ major.minor
:
+ *
+ * 1.00 (ES2.0), 1.10 (GL2.0), 1.20 (GL2.1), 1.50 GL(3.2), + * 3.30 (GL3.3), 4.40 (GL4.0) + *+ * + *
+ * Matching could also refer to the maximum GLSL version usable by this context + * since normal GL implementations are capable of using a lower GLSL version as well. + * The latter is not true on OSX w/ a GL3 context. + *
+ * + * @param GLSL version number if context has been made current at least once, otherwisenull
.
+ *
+ * @see #getGLVersionMajor()
+ * @see #getGLVersionMinor()
+ */
+ public final VersionNumber getGLSLVersionNumber() {
+ return ctxGLSLVersion;
+ }
+
+ /**
+ * Returns the GLSL version string as to be used in a shader program, including a terminating newline '\n',
+ * i.e.:
+ * + * #version 110 + *+ *
+ * If context has not been made current, null
is returned.
+ *
GL_ARB_ES2_compatibility
, otherwise false
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 249dc9c62..d2e0bb407 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -60,6 +60,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
@@ -971,7 +972,22 @@ public abstract class GLContextImpl extends GLContext {
ctxMinorVersion = minor;
ctxOptions = ctp;
if(setVersionString) {
- ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, getGL().glGetString(GL.GL_VERSION));
+ ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, gl.glGetString(GL.GL_VERSION));
+ ctxGLSLVersion = null;
+ if(ctxMajorVersion >= 2) { // >= ES2 || GL2.0
+ final String glslVersion = gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION);
+ if( null != glslVersion ) {
+ ctxGLSLVersion = new VersionNumber(glslVersion, ".");
+ if( ctxGLSLVersion.getMajor() < 1 ) {
+ ctxGLSLVersion = null; // failed ..
+ }
+ }
+ }
+ if( null == ctxGLSLVersion ){
+ final int[] sver = new int[2];
+ getStaticGLSLVersionNumber(ctxMajorVersion, ctxMinorVersion, ctxOptions, sver);
+ ctxGLSLVersion = new VersionNumber(sver[0], sver[1], 0);
+ }
}
}
--
cgit v1.2.3
From 9b6448b1d54716fd455c0cad0c6133c0edeb3bb8 Mon Sep 17 00:00:00 2001
From: Sven Gothel discard
command leads to undefined behavior or won't get compiled if being used. Appears to happen on Nvidia Tegra2. FIXME: Constrain version. */
+ public static final int GLSLBuggyDiscard = 6;
/** Number of quirks known. */
- public static final int COUNT = 5;
+ public static final int COUNT = 7;
private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval",
- "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget"
+ "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "RequiresBoundVAO",
+ "GLSLBuggyDiscard"
};
private final int _bitmask;
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index d2e0bb407..48184119b 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -98,7 +98,8 @@ public abstract class GLContextImpl extends GLContext {
private final GLStateTracker glStateTracker = new GLStateTracker();
private GLDebugMessageHandler glDebugHandler = null;
private final int[] boundFBOTarget = new int[] { 0, 0 }; // { draw, read }
-
+ private int defaultVAO = 0;
+
protected GLDrawableImpl drawable;
protected GLDrawableImpl drawableRead;
@@ -347,6 +348,12 @@ public abstract class GLContextImpl extends GLContext {
} catch (Throwable t) {
drawableContextRealizedException = t;
}
+ if(0 != defaultVAO) {
+ int[] tmp = new int[] { defaultVAO };
+ gl.getGL2GL3().glBindVertexArray(0);
+ gl.getGL2GL3().glDeleteVertexArrays(1, tmp, 0);
+ defaultVAO = 0;
+ }
glDebugHandler.enable(false);
if(lock.getHoldCount() > 1) {
// pending release() after makeCurrent()
@@ -563,6 +570,13 @@ public abstract class GLContextImpl extends GLContext {
final boolean created;
try {
created = createImpl(shareWith); // may throws exception if fails!
+ if( created && glRendererQuirks.exist(GLRendererQuirks.RequiresBoundVAO) ) {
+ // Workaround: Create a default VAO to be used per default on makeCurrent
+ final int[] tmp = new int[1];
+ gl.getGL2GL3().glGenVertexArrays(1, tmp, 0);
+ defaultVAO = tmp[0];
+ gl.getGL2GL3().glBindVertexArray(defaultVAO);
+ }
} finally {
if (null != shareWith) {
shareWith.getDrawableImpl().unlockSurface();
@@ -1292,11 +1306,18 @@ public abstract class GLContextImpl extends GLContext {
// OS related quirks
if( Platform.getOSType() == Platform.OSType.MACOS ) {
- final int quirk = GLRendererQuirks.NoOffscreenBitmap;
+ final int quirk1 = GLRendererQuirks.NoOffscreenBitmap;
if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk1)+": cause: OS "+Platform.getOSType());
+ }
+ quirks[i++] = quirk1;
+ if( 3 <= ctxMajorVersion ) {
+ final int quirk2 = GLRendererQuirks.RequiresBoundVAO;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk2)+": cause: OS "+Platform.getOSType());
+ }
+ quirks[i++] = quirk2;
}
- quirks[i++] = quirk;
} else if( Platform.getOSType() == Platform.OSType.WINDOWS ) {
final int quirk = GLRendererQuirks.NoDoubleBufferedBitmap;
if(DEBUG) {
--
cgit v1.2.3
From a192426862ad6f05c3351dbaf9880d00707c01bc Mon Sep 17 00:00:00 2001
From: Sven Gothel discard
command leads to undefined behavior or won't get compiled if being used. Appears to happen on Nvidia Tegra2. FIXME: Constrain version. */
- public static final int GLSLBuggyDiscard = 6;
+ public static final int GLSLBuggyDiscard = 5;
/** Number of quirks known. */
- public static final int COUNT = 7;
+ public static final int COUNT = 6;
private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval",
- "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "RequiresBoundVAO",
- "GLSLBuggyDiscard"
+ "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard"
};
private final int _bitmask;
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index ddb222bfe..de10a2815 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -814,6 +814,12 @@ public abstract class GLContext {
&& 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
}
+ /** Indicates whether this profile is capable of GL4 (core only). Includes [ GL4 ].
*/ + public final boolean isGL4core() { + return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED) + && 0 != (ctxOptions & CTX_PROFILE_CORE); + } + /** @see GLProfile#isGL3bc() */ public final boolean isGL3bc() { return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) @@ -828,6 +834,13 @@ public abstract class GLContext { && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)); } + /** Indicates whether this profile is capable of GL3 (core only).Includes [ GL4, GL3 ].
*/ + public final boolean isGL3core() { + return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) + && 0 != (ctxOptions & CTX_IS_ARB_CREATED) + && 0 != (ctxOptions & CTX_PROFILE_CORE); + } + /** @see GLProfile#isGL2() */ public final boolean isGL2() { return ctxMajorVersion>=1 && 0!=(ctxOptions & CTX_PROFILE_COMPAT); diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index a211f3840..65b523394 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -570,8 +570,11 @@ public abstract class GLContextImpl extends GLContext { final boolean created; try { created = createImpl(shareWith); // may throws exception if fails! - if( created && glRendererQuirks.exist(GLRendererQuirks.RequiresBoundVAO) ) { - // Workaround: Create a default VAO to be used per default on makeCurrent + if( created && isGL3core() && ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=2 ) ) { + // Due to GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331) + // There is no more default VAO buffer 0 bound, hence generating and binding one + // to avoid INVALID_OPERATION at VertexAttribPointer. + // More clear is GL 4.3 core spec: 10.4 (p 307). final int[] tmp = new int[1]; gl.getGL2GL3().glGenVertexArrays(1, tmp, 0); defaultVAO = tmp[0]; @@ -1311,13 +1314,6 @@ public abstract class GLContextImpl extends GLContext { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk1)+": cause: OS "+Platform.getOSType()); } quirks[i++] = quirk1; - if( isGL3() ) { - final int quirk2 = GLRendererQuirks.RequiresBoundVAO; - if(DEBUG) { - System.err.println("Quirk: "+GLRendererQuirks.toString(quirk2)+": cause: OS "+Platform.getOSType()); - } - quirks[i++] = quirk2; - } } else if( Platform.getOSType() == Platform.OSType.WINDOWS ) { final int quirk = GLRendererQuirks.NoDoubleBufferedBitmap; if(DEBUG) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java index d2c00f980..90f2ab988 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java @@ -89,6 +89,7 @@ public class TestGearsES2NEWT extends UITestCase { static boolean loop_shutdown = false; static boolean forceES2 = false; static boolean forceGL3 = false; + static boolean mainRun = false; @BeforeClass public static void initClass() { @@ -265,7 +266,7 @@ public class TestGearsES2NEWT extends UITestCase { } else { glp = GLProfile.getGL2ES2(); } - GLCapabilities caps = new GLCapabilities( glp ); + final GLCapabilities caps = new GLCapabilities( glp ); caps.setBackgroundOpaque(opaque); if(-1 < forceAlpha) { caps.setAlphaBits(forceAlpha); @@ -277,7 +278,21 @@ public class TestGearsES2NEWT extends UITestCase { } } - public static void main(String args[]) throws IOException { + @Test + public void test02GL3() throws InterruptedException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + } + final GLProfile glp = GLProfile.get(GLProfile.GL3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps, undecorated); + } + + public static void main(String args[]) throws IOException { + mainRun = true; + int x=0, y=0, w=640, h=480; boolean usePos = false; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java index f0c3bb684..21c09f78c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestRedSquareES2NEWT.java @@ -54,6 +54,8 @@ public class TestRedSquareES2NEWT extends UITestCase { static boolean loop_shutdown = false; static boolean vsync = false; static boolean forceES2 = false; + static boolean forceGL3 = false; + static boolean mainRun = false; static boolean doRotate = true; @BeforeClass @@ -127,17 +129,38 @@ public class TestRedSquareES2NEWT extends UITestCase { public void test01GL2ES2() throws InterruptedException { for(int i=1; i<=loops; i++) { System.err.println("Loop "+i+"/"+loops); - GLCapabilities caps = new GLCapabilities(forceES2 ? GLProfile.get(GLProfile.GLES2) : GLProfile.getGL2ES2()); + final GLProfile glp; + if(forceGL3) { + glp = GLProfile.get(GLProfile.GL3); + } else if(forceES2) { + glp = GLProfile.get(GLProfile.GLES2); + } else { + glp = GLProfile.getGL2ES2(); + } + final GLCapabilities caps = new GLCapabilities(glp); runTestGL(caps); if(loop_shutdown) { GLProfile.shutdown(); } } } + + @Test + public void test02GL3() throws InterruptedException { + if(mainRun) return; + + if( !GLProfile.isAvailable(GLProfile.GL3) ) { + System.err.println("GL3 n/a"); + } + final GLProfile glp = GLProfile.get(GLProfile.GL3); + final GLCapabilities caps = new GLCapabilities( glp ); + runTestGL(caps); + } static long duration = 500; // ms public static void main(String args[]) { + mainRun = true; for(int i=0; i+ * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0}, + * otherwise this is {@link GL#GL_FRONT} for single buffer configurations + * and {@link GL#GL_BACK} for double buffer configurations. + *
+ */ + public int getDefaultReadBuffer(); + } diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index de10a2815..235003c38 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -970,6 +970,32 @@ public abstract class GLContext { */ public abstract int getDefaultReadFramebuffer(); + /** + * Returns the default color buffer within the current bound + * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER​, + * which will be used as the source for pixel reading commands, + * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)} etc. + *+ * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0}, + * otherwise this is {@link GL#GL_FRONT} for single buffer configurations + * and {@link GL#GL_BACK} for double buffer configurations. + *
+ */ + public abstract int getDefaultReadBuffer(); + + /** On some platforms the mismatch between OpenGL's coordinate + system (origin at bottom left) and the window system's + coordinate system (origin at top left) necessitates a vertical + flip of pixels read from offscreen contexts. +
+ Default impl. is true
.
+
+ * If {@link GLCapabilities#getDoubleBuffered() double buffering} is not chosen, this is a NOP. + *
+ *+ * Must be called before {@link #isInitialized() initialization}, otherwise an exception is thrown. + *
+ * @return the new number of buffers (FBO) used, maybe different than the requestedbufferCount
(see above)
+ * @throws GLException if already initialized, see {@link #isInitialized()}.
+ */
+ int setNumBuffers(int bufferCount) throws GLException;
+
+ /**
+ * @return the number of buffers (FBO) being used. 1 if not using {@link GLCapabilities#getDoubleBuffered() double buffering},
+ * otherwise ≥ 2, depending on {@link #setNumBuffers(int)}.
+ */
+ int getNumBuffers();
/**
* @return the used {@link DoubleBufferMode}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index dcfc1f0dd..a9d4989dc 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -618,12 +618,18 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
public NativeSurface getNativeSurface() {
- throw new GLException("FIXME");
+ if(null != backend) {
+ return backend.getDrawable().getNativeSurface();
+ }
+ return null;
}
@Override
public long getHandle() {
- throw new GLException("FIXME");
+ if(null != backend) {
+ return backend.getDrawable().getNativeSurface().getSurfaceHandle();
+ }
+ return 0;
}
@Override
@@ -657,6 +663,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
if (oglPipelineEnabled) {
backend = new J2DOGLBackend();
} else {
+ backend = new SoftwareBackend();
+ /**
if (!hardwareAccelerationDisabled &&
factory.canCreateGLPbuffer(null)) {
backend = new PbufferBackend();
@@ -665,7 +673,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
throw new GLException("Fallback to software rendering disabled by user");
}
backend = new SoftwareBackend();
- }
+ } */
}
}
@@ -996,7 +1004,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 1);
// Actually read the pixels.
- gl.glReadBuffer(GL2.GL_FRONT);
+ gl.glReadBuffer(gl.getDefaultReadBuffer());
if (readBackBytes != null) {
gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackBytes);
} else if (readBackInts != null) {
@@ -1173,12 +1181,12 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
@Override
protected int getGLPixelType() {
- return offscreenContext.getOffscreenContextPixelDataType();
+ return offscreenContext.getDefaultPixelDataType();
}
@Override
protected boolean flipVertically() {
- return offscreenContext.offscreenImageNeedsVerticalFlip();
+ return offscreenContext.isGLOrientationFlippedVertical();
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 65b523394..24fc466b1 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1513,15 +1513,46 @@ public abstract class GLContextImpl extends GLContext {
throw new GLException("Not supported on non-pbuffer contexts");
}
- /** On some platforms the mismatch between OpenGL's coordinate
- system (origin at bottom left) and the window system's
- coordinate system (origin at top left) necessitates a vertical
- flip of pixels read from offscreen contexts. */
- public abstract boolean offscreenImageNeedsVerticalFlip();
+ @Override
+ public boolean isGLOrientationFlippedVertical() {
+ return true;
+ }
- /** Only called for offscreen contexts; needed by glReadPixels */
- public abstract int getOffscreenContextPixelDataType();
+ @Override
+ public int getDefaultPixelDataType() {
+ if(!pixelDataTypeEvaluated) {
+ synchronized(this) {
+ if(!pixelDataTypeEvaluated) {
+ evalPixelDataType();
+ pixelDataTypeEvaluated = true;
+ }
+ }
+ }
+ return pixelDataType;
+ }
+ private volatile boolean pixelDataTypeEvaluated = false;
+ int /* pixelDataInternalFormat, */ pixelDataFormat, pixelDataType;
+
+ private final void evalPixelDataType() {
+ /* if(isGL2GL3() && 3 == components) {
+ pixelDataInternalFormat=GL.GL_RGB;
+ pixelDataFormat=GL.GL_RGB;
+ pixelDataType = GL.GL_UNSIGNED_BYTE;
+ } else */ if(isGLES2Compatible() || isExtensionAvailable(GLExtensions.OES_read_format)) {
+ final int[] glImplColorReadVals = new int[] { 0, 0 };
+ gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
+ gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);
+ // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
+ pixelDataFormat = glImplColorReadVals[0];
+ pixelDataType = glImplColorReadVals[1];
+ } else {
+ // RGBA read is safe for all GL profiles
+ // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
+ pixelDataFormat=GL.GL_RGBA;
+ pixelDataType = GL.GL_UNSIGNED_BYTE;
+ }
+ }
//----------------------------------------------------------------------
// Helpers for buffer object optimizations
@@ -1599,8 +1630,10 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final int getDefaultDrawFramebuffer() { return drawable.getDefaultDrawFramebuffer(); }
@Override
- public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); }
-
+ public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); }
+ @Override
+ public final int getDefaultReadBuffer() { return drawable.getDefaultReadBuffer(gl); }
+
//---------------------------------------------------------------------------
// GL_ARB_debug_output, GL_AMD_debug_output helpers
//
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index df7f742aa..ccf0a8f0d 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -244,7 +244,16 @@ public abstract class GLDrawableImpl implements GLDrawable {
/** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/
protected int getDefaultDrawFramebuffer() { return 0; }
/** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */
- protected int getDefaultReadFramebuffer() { return 0; }
+ protected int getDefaultReadFramebuffer() { return 0; }
+ /** Callback for special implementations, allowing GLContext to fetch a custom default read buffer of current framebuffer. */
+ protected int getDefaultReadBuffer(GL gl) {
+ if(gl.isGLES() || getChosenGLCapabilities().getDoubleBuffered()) {
+ // Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer
+ // Note-2: ES3 only supports GL_BACK, GL_NONE or GL_COLOR_ATTACHMENT0+i
+ return GL.GL_BACK;
+ }
+ return GL.GL_FRONT ;
+ }
@Override
public final synchronized boolean isRealized() {
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index 7a468a41e..b72f79868 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -301,6 +301,9 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
@Override
protected final int getDefaultReadFramebuffer() { return initialized ? fbos[fboIFront].getReadFramebuffer() : 0; }
+ @Override
+ protected final int getDefaultReadBuffer(GL gl) { return initialized ? fbos[fboIFront].getDefaultReadBuffer() : GL.GL_COLOR_ATTACHMENT0 ; }
+
@Override
protected final void setRealizedImpl() {
final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration();
@@ -435,6 +438,17 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
}
}
+ @Override
+ public final int setNumBuffers(int bufferCount) throws GLException {
+ // FIXME: Implement
+ return bufferCount;
+ }
+
+ @Override
+ public final int getNumBuffers() {
+ return bufferCount;
+ }
+
/** // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
@Override
public final DoubleBufferMode getDoubleBufferMode() {
diff --git a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
index 7701f209f..59a00170d 100644
--- a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java
@@ -95,6 +95,16 @@ public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implemen
windowRepaintOp();
}
+ @Override
+ public final int setNumBuffers(int bufferCount) throws GLException {
+ return ((GLFBODrawableImpl)drawable).setNumBuffers(bufferCount);
+ }
+
+ @Override
+ public final int getNumBuffers() {
+ return ((GLFBODrawableImpl)drawable).getNumBuffers();
+ }
+
/** // TODO: Add or remove TEXTURE (only) DoubleBufferMode support
@Override
public DoubleBufferMode getDoubleBufferMode() {
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
index 84aeaa94a..deb3813b1 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
@@ -344,14 +344,4 @@ public abstract class EGLContext extends GLContextImpl {
public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
throw new GLException("Should not call this");
}
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- throw new GLException("Should not call this");
- }
-
- @Override
- public int getOffscreenContextPixelDataType() {
- throw new GLException("Should not call this");
- }
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index cde9841b8..63ed2ab7d 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -420,20 +420,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
return super.isExtensionAvailable(glExtensionName);
}
- @Override
- public int getOffscreenContextPixelDataType() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextReadBuffer() {
- throw new GLException("Should not call this");
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- throw new GLException("Should not call this");
- }
-
// Support for "mode switching" as described in MacOSXCGLDrawable
public void setOpenGLMode(GLBackendType mode) {
if (mode == openGLMode) {
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java
index 7b13ce22e..f2e636796 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java
@@ -49,18 +49,8 @@ public class MacOSXOffscreenCGLContext extends MacOSXPbufferCGLContext
}
@Override
- public int getOffscreenContextPixelDataType() {
- GL gl = getGL();
+ public int getDefaultPixelDataType() {
+ final GL gl = getGL();
return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
}
-
- @Override
- public int getOffscreenContextReadBuffer() {
- return GL.GL_FRONT;
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- return true;
- }
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java
index 51341a098..c8aac7f7b 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java
@@ -49,18 +49,12 @@ public class WindowsBitmapWGLContext extends WindowsWGLContext {
}
@Override
- public int getOffscreenContextPixelDataType() {
+ public int getDefaultPixelDataType() {
return GL.GL_UNSIGNED_BYTE;
}
@Override
- public int getOffscreenContextReadBuffer() {
- // On Windows these contexts are always single-buffered
- return GL.GL_FRONT;
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
+ public boolean isGLOrientationFlippedVertical() {
// We can take care of this in the DIB creation (see below)
return false;
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
index 57f16522c..92d75e3fd 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
@@ -537,20 +537,6 @@ public class WindowsWGLContext extends GLContextImpl {
return getWGLExt().wglAllocateMemoryNV(arg0, arg1, arg2, arg3);
}
- @Override
- public int getOffscreenContextPixelDataType() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextReadBuffer() {
- throw new GLException("Should not call this");
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- throw new GLException("Should not call this");
- }
-
@Override
public void bindPbufferToTexture() {
throw new GLException("Should not call this");
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index 76e0bc15c..bf1045132 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -618,20 +618,6 @@ public abstract class X11GLXContext extends GLContextImpl {
return getGLXExt().glXAllocateMemoryNV(arg0, arg1, arg2, arg3);
}
- @Override
- public int getOffscreenContextPixelDataType() {
- throw new GLException("Should not call this");
- }
-
- public int getOffscreenContextReadBuffer() {
- throw new GLException("Should not call this");
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- throw new GLException("Should not call this");
- }
-
@Override
public void bindPbufferToTexture() {
throw new GLException("Should not call this");
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java
index 96d0f18dc..1cfb7e427 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java
@@ -50,24 +50,9 @@ public class X11PixmapGLXContext extends X11GLXContext {
}
@Override
- public int getOffscreenContextPixelDataType() {
+ public int getDefaultPixelDataType() {
GL gl = getGL();
return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
}
- @Override
- public int getOffscreenContextReadBuffer() {
- GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities();
- if (caps.getDoubleBuffered()) {
- return GL.GL_BACK;
- }
- return GL.GL_FRONT;
- }
-
- @Override
- public boolean offscreenImageNeedsVerticalFlip() {
- // There doesn't seem to be a way to do this in the construction
- // of the Pixmap or GLXPixmap
- return true;
- }
}
--
cgit v1.2.3
From 13600772542d9d5ad65c6d73b3d568100d6445b6 Mon Sep 17 00:00:00 2001
From: Sven Gothel true
and the ctx version (by string) is lower than the given major.minor version,
+ * method aborts and returns false
, otherwise true
.
+ * @return returns true
if successful, otherwise false
. See strictVersionMatch
.
* @see #setContextVersion
* @see javax.media.opengl.GLContext#CTX_OPTION_ANY
* @see javax.media.opengl.GLContext#CTX_PROFILE_COMPAT
* @see javax.media.opengl.GLContext#CTX_IMPL_ES2_COMPAT
*/
- protected final void setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits) {
+ protected final boolean setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits, boolean strictVersionMatch) {
if(null!=this.gl && null!=glProcAddressTable && !force) {
- return; // already done and not forced
+ return true; // already done and not forced
}
if(null==this.gl || !verifyInstance(gl.getGLProfile(), "Impl", this.gl)) {
@@ -1206,7 +1206,13 @@ public abstract class GLContextImpl extends GLContext {
{
final VersionNumber setGLVersionNumber = new VersionNumber(major, minor, 0);
final VersionNumber strGLVersionNumber = getGLVersionNumber(ctxProfileBits, glVersion);
- if( null != strGLVersionNumber && ( strGLVersionNumber.compareTo(setGLVersionNumber) <= 0 || 0 == major ) ) {
+ if( null != strGLVersionNumber && ( strGLVersionNumber.compareTo(setGLVersionNumber) < 0 || 0 == major ) ) {
+ if( 0 < major && strictVersionMatch ) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch: "+major+"."+minor+", ctp "+toHexString(ctxProfileBits)+", "+glVersion+", "+strGLVersionNumber);
+ }
+ return false;
+ }
glVersionNumber = strGLVersionNumber;
major = glVersionNumber.getMajor();
minor = glVersionNumber.getMinor();
@@ -1299,8 +1305,9 @@ public abstract class GLContextImpl extends GLContext {
setDefaultSwapInterval();
if(DEBUG) {
- System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null));
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: OK "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null));
}
+ return true;
}
private final void setRendererQuirks(boolean hwAccel) {
@@ -1380,16 +1387,18 @@ public abstract class GLContextImpl extends GLContext {
}
synchronized(mappedContextTypeObjectLock) {
- ProcAddressTable table = mappedGLProcAddress.remove( contextFQN );
+ final ProcAddressTable table = mappedGLProcAddress.remove( contextFQN );
if(DEBUG) {
- System.err.println(getThreadName() + ": RM GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+table.hashCode());
+ final int hc = null != table ? table.hashCode() : 0;
+ System.err.println(getThreadName() + ": RM GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+toHexString(hc));
}
}
synchronized(mappedContextTypeObjectLock) {
- ExtensionAvailabilityCache eCache = mappedExtensionAvailabilityCache.remove( contextFQN );
+ final ExtensionAvailabilityCache eCache = mappedExtensionAvailabilityCache.remove( contextFQN );
if(DEBUG) {
- System.err.println(getThreadName() + ": RM GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+eCache.hashCode());
+ final int hc = null != eCache ? eCache.hashCode() : 0;
+ System.err.println(getThreadName() + ": RM GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+toHexString(hc));
}
}
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
index deb3813b1..bd8e7dee9 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
@@ -214,7 +214,7 @@ public abstract class EGLContext extends GLContextImpl {
throw new GLException("Error making context " +
toHexString(contextHandle) + " current: error code " + toHexString(EGL.eglGetError()));
}
- setGLFunctionAvailability(true, glProfile.usesNativeGLES2() ? 2 : 1, 0, CTX_PROFILE_ES);
+ setGLFunctionAvailability(true, glProfile.usesNativeGLES2() ? 2 : 1, 0, CTX_PROFILE_ES, false);
return true;
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java
index 84bd705db..da8fb519d 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java
@@ -45,7 +45,7 @@ public class EGLExternalContext extends EGLContext {
public EGLExternalContext(AbstractGraphicsScreen screen) {
super(null, null);
GLContextShareSet.contextCreated(this);
- setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES);
+ setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES, false);
getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
index 65ed5fc15..f121a2547 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java
@@ -64,7 +64,7 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext {
setOpenGLMode(isNSContext ? GLBackendType.NSOPENGL : GLBackendType.CGL );
this.contextHandle = handle;
GLContextShareSet.contextCreated(this);
- setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT);
+ setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false);
getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java
index f41400d83..bd183b900 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java
@@ -97,7 +97,7 @@ public class MacOSXJava2DCGLContext extends MacOSXCGLContext implements Java2DGL
}
return false;
}
- setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
+ setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION
contextHandle = ctx;
return true;
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
index f6cc2956d..84b29a09f 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java
@@ -65,7 +65,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext {
System.err.println(getThreadName() + ": Created external OpenGL context " + toHexString(ctx) + " for " + this);
}
GLContextShareSet.contextCreated(this);
- setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
+ setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION
getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
index 92d75e3fd..a654cdd04 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
@@ -308,7 +308,7 @@ public class WindowsWGLContext extends GLContextImpl {
if (!WGL.wglMakeCurrent(drawable.getHandle(), temp_ctx)) {
throw new GLException("Error making temp context current: 0x" + toHexString(temp_ctx) + ", werr: "+GDI.GetLastError());
}
- setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
+ setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION
WGL.wglMakeCurrent(0, 0); // release temp context
if( !createContextARBTried) {
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
index bebb4e68a..12fa5786a 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java
@@ -64,7 +64,7 @@ public class X11ExternalGLXContext extends X11GLXContext {
super(drawable, null);
this.contextHandle = ctx;
GLContextShareSet.contextCreated(this);
- setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT);
+ setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false);
getGLStateTracker().setEnabled(false); // external context usage can't track state in Java
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index bf1045132..5b0d32353 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -308,7 +308,7 @@ public abstract class X11GLXContext extends GLContextImpl {
if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) {
throw new GLException(getThreadName()+": Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable);
}
- setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
+ setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION
isDirect = GLX.glXIsDirect(display, contextHandle);
if (DEBUG) {
System.err.println(getThreadName() + ": createContextImpl: OK (old-1) share "+share+", direct "+isDirect+"/"+direct);
@@ -338,7 +338,7 @@ public abstract class X11GLXContext extends GLContextImpl {
if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx)) {
throw new GLException(getThreadName()+": Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable);
}
- setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION
+ setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION
glXMakeContextCurrent(display, 0, 0, 0); // release temp context
if( !createContextARBTried ) {
// is*Available calls are valid since setGLFunctionAvailability(..) was called
--
cgit v1.2.3
From 1ae0737f34143a5ed655bd9c4d5fe9b0437c7774 Mon Sep 17 00:00:00 2001
From: Sven Gothel discard
command leads to undefined behavior or won't get compiled if being used. Appears to happen on Nvidia Tegra2. FIXME: Constrain version. */
public static final int GLSLBuggyDiscard = 5;
+ /**
+ * Non compliant GL context, e.g. due to a buggy implementation rendering it not suitable for use.
+ * + * Mesa >= 9.0 (?), Intel driver, OpenGL 3.1 compatibility context is not compliant: + *
+ * GL_RENDERER: Mesa DRI Intel(R) Sandybridge Desktop + *+ * + */ + public static final int GLNonCompliant = 6; + /** Number of quirks known. */ - public static final int COUNT = 6; + public static final int COUNT = 7; private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval", - "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard" + "NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard", + "GLNonCompliant" }; private final int _bitmask; diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index f61b55497..c3c2eff4b 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -571,9 +571,10 @@ public abstract class GLContextImpl extends GLContext { final boolean created; try { created = createImpl(shareWith); // may throws exception if fails! - if( created && isGL3core() && ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=2 ) ) { - // Due to GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331) - // There is no more default VAO buffer 0 bound, hence generating and binding one + if( created && isGL3core() && ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) ) { + // Due to GL 3.1 core spec: E.1. DEPRECATED AND REMOVED FEATURES (p 296), + // GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331) + // there is no more default VAO buffer 0 bound, hence generating and binding one // to avoid INVALID_OPERATION at VertexAttribPointer. // More clear is GL 4.3 core spec: 10.4 (p 307). final int[] tmp = new int[1]; @@ -773,6 +774,29 @@ public abstract class GLContextImpl extends GLContext { boolean hasGL2 = false; boolean hasGL4 = false; boolean hasGL3 = false; + + // Even w/ PROFILE_ALIASING, try to use true core GL profiles + // ensuring proper user behavior across platforms due to different feature sets! + // + if(!hasGL4) { + hasGL4 = createContextARBMapVersionsAvailable(4, CTX_PROFILE_CORE); // GL4 + success |= hasGL4; + if(hasGL4) { + // Map all lower compatible profiles: GL3 + GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); + if(PROFILE_ALIASING) { + hasGL3 = true; + } + resetStates(); // clean this context states, since creation was temporary + } + } + if(!hasGL3) { + hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3 + success |= hasGL3; + if(hasGL3) { + resetStates(); // clean this context states, since creation was temporary + } + } if(!hasGL4bc) { hasGL4bc = createContextARBMapVersionsAvailable(4, CTX_PROFILE_COMPAT); // GL4bc success |= hasGL4bc; @@ -780,8 +804,12 @@ public abstract class GLContextImpl extends GLContext { // Map all lower compatible profiles: GL3bc, GL2, GL4, GL3 GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions); GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions); - GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); + if(!hasGL4) { + GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); + } + if(!hasGL3) { + GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); + } if(PROFILE_ALIASING) { hasGL3bc = true; hasGL2 = true; @@ -797,7 +825,9 @@ public abstract class GLContextImpl extends GLContext { if(hasGL3bc) { // Map all lower compatible profiles: GL2 and GL3 GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions); - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); + if(!hasGL3) { + GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); + } if(PROFILE_ALIASING) { hasGL2 = true; hasGL3 = true; @@ -812,25 +842,6 @@ public abstract class GLContextImpl extends GLContext { resetStates(); // clean this context states, since creation was temporary } } - if(!hasGL4) { - hasGL4 = createContextARBMapVersionsAvailable(4, CTX_PROFILE_CORE); // GL4 - success |= hasGL4; - if(hasGL4) { - // Map all lower compatible profiles: GL3 - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); - if(PROFILE_ALIASING) { - hasGL3 = true; - } - resetStates(); // clean this context states, since creation was temporary - } - } - if(!hasGL3) { - hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3 - success |= hasGL3; - if(hasGL3) { - resetStates(); // clean this context states, since creation was temporary - } - } if(success) { // only claim GL versions set [and hence detected] if ARB context creation was successful GLContext.setAvailableGLVersionsSet(device); @@ -883,7 +894,7 @@ public abstract class GLContextImpl extends GLContext { /* min */ majorMin, minorMin, /* res */ major, minor); - if(0==_context && CTX_PROFILE_CORE == reqProfile) { + if( 0 == _context && CTX_PROFILE_CORE == reqProfile && !PROFILE_ALIASING ) { // try w/ FORWARD instead of CORE ctp &= ~CTX_PROFILE_CORE ; ctp |= CTX_OPTION_FORWARD ; @@ -891,7 +902,7 @@ public abstract class GLContextImpl extends GLContext { /* max */ majorMax, minorMax, /* min */ majorMin, minorMin, /* res */ major, minor); - if(0==_context) { + if( 0 == _context ) { // Try a compatible one .. even though not requested .. last resort ctp &= ~CTX_PROFILE_CORE ; ctp &= ~CTX_OPTION_FORWARD ; @@ -903,7 +914,7 @@ public abstract class GLContextImpl extends GLContext { } } final boolean res; - if(0!=_context) { + if( 0 != _context ) { AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); // ctxMajorVersion, ctxMinorVersion, ctxOptions is being set by // createContextARBVersions(..) -> setGLFunctionAvailbility(..) -> setContextVersion(..) @@ -941,6 +952,10 @@ public abstract class GLContextImpl extends GLContext { if(0 != _context) { ok = setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags, true); + if(!ok) { + destroyContextARBImpl(_context); + _context = 0; + } } else { ok = false; } @@ -1157,7 +1172,7 @@ public abstract class GLContextImpl extends GLContext { * context. See {@link #isFunctionAvailable(String)} for more information on * the definition of "available". *
true
and the ctx version (by string) is lower than the given major.minor version,
- * method aborts and returns false
, otherwise true
.
- * @return returns true
if successful, otherwise false
. See strictVersionMatch
.
+ * @param strictMatch if true
the ctx must
+ * major.minor
version version, andfalse
.
+ * @return returns true
if successful, otherwise false
. See strictMatch
.
+ * If false
is returned, no data has been cached or mapped, i.e. ProcAddressTable, Extensions, Version, etc.
* @see #setContextVersion
* @see javax.media.opengl.GLContext#CTX_OPTION_ANY
* @see javax.media.opengl.GLContext#CTX_PROFILE_COMPAT
* @see javax.media.opengl.GLContext#CTX_IMPL_ES2_COMPAT
*/
- protected final boolean setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits, boolean strictVersionMatch) {
+ protected final boolean setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits, boolean strictMatch) {
if(null!=this.gl && null!=glProcAddressTable && !force) {
return true; // already done and not forced
}
@@ -1208,7 +1227,7 @@ public abstract class GLContextImpl extends GLContext {
final VersionNumber setGLVersionNumber = new VersionNumber(major, minor, 0);
final VersionNumber strGLVersionNumber = getGLVersionNumber(ctxProfileBits, glVersion);
if( null != strGLVersionNumber && ( strGLVersionNumber.compareTo(setGLVersionNumber) < 0 || 0 == major ) ) {
- if( 0 < major && strictVersionMatch ) {
+ if( strictMatch && 0 < major ) {
if(DEBUG) {
System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch: "+major+"."+minor+", ctp "+toHexString(ctxProfileBits)+", "+glVersion+", "+strGLVersionNumber);
}
@@ -1227,6 +1246,16 @@ public abstract class GLContextImpl extends GLContext {
if( 2 > major ) { // there is no ES2-compat for a profile w/ major < 2
ctxProfileBits &= ~GLContext.CTX_IMPL_ES2_COMPAT;
}
+
+ setRendererQuirks(major, minor, ctxProfileBits);
+
+ if( strictMatch && glRendererQuirks.exist(GLRendererQuirks.GLNonCompliant) ) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL is not compliant: "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion)+", "+glRenderer);
+ }
+ return false;
+ }
+
contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits);
if (DEBUG) {
System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion) + ", "+glVersionNumber);
@@ -1301,8 +1330,6 @@ public abstract class GLContextImpl extends GLContext {
//
setContextVersion(major, minor, ctxProfileBits, true);
- setRendererQuirks( 0 == ( ctxProfileBits & GLContext.CTX_IMPL_ACCEL_SOFT ) );
-
setDefaultSwapInterval();
if(DEBUG) {
@@ -1311,10 +1338,13 @@ public abstract class GLContextImpl extends GLContext {
return true;
}
- private final void setRendererQuirks(boolean hwAccel) {
+ private final void setRendererQuirks(int major, int minor, int ctp) {
int[] quirks = new int[GLRendererQuirks.COUNT];
int i = 0;
+ final boolean hwAccel = 0 == ( ctp & GLContext.CTX_IMPL_ACCEL_SOFT );
+ final boolean compatCtx = 0 != ( ctp & GLContext.CTX_PROFILE_COMPAT );
+
// OS related quirks
if( Platform.getOSType() == Platform.OSType.MACOS ) {
final int quirk1 = GLRendererQuirks.NoOffscreenBitmap;
@@ -1344,7 +1374,7 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
}
- quirks[i++] = quirk;
+ quirks[i++] = quirk;
}
if( hwAccel /* glRendererLowerCase.contains("intel(r)") || glRendererLowerCase.contains("amd") */ )
{
@@ -1354,7 +1384,16 @@ public abstract class GLContextImpl extends GLContext {
}
quirks[i++] = quirk;
}
+ if( glRendererLowerCase.contains("intel(r)") && compatCtx && ( major>3 || major==3 && minor>=1 ) )
+ {
+ final int quirk = GLRendererQuirks.GLNonCompliant;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
+ }
+ quirks[i++] = quirk;
+ }
}
+
glRendererQuirks = new GLRendererQuirks(quirks, 0, i);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java
new file mode 100644
index 000000000..90f0c5414
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java
@@ -0,0 +1,222 @@
+/**
+ * Copyright 2012 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLProfile;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.AfterClass;
+import org.junit.Test;
+
+/**
+ * Some GL state values are broken w/ Mesa 9.0 w/ multiple different context.
+ * + * This bug lies within Mesa3D (any renderer) and is fixed in + * commit 8dc79ae7d73cf6711c2182ff9a5d37ef6c989d23. + *
+ *+ * Mesa3D Version 9.0 still exposes this bug, + * where 9.0.1 has it fixed w/ above commit. + *
+ *+ * This bug lies within Mesa3D (any renderer) and is fixed in + * commit ??? (not yet). + *
+ *+ * Mesa3D Version 9.0 still exposes this bug, + * where 9.?.? has it fixed w/ above commit. + *
+ *true
the ctx must
* major.minor
version version, andmajor.minor
version, andfalse
.
* @return returns true
if successful, otherwise false
. See strictMatch
.
@@ -1207,42 +1203,84 @@ public abstract class GLContextImpl extends GLContext {
{
final boolean initGLRendererAndGLVersionStringsOK = initGLRendererAndGLVersionStrings();
- if(DEBUG) {
- if( !initGLRendererAndGLVersionStringsOK ) {
- System.err.println("Warning: setGLFunctionAvailability: intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null));
+ if( !initGLRendererAndGLVersionStringsOK ) {
+ final String errMsg = "Intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null);
+ if( strictMatch ) {
+ // query mode .. simply fail
+ if(DEBUG) {
+ System.err.println("Warning: setGLFunctionAvailability: "+errMsg);
+ }
+ return false;
} else {
- System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Given "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion));
+ // unusable GL context - non query mode - hard fail!
+ throw new GLException(errMsg);
}
+ } else if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Given "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion));
}
}
-
- if(!isCurrentContextHardwareRasterizer()) {
- ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT;
- }
- // Pick the version from the GL-version string,
- // if smaller _or_ given major == 0.
- final VersionNumber glVersionNumber;
- {
+ //
+ // Validate GL version either by GL-Integer or GL-String
+ //
+
+ if(major >= 3) {
+ // Validate the requested version w/ the GL-version from an integer query.
+ final int[] glIntMinor = new int[] { 0 }, glIntMajor = new int[] { 0 };
+ final boolean getGLIntVersionOK = getGLIntVersion(glIntMinor, glIntMajor);
+ if( !getGLIntVersionOK ) {
+ final String errMsg = "Fetching GL Integer Version failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null);
+ if( strictMatch ) {
+ // query mode .. simply fail
+ if(DEBUG) {
+ System.err.println("Warning: setGLFunctionAvailability: "+errMsg);
+ }
+ return false;
+ } else {
+ // unusable GL context - non query mode - hard fail!
+ throw new GLException(errMsg);
+ }
+ }
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: version verification (Int) - expected "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+", has "+glVersion+", "+glIntMajor[0]+"."+glIntMinor[0]);
+ }
+
+ if( glIntMajor[0]+ * Note: Non ARB ctx is limited to GL 3.0. + *
+ */ + private static final VersionNumber getGLVersionNumber(int ctp, String glVersionStr) { + if( null != glVersionStr ) { + final GLVersionNumber version = new GLVersionNumber(glVersionStr); + if ( version.isValid() ) { + int[] major = new int[] { version.getMajor() }; + int[] minor = new int[] { version.getMinor() }; + limitNonARBContextVersion(major, minor, ctp); + if ( GLContext.isValidGLVersion(major[0], minor[0]) ) { + return new VersionNumber(major[0], minor[0], 0); + } + } + } + return null; + } + + /** + * Returns false ifglGetIntegerv
is inaccessible, otherwise queries major.minor
+ * version for given arrays.
+ * + * If the GL query fails, major will be zero. + *
+ *+ * Note: Non ARB ctx is limited to GL 3.0. + *
+ */ + private final boolean getGLIntVersion(int[] glIntMajor, int[] glIntMinor, int ctp) { + glIntMajor[0] = 0; // clear final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper(); final long _glGetIntegerv = glDynLookupHelper.dynamicLookupFunction("glGetIntegerv"); if( 0 == _glGetIntegerv ) { @@ -1158,6 +1179,7 @@ public abstract class GLContextImpl extends GLContext { } else { glGetIntegervInt(GL2GL3.GL_MAJOR_VERSION, glIntMajor, 0, _glGetIntegerv); glGetIntegervInt(GL2GL3.GL_MINOR_VERSION, glIntMinor, 0, _glGetIntegerv); + limitNonARBContextVersion(glIntMajor, glIntMinor, ctp); return true; } } @@ -1193,6 +1215,10 @@ public abstract class GLContextImpl extends GLContext { return true; // already done and not forced } + if ( 0 < major && !GLContext.isValidGLVersion(major, minor) ) { + throw new GLException("Invalid GL Version Request "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); + } + if(null==this.gl || !verifyInstance(gl.getGLProfile(), "Impl", this.gl)) { setGL( createGL( getGLDrawable().getGLProfile() ) ); } @@ -1223,11 +1249,15 @@ public abstract class GLContextImpl extends GLContext { // // Validate GL version either by GL-Integer or GL-String // - - if(major >= 3) { + if (DEBUG) { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Pre version verification - expected "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+", strictMatch "+strictMatch); + } + boolean versionValidated = false; + boolean versionGL3IntFailed = false; + { // Validate the requested version w/ the GL-version from an integer query. - final int[] glIntMinor = new int[] { 0 }, glIntMajor = new int[] { 0 }; - final boolean getGLIntVersionOK = getGLIntVersion(glIntMinor, glIntMajor); + final int[] glIntMajor = new int[] { 0 }, glIntMinor = new int[] { 0 }; + final boolean getGLIntVersionOK = getGLIntVersion(glIntMajor, glIntMinor, ctxProfileBits); if( !getGLIntVersionOK ) { final String errMsg = "Fetching GL Integer Version failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null); if( strictMatch ) { @@ -1240,45 +1270,65 @@ public abstract class GLContextImpl extends GLContext { // unusable GL context - non query mode - hard fail! throw new GLException(errMsg); } - } + } if (DEBUG) { - System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: version verification (Int) - expected "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+", has "+glVersion+", "+glIntMajor[0]+"."+glIntMinor[0]); + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: version verification (Int): "+glVersion+", "+glIntMajor[0]+"."+glIntMinor[0]); } - - if( glIntMajor[0]bvp
*/
public static final String SUFFIX_VERTEX_BINARY = "bvp" ;
+ /** Unique resource suffix for {@link GL3#GL_GEOMETRY_SHADER} in source code: gp
*/
+ public static final String SUFFIX_GEOMETRY_SOURCE = "gp" ;
+
+ /** Unique resource suffix for {@link GL3#GL_GEOMETRY_SHADER} in binary: bgp
*/
+ public static final String SUFFIX_GEOMETRY_BINARY = "bgp" ;
+
/** Unique resource suffix for {@link GL2ES2#GL_FRAGMENT_SHADER} in source code: fp
*/
public static final String SUFFIX_FRAGMENT_SOURCE = "fp" ;
@@ -82,7 +89,7 @@ public class ShaderCode {
public static final String SUB_PATH_NVIDIA = "nvidia" ;
/**
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
* @param count number of shaders
* @param source CharSequence array containing the shader sources, organized as source[count][strings-per-shader]
.
* May be either an immutable String
- or mutable StringBuilder
array.
@@ -96,6 +103,7 @@ public class ShaderCode {
switch (type) {
case GL2ES2.GL_VERTEX_SHADER:
case GL2ES2.GL_FRAGMENT_SHADER:
+ case GL3.GL_GEOMETRY_SHADER:
break;
default:
throw new GLException("Unknown shader type: "+type);
@@ -114,7 +122,7 @@ public class ShaderCode {
}
/**
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
* @param count number of shaders
* @param binary binary buffer containing the shader binaries,
*/
@@ -122,6 +130,7 @@ public class ShaderCode {
switch (type) {
case GL2ES2.GL_VERTEX_SHADER:
case GL2ES2.GL_FRAGMENT_SHADER:
+ case GL3.GL_GEOMETRY_SHADER:
break;
default:
throw new GLException("Unknown shader type: "+type);
@@ -139,7 +148,7 @@ public class ShaderCode {
* which location is resolved using the context
class, see {@link #readShaderSource(Class, String)}.
*
* @param gl current GL object to determine whether a shader compiler is available. If null, no validation is performed.
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
* @param count number of shaders
* @param context class used to help resolving the source location
* @param sourceFiles array of source locations, organized as sourceFiles[count]
@@ -183,7 +192,7 @@ public class ShaderCode {
* Creates a complete {@link ShaderCode} object while reading the shader binary of binaryFile
,
* which location is resolved using the context
class, see {@link #readShaderBinary(Class, String)}.
*
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
* @param count number of shaders
* @param context class used to help resolving the source location
* @param binFormat a valid native binary format as they can be queried by {@link ShaderUtil#getShaderBinaryFormats(GL)}.
@@ -215,13 +224,15 @@ public class ShaderCode {
* type
is not supported
*
@@ -233,6 +244,8 @@ public class ShaderCode {
return binary?SUFFIX_VERTEX_BINARY:SUFFIX_VERTEX_SOURCE;
case GL2ES2.GL_FRAGMENT_SHADER:
return binary?SUFFIX_FRAGMENT_BINARY:SUFFIX_FRAGMENT_SOURCE;
+ case GL3.GL_GEOMETRY_SHADER:
+ return binary?SUFFIX_GEOMETRY_BINARY:SUFFIX_GEOMETRY_SOURCE;
default:
throw new GLException("illegal shader type: "+type);
}
@@ -311,7 +324,7 @@ public class ShaderCode {
*
* @param gl current GL object to determine whether a shader compiler is available (if source
is used),
* or to determine the shader binary format (if binary
is used).
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
* @param count number of shaders
* @param context class used to help resolving the source and binary location
* @param srcRoot relative root path for srcBasenames
@@ -411,7 +424,7 @@ public class ShaderCode {
*
* @param gl current GL object to determine whether a shader compiler is available (if source
is used),
* or to determine the shader binary format (if binary
is used).
- * @param type either {@link GL2ES2#GL_VERTEX_SHADER} or {@link GL2ES2#GL_FRAGMENT_SHADER}
+ * @param type either {@link GL2ES2#GL_VERTEX_SHADER}, {@link GL2ES2#GL_FRAGMENT_SHADER} or {@link GL3#GL_GEOMETRY_SHADER}
* @param context class used to help resolving the source and binary location
* @param srcRoot relative root path for basename
* @param binRoot relative root path for basename
@@ -447,6 +460,8 @@ public class ShaderCode {
return "VERTEX_SHADER";
case GL2ES2.GL_FRAGMENT_SHADER:
return "FRAGMENT_SHADER";
+ case GL3.GL_GEOMETRY_SHADER:
+ return "GEOMETRY_SHADER";
}
return "UNKNOWN_SHADER";
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
index 5afc5e38c..eceeea6db 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java
@@ -40,6 +40,7 @@ import java.util.*;
import javax.media.opengl.*;
import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.GLExtensions;
public class ShaderUtil {
public static String getShaderInfoLog(GL _gl, int shaderObj) {
@@ -210,6 +211,13 @@ public class ShaderUtil {
}
return info.shaderCompilerAvailable.booleanValue();
}
+
+ /** Returns true if GeometryShader is supported, i.e. whether GLContext is ≥ 3.2 or ARB_geometry_shader4 extension is available. */
+ public static boolean isGeometryShaderSupported(GL _gl) {
+ final GLContext ctx = _gl.getContext();
+ return ctx.getGLVersionNumber().compareTo(GLContext.Version32) >= 0 ||
+ ctx.isExtensionAvailable(GLExtensions.ARB_geometry_shader4);
+ }
public static void shaderSource(GL _gl, int shader, CharSequence[] source)
{
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 461d481a8..8cc29f1f2 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -116,6 +116,15 @@ public abstract class GLContext {
/** Indicates that a newly-created context was made current during the last call to {@link #makeCurrent makeCurrent}. */
public static final int CONTEXT_CURRENT_NEW = 2;
+ /** Version 3.2. As an OpenGL version, it qualifies for geometry shader */
+ public static final VersionNumber Version32 = new VersionNumber(3, 2, 0);
+
+ /** Version 3.1. As an OpenGL version, it qualifies for {@link #isGL3core()}, {@link #isGL3bc()} and {@link #isGL3()} */
+ public static final VersionNumber Version31 = new VersionNumber(3, 1, 0);
+
+ /** Version 3.0. As an OpenGL version, it qualifies for {@link #isGL2()} only */
+ public static final VersionNumber Version30 = new VersionNumber(3, 0, 0);
+
/** ARB_create_context
related: created via ARB_create_context. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IS_ARB_CREATED = 1 << 0;
/** ARB_create_context
related: desktop compatibility profile. Cache key value. See {@link #isGLCompatibilityProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
@@ -156,8 +165,7 @@ public abstract class GLContext {
resetStates();
}
- protected int ctxMajorVersion;
- protected int ctxMinorVersion;
+ protected VersionNumber ctxVersion;
protected int ctxOptions;
protected String ctxVersionString;
protected VersionNumber ctxGLSLVersion;
@@ -172,8 +180,7 @@ public abstract class GLContext {
System.err.println(getThreadName() + ": GLContext.resetStates()");
// Thread.dumpStack();
}
- ctxMajorVersion=-1;
- ctxMinorVersion=-1;
+ ctxVersion = new VersionNumber(-1, -1, -1);
ctxOptions=0;
ctxVersionString=null;
ctxGLSLVersion=null;
@@ -629,8 +636,15 @@ public abstract class GLContext {
return ctxVersionString;
}
- public final int getGLVersionMajor() { return ctxMajorVersion; }
- public final int getGLVersionMinor() { return ctxMinorVersion; }
+ /** @deprecated Use {@link #getGLVersionNumber()} */
+ public final int getGLVersionMajor() { return ctxVersion.getMajor(); }
+ /** @deprecated Use {@link #getGLVersionNumber()} */
+ public final int getGLVersionMinor() { return ctxVersion.getMinor(); }
+ /**
+ * Returns this context OpenGL version.
+ * @see #getGLSLVersionNumber()
+ **/
+ public final VersionNumber getGLVersionNumber() { return ctxVersion; }
public final boolean isGLCompatibilityProfile() { return ( 0 != ( CTX_PROFILE_COMPAT & ctxOptions ) ); }
public final boolean isGLCoreProfile() { return ( 0 != ( CTX_PROFILE_CORE & ctxOptions ) ); }
public final boolean isGLForwardCompatible() { return ( 0 != ( CTX_OPTION_FORWARD & ctxOptions ) ); }
@@ -659,8 +673,7 @@ public abstract class GLContext {
*
* @param GLSL version number if context has been made current at least once, otherwise null
.
*
- * @see #getGLVersionMajor()
- * @see #getGLVersionMinor()
+ * @see #getGLVersionNumber()
*/
public final VersionNumber getGLSLVersionNumber() {
return ctxGLSLVersion;
@@ -733,7 +746,7 @@ public abstract class GLContext {
public final boolean hasGLSL() {
return isGLES2() ||
isGL3() ||
- isGL2() && ctxMajorVersion>1 ;
+ isGL2() && ctxVersion.getMajor()>1 ;
}
/**
@@ -810,46 +823,46 @@ public abstract class GLContext {
/** @see GLProfile#isGL4bc() */
public final boolean isGL4bc() {
- return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & CTX_PROFILE_COMPAT);
+ return ctxVersion.getMajor() >= 4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
+ && 0 != (ctxOptions & CTX_PROFILE_COMPAT);
}
/** @see GLProfile#isGL4() */
public final boolean isGL4() {
- return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
- && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
+ return ctxVersion.getMajor() >= 4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED)
+ && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE));
}
/** Indicates whether this profile is capable of GL4 (core only). Includes [ GL4 ].
*/ public final boolean isGL4core() { - return ctxMajorVersion>=4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED) - && 0 != (ctxOptions & CTX_PROFILE_CORE); + return ctxVersion.getMajor() >= 4 && 0 != (ctxOptions & CTX_IS_ARB_CREATED) + && 0 != (ctxOptions & CTX_PROFILE_CORE); } /** @see GLProfile#isGL3bc() */ public final boolean isGL3bc() { - return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) + return ctxVersion.compareTo(Version31) >= 0 && 0 != (ctxOptions & CTX_IS_ARB_CREATED) && 0 != (ctxOptions & CTX_PROFILE_COMPAT); } /** @see GLProfile#isGL3() */ public final boolean isGL3() { - return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) + return ctxVersion.compareTo(Version31) >= 0 && 0 != (ctxOptions & CTX_IS_ARB_CREATED) && 0 != (ctxOptions & (CTX_PROFILE_COMPAT|CTX_PROFILE_CORE)); } - /** Indicates whether this profile is capable of GL3 (core only).Includes [ GL4, GL3 ].
*/ + /** Indicates whether this profile is capable of GL3 (core only). GL3 starts w/ OpenGL 3.1Includes [ GL4, GL3 ].
*/ public final boolean isGL3core() { - return ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) + return ctxVersion.compareTo(Version31) >= 0 && 0 != (ctxOptions & CTX_IS_ARB_CREATED) && 0 != (ctxOptions & CTX_PROFILE_CORE); } /** @see GLProfile#isGL2() */ public final boolean isGL2() { - return ctxMajorVersion>=1 && 0!=(ctxOptions & CTX_PROFILE_COMPAT); + return ctxVersion.getMajor()>=1 && 0!=(ctxOptions & CTX_PROFILE_COMPAT); } /** @see GLProfile#isGL2GL3() */ @@ -859,12 +872,12 @@ public abstract class GLContext { /** @see GLProfile#isGLES1() */ public final boolean isGLES1() { - return ctxMajorVersion==1 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ; + return ctxVersion.getMajor() == 1 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ; } /** @see GLProfile#isGLES2() */ public final boolean isGLES2() { - return ctxMajorVersion==2 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ; + return ctxVersion.getMajor() == 2 && 0 != ( ctxOptions & CTX_PROFILE_ES ) ; } /** @see GLProfile#isGLES() */ diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 36aaeb597..d960883d5 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -568,7 +568,7 @@ public abstract class GLContextImpl extends GLContext { final boolean created; try { created = createImpl(shareWith); // may throws exception if fails! - if( created && isGL3core() && ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) ) { + if( created && isGL3core() ) { // Due to GL 3.1 core spec: E.1. DEPRECATED AND REMOVED FEATURES (p 296), // GL 3.2 core spec: E.2. DEPRECATED AND REMOVED FEATURES (p 331) // there is no more default VAO buffer 0 bound, hence generating and binding one @@ -606,10 +606,10 @@ public abstract class GLContextImpl extends GLContext { if( 0 == ( ctxOptions & GLContext.CTX_PROFILE_ES) ) { // not ES profile final int reqMajor; final int reqProfile; - if(ctxMajorVersion<3 || ctxMajorVersion==3 && ctxMinorVersion==0) { + if( ctxVersion.compareTo(Version30) <= 0 ) { reqMajor = 2; } else { - reqMajor = ctxMajorVersion; + reqMajor = ctxVersion.getMajor(); } if( 0 != ( ctxOptions & GLContext.CTX_PROFILE_CORE) ) { reqProfile = GLContext.CTX_PROFILE_CORE; @@ -617,7 +617,7 @@ public abstract class GLContextImpl extends GLContext { reqProfile = GLContext.CTX_PROFILE_COMPAT; } GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, - ctxMajorVersion, ctxMinorVersion, ctxOptions); + ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); GLContext.setAvailableGLVersionsSet(device); if (DEBUG) { @@ -780,7 +780,7 @@ public abstract class GLContextImpl extends GLContext { success |= hasGL4; if(hasGL4) { // Map all lower compatible profiles: GL3 - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); + GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); if(PROFILE_ALIASING) { hasGL3 = true; } @@ -799,13 +799,13 @@ public abstract class GLContextImpl extends GLContext { success |= hasGL4bc; if(hasGL4bc) { // Map all lower compatible profiles: GL3bc, GL2, GL4, GL3 - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions); - GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions); + GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); if(!hasGL4) { - GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); + GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); } if(!hasGL3) { - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); + GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); } if(PROFILE_ALIASING) { hasGL3bc = true; @@ -821,9 +821,9 @@ public abstract class GLContextImpl extends GLContext { success |= hasGL3bc; if(hasGL3bc) { // Map all lower compatible profiles: GL2 and GL3 - GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxMajorVersion, ctxMinorVersion, ctxOptions); + GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); if(!hasGL3) { - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxMajorVersion, ctxMinorVersion, ctxOptions); + GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); } if(PROFILE_ALIASING) { hasGL2 = true; @@ -915,7 +915,7 @@ public abstract class GLContextImpl extends GLContext { AbstractGraphicsDevice device = drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); // ctxMajorVersion, ctxMinorVersion, ctxOptions is being set by // createContextARBVersions(..) -> setGLFunctionAvailbility(..) -> setContextVersion(..) - GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxMajorVersion, ctxMinorVersion, ctxOptions); + GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); destroyContextARBImpl(_context); if (DEBUG) { System.err.println(getThreadName() + ": createContextARB-MapVersionsAvailable HAVE: " +reqMajor+"."+reqProfile+ " -> "+getGLVersion()); @@ -978,13 +978,12 @@ public abstract class GLContextImpl extends GLContext { if (!GLContext.isValidGLVersion(major, minor)) { throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); } - ctxMajorVersion = major; - ctxMinorVersion = minor; + ctxVersion = new VersionNumber(major, minor, 0); ctxOptions = ctp; if(setVersionString) { - ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, gl.glGetString(GL.GL_VERSION)); + ctxVersionString = getGLVersion(major, minor, ctxOptions, gl.glGetString(GL.GL_VERSION)); ctxGLSLVersion = null; - if(ctxMajorVersion >= 2) { // >= ES2 || GL2.0 + if(major >= 2) { // >= ES2 || GL2.0 final String glslVersion = gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION); if( null != glslVersion ) { ctxGLSLVersion = new VersionNumber(glslVersion, "."); @@ -995,7 +994,7 @@ public abstract class GLContextImpl extends GLContext { } if( null == ctxGLSLVersion ){ final int[] sver = new int[2]; - getStaticGLSLVersionNumber(ctxMajorVersion, ctxMinorVersion, ctxOptions, sver); + getStaticGLSLVersionNumber(major, minor, ctxOptions, sver); ctxGLSLVersion = new VersionNumber(sver[0], sver[1], 0); } } @@ -1424,7 +1423,7 @@ public abstract class GLContextImpl extends GLContext { final int glErrX = gl.glGetError(); // clear GL error, maybe caused by above operations if(DEBUG) { - System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: OK "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null)+" - glErr "+toHexString(glErrX)); + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: OK "+contextFQN+" - "+GLContext.getGLVersion(ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions, null)+" - glErr "+toHexString(glErrX)); } return true; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index bd8e7dee9..572888bae 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -281,7 +281,7 @@ public abstract class EGLContext extends GLContextImpl { // /* pp */ void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) { - mapStaticGLVersion(device, ctxMajorVersion, ctxMinorVersion, ctxOptions); + mapStaticGLVersion(device, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); } /* pp */ int getContextOptions() { return ctxOptions; } /* pp */ static void mapStaticGLESVersion(AbstractGraphicsDevice device, GLCapabilitiesImmutable caps) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java new file mode 100644 index 000000000..929491187 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java @@ -0,0 +1,293 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.demos.gl3; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URLConnection; +import java.nio.FloatBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL3; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.common.util.IOUtil; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.util.glsl.ShaderUtil; +import com.jogamp.opengl.util.texture.Texture; +import com.jogamp.opengl.util.texture.TextureCoords; +import com.jogamp.opengl.util.texture.TextureData; +import com.jogamp.opengl.util.texture.TextureIO; + +/** + * JOGL Geometry ShaderCode test case using OpenGL 3.2 core profile features only. + *
+ * Demonstrates pass through
and XYZ flipping
+ * geometry shader.
+ *
+ * If the XYZ flipping
geometry shader functions properly,
+ * the texture will be flipped horizontally and vertically.
+ *
+ * Method exists merely for code validation of {@link #isCurrent()}. + *
+ */ + public final boolean isOwner(Thread thread) { + return lock.isOwner(thread); + } + + /** + * Returns true if there are other threads waiting for this GLContext to {@link #makeCurrent()}, otherwise false. + *+ * Since method does not perform any synchronization, accurate result are returned if lock is hold - only. + *
+ */ + public final boolean hasWaiters() { return lock.getQueueLength()>0; } + /** + * Returns the number of hold locks. See {@link RecursiveLock#getHoldCount()} for semantics. + *+ * Since method does not perform any synchronization, accurate result are returned if lock is hold - only. + *
+ */ + public final int getLockCount() { + return lock.getHoldCount(); + } + //--------------------------------------------------------------------------- // Special FBO hook // diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index 5b0d32353..c2b66801e 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -166,7 +166,7 @@ public abstract class X11GLXContext extends GLContextImpl { throw new InternalError("Given readDrawable but no driver support"); } } catch (RuntimeException re) { - if(DEBUG || TRACE_SWITCH) { + if(DEBUG_TRACE_SWITCH) { System.err.println(getThreadName()+": Warning: X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+ "dpy "+toHexString(dpy)+ ", write "+toHexString(writeDrawable)+ diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext01NEWT.java new file mode 100644 index 000000000..7b8529191 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestBug669RecursiveGLContext01NEWT.java @@ -0,0 +1,135 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.acore; + +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLContextImpl; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +/** + * Tests simple recursive GLContext behavior. + * + *+ * Issues {@link GLContext#makeCurrent()} and {@link GLContext#release()} + * from within {@link GLEventListener#display(GLAutoDrawable)}. + *
+ * + *+ * Issues {@link GLAutoDrawable#display()} of another {@link GLAutoDrawable} + * from within {@link GLEventListener#display(GLAutoDrawable)}. + *
+ * + *drawable yet,
+ * may be null
for lazy initialization
* @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}.
* @param ownDevice pass true
if {@link AbstractGraphicsDevice#close()} shall be issued,
* otherwise pass false
. Closing the device is required in case
@@ -78,9 +81,6 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAuto
if(null == drawable) {
throw new IllegalArgumentException("null drawable");
}
- if(null == context) {
- throw new IllegalArgumentException("null context");
- }
if(!drawable.isRealized()) {
throw new IllegalArgumentException("drawable not realized");
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
index cc81e4820..c03e4bfa4 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
@@ -27,17 +27,14 @@
*/
package com.jogamp.opengl.util;
-import java.util.ArrayList;
-import java.util.List;
-
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLEventListener;
-import javax.media.opengl.GLRunnable;
import jogamp.opengl.Debug;
+import jogamp.opengl.GLEventListenerState;
/**
* Providing utility functions dealing w/ {@link GLDrawable}s, {@link GLAutoDrawable} and their {@link GLEventListener}.
@@ -83,7 +80,7 @@ public class GLDrawableUtil {
dest.addGLEventListener(listener);
if(preserveInitState && initialized) {
dest.setGLEventListenerInitState(listener, true);
- dest.invoke(false, new ReshapeGLEventListener(listener));
+ dest.invoke(false, new GLEventListenerState.ReshapeGLEventListener(listener));
} // else .. !init state is default
}
@@ -121,108 +118,13 @@ public class GLDrawableUtil {
* @param b
*/
public static final void swapGLContextAndAllGLEventListener(GLAutoDrawable a, GLAutoDrawable b) {
- final List aGLCmds = new ArrayList();
- final List bGLCmds = new ArrayList();
- final GLAnimatorControl aAnim = a.getAnimator();
- final GLAnimatorControl bAnim = b.getAnimator();
- final boolean aIsPaused = isAnimatorAnimatingOnOtherThread(aAnim) && aAnim.pause();
- final boolean bIsPaused = isAnimatorAnimatingOnOtherThread(bAnim) && bAnim.pause();
-
- //
- // remove and cache all GLEventListener and their init-state
- //
- final int aSz = a.getGLEventListenerCount();
- final GLEventListener[] aGLE = new GLEventListener[aSz];
- final boolean[] aInit = new boolean[aSz];
- for(int i=0; idrawable
might be an inner GLDrawable instance if using a delegation pattern,
- * or this GLAutoDrawable instance.
+ * Associate the new context, newtCtx
, to this auto-drawable.
*
- * If the old or new context was current on this thread, it is being released before switching the drawable.
+ * The current context will be dis-associated from this auto-drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) setGLDrawable(null, true);} first.
+ *
+ *
+ * The new context will be associated with this auto-drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
+ *
+ *
+ * If the old or new context was current on this thread, it is being released before switching the association.
* The new context will be made current afterwards, if it was current before.
* However the user shall take extra care that no other thread
* attempts to make this context current.
*
*
- * Be aware that the old context is still bound to the drawable,
- * and that one context can only be bound to one drawable at one time!
- *
- *
* In case you do not intend to use the old context anymore, i.e.
- * not assigning it to another drawable, it shall be
- * destroyed before setting the new context, i.e.:
+ * not assigning it to another drawable, it shall be
+ * destroyed, i.e.:
*
- GLContext oldCtx = glad.getContext();
+ GLContext oldCtx = glad.setContext(newCtx);
if(null != oldCtx) {
oldCtx.destroy();
}
- glad.setContext(newCtx);
*
- * This is required, since a context must have a valid drawable at all times
- * and this API shall not restrict the user in any way.
*
*
- * @param newCtx the new context
- * @return the replaced GLContext, maybe null
+ * @param newCtx the new context, maybe null
for dis-association.
+ * @return the previous GLContext, maybe null
*
* @see GLContext#setGLDrawable(GLDrawable, boolean)
* @see GLContext#setGLReadDrawable(GLDrawable)
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 455f2d70d..4817add4d 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -217,15 +217,20 @@ public abstract class GLContext {
/**
* Sets the read/write drawable for framebuffer operations.
*
+ * If the arguments reflect the current state of this context
+ * this method is a no-operation and returns the old and current {@link GLDrawable}.
+ *
+ *
* If the context was current on this thread, it is being released before switching the drawable
* and made current afterwards. However the user shall take extra care that not other thread
* attempts to make this context current. Otherwise a race condition may happen.
*
- * @param readWrite the read/write drawable for framebuffer operations.
- * @param setWriteOnly if true
and if the current read-drawable differs
- * from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}),
- * only change the write-drawable. Otherwise set both drawables.
- * @return the replaced read/write drawable
+ * @param readWrite The read/write drawable for framebuffer operations, maybe null
to remove association.
+ * @param setWriteOnly Only change the write-drawable, if setWriteOnly
is true
and
+ * if the {@link #getGLReadDrawable() read-drawable} differs
+ * from the {@link #getGLDrawable() write-drawable}.
+ * Otherwise set both drawables, read and write.
+ * @return The previous read/write drawable
*
* @throws GLException in case null
is being passed or
* this context is made current on another thread.
@@ -239,6 +244,12 @@ public abstract class GLContext {
/**
* Returns the write-drawable this context uses for framebuffer operations.
+ *
+ * If the read-drawable has not been changed manually via {@link #setGLReadDrawable(GLDrawable)},
+ * it equals to the write-drawable (default).
+ *
+ * @see #setGLDrawable(GLDrawable, boolean)
+ * @see #setGLReadDrawable(GLDrawable)
*/
public abstract GLDrawable getGLDrawable();
@@ -259,7 +270,7 @@ public abstract class GLContext {
*
* @param read the read-drawable for read framebuffer operations.
* If null is passed, the default write drawable will be set.
- * @return the replaced read-drawable
+ * @return the previous read-drawable
*
* @throws GLException in case a read drawable is not supported or
* this context is made current on another thread.
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
index eadd59559..c20197e72 100644
--- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -74,8 +74,12 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking
/**
- * @param drawable upstream {@link GLDrawableImpl} instance, may be null for lazy initialization
- * @param context upstream {@link GLContextImpl} instance, may be null for lazy initialization
+ * @param drawable upstream {@link GLDrawableImpl} instance,
+ * may be null
for lazy initialization
+ * @param context upstream {@link GLContextImpl} instance,
+ * may not have been made current (created) yet,
+ * may not be associated w/ drawable yet,
+ * may be null
for lazy initialization
* @param ownsDevice pass true
if {@link AbstractGraphicsDevice#close()} shall be issued,
* otherwise pass false
. Closing the device is required in case
* the drawable is created w/ it's own new instance, e.g. offscreen drawables,
@@ -85,6 +89,9 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
this.drawable = drawable;
this.context = context;
this.ownsDevice = ownsDevice;
+ if(null != context && null != drawable) {
+ context.setGLDrawable(drawable, false);
+ }
resetFPSCounter();
}
@@ -326,7 +333,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
final GLContext oldCtx = context;
final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
+ if(newCtxCurrent) { // implies null != newCtx
context.makeCurrent();
}
return oldCtx;
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index f2c2cfada..2a2b6a8fd 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -203,8 +203,8 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final GLDrawable setGLDrawable(GLDrawable readWrite, boolean setWriteOnly) {
- if(null==readWrite) {
- throw new GLException("Null read/write drawable not allowed");
+ if( drawable == readWrite && ( setWriteOnly || drawableRead == readWrite ) ) {
+ return drawable; // no change.
}
final boolean lockHeld = lock.isOwner(Thread.currentThread());
if(lockHeld) {
@@ -212,16 +212,20 @@ public abstract class GLContextImpl extends GLContext {
} else if(lock.isLockedByOtherThread()) { // still could glitch ..
throw new GLException("GLContext current by other thread ("+lock.getOwner()+"), operation not allowed.");
}
- if(!setWriteOnly || drawableRead==drawable) { // if !setWriteOnly || !explicitReadDrawable
+ if( !setWriteOnly || drawableRead == drawable ) { // if !setWriteOnly || !explicitReadDrawable
drawableRead = (GLDrawableImpl) readWrite;
}
final GLDrawableImpl old = drawable;
- old.associateContext(this, false);
- drawableRetargeted = null != drawable;
+ if( null != old ) {
+ old.associateContext(this, false);
+ }
+ drawableRetargeted |= null != drawable && readWrite != drawable;
drawable = (GLDrawableImpl) readWrite ;
- drawable.associateContext(this, true);
- if(lockHeld) {
- makeCurrent();
+ if( null != drawable ) {
+ drawable.associateContext(this, true);
+ if( lockHeld ) {
+ makeCurrent();
+ }
}
return old;
}
@@ -334,7 +338,7 @@ public abstract class GLContextImpl extends GLContext {
", surf "+toHexString(drawable.getHandle())+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
if (contextHandle != 0) {
- int lockRes = drawable.lockSurface();
+ final int lockRes = drawable.lockSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
// this would be odd ..
throw new GLException("Surface not ready to lock: "+drawable);
@@ -408,7 +412,7 @@ public abstract class GLContextImpl extends GLContext {
throw new GLException("Destination OpenGL context has not been created");
}
- int lockRes = drawable.lockSurface();
+ final int lockRes = drawable.lockSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
// this would be odd ..
throw new GLException("Surface not ready to lock");
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index f8c58ee34..5d113ff83 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -131,30 +131,36 @@ public class GLDrawableHelper {
}
/**
- * Associate a new context to the drawable and also propagates the context/drawable switch by
- * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
- *
- * If the old or new context was current on this thread, it is being released before switching the drawable.
+ * Switch {@link GLContext} / {@link GLDrawable} association.
+ *
+ * Dis-associate oldCtx
from drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) oldCtx.setGLDrawable(null, true);}.
*
*
- * Be aware that the old context is still bound to the drawable,
- * and that one context can only bound to one drawable at one time!
+ * Re-associate newCtx
with drawable
+ * via {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}.
+ *
+ *
+ * If the old or new context was current on this thread, it is being released before switching the drawable.
*
*
* No locking is being performed on the drawable, caller is required to take care of it.
*
*
* @param drawable the drawable which context is changed
- * @param oldCtx the old context
- * @param newCtx the new context
+ * @param oldCtx the old context, maybe null
.
+ * @param newCtx the new context, maybe null
for dis-association.
* @param newCtxCreationFlags additional creation flags if newCtx is not null and not been created yet, see {@link GLContext#setContextCreationFlags(int)}
* @return true if the new context was current, otherwise false
*
* @see GLAutoDrawable#setContext(GLContext)
*/
public static final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int newCtxCreationFlags) {
- if( null != oldCtx && oldCtx.isCurrent() ) {
- oldCtx.release();
+ if( null != oldCtx ) {
+ if( oldCtx.isCurrent() ) {
+ oldCtx.release();
+ }
+ oldCtx.setGLDrawable(null, true); // dis-associate old pair
}
final boolean newCtxCurrent;
if(null!=newCtx) {
@@ -163,8 +169,8 @@ public class GLDrawableHelper {
newCtx.release();
}
newCtx.setContextCreationFlags(newCtxCreationFlags);
- newCtx.setGLDrawable(drawable, true); // propagate context/drawable switch
- } else {
+ newCtx.setGLDrawable(drawable, true); // re-associate new pair
+ } else {
newCtxCurrent = false;
}
return newCtxCurrent;
@@ -203,6 +209,7 @@ public class GLDrawableHelper {
}
context.getGL().glFinish();
context.release();
+ context.setGLDrawable(null, true); // dis-associate
}
if(null != proxySurface) {
diff --git a/src/jogl/classes/jogamp/opengl/GLEventListenerState.java b/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
new file mode 100644
index 000000000..dea2bc85b
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
@@ -0,0 +1,267 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.opengl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.media.nativewindow.AbstractGraphicsConfiguration;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.VisualIDHolder;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLRunnable;
+
+import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+
+/**
+ * GLEventListenerState is holding {@link GLAutoDrawable} components crucial
+ * to relocating all its {@link GLEventListener} w/ their operating {@link GLContext}, etc.
+ * The components are:
+ *
+ * - {@link AbstractGraphicsScreen}
+ * - {@link GLCapabilitiesImmutable}
+ * - {@link GLContext} operating all {@link GLEventListener}
+ * - All {@link GLEventListener}
+ * - All {@link GLEventListener}'s init state
+ * - {@link GLAnimatorControl}
+ *
+ *
+ * A GLEventListenerState instance can be created while components are {@link #moveFrom(GLAutoDrawable) moved from} a {@link GLAutoDrawable}
+ * to the new instance, which gains {@link #isOwner() ownership} of the moved components.
+ *
+ *
+ * A GLEventListenerState instance's components can be {@link #moveTo(GLAutoDrawable) moved to} a {@link GLAutoDrawable},
+ * while loosing {@link #isOwner() ownership} of the moved components.
+ *
+ *
+ */
+public class GLEventListenerState {
+ private GLEventListenerState(AbstractGraphicsScreen screen, GLCapabilitiesImmutable caps, GLContext context, int count, GLAnimatorControl anim) {
+ this.screen = screen;
+ this.caps = caps;
+ this.context = context;
+ this.listeners = new GLEventListener[count];
+ this.listenersInit = new boolean[count];
+ this.anim = anim;
+ this.owner = true;
+ }
+ /**
+ * Returns true
, if this instance is the current owner of the components,
+ * otherwise false
.
+ *
+ * Ownership is lost if {@link #moveTo(GLAutoDrawable)} is being called successfully
+ * and all components are transferred to the new {@link GLAutoDrawable}.
+ *
+ */
+ public final boolean isOwner() { return owner; }
+
+ public final int listenerCount() { return listeners.length; }
+
+ public final AbstractGraphicsScreen screen;
+ public final GLCapabilitiesImmutable caps;
+ public final GLContext context;
+ public final GLEventListener[] listeners;
+ public final boolean[] listenersInit;
+ public final GLAnimatorControl anim;
+
+ private boolean owner;
+
+ /**
+ * Last resort to destroy and loose ownership
+ */
+ public void destroy() {
+ if( owner ) {
+ final int aSz = listenerCount();
+ for(int i=0; i
+ * Note that all components are removed from the {@link GLAutoDrawable},
+ * i.e. the {@link GLContext}, all {@link GLEventListener}.
+ *
+ *
+ * If the {@link GLAutoDrawable} was added to a {@link GLAnimatorControl}, it is removed
+ * and the {@link GLAnimatorControl} added to the GLEventListenerState.
+ *
+ *
+ * The returned GLEventListenerState instance is the {@link #isOwner() owner of the components}.
+ *
+ *
+ * @param a {@link GLAutoDrawable} source to move components from
+ * @return new GLEventListenerState instance {@link #isOwner() owning} moved components.
+ *
+ * @see #moveTo(GLAutoDrawable)
+ */
+ public static GLEventListenerState moveFrom(GLAutoDrawable a) {
+ final int aSz = a.getGLEventListenerCount();
+
+ // Create new AbstractGraphicsScreen w/ cloned AbstractGraphicsDevice for future GLAutoDrawable
+ // allowing this AbstractGraphicsDevice to loose ownership -> not closing display/device!
+ final AbstractGraphicsConfiguration aCfg1 = a.getNativeSurface().getGraphicsConfiguration();
+ final GLCapabilitiesImmutable caps1 = (GLCapabilitiesImmutable) aCfg1.getChosenCapabilities();
+ final AbstractGraphicsScreen aScreen1 = aCfg1.getScreen();
+ final AbstractGraphicsDevice aDevice1 = aScreen1.getDevice();
+ final AbstractGraphicsDevice aDevice2 = (AbstractGraphicsDevice) aDevice1.clone();
+ final AbstractGraphicsScreen aScreen2 = NativeWindowFactory.createScreen( NativeWindowFactory.getNativeWindowType(false), aDevice2, aScreen1.getIndex() );
+
+ final GLAnimatorControl aAnim = a.getAnimator();
+ if( null != aAnim ) {
+ aAnim.remove(a); // also handles ECT
+ }
+
+ final GLEventListenerState glls = new GLEventListenerState(aScreen2, caps1, a.getContext(), aSz, aAnim);
+
+ //
+ // remove and cache all GLEventListener and their init-state
+ //
+ for(int i=0; i
+ * If the previous {@link GLAutoDrawable} was removed from a {@link GLAnimatorControl} by previous {@link #moveFrom(GLAutoDrawable)},
+ * the given {@link GLAutoDrawable} is added to the cached {@link GLAnimatorControl}.
+ * This operation is skipped, if the given {@link GLAutoDrawable} is already added to a {@link GLAnimatorControl} instance.
+ *
+ *
+ * Note: After this operation, the GLEventListenerState reference should be released.
+ *
+ *
+ * @param a {@link GLAutoDrawable} destination to move GLEventListenerState components to
+ *
+ * @throws GLException if the {@link GLAutoDrawable}'s configuration is incompatible, i.e. different {@link GLCapabilitiesImmutable}.
+ *
+ * @see #moveFrom(GLAutoDrawable)
+ * @see #isOwner()
+ */
+ public final void moveTo(GLAutoDrawable a) {
+ final List aGLCmds = new ArrayList();
+ final int aSz = listenerCount();
+
+ final MutableGraphicsConfiguration aCfg = (MutableGraphicsConfiguration) a.getNativeSurface().getGraphicsConfiguration();
+ final GLCapabilitiesImmutable aCaps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities();
+ if( caps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) != aCaps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) ) {
+ throw new GLException("XXX: Incompatible - Prev Holder: "+caps+", New Holder "+caps);
+ }
+ final GLContext prevContext = a.getContext();
+ if( null != prevContext) {
+ prevContext.destroy();
+ }
+ final AbstractGraphicsScreen preScreen = aCfg.getScreen();
+ aCfg.setScreen( screen );
+ preScreen.getDevice().close();
+ a.setContext( context );
+ owner = false;
+
+ //
+ // Trigger GL-Viewport reset and reshape of all initialized GLEventListeners
+ //
+ aGLCmds.add(setViewport);
+ for(int i=0; i= 0 is specific screen
* @return
- * @throws UnsupportedOperationException
*/
- public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) throws UnsupportedOperationException {
- if( isX11 ) {
- X11GraphicsDevice x11Device = (X11GraphicsDevice)device;
- if(0 > screen) {
- screen = x11Device.getDefaultScreen();
- }
- return new X11GraphicsScreen(x11Device, screen);
- }
- if(0 > screen) {
- screen = 0; // FIXME: Needs native API utilization
- }
- if( isWindows || isOSX ) {
- return new DefaultGraphicsScreen(device, screen);
- }
- throw new UnsupportedOperationException("n/a for this windowing system: "+nwt);
+ public static AbstractGraphicsScreen getScreen(AbstractGraphicsDevice device, int screen) {
+ return NativeWindowFactory.createScreen(nwt, device, screen);
}
public static int getNativeVisualID(AbstractGraphicsDevice device, long windowHandle) {
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
index 0f28ca67c..da3b31de4 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java
@@ -45,7 +45,7 @@ import javax.media.nativewindow.ToolkitLock;
*/
public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
- final boolean handleOwner;
+ /* final */ boolean handleOwner;
final boolean isXineramaEnabled;
/** Constructs a new X11GraphicsDevice corresponding to the given connection and default
@@ -153,5 +153,13 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl
}
return super.close();
}
+
+ @Override
+ public boolean isHandleOwner() {
+ return handleOwner;
+ }
+ @Override
+ public void clearHandleOwner() {
+ handleOwner = false;
+ }
}
-
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
index ebdaf2fbb..4e45113d4 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsConfiguration.java
@@ -42,8 +42,9 @@ package javax.media.nativewindow;
/** A marker interface describing a graphics configuration, visual, or
pixel format in a toolkit-independent manner. */
-
public interface AbstractGraphicsConfiguration extends VisualIDHolder, Cloneable {
+ public Object clone();
+
/**
* Return the screen this graphics configuration is valid for
*/
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
index 8ecd5242d..585cd1f09 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java
@@ -45,7 +45,6 @@ import jogamp.nativewindow.Debug;
/** A interface describing a graphics device in a
toolkit-independent manner.
*/
-
public interface AbstractGraphicsDevice extends Cloneable {
public static final boolean DEBUG = Debug.debug("GraphicsDevice");
@@ -58,6 +57,8 @@ public interface AbstractGraphicsDevice extends Cloneable {
/** Default unit id for the 1st device: 0 */
public static int DEFAULT_UNIT = 0;
+ public Object clone();
+
/**
* Returns the type of the underlying subsystem, ie
* NativeWindowFactory.TYPE_KD, NativeWindowFactory.TYPE_X11, ..
@@ -143,10 +144,17 @@ public interface AbstractGraphicsDevice extends Cloneable {
*
* Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice}
* or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice}
- * issue the native close operation or skip it depending on the handles's ownership.
+ * issue the native close operation or skip it depending on the {@link #isHandleOwner() handles's ownership}.
*
*
* @return true if the handle was not null
and closing was successful, otherwise false.
*/
public boolean close();
+
+ /**
+ * @return true
if instance owns the handle to issue {@link #close()}, otherwise false
.
+ */
+ public boolean isHandleOwner();
+
+ public void clearHandleOwner();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
index eb2cc9120..acb98073b 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsScreen.java
@@ -44,6 +44,8 @@ package javax.media.nativewindow;
*/
public interface AbstractGraphicsScreen extends Cloneable {
+ public Object clone();
+
/**
* Return the device this graphics configuration is valid for
*/
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
index a33c3792a..6b23172e1 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsConfiguration.java
@@ -93,25 +93,26 @@ public class DefaultGraphicsConfiguration implements Cloneable, AbstractGraphics
/**
* Set the capabilities to a new value.
*
+ *
* The use case for setting the Capabilities at a later time is
- * a change of the graphics device in a multi-screen environment.
- *
+ * a change or re-validation of capabilities.
+ *
* @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen)
*/
protected void setChosenCapabilities(CapabilitiesImmutable capsChosen) {
- capabilitiesChosen = capsChosen;
+ this.capabilitiesChosen = capsChosen;
}
/**
* Set a new screen.
*
+ *
* the use case for setting a new screen at a later time is
- * a change of the graphics device in a multi-screen environment.
- *
- * A copy of the passed object is being used.
+ * a change of the graphics device in a multi-screen environment.
+ *
*/
- final protected void setScreen(DefaultGraphicsScreen screen) {
- this.screen = (AbstractGraphicsScreen) screen.clone();
+ protected void setScreen(AbstractGraphicsScreen screen) {
+ this.screen = screen;
}
@Override
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
index 9288652d9..b3ae4628c 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java
@@ -37,10 +37,10 @@ import jogamp.nativewindow.NativeWindowFactoryImpl;
public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice {
private static final String separator = "_";
- private String type;
- protected String connection;
- protected int unitID;
- protected String uniqueID;
+ private final String type;
+ protected final String connection;
+ protected final int unitID;
+ protected final String uniqueID;
protected long handle;
protected ToolkitLock toolkitLock;
@@ -170,9 +170,18 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice
return false;
}
+ @Override
+ public boolean isHandleOwner() {
+ return false;
+ }
+
+ @Override
+ public void clearHandleOwner() {
+ }
+
@Override
public String toString() {
- return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", "+toolkitLock+"]";
+ return getClass().getSimpleName()+"[type "+getType()+", connection "+getConnection()+", unitID "+getUnitID()+", handle 0x"+Long.toHexString(getHandle())+", owner "+isHandleOwner()+", "+toolkitLock+"]";
}
/**
diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
index f50bd0e14..9fa58c7a3 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsScreen.java
@@ -33,8 +33,8 @@
package javax.media.nativewindow;
public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen {
- AbstractGraphicsDevice device;
- private int idx;
+ private final AbstractGraphicsDevice device;
+ private final int idx;
public DefaultGraphicsScreen(AbstractGraphicsDevice device, int idx) {
this.device = device;
@@ -57,7 +57,7 @@ public class DefaultGraphicsScreen implements Cloneable, AbstractGraphicsScreen
public AbstractGraphicsDevice getDevice() {
return device;
}
-
+
public int getIndex() {
return idx;
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index d7f28a986..07702c762 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -48,6 +48,10 @@ import jogamp.nativewindow.ResourceToolkitLock;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
+import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
+import com.jogamp.nativewindow.x11.X11GraphicsDevice;
+import com.jogamp.nativewindow.x11.X11GraphicsScreen;
/** Provides a pluggable mechanism for arbitrary window toolkits to
adapt their components to the {@link NativeWindow} interface,
@@ -428,6 +432,29 @@ public abstract class NativeWindowFactory {
return NativeWindowFactoryImpl.getNullToolkitLock();
}
+ /**
+ * @param device
+ * @param screen -1 is default screen of the given device, e.g. maybe 0 or determined by native API. >= 0 is specific screen
+ * @return newly created AbstractGraphicsScreen of given native type
+ */
+ public static AbstractGraphicsScreen createScreen(String type, AbstractGraphicsDevice device, int screen) {
+ if( TYPE_X11 == type ) {
+ final X11GraphicsDevice x11Device = (X11GraphicsDevice)device;
+ if(0 > screen) {
+ screen = x11Device.getDefaultScreen();
+ }
+ return new X11GraphicsScreen(x11Device, screen);
+ }
+ if(0 > screen) {
+ screen = 0; // FIXME: Needs native API utilization
+ }
+ if( TYPE_AWT == type ) {
+ final AWTGraphicsDevice awtDevice = (AWTGraphicsDevice) device;
+ return new AWTGraphicsScreen(awtDevice);
+ }
+ return new DefaultGraphicsScreen(device, screen);
+ }
+
/** Returns the appropriate NativeWindowFactory to handle window
objects of the given type. The windowClass might be {@link
NativeWindow NativeWindow}, in which case the client has
diff --git a/src/nativewindow/native/x11/Xmisc.c b/src/nativewindow/native/x11/Xmisc.c
index a8d45f288..017c52df2 100644
--- a/src/nativewindow/native/x11/Xmisc.c
+++ b/src/nativewindow/native/x11/Xmisc.c
@@ -180,7 +180,7 @@ static int errorHandlerThrowException = 0;
static int x11ErrorHandler(Display *dpy, XErrorEvent *e)
{
- if(!errorHandlerQuiet) {
+ if( !errorHandlerQuiet || errorHandlerDebug ) {
const char * errnoStr = strerror(errno);
char errCodeStr[80];
char reqCodeStr[80];
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index 96d0f6e3b..7fccb6622 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -458,24 +458,22 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
} else {
t0 = 0;
}
-
- /* if (nativeWindowCreated && null != context) {
- throw new GLException("InternalError: Native Windows has been just created, but context wasn't destroyed (is not null)");
- } */
- if (null == context && visible && 0 != window.getWindowHandle() && 0 ctx1/draw2, ctx2/draw1.
+ */
+public class TestGLContextDrawableSwitch01NEWT extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ glp = GLProfile.getGL2ES2();
+ caps = new GLCapabilities(glp);
+ width = 256;
+ height = 256;
+ }
+
+ private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
+ final Window window = NewtFactory.createWindow(caps);
+ Assert.assertNotNull(window);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLDrawable drawable = factory.createGLDrawable(window);
+ Assert.assertNotNull(drawable);
+
+ drawable.setRealized(true);
+ Assert.assertTrue(drawable.isRealized());
+
+ final GLContext context = drawable.createContext(null);
+ Assert.assertNotNull(context);
+
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) {
+ @Override
+ protected void destroyImplInLock() {
+ super.destroyImplInLock();
+ window.destroy(); // destroys the actual window
+ }
+ };
+
+ // add basic window interaction
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowRepaint(WindowUpdateEvent e) {
+ glad.windowRepaintOp();
+ }
+ @Override
+ public void windowResized(WindowEvent e) {
+ glad.windowResizedOp(window.getWidth(), window.getHeight());
+ }
+ @Override
+ public void windowDestroyNotify(WindowEvent e) {
+ glad.windowDestroyNotifyOp();
+ }
+ });
+ window.addWindowListener(wl);
+
+ return glad;
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2WindowSingleContext() throws InterruptedException {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
+ GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
+
+ // create single context using glad1 and assign it to glad1,
+ // destroy the prev. context afterwards.
+ {
+ final GLContext newCtx = glad1.createContext(null);
+ Assert.assertNotNull(newCtx);
+ final GLContext oldCtx = glad1.setContext(newCtx);
+ Assert.assertNotNull(oldCtx);
+ oldCtx.destroy();
+ final int res = newCtx.makeCurrent();
+ Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
+ newCtx.release();
+ }
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ GearsES2 gears = new GearsES2(1);
+ glad1.addGLEventListener(gears);
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Animator animator = new Animator();
+ animator.add(glad1);
+ animator.add(glad2);
+ animator.start();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+
+ // switch context _and_ the demo synchronously
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glad1, glad2);
+
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ glad1.destroy();
+ glad2.destroy();
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowOneDemo() throws InterruptedException {
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GearsES2 gears = new GearsES2(1);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ GLWindow glWindow1 = GLWindow.create(caps);
+ glWindow1.setTitle("win1");
+ glWindow1.setSize(width, height);
+ glWindow1.setPosition(64, 64);
+ glWindow1.addGLEventListener(0, gears);
+ glWindow1.addGLEventListener(snapshotGLEventListener);
+ glWindow1.addWindowListener(quitAdapter);
+
+ GLWindow glWindow2 = GLWindow.create(caps);
+ glWindow2.setTitle("win2");
+ glWindow2.setSize(width+100, height+100);
+ glWindow2.setPosition(2*64+width, 64);
+ glWindow2.addWindowListener(quitAdapter);
+
+ Animator animator = new Animator();
+ animator.add(glWindow1);
+ animator.add(glWindow2);
+ animator.start();
+
+ glWindow1.setVisible(true);
+ glWindow2.setVisible(true);
+
+ snapshotGLEventListener.setMakeSnapshot();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+ System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+
+ // switch context _and_ the demo synchronously
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
+
+ System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+
+ snapshotGLEventListener.setMakeSnapshot();
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ glWindow1.destroy();
+ glWindow2.destroy();
+
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowEachWithOwnDemo() throws InterruptedException {
+ final GearsES2 gears = new GearsES2(1);
+ final RedSquareES2 rsquare = new RedSquareES2(1);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ final SnapshotGLEventListener snapshotGLEventListener1 = new SnapshotGLEventListener();
+ final SnapshotGLEventListener snapshotGLEventListener2 = new SnapshotGLEventListener();
+
+ GLWindow glWindow1 = GLWindow.create(caps);
+ glWindow1.setTitle("win1");
+ glWindow1.setSize(width, height);
+ glWindow1.setPosition(64, 64);
+ glWindow1.addGLEventListener(0, gears);
+ glWindow1.addGLEventListener(snapshotGLEventListener1);
+ glWindow1.addWindowListener(quitAdapter);
+
+ GLWindow glWindow2 = GLWindow.create(caps);
+ glWindow2.setTitle("win2");
+ glWindow2.setSize(width+100, height+100);
+ glWindow2.setPosition(2*64+width, 64);
+ glWindow2.addGLEventListener(0, rsquare);
+ glWindow2.addGLEventListener(snapshotGLEventListener2);
+ glWindow2.addWindowListener(quitAdapter);
+
+ Animator animator = new Animator();
+ animator.add(glWindow1);
+ animator.add(glWindow2);
+ animator.start();
+
+ glWindow1.setVisible(true);
+ glWindow2.setVisible(true);
+
+ snapshotGLEventListener1.setMakeSnapshot();
+ snapshotGLEventListener2.setMakeSnapshot();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+ System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
+ System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+ snapshotGLEventListener1.setMakeSnapshot();
+ snapshotGLEventListener2.setMakeSnapshot();
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ // System.err.println("pre -del-w1: w1: "+glWindow1);
+ // System.err.println("pre -del-w1: w2: "+glWindow2);
+ glWindow1.destroy();
+ // System.err.println("post-del-w1: w1: "+glWindow1);
+ // System.err.println("post-del-w1: w2: "+glWindow2);
+ glWindow2.destroy();
+
+ }
+
+ // default timing for 2 switches
+ static long duration = 2200; // ms
+ static long period = 1000; // ms
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ *
+ */
+public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
+ static GLProfile glp;
+ static GLCapabilities caps;
+ static int width, height;
+
+ @BeforeClass
+ public static void initClass() {
+ glp = GLProfile.getGL2ES2();
+ caps = new GLCapabilities(glp);
+ width = 256;
+ height = 256;
+ }
+
+ private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
+ final Window window = NewtFactory.createWindow(caps);
+ Assert.assertNotNull(window);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLDrawable drawable = factory.createGLDrawable(window);
+ Assert.assertNotNull(drawable);
+
+ drawable.setRealized(true);
+ Assert.assertTrue(drawable.isRealized());
+
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false, null) {
+ @Override
+ protected void destroyImplInLock() {
+ super.destroyImplInLock();
+ window.destroy(); // destroys the actual window
+ }
+ };
+
+ // add basic window interaction
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowRepaint(WindowUpdateEvent e) {
+ glad.windowRepaintOp();
+ }
+ @Override
+ public void windowResized(WindowEvent e) {
+ glad.windowResizedOp(window.getWidth(), window.getHeight());
+ }
+ @Override
+ public void windowDestroyNotify(WindowEvent e) {
+ glad.windowDestroyNotifyOp();
+ }
+ });
+ window.addWindowListener(wl);
+
+ return glad;
+ }
+
+ @Test(timeout=30000)
+ public void test01() throws InterruptedException {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ final GLEventListenerCounter glelCounter = new GLEventListenerCounter();
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final long t0 = System.currentTimeMillis();
+ final GLEventListenerState glls1;
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ final GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
+ final GLContext context1 = glad1.createContext(null);
+ glad1.setContext(context1);
+ animator.add(glad1);
+
+ glad1.addGLEventListener(glelCounter);
+ glad1.addGLEventListener(new GearsES2(1));
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/2 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ // - dis-associate context from glad1
+ // - destroy glad1
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(context1, glad1.getContext());
+ Assert.assertEquals(3, glad1.getGLEventListenerCount());
+ Assert.assertEquals(context1.getGLReadDrawable(), glad1.getDelegatedDrawable());
+ Assert.assertEquals(context1.getGLDrawable(), glad1.getDelegatedDrawable());
+
+ glls1 = GLEventListenerState.moveFrom(glad1);
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(context1, glls1.context);
+ Assert.assertNull(context1.getGLReadDrawable());
+ Assert.assertNull(context1.getGLDrawable());
+ Assert.assertEquals(3, glls1.listenerCount());
+ Assert.assertEquals(true, glls1.isOwner());
+ Assert.assertEquals(null, glad1.getContext());
+ Assert.assertEquals(0, glad1.getGLEventListenerCount());
+
+ glad1.destroy();
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ final GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Assert.assertEquals(null, glad2.getContext());
+ Assert.assertEquals(0, glad2.getGLEventListenerCount());
+
+ glls1.moveTo(glad2);
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(glls1.context, glad2.getContext());
+ Assert.assertEquals(3, glad2.getGLEventListenerCount());
+ Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(false, glls1.isOwner());
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/1 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ glad2.destroy();
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(1, glelCounter.disposeCount);
+ }
+ animator.stop();
+ }
+
+ @Test(timeout=30000)
+ public void test02() throws InterruptedException {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GLEventListenerCounter glelTracker = new GLEventListenerCounter();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final long t0 = System.currentTimeMillis();
+ final GLEventListenerState glls1;
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ final GLWindow glad1 = GLWindow.create(caps);
+ glad1.setSize(width, height);
+ glad1.setPosition(64, 64);
+ glad1.addWindowListener(quitAdapter);
+ glad1.setVisible(true);
+ animator.add(glad1);
+
+ glad1.addGLEventListener(glelTracker);
+ glad1.addGLEventListener(new GearsES2(1));
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/2 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ // - dis-associate context from glad1
+ // - destroy glad1
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ Assert.assertEquals(3, glad1.getGLEventListenerCount());
+ Assert.assertEquals(glad1.getContext().getGLReadDrawable(), glad1.getDelegatedDrawable());
+ Assert.assertEquals(glad1.getContext().getGLDrawable(), glad1.getDelegatedDrawable());
+
+ final GLContext context1 = glad1.getContext();
+ glls1 = GLEventListenerState.moveFrom(glad1);
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ Assert.assertEquals(context1, glls1.context);
+ Assert.assertNull(context1.getGLReadDrawable());
+ Assert.assertNull(context1.getGLDrawable());
+ Assert.assertEquals(3, glls1.listenerCount());
+ Assert.assertEquals(true, glls1.isOwner());
+ Assert.assertEquals(null, glad1.getContext());
+ Assert.assertEquals(0, glad1.getGLEventListenerCount());
+
+ glad1.destroy();
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ final GLWindow glad2 = GLWindow.create(caps);
+ glad2.setSize(width+100, height+100);
+ glad2.setPosition(2*64+width, 64);
+ glad2.addWindowListener(quitAdapter);
+ glad2.setVisible(true);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Assert.assertNotNull(glad2.getContext());
+ Assert.assertEquals(0, glad2.getGLEventListenerCount());
+
+ glls1.moveTo(glad2);
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ Assert.assertEquals(glls1.context, glad2.getContext());
+ Assert.assertEquals(3, glad2.getGLEventListenerCount());
+ Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(false, glls1.isOwner());
+
+ long t1 = System.currentTimeMillis();
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/1 ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ glad2.destroy();
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(1, glelTracker.disposeCount);
+ }
+ animator.stop();
+ }
+
+ // default timing for 2 switches
+ static long duration = 2200; // ms
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
-
- // switch context _and_ the demo synchronously
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glad1, glad2);
-
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- glad1.destroy();
- glad2.destroy();
- }
-
- @Test(timeout=30000)
- public void testSwitch2GLWindowOneDemo() throws InterruptedException {
- GearsES2 gears = new GearsES2(1);
- final QuitAdapter quitAdapter = new QuitAdapter();
-
- GLWindow glWindow1 = GLWindow.create(caps);
- glWindow1.setTitle("win1");
- glWindow1.setSize(width, height);
- glWindow1.setPosition(64, 64);
- glWindow1.addGLEventListener(0, gears);
- glWindow1.addWindowListener(quitAdapter);
-
- GLWindow glWindow2 = GLWindow.create(caps);
- glWindow2.setTitle("win2");
- glWindow2.setSize(width+100, height+100);
- glWindow2.setPosition(2*64+width, 64);
- glWindow2.addWindowListener(quitAdapter);
-
- Animator animator = new Animator();
- animator.add(glWindow1);
- animator.add(glWindow2);
- animator.start();
-
- glWindow1.setVisible(true);
- glWindow2.setVisible(true);
-
- int s = 0;
- long t0 = System.currentTimeMillis();
- long t1 = t0;
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
- if( ( t1 - t0 ) / period > s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
- System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
-
- // switch context _and_ the demo synchronously
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
-
- System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- glWindow1.destroy();
- glWindow2.destroy();
-
- }
-
- @Test(timeout=30000)
- public void testSwitch2GLWindowEachWithOwnDemo() throws InterruptedException {
- GearsES2 gears = new GearsES2(1);
- RedSquareES2 rsquare = new RedSquareES2(1);
- final QuitAdapter quitAdapter = new QuitAdapter();
-
- GLWindow glWindow1 = GLWindow.create(caps);
- glWindow1.setTitle("win1");
- glWindow1.setSize(width, height);
- glWindow1.setPosition(64, 64);
- glWindow1.addGLEventListener(0, gears);
- glWindow1.addWindowListener(quitAdapter);
-
- GLWindow glWindow2 = GLWindow.create(caps);
- glWindow2.setTitle("win2");
- glWindow2.setSize(width+100, height+100);
- glWindow2.setPosition(2*64+width, 64);
- glWindow2.addGLEventListener(0, rsquare);
- glWindow2.addWindowListener(quitAdapter);
-
- Animator animator = new Animator();
- animator.add(glWindow1);
- animator.add(glWindow2);
- animator.start();
-
- glWindow1.setVisible(true);
- glWindow2.setVisible(true);
-
- int s = 0;
- long t0 = System.currentTimeMillis();
- long t1 = t0;
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
- if( ( t1 - t0 ) / period > s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
- System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
- System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- // System.err.println("pre -del-w1: w1: "+glWindow1);
- // System.err.println("pre -del-w1: w2: "+glWindow2);
- glWindow1.destroy();
- // System.err.println("post-del-w1: w1: "+glWindow1);
- // System.err.println("post-del-w1: w2: "+glWindow2);
- glWindow2.destroy();
-
- }
-
- // default timing for 2 switches
- static long duration = 2200; // ms
- static long period = 1000; // ms
-
- public static void main(String args[]) throws IOException {
- for(int i=0; i
Date: Sun, 27 Jan 2013 14:08:07 +0100
Subject: Bug 665 (part 3) - Allow dis-association of GLContext's GLDrawable ..
- Add EGL/ES2 tests, attempt to fix wrapped EGL case
- Bug 665 (part 2) was commit 7fd5f76e1eb4bbf93fe9b1171744bd755d8f96e4
- Add EGL/ES2 tests in
- TestGLContextDrawableSwitch01NEWT
- TestGLContextDrawableSwitch11NEWT
- Attempt to fix wrapped EGL case (incomplete)
- Using EGL/ES w/ non native EGL device/surface, but natively wrapped instances (most of the cases),
a 'complicated' delegation of
Native-Upstream -> EGL-Proxy -> EGL-Instance
is being used heavily relying on the objects lifecycle.
GLEventListenerState tries to roll back the realized state
and even sets the upstream device handle,
but this doesn't seem to be sufficient on X11.
Discussion:
It might turn out that we only can implement the survival of GLContext
and it's display device reliable w/ EGL within the GLAutoDrawable implementation,
which can hold the previous not destructed instances.
---
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 9 +-
.../jogamp/opengl/GLEventListenerState.java | 134 +++++++++++++++++----
.../com/jogamp/nativewindow/swt/SWTAccessor.java | 2 +-
.../javax/media/nativewindow/NativeSurface.java | 2 +-
.../media/nativewindow/NativeWindowFactory.java | 5 +-
.../acore/TestGLContextDrawableSwitch01NEWT.java | 57 +++++++--
.../acore/TestGLContextDrawableSwitch11NEWT.java | 63 +++++++---
7 files changed, 219 insertions(+), 53 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 2a2b6a8fd..b17fce569 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -206,11 +206,12 @@ public abstract class GLContextImpl extends GLContext {
if( drawable == readWrite && ( setWriteOnly || drawableRead == readWrite ) ) {
return drawable; // no change.
}
- final boolean lockHeld = lock.isOwner(Thread.currentThread());
+ final Thread currentThread = Thread.currentThread();
+ final boolean lockHeld = lock.isOwner(currentThread);
if(lockHeld) {
release();
} else if(lock.isLockedByOtherThread()) { // still could glitch ..
- throw new GLException("GLContext current by other thread ("+lock.getOwner()+"), operation not allowed.");
+ throw new GLException("GLContext current by other thread "+lock.getOwner().getName()+", operation not allowed on this thread "+currentThread.getName());
}
if( !setWriteOnly || drawableRead == drawable ) { // if !setWriteOnly || !explicitReadDrawable
drawableRead = (GLDrawableImpl) readWrite;
@@ -339,7 +340,7 @@ public abstract class GLContextImpl extends GLContext {
}
if (contextHandle != 0) {
final int lockRes = drawable.lockSurface();
- if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
+ if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
// this would be odd ..
throw new GLException("Surface not ready to lock: "+drawable);
}
@@ -413,7 +414,7 @@ public abstract class GLContextImpl extends GLContext {
}
final int lockRes = drawable.lockSurface();
- if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
+ if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
// this would be odd ..
throw new GLException("Surface not ready to lock");
}
diff --git a/src/jogl/classes/jogamp/opengl/GLEventListenerState.java b/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
index dea2bc85b..7a2569850 100644
--- a/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
+++ b/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
@@ -33,7 +33,9 @@ import java.util.List;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
+import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.VisualIDHolder;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
@@ -43,6 +45,7 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLRunnable;
+import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
/**
@@ -68,7 +71,11 @@ import com.jogamp.nativewindow.MutableGraphicsConfiguration;
*
*/
public class GLEventListenerState {
- private GLEventListenerState(AbstractGraphicsScreen screen, GLCapabilitiesImmutable caps, GLContext context, int count, GLAnimatorControl anim) {
+ private static final boolean DEBUG = true;
+
+ private GLEventListenerState(AbstractGraphicsScreen upstreamScreen, AbstractGraphicsScreen screen, GLCapabilitiesImmutable caps,
+ GLContext context, int count, GLAnimatorControl anim) {
+ this.upstreamScreen = upstreamScreen;
this.screen = screen;
this.caps = caps;
this.context = context;
@@ -89,6 +96,7 @@ public class GLEventListenerState {
public final int listenerCount() { return listeners.length; }
+ public final AbstractGraphicsScreen upstreamScreen;
public final AbstractGraphicsScreen screen;
public final GLCapabilitiesImmutable caps;
public final GLContext context;
@@ -112,6 +120,11 @@ public class GLEventListenerState {
owner = false;
}
}
+
+ private static AbstractGraphicsScreen cloneScreen(AbstractGraphicsScreen aScreen) {
+ final AbstractGraphicsDevice aDevice2 = (AbstractGraphicsDevice) aScreen.getDevice().clone();
+ return NativeWindowFactory.createScreen( aDevice2, aScreen.getIndex() );
+ }
/**
* Moves all GLEventListenerState components from the given {@link GLAutoDrawable}
@@ -138,19 +151,45 @@ public class GLEventListenerState {
// Create new AbstractGraphicsScreen w/ cloned AbstractGraphicsDevice for future GLAutoDrawable
// allowing this AbstractGraphicsDevice to loose ownership -> not closing display/device!
- final AbstractGraphicsConfiguration aCfg1 = a.getNativeSurface().getGraphicsConfiguration();
- final GLCapabilitiesImmutable caps1 = (GLCapabilitiesImmutable) aCfg1.getChosenCapabilities();
- final AbstractGraphicsScreen aScreen1 = aCfg1.getScreen();
- final AbstractGraphicsDevice aDevice1 = aScreen1.getDevice();
- final AbstractGraphicsDevice aDevice2 = (AbstractGraphicsDevice) aDevice1.clone();
- final AbstractGraphicsScreen aScreen2 = NativeWindowFactory.createScreen( NativeWindowFactory.getNativeWindowType(false), aDevice2, aScreen1.getIndex() );
+ final NativeSurface aSurface = a.getNativeSurface();
+ final AbstractGraphicsConfiguration aCfg = aSurface.getGraphicsConfiguration();
+ final AbstractGraphicsScreen aScreen1 = aCfg.getScreen();
+ final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities();
+ final AbstractGraphicsScreen aScreen2 = cloneScreen(aScreen1);
+ if( DEBUG ) {
+ System.err.println("X00 NativeSurface: "+aSurface.getClass().getName()+", "+aSurface);
+ }
+ aScreen1.getDevice().clearHandleOwner(); // don't close device handle
+
+ final AbstractGraphicsScreen aUpScreen2;
+ {
+ AbstractGraphicsScreen _aUpScreen2=null;
+ if(aSurface instanceof ProxySurface) {
+ final ProxySurface aProxy = (ProxySurface)aSurface;
+ final NativeSurface aUpSurface = aProxy.getUpstreamSurface();
+ if(null != aUpSurface) {
+ System.err.println("X00 UpstreamSurface: "+aUpSurface.getClass().getName()+", "+aUpSurface);
+ }
+ aProxy.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); // don't close device handle
+ if(null != aUpSurface) {
+ final AbstractGraphicsScreen aUpScreen1 = aUpSurface.getGraphicsConfiguration().getScreen();
+ _aUpScreen2 = cloneScreen(aUpScreen1);
+ if(null != aUpScreen1) {
+ aUpScreen1.getDevice().clearHandleOwner(); // don't close device handle
+ }
+ System.err.println("X0X NativeSurface: "+aSurface.getClass().getName()+", "+aSurface);
+ System.err.println("X0X UpstreamSurface: "+aUpSurface.getClass().getName()+", "+aUpSurface);
+ }
+ }
+ aUpScreen2=_aUpScreen2;
+ }
final GLAnimatorControl aAnim = a.getAnimator();
if( null != aAnim ) {
aAnim.remove(a); // also handles ECT
}
- final GLEventListenerState glls = new GLEventListenerState(aScreen2, caps1, a.getContext(), aSz, aAnim);
+ final GLEventListenerState glls = new GLEventListenerState(aUpScreen2, aScreen2, caps, a.getContext(), aSz, aAnim);
//
// remove and cache all GLEventListener and their init-state
@@ -167,7 +206,6 @@ public class GLEventListenerState {
a.invoke(true, glFinish);
a.setContext( null );
- aDevice1.clearHandleOwner(); // don't close handle
return glls;
}
@@ -195,19 +233,71 @@ public class GLEventListenerState {
final List aGLCmds = new ArrayList();
final int aSz = listenerCount();
- final MutableGraphicsConfiguration aCfg = (MutableGraphicsConfiguration) a.getNativeSurface().getGraphicsConfiguration();
+ final NativeSurface aSurface = a.getNativeSurface();
+ final MutableGraphicsConfiguration aCfg = (MutableGraphicsConfiguration) aSurface.getGraphicsConfiguration();
final GLCapabilitiesImmutable aCaps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities();
- if( caps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) != aCaps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) ) {
- throw new GLException("XXX: Incompatible - Prev Holder: "+caps+", New Holder "+caps);
+ if( caps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) != aCaps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) ||
+ caps.getVisualID(VisualIDHolder.VIDType.NATIVE) != aCaps.getVisualID(VisualIDHolder.VIDType.NATIVE) ) {
+ throw new GLException("Incompatible Capabilities - Prev-Holder: "+caps+", New-Holder "+caps);
}
- final GLContext prevContext = a.getContext();
- if( null != prevContext) {
- prevContext.destroy();
+ // Destroy and remove currently associated GLContext, if any (will be replaced)
+ {
+ final GLContext ctx = a.getContext();
+ if( null != ctx) {
+ ctx.destroy();
+ }
+ a.setContext( null );
+ }
+ final boolean aRealized = a.isRealized();
+ if( aRealized ) {
+ a.setRealized(false);
+ }
+ // Set new Screen and close previous one
+ {
+ if( DEBUG ) {
+ System.err.println("XX0 NativeSurface: "+aSurface.getClass().getName()+", "+aSurface);
+ }
+ final AbstractGraphicsScreen aScreen1 = aCfg.getScreen();
+ aCfg.setScreen( screen );
+ aScreen1.getDevice().close();
+ System.err.println("XXX NativeSurface: "+aSurface.getClass().getName()+", "+aSurface);
+ }
+ // If using a ProxySurface w/ an upstream surface, set new Screen and close previous one on it
+ {
+ boolean upstreamSet = false;
+ if(aSurface instanceof ProxySurface) {
+ final ProxySurface aProxy = (ProxySurface)aSurface;
+ final NativeSurface aUpSurface = aProxy.getUpstreamSurface();
+ if(null != aUpSurface) {
+ final MutableGraphicsConfiguration aUpCfg = (MutableGraphicsConfiguration) aUpSurface.getGraphicsConfiguration();
+ final AbstractGraphicsScreen aUpScreen1 = aUpCfg.getScreen();
+ if( null != upstreamScreen ) {
+ System.err.println("XX0 UpstreamSurface: "+aUpSurface.getClass().getName()+", "+aUpSurface);
+ aUpCfg.setScreen( upstreamScreen );
+ aUpScreen1.getDevice().close();
+ upstreamSet = true;
+ System.err.println("XXX UpstreamSurface: "+aUpSurface.getClass().getName()+", "+aUpSurface);
+ } else {
+ throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = false, New-Holder = true");
+ }
+ }
+ }
+ if( !upstreamSet && null != upstreamScreen ) {
+ throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = true, New-Holder = false");
+ }
+ }
+
+ if( aRealized ) {
+ a.setRealized(true);
+ }
+ final boolean surfaceLocked = false; // NativeSurface.LOCK_SURFACE_NOT_READY < aSurface.lockSurface();
+ try {
+ a.setContext( context );
+ } finally {
+ if( surfaceLocked ) {
+ aSurface.unlockSurface();
+ }
}
- final AbstractGraphicsScreen preScreen = aCfg.getScreen();
- aCfg.setScreen( screen );
- preScreen.getDevice().close();
- a.setContext( context );
owner = false;
//
@@ -220,15 +310,13 @@ public class GLEventListenerState {
}
}
aGLCmds.add(glFinish);
- a.invoke(true, aGLCmds);
+ a.invoke(aRealized, aGLCmds); // only wait if already realized
// add all cached GLEventListener to their destination and fix their init-state
for(int i=0; i
- * boolean ok = lockSurface() > LOCK_SURFACE_NOT_READY;
+ * boolean ok = LOCK_SURFACE_NOT_READY < lockSurface();
*
*
*
diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
index 07702c762..b6a052253 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/NativeWindowFactory.java
@@ -435,9 +435,10 @@ public abstract class NativeWindowFactory {
/**
* @param device
* @param screen -1 is default screen of the given device, e.g. maybe 0 or determined by native API. >= 0 is specific screen
- * @return newly created AbstractGraphicsScreen of given native type
+ * @return newly created AbstractGraphicsScreen matching device's native type
*/
- public static AbstractGraphicsScreen createScreen(String type, AbstractGraphicsDevice device, int screen) {
+ public static AbstractGraphicsScreen createScreen(AbstractGraphicsDevice device, int screen) {
+ final String type = device.getType();
if( TYPE_X11 == type ) {
final X11GraphicsDevice x11Device = (X11GraphicsDevice)device;
if(0 > screen) {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java
index 08a0857a9..8b1449493 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java
@@ -64,14 +64,18 @@ import org.junit.Test;
* i.e. ctx1/draw1, ctx2/draw2 -> ctx1/draw2, ctx2/draw1.
*/
public class TestGLContextDrawableSwitch01NEWT extends UITestCase {
- static GLProfile glp;
- static GLCapabilities caps;
static int width, height;
+ static GLCapabilities getCaps(String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
@BeforeClass
public static void initClass() {
- glp = GLProfile.getGL2ES2();
- caps = new GLCapabilities(glp);
width = 256;
height = 256;
}
@@ -124,7 +128,20 @@ public class TestGLContextDrawableSwitch01NEWT extends UITestCase {
}
@Test(timeout=30000)
- public void testSwitch2WindowSingleContext() throws InterruptedException {
+ public void testSwitch2WindowSingleContextGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testSwitch2WindowSingleContextImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2WindowSingleContextGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testSwitch2WindowSingleContextImpl(reqGLCaps);
+ }
+
+ private void testSwitch2WindowSingleContextImpl(GLCapabilities caps) throws InterruptedException {
final QuitAdapter quitAdapter = new QuitAdapter();
GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
@@ -178,7 +195,20 @@ public class TestGLContextDrawableSwitch01NEWT extends UITestCase {
}
@Test(timeout=30000)
- public void testSwitch2GLWindowOneDemo() throws InterruptedException {
+ public void testSwitch2GLWindowOneDemoGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowOneDemoImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowOneDemoGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowOneDemoImpl(reqGLCaps);
+ }
+
+ private void testSwitch2GLWindowOneDemoImpl(GLCapabilities caps) throws InterruptedException {
final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
final GearsES2 gears = new GearsES2(1);
final QuitAdapter quitAdapter = new QuitAdapter();
@@ -238,7 +268,20 @@ public class TestGLContextDrawableSwitch01NEWT extends UITestCase {
}
@Test(timeout=30000)
- public void testSwitch2GLWindowEachWithOwnDemo() throws InterruptedException {
+ public void testSwitch2GLWindowEachWithOwnDemoGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowEachWithOwnDemoGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps);
+ }
+
+ public void testSwitch2GLWindowEachWithOwnDemoImpl(GLCapabilities caps) throws InterruptedException {
final GearsES2 gears = new GearsES2(1);
final RedSquareES2 rsquare = new RedSquareES2(1);
final QuitAdapter quitAdapter = new QuitAdapter();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch11NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch11NEWT.java
index cd308e165..4af9a3932 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch11NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch11NEWT.java
@@ -69,19 +69,23 @@ import org.junit.Test;
*
*/
public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
- static GLProfile glp;
- static GLCapabilities caps;
static int width, height;
+ static GLCapabilities getCaps(String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
@BeforeClass
public static void initClass() {
- glp = GLProfile.getGL2ES2();
- caps = new GLCapabilities(glp);
width = 256;
height = 256;
}
- private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
+ private GLAutoDrawable createGLAutoDrawableWithoutContext(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
final Window window = NewtFactory.createWindow(caps);
Assert.assertNotNull(window);
window.setPosition(x, y);
@@ -126,7 +130,20 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
}
@Test(timeout=30000)
- public void test01() throws InterruptedException {
+ public void test01GLADDelegateGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ test01GLADDelegateImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void test01GLADDelegateGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ test01GLADDelegateImpl(reqGLCaps);
+ }
+
+ private void test01GLADDelegateImpl(GLCapabilities caps) throws InterruptedException {
final QuitAdapter quitAdapter = new QuitAdapter();
final GLEventListenerCounter glelCounter = new GLEventListenerCounter();
@@ -140,7 +157,7 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
// - create glad1 w/o context
// - create context using glad1 and assign it to glad1
{
- final GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
+ final GLAutoDrawable glad1 = createGLAutoDrawableWithoutContext(caps, 64, 64, width, height, quitAdapter);
final GLContext context1 = glad1.createContext(null);
glad1.setContext(context1);
animator.add(glad1);
@@ -149,7 +166,7 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
glad1.addGLEventListener(new GearsES2(1));
glad1.addGLEventListener(snapshotGLEventListener);
snapshotGLEventListener.setMakeSnapshot();
-
+
long t1 = System.currentTimeMillis();
while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/2 ) {
@@ -157,8 +174,6 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
t1 = System.currentTimeMillis();
}
- // - dis-associate context from glad1
- // - destroy glad1
Assert.assertEquals(1, glelCounter.initCount);
Assert.assertTrue(1 <= glelCounter.reshapeCount);
Assert.assertTrue(1 <= glelCounter.displayCount);
@@ -168,6 +183,8 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
Assert.assertEquals(context1.getGLReadDrawable(), glad1.getDelegatedDrawable());
Assert.assertEquals(context1.getGLDrawable(), glad1.getDelegatedDrawable());
+ // - dis-associate context from glad1
+ // - destroy glad1
glls1 = GLEventListenerState.moveFrom(glad1);
Assert.assertEquals(1, glelCounter.initCount);
@@ -191,7 +208,7 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
// - create glad2 w/ survived context
{
- final GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
+ final GLAutoDrawable glad2 = createGLAutoDrawableWithoutContext(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
snapshotGLEventListener.setMakeSnapshot();
Assert.assertEquals(null, glad2.getContext());
@@ -199,6 +216,8 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
glls1.moveTo(glad2);
+ Assert.assertTrue(glad2.isRealized());
+
Assert.assertEquals(1, glelCounter.initCount);
Assert.assertTrue(1 <= glelCounter.reshapeCount);
Assert.assertTrue(1 <= glelCounter.displayCount);
@@ -226,7 +245,20 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
}
@Test(timeout=30000)
- public void test02() throws InterruptedException {
+ public void test02GLWindowGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ test02GLWindowImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void test02GLWindowGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ test02GLWindowImpl(reqGLCaps);
+ }
+
+ private void test02GLWindowImpl(GLCapabilities caps) throws InterruptedException {
final QuitAdapter quitAdapter = new QuitAdapter();
final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
@@ -244,7 +276,6 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
glad1.setSize(width, height);
glad1.setPosition(64, 64);
glad1.addWindowListener(quitAdapter);
- glad1.setVisible(true);
animator.add(glad1);
glad1.addGLEventListener(glelTracker);
@@ -252,6 +283,8 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
glad1.addGLEventListener(snapshotGLEventListener);
snapshotGLEventListener.setMakeSnapshot();
+ glad1.setVisible(true);
+
long t1 = System.currentTimeMillis();
while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/2 ) {
@@ -297,13 +330,13 @@ public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
glad2.setSize(width+100, height+100);
glad2.setPosition(2*64+width, 64);
glad2.addWindowListener(quitAdapter);
- glad2.setVisible(true);
snapshotGLEventListener.setMakeSnapshot();
+ glad2.setVisible(true);
Assert.assertNotNull(glad2.getContext());
Assert.assertEquals(0, glad2.getGLEventListenerCount());
- glls1.moveTo(glad2);
+ glls1.moveTo(glad2);
Assert.assertEquals(1, glelTracker.initCount);
Assert.assertTrue(1 <= glelTracker.reshapeCount);
--
cgit v1.2.3
From 6d508eb203fea16e094039b27a7368748aff122b Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Mon, 11 Feb 2013 23:43:16 +0100
Subject: GLContext: *TRACE_SWITCH spacing
---
src/jogl/classes/javax/media/opengl/GLContext.java | 2 +-
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 24 +++++++++++-----------
.../jogamp/opengl/x11/glx/X11GLXContext.java | 2 +-
3 files changed, 14 insertions(+), 14 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 4817add4d..c31b76401 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -442,7 +442,7 @@ public abstract class GLContext {
* new GLContext implementations; not for use by end users.
*/
protected static void setCurrent(GLContext cur) {
- if(TRACE_SWITCH) {
+ if( TRACE_SWITCH ) {
if(null == cur) {
System.err.println(getThreadName()+": GLContext.ContextSwitch: - setCurrent() - NULL");
} else {
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index b17fce569..a0027f308 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -278,14 +278,14 @@ public abstract class GLContextImpl extends GLContext {
release(false);
}
private void release(boolean inDestruction) throws GLException {
- if(TRACE_SWITCH) {
+ if( TRACE_SWITCH ) {
System.err.println(getThreadName() +": GLContext.ContextSwitch[release.0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+", inDestruction: "+inDestruction+", "+lock);
}
if ( !lock.isOwner(Thread.currentThread()) ) {
final String msg = getThreadName() +": Context not current on current thread, obj " + toHexString(hashCode())+", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+", inDestruction: "+inDestruction+", "+lock;
if( DEBUG_TRACE_SWITCH ) {
System.err.println(msg);
- if( null != lastCtxReleaseStack) {
+ if( null != lastCtxReleaseStack ) {
System.err.print("Last release call: ");
lastCtxReleaseStack.printStackTrace();
} else {
@@ -318,7 +318,7 @@ public abstract class GLContextImpl extends GLContext {
if( DEBUG_TRACE_SWITCH ) {
final String msg = getThreadName() +": GLContext.ContextSwitch[release.X]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - "+(actualRelease?"switch":"keep ")+" - "+lock;
lastCtxReleaseStack = new Throwable(msg);
- if(TRACE_SWITCH) {
+ if( TRACE_SWITCH ) {
System.err.println(msg);
// Thread.dumpStack();
}
@@ -334,7 +334,7 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final void destroy() {
- if (DEBUG_TRACE_SWITCH) {
+ if ( DEBUG_TRACE_SWITCH ) {
System.err.println(getThreadName() + ": GLContextImpl.destroy.0: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
", surf "+toHexString(drawable.getHandle())+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
@@ -351,7 +351,7 @@ public abstract class GLContextImpl extends GLContext {
lock.lock(); // holdCount++ -> 1 - n (1: not locked, 2-n: destroy while rendering)
if ( lock.getHoldCount() > 2 ) {
final String msg = getThreadName() + ": GLContextImpl.destroy: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle);
- if (DEBUG_TRACE_SWITCH) {
+ if ( DEBUG_TRACE_SWITCH ) {
System.err.println(msg+" - Lock was hold more than once - makeCurrent/release imbalance: "+lock);
Thread.dumpStack();
}
@@ -388,7 +388,7 @@ public abstract class GLContextImpl extends GLContext {
}
} finally {
lock.unlock();
- if (TRACE_SWITCH) {
+ if ( DEBUG_TRACE_SWITCH ) {
System.err.println(getThreadName() + ": GLContextImpl.destroy.X: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
@@ -468,14 +468,14 @@ public abstract class GLContextImpl extends GLContext {
*/
@Override
public int makeCurrent() throws GLException {
- if(TRACE_SWITCH) {
+ if( TRACE_SWITCH ) {
System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - "+lock);
}
// Note: the surface is locked within [makeCurrent .. swap .. release]
final int lockRes = drawable.lockSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
- if(DEBUG_TRACE_SWITCH) {
+ if( DEBUG_TRACE_SWITCH ) {
System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X1]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - Surface Not Ready - CONTEXT_NOT_CURRENT - "+lock);
}
return CONTEXT_NOT_CURRENT;
@@ -503,7 +503,7 @@ public abstract class GLContextImpl extends GLContext {
// For Mac OS X, however, we need to update the context to track resizes
drawableUpdatedNotify();
unlockContextAndSurface = false; // success
- if(TRACE_SWITCH) {
+ if( TRACE_SWITCH ) {
System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X2]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - keep - CONTEXT_CURRENT - "+lock);
}
return CONTEXT_CURRENT;
@@ -526,7 +526,7 @@ public abstract class GLContextImpl extends GLContext {
throw e;
} finally {
if (unlockContextAndSurface) {
- if(DEBUG_TRACE_SWITCH) {
+ if( DEBUG_TRACE_SWITCH ) {
System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.1]: Context lock.unlock() due to error, res "+makeCurrentResultToString(res)+", "+lock);
}
lock.unlock();
@@ -575,7 +575,7 @@ public abstract class GLContextImpl extends GLContext {
}
*/
}
- if(TRACE_SWITCH) {
+ if( TRACE_SWITCH ) {
System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X3]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - switch - "+makeCurrentResultToString(res)+" - "+lock);
}
return res;
@@ -611,7 +611,7 @@ public abstract class GLContextImpl extends GLContext {
shareWith.getDrawableImpl().unlockSurface();
}
}
- if (DEBUG_TRACE_SWITCH) {
+ if ( DEBUG_TRACE_SWITCH ) {
if(created) {
System.err.println(getThreadName() + ": Create GL context OK: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) + ", surf "+toHexString(drawable.getHandle())+" for " + getClass().getName()+" - "+getGLVersion());
// Thread.dumpStack();
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index feda64f30..e36515088 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -166,7 +166,7 @@ public abstract class X11GLXContext extends GLContextImpl {
throw new InternalError("Given readDrawable but no driver support");
}
} catch (RuntimeException re) {
- if(DEBUG_TRACE_SWITCH) {
+ if( DEBUG_TRACE_SWITCH ) {
System.err.println(getThreadName()+": Warning: X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+
"dpy "+toHexString(dpy)+
", write "+toHexString(writeDrawable)+
--
cgit v1.2.3
From 10b4957dc36005453d2a4e7a3b4de4df20d0c901 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Wed, 20 Feb 2013 21:52:42 +0100
Subject: Fix NPE of Bug 679: The ctx was released w/o fully initialized (no
proper ARB ctx of expected version ?)
---
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 2 +-
src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index a0027f308..e279c0423 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -811,7 +811,7 @@ public abstract class GLContextImpl extends GLContext {
if(PROFILE_ALIASING) {
hasGL3 = true;
}
- resetStates(); // clean this context states, since creation was temporary
+ resetStates(); // clean context states, since creation was temporary
}
}
if(!hasGL3) {
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index 9e0174595..dbb1d4931 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -793,7 +793,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean release(long ctx) {
try {
- gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze
+ if( null != MacOSXCGLContext.this.getGLProcAddressTable() ) { // gl successfully initialized ?
+ gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze
+ }
} catch (GLException gle) {
if(DEBUG) {
System.err.println("MacOSXCGLContext.NSOpenGLImpl.release: INFO: glFlush() catched exception:");
--
cgit v1.2.3
From 97401c4b832aa6f65bfbad47c54d18e4b720dbce Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Thu, 21 Feb 2013 09:35:05 +0100
Subject: Relax GLContextImpl.setGLFunctionAvailability(..)'s Version Matching
if testing major < 3 versions. (Bug 679)
On OSX, we 'only' support the ctx ARB creation and hence have no !ARM fallback.
If querying a version [2.0 .. 3.0] for GL2, it is acceptable if a valid OpenGL version is lower, e.g. 1.4.
---
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index e279c0423..98b9ede36 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1301,7 +1301,7 @@ public abstract class GLContextImpl extends GLContext {
// Only validate if a valid int version was fetched, otherwise cont. w/ version-string method -> 3.0 > Version || Version > MAX!
if ( GLContext.isValidGLVersion(glIntMajor[0], glIntMinor[0]) ) {
if( glIntMajor[0] "+glVersion+", "+glIntMajor[0]+"."+glIntMinor[0]);
}
@@ -1326,7 +1326,7 @@ public abstract class GLContextImpl extends GLContext {
// Only validate if a valid string version was fetched -> MIN > Version || Version > MAX!
if( null != strGLVersionNumber ) {
if( strGLVersionNumber.compareTo(setGLVersionNumber) < 0 || 0 == major ) {
- if( strictMatch && 0 < major ) {
+ if( strictMatch && 2 < major ) { // relaxed match for versions major < 3 requests, last resort!
if(DEBUG) {
System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch (String): "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+" -> "+glVersion+", "+strGLVersionNumber);
}
--
cgit v1.2.3
From ffcf0cb5beaf3c7c363d45cef0b9d18dcf3f50c6 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Thu, 21 Feb 2013 10:27:31 +0100
Subject: Bug 548 and Bug 679: Add 'glFlush()' requirement (OSX < 10.7.3 &&
NVIDIA GPU) to GLRendererQuirks and perform only if exists.
---
.../com/jogamp/opengl/GLRendererQuirks.java | 12 +++++-
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 50 ++++++++++++++++------
.../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 9 ++--
3 files changed, 54 insertions(+), 17 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
index 9a13ff904..715511d1b 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
@@ -73,12 +73,20 @@ public class GLRendererQuirks {
*/
public static final int GLNonCompliant = 6;
+ /**
+ * The OpenGL Context needs a glFlush()
before releasing it, otherwise driver may freeze:
+ *
+ * - OSX < 10.7.3 - NVidia Driver. Bug 533 and Bug 548 @ https://jogamp.org/bugzilla/.
+ *
+ */
+ public static final int GLFlushBeforeRelease = 7;
+
/** Number of quirks known. */
- public static final int COUNT = 7;
+ public static final int COUNT = 8;
private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval",
"NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard",
- "GLNonCompliant"
+ "GLNonCompliant", "GLFlushBeforeRelease"
};
private final int _bitmask;
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 98b9ede36..42364dbfd 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1462,29 +1462,55 @@ public abstract class GLContextImpl extends GLContext {
final boolean hwAccel = 0 == ( ctp & GLContext.CTX_IMPL_ACCEL_SOFT );
final boolean compatCtx = 0 != ( ctp & GLContext.CTX_PROFILE_COMPAT );
+ //
// OS related quirks
+ //
if( Platform.getOSType() == Platform.OSType.MACOS ) {
- final int quirk1 = GLRendererQuirks.NoOffscreenBitmap;
- if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk1)+": cause: OS "+Platform.getOSType());
+ //
+ // OSX
+ //
+ {
+ final int quirk = GLRendererQuirks.NoOffscreenBitmap;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
+ }
+ quirks[i++] = quirk;
+ }
+
+ final VersionNumber OSXVersion173 = new VersionNumber(1,7,3);
+ if( Platform.getOSVersionNumber().compareTo(OSXVersion173) < 0 && glRendererLowerCase.contains("nvidia") ) {
+ final int quirk = GLRendererQuirks.GLFlushBeforeRelease;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", Renderer "+glRenderer);
+ }
+ quirks[i++] = quirk;
}
- quirks[i++] = quirk1;
} else if( Platform.getOSType() == Platform.OSType.WINDOWS ) {
+ //
+ // WINDOWS
+ //
final int quirk = GLRendererQuirks.NoDoubleBufferedBitmap;
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
}
quirks[i++] = quirk;
- }
-
- // Renderer related quirks, may also involve OS
- if( Platform.OSType.ANDROID == Platform.getOSType() && glRendererLowerCase.contains("powervr") ) {
- final int quirk = GLRendererQuirks.NoSetSwapInterval;
- if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer);
+ } else if( Platform.OSType.ANDROID == Platform.getOSType() ) {
+ //
+ // ANDROID
+ //
+ // Renderer related quirks, may also involve OS
+ if( glRendererLowerCase.contains("powervr") ) {
+ final int quirk = GLRendererQuirks.NoSetSwapInterval;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer);
+ }
+ quirks[i++] = quirk;
}
- quirks[i++] = quirk;
}
+
+ //
+ // RENDERER related quirks
+ //
if( glRendererLowerCase.contains("mesa") || glRendererLowerCase.contains("gallium") ) {
{
final int quirk = GLRendererQuirks.NoSetSwapIntervalPostRetarget;
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index dbb1d4931..3825f855c 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -74,6 +74,7 @@ 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.GLRendererQuirks;
import com.jogamp.opengl.util.PMVMatrix;
import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
@@ -793,8 +794,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean release(long ctx) {
try {
- if( null != MacOSXCGLContext.this.getGLProcAddressTable() ) { // gl successfully initialized ?
- gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze
+ if( hasRendererQuirk(GLRendererQuirks.GLFlushBeforeRelease) && null != MacOSXCGLContext.this.getGLProcAddressTable() ) {
+ gl.glFlush();
}
} catch (GLException gle) {
if(DEBUG) {
@@ -975,7 +976,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean release(long ctx) {
try {
- gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze
+ if( hasRendererQuirk(GLRendererQuirks.GLFlushBeforeRelease) && null != MacOSXCGLContext.this.getGLProcAddressTable() ) {
+ gl.glFlush();
+ }
} catch (GLException gle) {
if(DEBUG) {
System.err.println("MacOSXCGLContext.CGLImpl.release: INFO: glFlush() catched exception:");
--
cgit v1.2.3
From c225285e09f0a29fca418601bf1aa07cafb54339 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Wed, 13 Mar 2013 06:35:30 +0100
Subject: Bug 665: Allow re-association of GLContext/GLEventListener to a
GLDrawable (Part 4)
Note:
- GLEventListenerState preservs the GLAutoDrawable state,
i.e. GLContext, all GLEventListener and the GLAnimatorControl association.
- GLEventListenerState may be utilized to move the state from a dying GLAutoDrawable,
to be moved to a new created GLAutoDrawable at a later time.
- GLEventListenerState will be made public soon.
+++
Exessive unit tests cover the new feature, tested manually on GNU/Linux/X11 and OSX(Java6/Java7).
+++
- GLAutoDrawable
- Change 'setContext(..)' to allow the destruction of the unbound old context:
'setContext(GLContext newCtx)' -> 'setContext(GLContext newCtx, boolean destroyPrevCtx)'
- Implementations: Properly implement 'setRealized(..)' incl. obeying threading constraints if exists.
Method is being utilized at least for GLEventListenerState.moveTo(..)
to unrealize and realize the drawable resources.
+++
Fix propagation of GLContext/GLDrawable association change (Bottom -> Top):
GLDrawableImpl.associateContext
GLContextImpl.associateDrawable
GLContextImpl.makeCurrent
GLContextImpl.destroy
GLContext.setGLDrawable
...
GLDrawableHelper.switchContext
GLAutoDrawble.setContext
associateDrawable(..)/associateContext(..) unifies and hence:
- GLContextImpl.contextRealized() (removed)
- GLDrawableImpl.contextRealized() (removed)
- GLDrawableImpl.associateContext(..) (merged)
- MacOSXCGLContext.drawableChangedNotify(..) (removed)
+++
- EGLUpstreamSurfaceHook.evalUpstreamSurface() validates the surface's device for reusage,
which is valid in case of GLEventListenerState.moveTo(..)
- MacOSXCGLContext.NSOpenGLImpl: pixelFormat replaces NSOpenGLLayerPfmt and has simplified lifecycle [create..destroy],
while native NSOpenGLLayer code only holds the reference until released.
---
make/scripts/tests.sh | 45 ++-
.../com/jogamp/opengl/GLAutoDrawableDelegate.java | 5 -
.../classes/com/jogamp/opengl/swt/GLCanvas.java | 7 +-
.../com/jogamp/opengl/util/GLDrawableUtil.java | 2 +-
.../classes/javax/media/opengl/GLAutoDrawable.java | 21 +-
.../classes/javax/media/opengl/awt/GLCanvas.java | 90 ++---
.../classes/javax/media/opengl/awt/GLJPanel.java | 7 +-
.../classes/jogamp/opengl/GLAutoDrawableBase.java | 25 +-
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 59 ++--
.../classes/jogamp/opengl/GLDrawableHelper.java | 45 +--
src/jogl/classes/jogamp/opengl/GLDrawableImpl.java | 40 +--
.../jogamp/opengl/GLEventListenerState.java | 55 +--
.../classes/jogamp/opengl/GLFBODrawableImpl.java | 14 +-
src/jogl/classes/jogamp/opengl/GLPbufferImpl.java | 10 +-
.../jogamp/opengl/egl/EGLUpstreamSurfaceHook.java | 53 ++-
.../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 132 +++----
.../opengl/macosx/cgl/MacOSXCGLDrawable.java | 1 -
.../macosx/MacOSXWindowSystemInterface-calayer.m | 17 +-
.../acore/TestGLContextDrawableSwitch01NEWT.java | 374 --------------------
.../acore/TestGLContextDrawableSwitch11NEWT.java | 386 ---------------------
.../acore/glels/GLContextDrawableSwitchBase.java | 276 +++++++++++++++
.../glels/TestGLContextDrawableSwitch01NEWT.java | 374 ++++++++++++++++++++
.../glels/TestGLContextDrawableSwitch10NEWT.java | 274 +++++++++++++++
.../TestGLContextDrawableSwitch11NewtAWT.java | 118 +++++++
.../glels/TestGLContextDrawableSwitch12AWT.java | 144 ++++++++
.../TestGLContextDrawableSwitch21Newt2AWT.java | 165 +++++++++
.../demos/es2/newt/TestGearsES2NewtCanvasAWT.java | 31 +-
.../jogamp/opengl/test/junit/util/QuitAdapter.java | 19 +-
28 files changed, 1730 insertions(+), 1059 deletions(-)
delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java
delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch11NEWT.java
create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/GLContextDrawableSwitchBase.java
create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java
create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch10NEWT.java
create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch11NewtAWT.java
create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch12AWT.java
create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch21Newt2AWT.java
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 5d259d6be..8cc3fd84a 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -106,10 +106,11 @@ function jrun() {
#D_ARGS="-Djogamp.debug=all"
#D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all"
#D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all"
- #D_ARGS="-Dnativewindow.debug.X11Util -Djogl.debug.EGLDisplayUtil -Djogl.debug.GLDrawable"
+ #D_ARGS="-Dnativewindow.debug.X11Util -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Djogl.debug.EGLDisplayUtil -Djogl.debug.GLDrawable"
#D_ARGS="-Dnativewindow.debug.X11Util"
#D_ARGS="-Djogl.debug.Animator"
#D_ARGS="-Djogl.debug=all -Dnewt.debug=all"
+ #D_ARGS="-Djogl.debug.EGLDisplayUtil -Djogl.debug.GLDrawable"
#D_ARGS="-Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.GLCanvas"
#D_ARGS="-Djogl.debug.GLDrawable"
#D_ARGS="-Djogl.fbo.force.none"
@@ -194,7 +195,6 @@ function jrun() {
#D_ARGS="-Djogl.debug.GLContext -Dnewt.debug=all -Djogamp.debug.Lock -Djogamp.common.utils.locks.Lock.timeout=10000"
#D_ARGS="-Djogl.debug.GLContext -Dnewt.debug=all"
#D_ARGS="-Dnewt.debug=all"
- #D_ARGS="-Dnewt.debug=all"
#D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel"
#X_ARGS="-Dsun.java2d.noddraw=True -Dsun.java2d.opengl=True -Dsun.java2d.xrender=false"
#X_ARGS="-Dsun.java2d.noddraw=True -Dsun.java2d.opengl=false -Dsun.java2d.xrender=false"
@@ -312,17 +312,9 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT2 $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES1NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitch01NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitch02NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLPointsNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLMesaBug651NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLMesaBug658NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimNEWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimAWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext02FPSAnimNEWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext02FPSAnimAWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext11VSyncAnimNEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext12FPSAnimNEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer01GLCanvasAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer02NewtCanvasAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.acore.TestAddRemove01GLCanvasSwingAWT $*
@@ -339,15 +331,27 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitch01NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitch11NEWT $*
-
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableFactoryNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOOffThreadSharedContextMix2DemosES2NEWT $*
-testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOOnThreadSharedContext1DemoES2NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOOnThreadSharedContext1DemoES2NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimNEWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimAWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext02FPSAnimNEWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext02FPSAnimAWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext11VSyncAnimNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext12FPSAnimNEWT $*
+
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch10NEWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch11NewtAWT $*
+#testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch12AWT $*
+testawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch21Newt2AWT $*
+
+#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $*
+
#testawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT
@@ -560,9 +564,6 @@ testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOOnThreadSharedContext1D
# Child too low
#testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT $*
-# NPE:
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitch11NEWT $*
-
# test rotation change
#testnoawt com.jogamp.opengl.test.junit.newt.TestScreenMode02NEWT
@@ -580,5 +581,15 @@ testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOOnThreadSharedContext1D
# ../../src/xcb_io.c:178: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $*
+# NEW
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableFactoryNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestBug605FlippedImageNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestBug605FlippedImageAWT $*
+
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.glels.TestGLContextDrawableSwitch11NEWT $*
+
+#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $*
+
+
$spath/count-edt-start.sh java-run.log
diff --git a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
index 0f0f03ac4..bec05a0bd 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java
@@ -169,11 +169,6 @@ public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAuto
return drawable.getFactory();
}
- @Override
- public final void setRealized(boolean realized) {
- drawable.setRealized(realized);
- }
-
@Override
public final void swapBuffers() throws GLException {
defaultSwapBuffers();
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 80e1aa80d..169266152 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -705,16 +705,13 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
}
@Override
- public GLContext setContext(GLContext newCtx) {
+ public GLContext setContext(GLContext newCtx, boolean destroyPrevCtx) {
final RecursiveLock _lock = lock;
_lock.lock();
try {
final GLContext oldCtx = context;
- final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
- context.makeCurrent();
- }
return oldCtx;
} finally {
_lock.unlock();
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
index c03e4bfa4..83414ddb0 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java
@@ -151,7 +151,7 @@ public class GLDrawableUtil {
for(int i = dest.getGLEventListenerCount() - 1; 0 <= i; i--) {
dest.disposeGLEventListener(dest.getGLEventListener(i), false);
}
- dest.setContext( src.setContext( dest.getContext() ) );
+ dest.setContext( src.setContext( dest.getContext(), false ), false );
src.invoke(true, GLEventListenerState.setViewport);
dest.invoke(true, GLEventListenerState.setViewport);
diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
index 6abe4308b..bdbbd96a5 100644
--- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java
@@ -132,7 +132,8 @@ public interface GLAutoDrawable extends GLDrawable {
/**
* Associate the new context, newtCtx
, to this auto-drawable.
*
- * The current context will be dis-associated from this auto-drawable
+ * The current context will be destroyed if destroyPrevCtx
is true
,
+ * otherwise it will be dis-associated from this auto-drawable
* via {@link GLContext#setGLDrawable(GLDrawable, boolean) setGLDrawable(null, true);} first.
*
*
@@ -145,26 +146,16 @@ public interface GLAutoDrawable extends GLDrawable {
* However the user shall take extra care that no other thread
* attempts to make this context current.
*
- *
- * In case you do not intend to use the old context anymore, i.e.
- * not assigning it to another drawable, it shall be
- * destroyed, i.e.:
- *
- GLContext oldCtx = glad.setContext(newCtx);
- if(null != oldCtx) {
- oldCtx.destroy();
- }
- *
- *
*
* @param newCtx the new context, maybe null
for dis-association.
+ * @param destroyPrevCtx if true
, destroy the previous context if exists
* @return the previous GLContext, maybe null
*
* @see GLContext#setGLDrawable(GLDrawable, boolean)
* @see GLContext#setGLReadDrawable(GLDrawable)
- * @see jogamp.opengl.GLDrawableHelper#switchContext(GLDrawable, GLContext, GLContext, int)
+ * @see jogamp.opengl.GLDrawableHelper#switchContext(GLDrawable, GLContext, boolean, GLContext, int)
*/
- public GLContext setContext(GLContext newCtx);
+ public GLContext setContext(GLContext newCtx, boolean destroyPrevCtx);
/**
* Adds the given {@link GLEventListener listener} to the end of this drawable queue.
@@ -500,7 +491,7 @@ public interface GLAutoDrawable extends GLDrawable {
*
* This GLAutoDrawable implementation holds it's own GLContext reference,
* thus created a GLContext using this methods won't replace it implicitly.
- * To replace or set this GLAutoDrawable's GLContext you need to call {@link #setContext(GLContext)}.
+ * To replace or set this GLAutoDrawable's GLContext you need to call {@link #setContext(GLContext, boolean)}.
*
*
* The GLAutoDrawable implementation shall also set the
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index ebc25e2ad..63c18db5d 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -429,8 +429,29 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
}
+ private final void setRealizedImpl(boolean realized) {
+ final RecursiveLock _lock = lock;
+ _lock.lock();
+ try {
+ final GLDrawable _drawable = drawable;
+ if( null == _drawable || realized && ( 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) ) {
+ return;
+ }
+ _drawable.setRealized(realized);
+ if( realized && _drawable.isRealized() ) {
+ sendReshape=true; // ensure a reshape is being send ..
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+ private final Runnable realizeOnEDTAction = new Runnable() { public void run() { setRealizedImpl(true); } };
+ private final Runnable unrealizeOnEDTAction = new Runnable() { public void run() { setRealizedImpl(false); } };
+
@Override
- public void setRealized(boolean realized) {
+ public final void setRealized(boolean realized) {
+ // Make sure drawable realization happens on AWT-EDT and only there. Consider the AWTTree lock!
+ AWTEDTExecutor.singleton.invoke(getTreeLock(), false /* allowOnNonEDT */, true /* wait */, realized ? realizeOnEDTAction : unrealizeOnEDTAction);
}
@Override
@@ -595,46 +616,28 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
private boolean validateGLDrawable() {
- if( Beans.isDesignTime() || !isDisplayable() ) {
- return false; // early out!
- }
- final GLDrawable _drawable = drawable;
- if ( null != _drawable ) {
- if( _drawable.isRealized() ) {
- return true;
- }
- if( 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) {
- return false; // early out!
- }
- // Make sure drawable realization happens on AWT-EDT and only there. Consider the AWTTree lock!
- final boolean res0 = AWTEDTExecutor.singleton.invoke(getTreeLock(), false /* allowOnNonEDT */, true /* wait */, setRealizedOnEDTAction);
- final boolean res1 = res0 && _drawable.isRealized();
- if(DEBUG) {
- System.err.println(getThreadName()+": Realized Drawable: invoked "+res0+", probedIsRealized "+res1+", "+_drawable.toString());
- Thread.dumpStack();
- }
- return res1;
- }
- return false;
- }
- private Runnable setRealizedOnEDTAction = new Runnable() {
- public void run() {
- final RecursiveLock _lock = lock;
- _lock.lock();
- try {
- final GLDrawable _drawable = drawable;
- if( null == _drawable || 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) {
- return;
- }
- _drawable.setRealized(true);
- if( _drawable.isRealized() ) {
- sendReshape=true; // ensure a reshape is being send ..
- }
- } finally {
- _lock.unlock();
+ if( Beans.isDesignTime() || !isDisplayable() ) {
+ return false; // early out!
+ }
+ final GLDrawable _drawable = drawable;
+ if ( null != _drawable ) {
+ if( _drawable.isRealized() ) {
+ return true;
}
- } };
-
+ if( 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) {
+ return false; // early out!
+ }
+ setRealized(true);
+ final boolean res = _drawable.isRealized();
+ if(DEBUG) {
+ System.err.println(getThreadName()+": Realized Drawable: isRealized "+res+", "+_drawable.toString());
+ Thread.dumpStack();
+ }
+ return res;
+ }
+ return false;
+ }
+
/**
Overridden to track when this component is removed from a
container. Subclasses which override this method must call
super.removeNotify() in their removeNotify() method in order to
@@ -791,16 +794,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public GLContext setContext(GLContext newCtx) {
+ public GLContext setContext(GLContext newCtx, boolean destroyPrevCtx) {
final RecursiveLock _lock = lock;
_lock.lock();
try {
final GLContext oldCtx = context;
- final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
context=(GLContextImpl)newCtx;
- if(newCtxCurrent) {
- context.makeCurrent();
- }
return oldCtx;
} finally {
_lock.unlock();
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index 8d9493cbf..d62967d7f 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -519,16 +519,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
@Override
- public GLContext setContext(GLContext newCtx) {
+ public GLContext setContext(GLContext newCtx, boolean destroyPrevCtx) {
if (backend == null) {
return null;
}
final GLContext oldCtx = backend.getContext();
- final boolean newCtxCurrent = GLDrawableHelper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags);
+ GLDrawableHelper.switchContext(backend.getDrawable(), oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
backend.setContext(newCtx);
- if(newCtxCurrent) {
- newCtx.makeCurrent();
- }
return oldCtx;
}
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
index c20197e72..ad67f8281 100644
--- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -326,16 +326,13 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
@Override
- public final GLContext setContext(GLContext newCtx) {
+ public final GLContext setContext(GLContext newCtx, boolean destroyPrevCtx) {
final RecursiveLock lock = getLock();
lock.lock();
try {
final GLContext oldCtx = context;
- final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags);
+ GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
context=(GLContextImpl)newCtx;
- if(newCtxCurrent) { // implies null != newCtx
- context.makeCurrent();
- }
return oldCtx;
} finally {
lock.unlock();
@@ -530,6 +527,24 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter {
}
}
+ @Override
+ public final void setRealized(boolean realized) {
+ final RecursiveLock _lock = getLock();
+ _lock.lock();
+ try {
+ final GLDrawable _drawable = drawable;
+ if( null == _drawable || realized && ( 0 >= _drawable.getWidth() || 0 >= _drawable.getHeight() ) ) {
+ return;
+ }
+ _drawable.setRealized(realized);
+ if( realized && _drawable.isRealized() ) {
+ sendReshape=true; // ensure a reshape is being send ..
+ }
+ } finally {
+ _lock.unlock();
+ }
+ }
+
@Override
public final boolean isRealized() {
final GLDrawable _drawable = drawable;
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 42364dbfd..4121e8f77 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -133,9 +133,6 @@ public abstract class GLContextImpl extends GLContext {
GLContextShareSet.synchronizeBufferObjectSharing(shareWith, this);
this.drawable = drawable;
- if(null != drawable) {
- drawable.associateContext(this, true);
- }
this.drawableRead = drawable;
this.glDebugHandler = new GLDebugMessageHandler(this);
@@ -207,25 +204,36 @@ public abstract class GLContextImpl extends GLContext {
return drawable; // no change.
}
final Thread currentThread = Thread.currentThread();
+ if( lock.isLockedByOtherThread() ) {
+ throw new GLException("GLContext current by other thread "+lock.getOwner().getName()+", operation not allowed on this thread "+currentThread.getName());
+ }
final boolean lockHeld = lock.isOwner(currentThread);
+ if( lockHeld && lock.getHoldCount() > 1 ) {
+ // would need to makeCurrent * holdCount
+ throw new GLException("GLContext is recursively locked - unsupported for setGLDrawable(..)");
+ }
+ final GLDrawableImpl old = drawable;
+ if( isCreated() && null != old && old.isRealized() ) {
+ if(!lockHeld) {
+ makeCurrent();
+ }
+ associateDrawable(false);
+ if(!lockHeld) {
+ release();
+ }
+ }
if(lockHeld) {
release();
- } else if(lock.isLockedByOtherThread()) { // still could glitch ..
- throw new GLException("GLContext current by other thread "+lock.getOwner().getName()+", operation not allowed on this thread "+currentThread.getName());
- }
+ }
if( !setWriteOnly || drawableRead == drawable ) { // if !setWriteOnly || !explicitReadDrawable
drawableRead = (GLDrawableImpl) readWrite;
}
- final GLDrawableImpl old = drawable;
- if( null != old ) {
- old.associateContext(this, false);
- }
drawableRetargeted |= null != drawable && readWrite != drawable;
drawable = (GLDrawableImpl) readWrite ;
- if( null != drawable ) {
- drawable.associateContext(this, true);
- if( lockHeld ) {
- makeCurrent();
+ if( isCreated() && null != drawable && drawable.isRealized() ) {
+ makeCurrent(true); // implicit: associateDrawable(true)
+ if( !lockHeld ) {
+ release();
}
}
return old;
@@ -363,8 +371,7 @@ public abstract class GLContextImpl extends GLContext {
makeCurrent();
}
try {
- contextRealized(false);
- drawable.associateContext(this, false);
+ associateDrawable(false);
} catch (Throwable t) {
drawableContextRealizedException = t;
}
@@ -467,7 +474,11 @@ public abstract class GLContextImpl extends GLContext {
* @see #destroyContextARBImpl
*/
@Override
- public int makeCurrent() throws GLException {
+ public final int makeCurrent() throws GLException {
+ return makeCurrent(false);
+ }
+
+ protected final int makeCurrent(boolean forceDrawableAssociation) throws GLException {
if( TRACE_SWITCH ) {
System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.0]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - "+lock);
}
@@ -561,7 +572,11 @@ public abstract class GLContextImpl extends GLContext {
gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) );
}
- contextRealized(true);
+ forceDrawableAssociation = true;
+ }
+
+ if( forceDrawableAssociation ) {
+ associateDrawable(true);
}
contextMadeCurrent(true);
@@ -662,14 +677,14 @@ public abstract class GLContextImpl extends GLContext {
protected abstract void makeCurrentImpl() throws GLException;
/**
- * @see GLDrawableImpl#contextRealized(GLContext, boolean)
+ * Calls {@link GLDrawableImpl#associateContext(GLContext, boolean)}
*/
- protected void contextRealized(boolean realized) {
- drawable.contextRealized(this, realized);
+ protected void associateDrawable(boolean bound) {
+ drawable.associateContext(this, bound);
}
/**
- * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean)
+ * Calls {@link GLDrawableImpl#contextMadeCurrent(GLContext, boolean)}
*/
protected void contextMadeCurrent(boolean current) {
drawable.contextMadeCurrent(this, current);
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index 3eedf918e..1caa942ba 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -59,7 +59,7 @@ import javax.media.opengl.GLFBODrawable;
import javax.media.opengl.GLRunnable;
/** Encapsulates the implementation of most of the GLAutoDrawable's
- methods to be able to share it between GLCanvas and GLJPanel. */
+ methods to be able to share it between GLAutoDrawable implementations like GLAutoDrawableBase, GLCanvas and GLJPanel. */
public class GLDrawableHelper {
/** true if property jogl.debug.GLDrawable.PerfStats
is defined. */
private static final boolean PERF_STATS = Debug.isPropertyDefined("jogl.debug.GLDrawable.PerfStats", true);
@@ -113,6 +113,9 @@ public class GLDrawableHelper {
return sb.toString();
}
+ /** Limit release calls of {@link #forceNativeRelease(GLContext)} to {@value}. */
+ private static final int MAX_RELEASE_ITER = 512;
+
/**
* Since GLContext's {@link GLContext#makeCurrent()} and {@link GLContext#release()}
* is recursive, a call to {@link GLContext#release()} may not natively release the context.
@@ -122,18 +125,25 @@ public class GLDrawableHelper {
* @param ctx
*/
public static final void forceNativeRelease(GLContext ctx) {
+ int releaseCount = 0;
do {
ctx.release();
+ releaseCount++;
if (DEBUG) {
- System.err.println("GLDrawableHelper.forceNativeRelease() -- currentThread "+Thread.currentThread()+" -> "+GLContext.getCurrent());
+ System.err.println("GLDrawableHelper.forceNativeRelease() #"+releaseCount+" -- currentThread "+Thread.currentThread()+" -> "+GLContext.getCurrent());
}
- } while( ctx == GLContext.getCurrent() );
+ } while( MAX_RELEASE_ITER > releaseCount && ctx.isCurrent() );
+
+ if( ctx.isCurrent() ) {
+ throw new GLException("Context still current after "+MAX_RELEASE_ITER+" releases: "+ctx);
+ }
}
/**
* Switch {@link GLContext} / {@link GLDrawable} association.
*
- * Dis-associate oldCtx
from drawable
+ * The oldCtx
will be destroyed if destroyPrevCtx
is true
,
+ * otherwise dis-associate oldCtx
from drawable
* via {@link GLContext#setGLDrawable(GLDrawable, boolean) oldCtx.setGLDrawable(null, true);}.
*
*
@@ -149,31 +159,25 @@ public class GLDrawableHelper {
*
* @param drawable the drawable which context is changed
* @param oldCtx the old context, maybe null
.
+ * @param destroyOldCtx if true
, destroy the oldCtx
* @param newCtx the new context, maybe null
for dis-association.
* @param newCtxCreationFlags additional creation flags if newCtx is not null and not been created yet, see {@link GLContext#setContextCreationFlags(int)}
- * @return true if the new context was current, otherwise false
*
- * @see GLAutoDrawable#setContext(GLContext)
+ * @see GLAutoDrawable#setContext(GLContext, boolean)
*/
- public static final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int newCtxCreationFlags) {
+ public static final void switchContext(GLDrawable drawable, GLContext oldCtx, boolean destroyOldCtx, GLContext newCtx, int newCtxCreationFlags) {
if( null != oldCtx ) {
- if( oldCtx.isCurrent() ) {
- oldCtx.release();
+ if( destroyOldCtx ) {
+ oldCtx.destroy();
+ } else {
+ oldCtx.setGLDrawable(null, true); // dis-associate old pair
}
- oldCtx.setGLDrawable(null, true); // dis-associate old pair
}
- final boolean newCtxCurrent;
+
if(null!=newCtx) {
- newCtxCurrent = newCtx.isCurrent();
- if(newCtxCurrent) {
- newCtx.release();
- }
newCtx.setContextCreationFlags(newCtxCreationFlags);
- newCtx.setGLDrawable(drawable, true); // re-associate new pair
- } else {
- newCtxCurrent = false;
+ newCtx.setGLDrawable(drawable, true); // re-associate new pair
}
- return newCtxCurrent;
}
/**
@@ -208,7 +212,6 @@ public class GLDrawableHelper {
context.makeCurrent();
}
context.getGL().glFinish();
- context.release();
context.setGLDrawable(null, true); // dis-associate
}
@@ -837,7 +840,7 @@ public class GLDrawableHelper {
if( null != exclusiveContextThread ) {
throw new GLException("Release current exclusive Context Thread "+exclusiveContextThread+" first");
}
- if( null != context && GLContext.getCurrent() == context ) {
+ if( null != context && context.isCurrent() ) {
try {
forceNativeRelease(context);
} catch (Throwable ex) {
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index c0c28a5f2..d0c1461a9 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -164,13 +164,14 @@ public abstract class GLDrawableImpl implements GLDrawable {
@Override
public final void setRealized(boolean realizedArg) {
if ( realized != realizedArg ) { // volatile: OK (locked below)
+ final boolean isProxySurface = surface instanceof ProxySurface;
if(DEBUG) {
- System.err.println(getThreadName() + ": setRealized: "+getClass().getSimpleName()+" "+realized+" -> "+realizedArg);
+ System.err.println(getThreadName() + ": setRealized: drawable "+getClass().getSimpleName()+", surface "+surface.getClass().getSimpleName()+", isProxySurface "+isProxySurface+": "+realized+" -> "+realizedArg);
Thread.dumpStack();
}
AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice();
if(realizedArg) {
- if(surface instanceof ProxySurface) {
+ if(isProxySurface) {
((ProxySurface)surface).createNotify();
}
if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) {
@@ -195,7 +196,7 @@ public abstract class GLDrawableImpl implements GLDrawable {
unlockSurface();
} else {
aDevice.unlock();
- if(surface instanceof ProxySurface) {
+ if(isProxySurface) {
((ProxySurface)surface).destroyNotify();
}
}
@@ -210,18 +211,26 @@ public abstract class GLDrawableImpl implements GLDrawable {
*/
protected abstract void setRealizedImpl();
- /**
- * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: construct
, destroy
.
+ /**
+ * Callback for special implementations, allowing
+ *
+ * - to associate bound context to this drawable (bound == true)
+ * or to remove such association (bound == false).
+ * - to trigger GLContext/GLDrawable related lifecycle:
construct
, destroy
.
+ *
*
- * If realized
is true
, the context has just been created and made current.
+ * If bound
is true
, the context is current and being newly associated w/ this drawable.
*
*
- * If realized
is false
, the context is still current and will be released and destroyed after this method returns.
+ * If bound
is false
, the context is still current and will be unbound (released and destroyed, or simply disassociated).
*
*
- * @see #contextMadeCurrent(GLContext, boolean)
+ * Being called by {@link GLContextImpl#associateDrawable(boolean)}.
+ *
+ * @param ctx the just bounded or unbounded context
+ * @param bound if true
create an association, otherwise remove it
*/
- protected void contextRealized(GLContext glc, boolean realized) {}
+ protected void associateContext(GLContext ctx, boolean bound) { }
/**
* Callback for special implementations, allowing GLContext to trigger GL related lifecycle: makeCurrent
, release
.
@@ -232,21 +241,12 @@ public abstract class GLDrawableImpl implements GLDrawable {
* If current
is false
, the context is still current and will be release after this method returns.
*
*
- * Note: Will also be called after {@link #contextRealized(GLContext, boolean) contextRealized(ctx, true)}
- * but not at context destruction, i.e. {@link #contextRealized(GLContext, boolean) contextRealized(ctx, false)}.
+ * Being called by {@link GLContextImpl#contextMadeCurrent(boolean)}.
*
- * @see #contextRealized(GLContext, boolean)
+ * @see #associateContext(GLContext, boolean)
*/
protected void contextMadeCurrent(GLContext glc, boolean current) { }
- /**
- * Callback for special implementations, allowing to associate bound context to this drawable (bound == true)
- * or to remove such association (bound == false).
- * @param ctx the just bounded or unbounded context
- * @param bound if true
create an association, otherwise remove it
- */
- protected void associateContext(GLContext ctx, boolean bound) { }
-
/** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/
protected int getDefaultDrawFramebuffer() { return 0; }
/** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */
diff --git a/src/jogl/classes/jogamp/opengl/GLEventListenerState.java b/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
index 7a2569850..2385460fe 100644
--- a/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
+++ b/src/jogl/classes/jogamp/opengl/GLEventListenerState.java
@@ -45,7 +45,6 @@ import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLRunnable;
-import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
/**
@@ -71,11 +70,12 @@ import com.jogamp.nativewindow.MutableGraphicsConfiguration;
*
*/
public class GLEventListenerState {
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = GLDrawableImpl.DEBUG;
- private GLEventListenerState(AbstractGraphicsScreen upstreamScreen, AbstractGraphicsScreen screen, GLCapabilitiesImmutable caps,
+ private GLEventListenerState(AbstractGraphicsScreen upstreamScreen, boolean proxyOwnsUpstreamDevice, AbstractGraphicsScreen screen, GLCapabilitiesImmutable caps,
GLContext context, int count, GLAnimatorControl anim) {
this.upstreamScreen = upstreamScreen;
+ this.proxyOwnsUpstreamDevice = proxyOwnsUpstreamDevice;
this.screen = screen;
this.caps = caps;
this.context = context;
@@ -97,6 +97,7 @@ public class GLEventListenerState {
public final int listenerCount() { return listeners.length; }
public final AbstractGraphicsScreen upstreamScreen;
+ public final boolean proxyOwnsUpstreamDevice;
public final AbstractGraphicsScreen screen;
public final GLCapabilitiesImmutable caps;
public final GLContext context;
@@ -161,25 +162,30 @@ public class GLEventListenerState {
}
aScreen1.getDevice().clearHandleOwner(); // don't close device handle
- final AbstractGraphicsScreen aUpScreen2;
+ final AbstractGraphicsScreen aUpScreen2;
+ final boolean proxyOwnsUpstreamDevice;
{
AbstractGraphicsScreen _aUpScreen2=null;
if(aSurface instanceof ProxySurface) {
final ProxySurface aProxy = (ProxySurface)aSurface;
+ proxyOwnsUpstreamDevice = aProxy.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
final NativeSurface aUpSurface = aProxy.getUpstreamSurface();
- if(null != aUpSurface) {
+ if(DEBUG && null != aUpSurface) {
System.err.println("X00 UpstreamSurface: "+aUpSurface.getClass().getName()+", "+aUpSurface);
}
- aProxy.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); // don't close device handle
if(null != aUpSurface) {
final AbstractGraphicsScreen aUpScreen1 = aUpSurface.getGraphicsConfiguration().getScreen();
_aUpScreen2 = cloneScreen(aUpScreen1);
if(null != aUpScreen1) {
aUpScreen1.getDevice().clearHandleOwner(); // don't close device handle
}
- System.err.println("X0X NativeSurface: "+aSurface.getClass().getName()+", "+aSurface);
- System.err.println("X0X UpstreamSurface: "+aUpSurface.getClass().getName()+", "+aUpSurface);
+ if(DEBUG) {
+ System.err.println("X0X NativeSurface: "+aSurface.getClass().getName()+", "+aSurface);
+ System.err.println("X0X UpstreamSurface: "+aUpSurface.getClass().getName()+", "+aUpSurface);
+ }
}
+ } else {
+ proxyOwnsUpstreamDevice = false;
}
aUpScreen2=_aUpScreen2;
}
@@ -189,7 +195,7 @@ public class GLEventListenerState {
aAnim.remove(a); // also handles ECT
}
- final GLEventListenerState glls = new GLEventListenerState(aUpScreen2, aScreen2, caps, a.getContext(), aSz, aAnim);
+ final GLEventListenerState glls = new GLEventListenerState(aUpScreen2, proxyOwnsUpstreamDevice, aScreen2, caps, a.getContext(), aSz, aAnim);
//
// remove and cache all GLEventListener and their init-state
@@ -205,7 +211,7 @@ public class GLEventListenerState {
//
a.invoke(true, glFinish);
- a.setContext( null );
+ a.setContext( null, false );
return glls;
}
@@ -241,13 +247,7 @@ public class GLEventListenerState {
throw new GLException("Incompatible Capabilities - Prev-Holder: "+caps+", New-Holder "+caps);
}
// Destroy and remove currently associated GLContext, if any (will be replaced)
- {
- final GLContext ctx = a.getContext();
- if( null != ctx) {
- ctx.destroy();
- }
- a.setContext( null );
- }
+ a.setContext( null, true );
final boolean aRealized = a.isRealized();
if( aRealized ) {
a.setRealized(false);
@@ -260,8 +260,11 @@ public class GLEventListenerState {
final AbstractGraphicsScreen aScreen1 = aCfg.getScreen();
aCfg.setScreen( screen );
aScreen1.getDevice().close();
- System.err.println("XXX NativeSurface: "+aSurface.getClass().getName()+", "+aSurface);
+ if( DEBUG ) {
+ System.err.println("XXX NativeSurface: "+aSurface.getClass().getName()+", "+aSurface);
+ }
}
+
// If using a ProxySurface w/ an upstream surface, set new Screen and close previous one on it
{
boolean upstreamSet = false;
@@ -270,13 +273,19 @@ public class GLEventListenerState {
final NativeSurface aUpSurface = aProxy.getUpstreamSurface();
if(null != aUpSurface) {
final MutableGraphicsConfiguration aUpCfg = (MutableGraphicsConfiguration) aUpSurface.getGraphicsConfiguration();
- final AbstractGraphicsScreen aUpScreen1 = aUpCfg.getScreen();
if( null != upstreamScreen ) {
- System.err.println("XX0 UpstreamSurface: "+aUpSurface.getClass().getName()+", "+aUpSurface);
+ if( DEBUG ) {
+ System.err.println("XX0 UpstreamSurface: "+aUpSurface.getClass().getName()+", "+aUpSurface+", "+aProxy.getUpstreamOptionBits(null).toString());
+ }
+ aUpCfg.getScreen().getDevice().close();
aUpCfg.setScreen( upstreamScreen );
- aUpScreen1.getDevice().close();
+ if( proxyOwnsUpstreamDevice ) {
+ aProxy.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
upstreamSet = true;
- System.err.println("XXX UpstreamSurface: "+aUpSurface.getClass().getName()+", "+aUpSurface);
+ if( DEBUG ) {
+ System.err.println("XXX UpstreamSurface: "+aUpSurface.getClass().getName()+", "+aUpSurface+", "+aProxy.getUpstreamOptionBits(null).toString());
+ }
} else {
throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = false, New-Holder = true");
}
@@ -292,7 +301,7 @@ public class GLEventListenerState {
}
final boolean surfaceLocked = false; // NativeSurface.LOCK_SURFACE_NOT_READY < aSurface.lockSurface();
try {
- a.setContext( context );
+ a.setContext( context, false );
} finally {
if( surfaceLocked ) {
aSurface.unlockSurface();
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index 86cfa4f4c..51ec7dda6 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -38,6 +38,7 @@ import com.jogamp.opengl.JoglVersion;
*/
public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
protected static final boolean DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject");
+ protected static final boolean DEBUG_SWAP = Debug.isPropertyDefined("jogl.debug.FBObject.Swap", true);
private final GLDrawableImpl parent;
private GLCapabilitiesImmutable origParentChosenCaps;
@@ -92,6 +93,9 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
}
private final void initialize(boolean realize, GL gl) {
+ if( initialized == realize ) {
+ throw new InternalError("Already set to initialize := "+realize+": "+this);
+ }
if(realize) {
final GLCapabilities chosenFBOCaps = (GLCapabilities) getChosenGLCapabilities(); // cloned at setRealized(true)
@@ -323,8 +327,8 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
}
@Override
- protected final void contextRealized(GLContext glc, boolean realized) {
- initialize(realized, glc.getGL());
+ protected void associateContext(GLContext glc, boolean bound) {
+ initialize(bound, glc.getGL());
}
@Override
@@ -338,7 +342,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
swapFBOImpl(glc);
swapFBOImplPost(glc);
fboBound=false;
- if(DEBUG) {
+ if(DEBUG_SWAP) {
System.err.println("Post FBO swap(@release): done");
}
}
@@ -354,7 +358,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
swapFBOImpl(ctx);
doPostSwap = true;
fboBound=false;
- if(DEBUG) {
+ if(DEBUG_SWAP) {
System.err.println("Post FBO swap(@swap): done");
}
}
@@ -406,7 +410,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbos[fboIFront].getReadFramebuffer());
} */
- if(DEBUG) {
+ if(DEBUG_SWAP) {
System.err.println("Post FBO swap(X): fboI back "+fboIBack+", front "+fboIFront+", num "+fbos.length);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
index b438131bc..ddc6d5917 100644
--- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
@@ -86,9 +86,10 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
//
@Override
- public final void setRealized(boolean realized) {
+ public final void swapBuffers() throws GLException {
+ defaultSwapBuffers();
}
-
+
//
// GLAutoDrawable completion
//
@@ -125,11 +126,6 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
}
}
- @Override
- public final void swapBuffers() throws GLException {
- defaultSwapBuffers();
- }
-
//----------------------------------------------------------------------
// Internals only below this point
//
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
index 342c4c417..77e9dc173 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java
@@ -47,7 +47,7 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize {
public final void create(ProxySurface surface) {
final String dbgPrefix;
if(DEBUG) {
- dbgPrefix = getThreadName() + ": EGLUpstreamSurfaceHook.create("+surface.getClass().getSimpleName()+"): ";
+ dbgPrefix = getThreadName() + ": EGLUpstreamSurfaceHook.create( up "+upstreamSurface.getClass().getSimpleName()+" -> this "+surface.getClass().getSimpleName()+" ): ";
System.err.println(dbgPrefix+this);
} else {
dbgPrefix = null;
@@ -76,24 +76,51 @@ public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize {
boolean isEGLSurfaceValid = true; // assume yes
- final AbstractGraphicsConfiguration aConfig = upstreamSurface.getGraphicsConfiguration();
- final AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice();
-
final EGLGraphicsDevice eglDevice;
- if( aDevice instanceof EGLGraphicsDevice ) {
- eglDevice = (EGLGraphicsDevice) aDevice;
+ final AbstractGraphicsConfiguration aConfig;
+ {
+ final AbstractGraphicsConfiguration surfaceConfig = surface.getGraphicsConfiguration();
+ final AbstractGraphicsDevice surfaceDevice = null != surfaceConfig ? surfaceConfig.getScreen().getDevice() : null;
+ if(DEBUG) {
+ System.err.println(dbgPrefix+"SurfaceDevice: "+surfaceDevice.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(surfaceDevice.hashCode())+", "+surfaceDevice);
+ System.err.println(dbgPrefix+"SurfaceConfig: "+surfaceConfig.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(surfaceConfig.hashCode())+", "+surfaceConfig);
+ }
+
+ final AbstractGraphicsConfiguration upstreamConfig = upstreamSurface.getGraphicsConfiguration();
+ final AbstractGraphicsDevice upstreamDevice = upstreamConfig.getScreen().getDevice();
if(DEBUG) {
- System.err.println(dbgPrefix+"Reusing eglDevice: "+eglDevice);
+ System.err.println(dbgPrefix+"UpstreamDevice: "+upstreamDevice.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(upstreamDevice.hashCode())+", "+upstreamDevice);
+ System.err.println(dbgPrefix+"UpstreamConfig: "+upstreamConfig.getClass().getSimpleName()+", hash 0x"+Integer.toHexString(upstreamConfig.hashCode())+", "+upstreamConfig);
}
- if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) {
- eglDevice.open();
+
+ if( surfaceDevice instanceof EGLGraphicsDevice ) {
+ eglDevice = (EGLGraphicsDevice) surfaceDevice;
+ aConfig = surfaceConfig;
+ if(DEBUG) {
+ System.err.println(dbgPrefix+"Reusing this eglDevice: "+eglDevice+", using this config "+aConfig.getClass().getSimpleName()+" "+aConfig);
+ }
+ if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) {
+ eglDevice.open();
+ isEGLSurfaceValid = false;
+ surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ } else if( upstreamDevice instanceof EGLGraphicsDevice ) {
+ eglDevice = (EGLGraphicsDevice) upstreamDevice;
+ aConfig = upstreamConfig;
+ if(DEBUG) {
+ System.err.println(dbgPrefix+"Reusing upstream eglDevice: "+eglDevice+", using upstream config "+aConfig.getClass().getSimpleName()+" "+aConfig);
+ }
+ if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) {
+ eglDevice.open();
+ isEGLSurfaceValid = false;
+ surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
+ }
+ } else {
+ eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface);
+ aConfig = upstreamConfig;
isEGLSurfaceValid = false;
surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
}
- } else {
- eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface);
- isEGLSurfaceValid = false;
- surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE );
}
final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities();
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index 3825f855c..a03850043 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -85,10 +85,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
// NSOpenGL-based or CGL-based)
protected interface GLBackendImpl {
boolean isNSContext();
- void drawableChangedNotify();
long create(long share, int ctp, int major, int minor);
boolean destroy(long ctx);
- boolean contextRealized(boolean realized);
+ void associateDrawable(boolean bound);
boolean copyImpl(long src, int mask);
boolean makeCurrent(long ctx);
boolean release(long ctx);
@@ -328,20 +327,15 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
@Override
- protected void contextRealized(boolean realized) {
+ protected void associateDrawable(boolean bound) {
// context stuff depends on drawable stuff
- if(realized) {
- super.contextRealized(true); // 1) init drawable stuff
- impl.contextRealized(true); // 2) init context stuff
+ System.err.println("MaxOSXCGLContext.associateDrawable: "+bound);
+ if(bound) {
+ super.associateDrawable(true); // 1) init drawable stuff
+ impl.associateDrawable(true); // 2) init context stuff
} else {
- impl.contextRealized(false); // 1) free context stuff
- super.contextRealized(false); // 2) free drawable stuff
- }
- }
-
- /* pp */ void drawableChangedNotify() {
- if( 0 != contextHandle) {
- impl.drawableChangedNotify();
+ impl.associateDrawable(false); // 1) free context stuff
+ super.associateDrawable(false); // 2) free drawable stuff
}
}
@@ -467,9 +461,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl
// NSOpenGLContext-based implementation
class NSOpenGLImpl implements GLBackendImpl {
- private OffscreenLayerSurface backingLayerHost = null;
- private long nsOpenGLLayer = 0;
- private long nsOpenGLLayerPFmt = 0; // lifecycle: [create - contextRealized]
+ private long pixelFormat = 0; // lifecycle: [create - destroy]
+ private long nsOpenGLLayer = 0; // lifecycle: [associateDrawable_true - associateDrawable_false]
private float screenVSyncTimeout; // microSec
private int vsyncTimeout; // microSec - for nsOpenGLLayer mode
private int lastWidth=0, lastHeight=0; // allowing to detect size change
@@ -479,18 +472,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean isNSContext() { return true; }
- @Override
- public void drawableChangedNotify() {
- backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(drawable.getNativeSurface(), true);
- if( null == backingLayerHost ) {
- boolean[] isPBuffer = { false };
- boolean[] isFBO = { false };
- CGL.setContextView(contextHandle, getNSViewHandle(isPBuffer, isFBO));
- } else {
- nsOpenGLLayer = backingLayerHost.getAttachedSurfaceLayer();
- }
- }
-
private long getNSViewHandle(boolean[] isPBuffer, boolean[] isFBO) {
final long nsViewHandle;
if(drawable instanceof GLFBODrawableImpl) {
@@ -549,13 +530,12 @@ public abstract class MacOSXCGLContext extends GLContextImpl
isPBuffer = _isPBuffer[0];
isFBO = _isFBO[0];
}
- backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
+ final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
boolean incompleteView = null != backingLayerHost;
if( !incompleteView && surface instanceof ProxySurface ) {
incompleteView = ((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE );
}
- long pixelFormat;
{
final GLCapabilitiesImmutable targetCaps;
if( isFBO ) {
@@ -606,48 +586,54 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
config.setChosenCapabilities(fixedCaps);
- try {
- final IntBuffer viewNotReady = Buffers.newDirectIntBuffer(1);
- // Try to allocate a context with this
- ctx = CGL.createContext(share,
- nsViewHandle, incompleteView,
- pixelFormat,
- chosenCaps.isBackgroundOpaque(),
- viewNotReady);
- if (0 == ctx) {
- if(DEBUG) {
- System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady.get(0)));
- }
- return 0;
+ final IntBuffer viewNotReady = Buffers.newDirectIntBuffer(1);
+ // Try to allocate a context with this
+ ctx = CGL.createContext(share, nsViewHandle, incompleteView,
+ pixelFormat, chosenCaps.isBackgroundOpaque(), viewNotReady);
+ if (0 == ctx) {
+ if(DEBUG) {
+ System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady.get(0)));
}
+ return 0;
+ }
- if(null != backingLayerHost) {
- nsOpenGLLayerPFmt = pixelFormat;
- pixelFormat = 0;
- }
-
- if (chosenCaps.isOnscreen() && !chosenCaps.isBackgroundOpaque()) {
- // Set the context opacity
- CGL.setContextOpacity(ctx, 0);
- }
- } finally {
- if(0!=pixelFormat) {
- CGL.deletePixelFormat(pixelFormat);
- pixelFormat = 0;
- }
+ if (chosenCaps.isOnscreen() && !chosenCaps.isBackgroundOpaque()) {
+ // Set the context opacity
+ CGL.setContextOpacity(ctx, 0);
}
return ctx;
}
@Override
public boolean destroy(long ctx) {
+ if(0!=pixelFormat) {
+ CGL.deletePixelFormat(pixelFormat);
+ pixelFormat = 0;
+ }
return CGL.deleteContext(ctx, true);
+
}
@Override
- public boolean contextRealized(boolean realized) {
- if( realized ) {
+ public void associateDrawable(boolean bound) {
+ final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(drawable.getNativeSurface(), true);
+
+ if(DEBUG) {
+ System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable: "+bound+", ctx "+toHexString(contextHandle)+", hasBackingLayerHost "+(null!=backingLayerHost));
+ }
+
+ if( bound ) {
+
if( null != backingLayerHost ) {
+
+ if( 0 != nsOpenGLLayer ) { // FIXME: redundant
+ throw new InternalError("Lifecycle: bound=true, hasBackingLayerHost=true, but 'nsOpenGLLayer' is already/still set local: "+nsOpenGLLayer+", "+this);
+ }
+ nsOpenGLLayer = backingLayerHost.getAttachedSurfaceLayer();
+ if( 0 != nsOpenGLLayer ) { // FIXME: redundant
+ throw new InternalError("Lifecycle: bound=true, hasBackingLayerHost=true, but 'nsOpenGLLayer' is already/still set on backingLayerHost: "+nsOpenGLLayer+", "+this);
+ }
+
//
// handled layered surface
//
@@ -700,8 +686,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
final boolean ctxUnlocked = CGL.kCGLNoError == CGL.CGLUnlockContext(cglCtx);
try {
- nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, gl3ShaderProgramName, nsOpenGLLayerPFmt, pbufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight);
- nsOpenGLLayerPFmt = 0; // NSOpenGLLayer will release pfmt
+ nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, gl3ShaderProgramName, pixelFormat, 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);
}
@@ -718,17 +703,22 @@ public abstract class MacOSXCGLContext extends GLContextImpl
} else {
lastWidth = drawable.getWidth();
lastHeight = drawable.getHeight();
+ boolean[] isPBuffer = { false };
+ boolean[] isFBO = { false };
+ CGL.setContextView(contextHandle, getNSViewHandle(isPBuffer, isFBO));
}
} else {
if( 0 != nsOpenGLLayer ) {
- final NativeSurface surface = drawable.getNativeSurface();
+ if( null == backingLayerHost ) { // FIXME: redundant
+ throw new InternalError("Lifecycle: bound=false, hasNSOpneGLLayer=true, but 'backingLayerHost' is null local: "+nsOpenGLLayer+", "+this);
+ }
+
if (DEBUG) {
System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", "+drawable);
}
- final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true);
- if(null != ols && ols.isSurfaceLayerAttached()) {
+ if( backingLayerHost.isSurfaceLayerAttached() ) {
// still having a valid OLS attached to surface (parent OLS could have been removed)
- ols.detachSurfaceLayer();
+ backingLayerHost.detachSurfaceLayer();
}
CGL.releaseNSOpenGLLayer(nsOpenGLLayer);
if( null != gl3ShaderProgram ) {
@@ -738,8 +728,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
nsOpenGLLayer = 0;
}
}
- backingLayerHost = null;
- return true;
}
private final void validatePBufferConfig(long ctx) {
@@ -888,11 +876,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean isNSContext() { return false; }
- @Override
- public void drawableChangedNotify() {
- // FIXME
- }
-
@Override
public long create(long share, int ctp, int major, int minor) {
long ctx = 0;
@@ -947,8 +930,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
@Override
- public boolean contextRealized(boolean realized) {
- return true;
+ public void associateDrawable(boolean bound) {
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
index ff1772860..0f282d33f 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java
@@ -119,7 +119,6 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl {
if(bound) {
final MacOSXCGLContext osxCtx = (MacOSXCGLContext)ctx;
createdContexts.add(new WeakReference(osxCtx));
- osxCtx.drawableChangedNotify();
} else {
for(int i=0; i ref = createdContexts.get(i);
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
index 2cf74380c..abc9d7958 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
@@ -275,7 +275,7 @@ static const GLfloat gl_verts[] = {
vboBufTexCoord = 0;
vertAttrLoc = 0;
texCoordAttrLoc = 0;
- parentPixelFmt = _parentPixelFmt;
+ parentPixelFmt = [_parentPixelFmt retain]; // until destruction
swapInterval = 1; // defaults to on (as w/ new GL profiles)
swapIntervalCounter = 0;
timespec_now(&lastWaitTime);
@@ -338,13 +338,13 @@ static const GLfloat gl_verts[] = {
#ifdef VERBOSE_ON
CGRect lRect = [self bounds];
if(NULL != pbuffer) {
- DBG_PRINT("MyNSOpenGLLayer::init (pbuffer) %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, pbuffer %dx%d -> tex %dx%d, bounds: %lf/%lf %lfx%lf (refcnt %d)\n",
+ DBG_PRINT("MyNSOpenGLLayer::init (pbuffer) %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, pbuffer %dx%d -> tex %dx%d, bounds: %lf/%lf %lfx%lf, displayLink %p (refcnt %d)\n",
self, parentCtx, parentPixelFmt, pbuffer, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight,
- lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]);
+ lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, displayLink, (int)[self retainCount]);
} else {
- DBG_PRINT("MyNSOpenGLLayer::init (texture) %p, ctx %p, pfmt %p, opaque %d, tex[id %d, %dx%d], bounds: %lf/%lf %lfx%lf (refcnt %d)\n",
+ DBG_PRINT("MyNSOpenGLLayer::init (texture) %p, ctx %p, pfmt %p, opaque %d, tex[id %d, %dx%d], bounds: %lf/%lf %lfx%lf, displayLink %p (refcnt %d)\n",
self, parentCtx, parentPixelFmt, opaque, (int)textureID, texWidth, texHeight,
- lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]);
+ lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, displayLink, (int)[self retainCount]);
}
#endif
return self;
@@ -498,7 +498,10 @@ static const GLfloat gl_verts[] = {
myCtx = NULL;
}
parentCtx = NULL;
- [parentPixelFmt release];
+ if( NULL != parentPixelFmt ) {
+ [parentPixelFmt release];
+ parentPixelFmt = NULL;
+ }
pthread_mutex_unlock(&renderLock);
[self release];
DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p\n", self);
@@ -623,7 +626,7 @@ static const GLfloat gl_verts[] = {
{
DBG_PRINT("MyNSOpenGLLayer::openGLPixelFormatForDisplayMask: %p (refcnt %d) - parent-pfmt %p -> new-pfmt %p\n",
self, (int)[self retainCount], parentPixelFmt, parentPixelFmt);
- // We simply take over ownership of parent PixelFormat ..
+ // We simply take over ownership of parent PixelFormat until releaseLayer..
return parentPixelFmt;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java
deleted file mode 100644
index cce4149ba..000000000
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitch01NEWT.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/**
- * Copyright 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this list of
- * conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice, this list
- * of conditions and the following disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those of the
- * authors and should not be interpreted as representing official policies, either expressed
- * or implied, of JogAmp Community.
- */
-
-package com.jogamp.opengl.test.junit.jogl.acore;
-
-import java.io.IOException;
-
-import com.jogamp.newt.NewtFactory;
-import com.jogamp.newt.Window;
-import com.jogamp.newt.event.WindowAdapter;
-import com.jogamp.newt.event.WindowEvent;
-import com.jogamp.newt.event.WindowListener;
-import com.jogamp.newt.event.WindowUpdateEvent;
-import com.jogamp.newt.opengl.GLWindow;
-
-import javax.media.opengl.GLAutoDrawable;
-import javax.media.opengl.GLCapabilities;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLDrawable;
-import javax.media.opengl.GLDrawableFactory;
-import javax.media.opengl.GLProfile;
-
-import com.jogamp.opengl.GLAutoDrawableDelegate;
-import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.GLDrawableUtil;
-
-import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
-import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
-import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
-import com.jogamp.opengl.test.junit.util.QuitAdapter;
-import com.jogamp.opengl.test.junit.util.UITestCase;
-
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- * Test re-association (switching) of GLContext/GLDrawables,
- * i.e. ctx1/draw1, ctx2/draw2 -> ctx1/draw2, ctx2/draw1.
- */
-public class TestGLContextDrawableSwitch01NEWT extends UITestCase {
- static int width, height;
-
- static GLCapabilities getCaps(String profile) {
- if( !GLProfile.isAvailable(profile) ) {
- System.err.println("Profile "+profile+" n/a");
- return null;
- }
- return new GLCapabilities(GLProfile.get(profile));
- }
-
- @BeforeClass
- public static void initClass() {
- width = 256;
- height = 256;
- }
-
- private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
- final Window window = NewtFactory.createWindow(caps);
- Assert.assertNotNull(window);
- window.setPosition(x, y);
- window.setSize(width, height);
- window.setVisible(true);
- Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
-
- final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
- final GLDrawable drawable = factory.createGLDrawable(window);
- Assert.assertNotNull(drawable);
-
- drawable.setRealized(true);
- Assert.assertTrue(drawable.isRealized());
-
- final GLContext context = drawable.createContext(null);
- Assert.assertNotNull(context);
-
- final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) {
- @Override
- protected void destroyImplInLock() {
- super.destroyImplInLock();
- window.destroy(); // destroys the actual window
- }
- };
-
- window.setWindowDestroyNotifyAction( new Runnable() {
- public void run() {
- glad.windowDestroyNotifyOp();
- } } );
-
- // add basic window interaction
- window.addWindowListener(new WindowAdapter() {
- @Override
- public void windowRepaint(WindowUpdateEvent e) {
- glad.windowRepaintOp();
- }
- @Override
- public void windowResized(WindowEvent e) {
- glad.windowResizedOp(window.getWidth(), window.getHeight());
- }
- });
- window.addWindowListener(wl);
-
- return glad;
- }
-
- @Test(timeout=30000)
- public void testSwitch2WindowSingleContextGL2ES2() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
- if(null == reqGLCaps) return;
- testSwitch2WindowSingleContextImpl(reqGLCaps);
- }
-
- @Test(timeout=30000)
- public void testSwitch2WindowSingleContextGLES2() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
- if(null == reqGLCaps) return;
- testSwitch2WindowSingleContextImpl(reqGLCaps);
- }
-
- private void testSwitch2WindowSingleContextImpl(GLCapabilities caps) throws InterruptedException {
- final QuitAdapter quitAdapter = new QuitAdapter();
-
- GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
- GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
-
- // create single context using glad1 and assign it to glad1,
- // destroy the prev. context afterwards.
- {
- final GLContext newCtx = glad1.createContext(null);
- Assert.assertNotNull(newCtx);
- final GLContext oldCtx = glad1.setContext(newCtx);
- Assert.assertNotNull(oldCtx);
- oldCtx.destroy();
- final int res = newCtx.makeCurrent();
- Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
- newCtx.release();
- }
-
- final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
- GearsES2 gears = new GearsES2(1);
- glad1.addGLEventListener(gears);
- glad1.addGLEventListener(snapshotGLEventListener);
- snapshotGLEventListener.setMakeSnapshot();
-
- Animator animator = new Animator();
- animator.add(glad1);
- animator.add(glad2);
- animator.start();
-
- int s = 0;
- long t0 = System.currentTimeMillis();
- long t1 = t0;
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
- if( ( t1 - t0 ) / period > s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
-
- // switch context _and_ the demo synchronously
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glad1, glad2);
-
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- glad1.destroy();
- glad2.destroy();
- }
-
- @Test(timeout=30000)
- public void testSwitch2GLWindowOneDemoGL2ES2() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
- if(null == reqGLCaps) return;
- testSwitch2GLWindowOneDemoImpl(reqGLCaps);
- }
-
- @Test(timeout=30000)
- public void testSwitch2GLWindowOneDemoGLES2() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
- if(null == reqGLCaps) return;
- testSwitch2GLWindowOneDemoImpl(reqGLCaps);
- }
-
- private void testSwitch2GLWindowOneDemoImpl(GLCapabilities caps) throws InterruptedException {
- final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
- final GearsES2 gears = new GearsES2(1);
- final QuitAdapter quitAdapter = new QuitAdapter();
-
- GLWindow glWindow1 = GLWindow.create(caps);
- glWindow1.setTitle("win1");
- glWindow1.setSize(width, height);
- glWindow1.setPosition(64, 64);
- glWindow1.addGLEventListener(0, gears);
- glWindow1.addGLEventListener(snapshotGLEventListener);
- glWindow1.addWindowListener(quitAdapter);
-
- GLWindow glWindow2 = GLWindow.create(caps);
- glWindow2.setTitle("win2");
- glWindow2.setSize(width+100, height+100);
- glWindow2.setPosition(2*64+width, 64);
- glWindow2.addWindowListener(quitAdapter);
-
- Animator animator = new Animator();
- animator.add(glWindow1);
- animator.add(glWindow2);
- animator.start();
-
- glWindow1.setVisible(true);
- glWindow2.setVisible(true);
-
- snapshotGLEventListener.setMakeSnapshot();
-
- int s = 0;
- long t0 = System.currentTimeMillis();
- long t1 = t0;
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
- if( ( t1 - t0 ) / period > s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
- System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
-
- // switch context _and_ the demo synchronously
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
-
- System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
-
- snapshotGLEventListener.setMakeSnapshot();
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- glWindow1.destroy();
- glWindow2.destroy();
-
- }
-
- @Test(timeout=30000)
- public void testSwitch2GLWindowEachWithOwnDemoGL2ES2() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
- if(null == reqGLCaps) return;
- testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps);
- }
-
- @Test(timeout=30000)
- public void testSwitch2GLWindowEachWithOwnDemoGLES2() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
- if(null == reqGLCaps) return;
- testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps);
- }
-
- public void testSwitch2GLWindowEachWithOwnDemoImpl(GLCapabilities caps) throws InterruptedException {
- final GearsES2 gears = new GearsES2(1);
- final RedSquareES2 rsquare = new RedSquareES2(1);
- final QuitAdapter quitAdapter = new QuitAdapter();
- final SnapshotGLEventListener snapshotGLEventListener1 = new SnapshotGLEventListener();
- final SnapshotGLEventListener snapshotGLEventListener2 = new SnapshotGLEventListener();
-
- GLWindow glWindow1 = GLWindow.create(caps);
- glWindow1.setTitle("win1");
- glWindow1.setSize(width, height);
- glWindow1.setPosition(64, 64);
- glWindow1.addGLEventListener(0, gears);
- glWindow1.addGLEventListener(snapshotGLEventListener1);
- glWindow1.addWindowListener(quitAdapter);
-
- GLWindow glWindow2 = GLWindow.create(caps);
- glWindow2.setTitle("win2");
- glWindow2.setSize(width+100, height+100);
- glWindow2.setPosition(2*64+width, 64);
- glWindow2.addGLEventListener(0, rsquare);
- glWindow2.addGLEventListener(snapshotGLEventListener2);
- glWindow2.addWindowListener(quitAdapter);
-
- Animator animator = new Animator();
- animator.add(glWindow1);
- animator.add(glWindow2);
- animator.start();
-
- glWindow1.setVisible(true);
- glWindow2.setVisible(true);
-
- snapshotGLEventListener1.setMakeSnapshot();
- snapshotGLEventListener2.setMakeSnapshot();
-
- int s = 0;
- long t0 = System.currentTimeMillis();
- long t1 = t0;
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
- if( ( t1 - t0 ) / period > s) {
- s++;
- System.err.println(s+" - switch - START "+ ( t1 - t0 ));
- System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
- System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
- System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
- System.err.println(s+" - switch - END "+ ( t1 - t0 ));
- snapshotGLEventListener1.setMakeSnapshot();
- snapshotGLEventListener2.setMakeSnapshot();
- }
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- animator.stop();
- // System.err.println("pre -del-w1: w1: "+glWindow1);
- // System.err.println("pre -del-w1: w2: "+glWindow2);
- glWindow1.destroy();
- // System.err.println("post-del-w1: w1: "+glWindow1);
- // System.err.println("post-del-w1: w2: "+glWindow2);
- glWindow2.destroy();
-
- }
-
- // default timing for 2 switches
- static long duration = 2200; // ms
- static long period = 1000; // ms
-
- public static void main(String args[]) throws IOException {
- for(int i=0; i
- * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
- *
- */
-public class TestGLContextDrawableSwitch11NEWT extends UITestCase {
- static int width, height;
-
- static GLCapabilities getCaps(String profile) {
- if( !GLProfile.isAvailable(profile) ) {
- System.err.println("Profile "+profile+" n/a");
- return null;
- }
- return new GLCapabilities(GLProfile.get(profile));
- }
-
- @BeforeClass
- public static void initClass() {
- width = 256;
- height = 256;
- }
-
- private GLAutoDrawable createGLAutoDrawableWithoutContext(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
- final Window window = NewtFactory.createWindow(caps);
- Assert.assertNotNull(window);
- window.setPosition(x, y);
- window.setSize(width, height);
- window.setVisible(true);
- Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
- Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
-
- final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
- final GLDrawable drawable = factory.createGLDrawable(window);
- Assert.assertNotNull(drawable);
-
- drawable.setRealized(true);
- Assert.assertTrue(drawable.isRealized());
-
- final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false, null) {
- @Override
- protected void destroyImplInLock() {
- super.destroyImplInLock();
- window.destroy(); // destroys the actual window
- }
- };
-
- window.setWindowDestroyNotifyAction( new Runnable() {
- public void run() {
- glad.windowDestroyNotifyOp();
- } } );
-
- // add basic window interaction
- window.addWindowListener(new WindowAdapter() {
- @Override
- public void windowRepaint(WindowUpdateEvent e) {
- glad.windowRepaintOp();
- }
- @Override
- public void windowResized(WindowEvent e) {
- glad.windowResizedOp(window.getWidth(), window.getHeight());
- }
- });
- window.addWindowListener(wl);
-
- return glad;
- }
-
- @Test(timeout=30000)
- public void test01GLADDelegateGL2ES2() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
- if(null == reqGLCaps) return;
- test01GLADDelegateImpl(reqGLCaps);
- }
-
- @Test(timeout=30000)
- public void test01GLADDelegateGLES2() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
- if(null == reqGLCaps) return;
- test01GLADDelegateImpl(reqGLCaps);
- }
-
- private void test01GLADDelegateImpl(GLCapabilities caps) throws InterruptedException {
- final QuitAdapter quitAdapter = new QuitAdapter();
-
- final GLEventListenerCounter glelCounter = new GLEventListenerCounter();
- final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
- final Animator animator = new Animator();
- animator.start();
-
- final long t0 = System.currentTimeMillis();
- final GLEventListenerState glls1;
-
- // - create glad1 w/o context
- // - create context using glad1 and assign it to glad1
- {
- final GLAutoDrawable glad1 = createGLAutoDrawableWithoutContext(caps, 64, 64, width, height, quitAdapter);
- final GLContext context1 = glad1.createContext(null);
- glad1.setContext(context1);
- animator.add(glad1);
-
- glad1.addGLEventListener(glelCounter);
- glad1.addGLEventListener(new GearsES2(1));
- glad1.addGLEventListener(snapshotGLEventListener);
- snapshotGLEventListener.setMakeSnapshot();
-
- long t1 = System.currentTimeMillis();
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/2 ) {
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- Assert.assertEquals(1, glelCounter.initCount);
- Assert.assertTrue(1 <= glelCounter.reshapeCount);
- Assert.assertTrue(1 <= glelCounter.displayCount);
- Assert.assertEquals(0, glelCounter.disposeCount);
- Assert.assertEquals(context1, glad1.getContext());
- Assert.assertEquals(3, glad1.getGLEventListenerCount());
- Assert.assertEquals(context1.getGLReadDrawable(), glad1.getDelegatedDrawable());
- Assert.assertEquals(context1.getGLDrawable(), glad1.getDelegatedDrawable());
-
- // - dis-associate context from glad1
- // - destroy glad1
- glls1 = GLEventListenerState.moveFrom(glad1);
-
- Assert.assertEquals(1, glelCounter.initCount);
- Assert.assertTrue(1 <= glelCounter.reshapeCount);
- Assert.assertTrue(1 <= glelCounter.displayCount);
- Assert.assertEquals(0, glelCounter.disposeCount);
- Assert.assertEquals(context1, glls1.context);
- Assert.assertNull(context1.getGLReadDrawable());
- Assert.assertNull(context1.getGLDrawable());
- Assert.assertEquals(3, glls1.listenerCount());
- Assert.assertEquals(true, glls1.isOwner());
- Assert.assertEquals(null, glad1.getContext());
- Assert.assertEquals(0, glad1.getGLEventListenerCount());
-
- glad1.destroy();
- Assert.assertEquals(1, glelCounter.initCount);
- Assert.assertTrue(1 <= glelCounter.reshapeCount);
- Assert.assertTrue(1 <= glelCounter.displayCount);
- Assert.assertEquals(0, glelCounter.disposeCount);
- }
-
- // - create glad2 w/ survived context
- {
- final GLAutoDrawable glad2 = createGLAutoDrawableWithoutContext(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
- snapshotGLEventListener.setMakeSnapshot();
-
- Assert.assertEquals(null, glad2.getContext());
- Assert.assertEquals(0, glad2.getGLEventListenerCount());
-
- glls1.moveTo(glad2);
-
- Assert.assertTrue(glad2.isRealized());
-
- Assert.assertEquals(1, glelCounter.initCount);
- Assert.assertTrue(1 <= glelCounter.reshapeCount);
- Assert.assertTrue(1 <= glelCounter.displayCount);
- Assert.assertEquals(0, glelCounter.disposeCount);
- Assert.assertEquals(glls1.context, glad2.getContext());
- Assert.assertEquals(3, glad2.getGLEventListenerCount());
- Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable());
- Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable());
- Assert.assertEquals(false, glls1.isOwner());
-
- long t1 = System.currentTimeMillis();
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/1 ) {
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- glad2.destroy();
- Assert.assertEquals(1, glelCounter.initCount);
- Assert.assertTrue(1 <= glelCounter.reshapeCount);
- Assert.assertTrue(1 <= glelCounter.displayCount);
- Assert.assertEquals(1, glelCounter.disposeCount);
- }
- animator.stop();
- }
-
- @Test(timeout=30000)
- public void test02GLWindowGL2ES2() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
- if(null == reqGLCaps) return;
- test02GLWindowImpl(reqGLCaps);
- }
-
- @Test(timeout=30000)
- public void test02GLWindowGLES2() throws InterruptedException {
- final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
- if(null == reqGLCaps) return;
- test02GLWindowImpl(reqGLCaps);
- }
-
- private void test02GLWindowImpl(GLCapabilities caps) throws InterruptedException {
- final QuitAdapter quitAdapter = new QuitAdapter();
-
- final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
- final GLEventListenerCounter glelTracker = new GLEventListenerCounter();
- final Animator animator = new Animator();
- animator.start();
-
- final long t0 = System.currentTimeMillis();
- final GLEventListenerState glls1;
-
- // - create glad1 w/o context
- // - create context using glad1 and assign it to glad1
- {
- final GLWindow glad1 = GLWindow.create(caps);
- glad1.setSize(width, height);
- glad1.setPosition(64, 64);
- glad1.addWindowListener(quitAdapter);
- animator.add(glad1);
-
- glad1.addGLEventListener(glelTracker);
- glad1.addGLEventListener(new GearsES2(1));
- glad1.addGLEventListener(snapshotGLEventListener);
- snapshotGLEventListener.setMakeSnapshot();
-
- glad1.setVisible(true);
-
- long t1 = System.currentTimeMillis();
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/2 ) {
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- // - dis-associate context from glad1
- // - destroy glad1
- Assert.assertEquals(1, glelTracker.initCount);
- Assert.assertTrue(1 <= glelTracker.reshapeCount);
- Assert.assertTrue(1 <= glelTracker.displayCount);
- Assert.assertEquals(0, glelTracker.disposeCount);
- Assert.assertEquals(3, glad1.getGLEventListenerCount());
- Assert.assertEquals(glad1.getContext().getGLReadDrawable(), glad1.getDelegatedDrawable());
- Assert.assertEquals(glad1.getContext().getGLDrawable(), glad1.getDelegatedDrawable());
-
- final GLContext context1 = glad1.getContext();
- glls1 = GLEventListenerState.moveFrom(glad1);
-
- Assert.assertEquals(1, glelTracker.initCount);
- Assert.assertTrue(1 <= glelTracker.reshapeCount);
- Assert.assertTrue(1 <= glelTracker.displayCount);
- Assert.assertEquals(0, glelTracker.disposeCount);
- Assert.assertEquals(context1, glls1.context);
- Assert.assertNull(context1.getGLReadDrawable());
- Assert.assertNull(context1.getGLDrawable());
- Assert.assertEquals(3, glls1.listenerCount());
- Assert.assertEquals(true, glls1.isOwner());
- Assert.assertEquals(null, glad1.getContext());
- Assert.assertEquals(0, glad1.getGLEventListenerCount());
-
- glad1.destroy();
- Assert.assertEquals(1, glelTracker.initCount);
- Assert.assertTrue(1 <= glelTracker.reshapeCount);
- Assert.assertTrue(1 <= glelTracker.displayCount);
- Assert.assertEquals(0, glelTracker.disposeCount);
- }
-
- // - create glad2 w/ survived context
- {
- final GLWindow glad2 = GLWindow.create(caps);
- glad2.setSize(width+100, height+100);
- glad2.setPosition(2*64+width, 64);
- glad2.addWindowListener(quitAdapter);
- snapshotGLEventListener.setMakeSnapshot();
- glad2.setVisible(true);
-
- Assert.assertNotNull(glad2.getContext());
- Assert.assertEquals(0, glad2.getGLEventListenerCount());
-
- glls1.moveTo(glad2);
-
- Assert.assertEquals(1, glelTracker.initCount);
- Assert.assertTrue(1 <= glelTracker.reshapeCount);
- Assert.assertTrue(1 <= glelTracker.displayCount);
- Assert.assertEquals(0, glelTracker.disposeCount);
- Assert.assertEquals(glls1.context, glad2.getContext());
- Assert.assertEquals(3, glad2.getGLEventListenerCount());
- Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable());
- Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable());
- Assert.assertEquals(false, glls1.isOwner());
-
- long t1 = System.currentTimeMillis();
-
- while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration/1 ) {
- Thread.sleep(100);
- t1 = System.currentTimeMillis();
- }
-
- glad2.destroy();
- Assert.assertEquals(1, glelTracker.initCount);
- Assert.assertTrue(1 <= glelTracker.reshapeCount);
- Assert.assertTrue(1 <= glelTracker.displayCount);
- Assert.assertEquals(1, glelTracker.disposeCount);
- }
- animator.stop();
- }
-
- // default timing for 2 switches
- static long duration = 2200; // ms
-
- public static void main(String args[]) throws IOException {
- for(int i=0; i
+ * Test utilizes {@link GLEventListenerState} for preserving the
+ * GLAutoDrawable state, i.e. GLContext, all GLEventListener
+ * and the GLAnimatorControl association.
+ *
+ *
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ *
+ */
+public abstract class GLContextDrawableSwitchBase extends UITestCase {
+ static protected enum GLADType { GLCanvasOnscreen, GLCanvasOffscreen, GLWindow, GLOffscreen };
+
+ // default period for 1 GLAD cycle
+ static long duration = 1000; // ms
+
+ static int width, height;
+
+ static GLCapabilities getCaps(String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ @BeforeClass
+ public static void initClass() {
+ width = 256;
+ height = 256;
+ }
+
+ static void setGLCanvasSize(final GLCanvas glc, final Dimension new_sz) {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ glc.setMinimumSize(new_sz);
+ glc.setPreferredSize(new_sz);
+ glc.setSize(new_sz);
+ } } );
+ } catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ static void setFrameVisible(final Frame frame) throws InterruptedException {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.pack();
+ frame.setVisible(true);
+ }});
+ } catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ static void destroyFrame(final Frame frame) throws InterruptedException {
+ try {
+ javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame.dispose();
+ }});
+ } catch( Throwable throwable ) {
+ throwable.printStackTrace();
+ Assume.assumeNoException( throwable );
+ }
+ }
+
+ private GLOffscreenAutoDrawable createGLOffscreenAutoDrawable(GLCapabilities caps, int width, int height) throws InterruptedException {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ return factory.createOffscreenAutoDrawable(null, caps, null, width, height, null);
+ }
+
+ protected static boolean validateOnOffscreenLayer(GLADType gladType1, GLADType gladType2) {
+ final boolean useOffscreenLayer = GLADType.GLCanvasOffscreen == gladType1 || GLADType.GLCanvasOffscreen == gladType2 ;
+ final boolean useOnscreenLayer = GLADType.GLCanvasOnscreen == gladType1 || GLADType.GLCanvasOnscreen == gladType2 ;
+ if( useOffscreenLayer ) {
+ if( !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("Platform doesn't support offscreen rendering.");
+ return false;
+ }
+ } else if( useOnscreenLayer ) {
+ if( JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("Platform requires offscreen rendering.");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ protected void testGLADOneLifecycle(GLCapabilities caps, GLADType gladType, int width, int height,
+ GLEventListenerCounter glelTracker, SnapshotGLEventListener snapshotGLEventListener,
+ GLEventListenerState glelsIn, GLEventListenerState glelsOut[], GLAnimatorControl animator)
+ throws InterruptedException {
+
+ final Frame frame;
+ final GLAutoDrawable glad;
+ if( GLADType.GLCanvasOnscreen == gladType ) {
+ if( jogamp.nativewindow.jawt.JAWTUtil.isOffscreenLayerRequired() ) {
+ throw new InternalError("Platform requires offscreen rendering, but onscreen requested: "+gladType);
+ }
+ frame = new Frame("AWT GLCanvas");
+
+ glad = new GLCanvas(caps);
+ setGLCanvasSize((GLCanvas)glad, new Dimension(width, height));
+ frame.add((GLCanvas)glad);
+ } else if( GLADType.GLCanvasOffscreen == gladType ) {
+ if( !jogamp.nativewindow.jawt.JAWTUtil.isOffscreenLayerSupported() ) {
+ throw new InternalError("Platform doesn't support offscreen rendering: "+gladType);
+ }
+ frame = new Frame("AWT GLCanvas");
+
+ glad = new GLCanvas(caps);
+ ((GLCanvas)glad).setShallUseOffscreenLayer(true);
+ setGLCanvasSize((GLCanvas)glad, new Dimension(width, height));
+ frame.add((GLCanvas)glad);
+ } else if( GLADType.GLWindow == gladType ) {
+ frame = null;
+
+ glad = GLWindow.create(caps);
+ ((GLWindow)glad).setTitle("Newt GLWindow");
+ ((GLWindow)glad).setSize(width, height);
+ } else if( GLADType.GLOffscreen == gladType ) {
+ frame = null;
+
+ glad = this.createGLOffscreenAutoDrawable(caps, width, height);
+ } else {
+ throw new InternalError("Unsupported: "+gladType);
+ }
+
+ if( null == glelsIn ) {
+ if( null != animator ) {
+ animator.add(glad);
+ }
+ glad.addGLEventListener(glelTracker);
+ glad.addGLEventListener(new GearsES2(1));
+ glad.addGLEventListener(snapshotGLEventListener);
+ }
+ snapshotGLEventListener.setMakeSnapshot();
+
+ if( GLADType.GLCanvasOnscreen == gladType || GLADType.GLCanvasOffscreen == gladType ) {
+ setFrameVisible(frame);
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
+ } else if( GLADType.GLWindow == gladType ) {
+ ((GLWindow)glad).setVisible(true);
+ }
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glad, true));
+ Assert.assertNotNull(glad.getContext());
+ Assert.assertTrue(glad.isRealized());
+
+ if( null != glelsIn ) {
+ Assert.assertEquals(0, glad.getGLEventListenerCount());
+ glelsIn.moveTo(glad);
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ Assert.assertEquals(3, glad.getGLEventListenerCount());
+
+ Assert.assertEquals(glelsIn.context, glad.getContext());
+ Assert.assertEquals(glelsIn.listenerCount(), glad.getGLEventListenerCount());
+ Assert.assertEquals(glelsIn.context.getGLReadDrawable(), glad.getDelegatedDrawable());
+ Assert.assertEquals(glelsIn.context.getGLDrawable(), glad.getDelegatedDrawable());
+ Assert.assertEquals(false, glelsIn.isOwner());
+ }
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( ( t1 - t0 ) < duration ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ Assert.assertEquals(0, glelTracker.disposeCount);
+
+ if( null != glelsOut ) {
+ final GLContext context1 = glad.getContext();
+ final GLEventListenerState _gllsOut = GLEventListenerState.moveFrom(glad);
+
+ Assert.assertEquals(context1, _gllsOut.context);
+ Assert.assertNull(context1.getGLReadDrawable());
+ Assert.assertNull(context1.getGLDrawable());
+ Assert.assertEquals(3, _gllsOut.listenerCount());
+ Assert.assertEquals(true, _gllsOut.isOwner());
+ Assert.assertEquals(null, glad.getContext());
+ Assert.assertEquals(0, glad.getGLEventListenerCount());
+
+ glelsOut[0] = _gllsOut;
+ }
+ if( GLADType.GLCanvasOnscreen == gladType || GLADType.GLCanvasOffscreen == gladType ) {
+ destroyFrame(frame);
+ Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, false));
+ } else if( GLADType.GLWindow == gladType ) {
+ glad.destroy();
+ } else if( GLADType.GLOffscreen == gladType ) {
+ glad.destroy();
+ }
+ Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glad, false));
+
+ Assert.assertEquals(1, glelTracker.initCount);
+ Assert.assertTrue(1 <= glelTracker.reshapeCount);
+ Assert.assertTrue(1 <= glelTracker.displayCount);
+ if( null != glelsOut ) {
+ Assert.assertEquals(0, glelTracker.disposeCount);
+ } else {
+ Assert.assertEquals(1, glelTracker.disposeCount);
+ }
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java
new file mode 100644
index 000000000..5f2b9fb53
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/glels/TestGLContextDrawableSwitch01NEWT.java
@@ -0,0 +1,374 @@
+/**
+ * Copyright 2010 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore.glels;
+
+import java.io.IOException;
+
+import com.jogamp.newt.NewtFactory;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.WindowAdapter;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.event.WindowListener;
+import com.jogamp.newt.event.WindowUpdateEvent;
+import com.jogamp.newt.opengl.GLWindow;
+
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLProfile;
+
+import com.jogamp.opengl.GLAutoDrawableDelegate;
+import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.GLDrawableUtil;
+
+import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
+import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2;
+import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
+import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test re-association (switching) of GLContext/GLDrawables,
+ * i.e. ctx1/draw1, ctx2/draw2 -> ctx1/draw2, ctx2/draw1.
+ */
+public class TestGLContextDrawableSwitch01NEWT extends UITestCase {
+ static int width, height;
+
+ static GLCapabilities getCaps(String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ @BeforeClass
+ public static void initClass() {
+ width = 256;
+ height = 256;
+ }
+
+ private GLAutoDrawable createGLAutoDrawable(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
+ final Window window = NewtFactory.createWindow(caps);
+ Assert.assertNotNull(window);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLDrawable drawable = factory.createGLDrawable(window);
+ Assert.assertNotNull(drawable);
+
+ drawable.setRealized(true);
+ Assert.assertTrue(drawable.isRealized());
+
+ final GLContext context = drawable.createContext(null);
+ Assert.assertNotNull(context);
+
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) {
+ @Override
+ protected void destroyImplInLock() {
+ super.destroyImplInLock();
+ window.destroy(); // destroys the actual window
+ }
+ };
+
+ window.setWindowDestroyNotifyAction( new Runnable() {
+ public void run() {
+ glad.windowDestroyNotifyOp();
+ } } );
+
+ // add basic window interaction
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowRepaint(WindowUpdateEvent e) {
+ glad.windowRepaintOp();
+ }
+ @Override
+ public void windowResized(WindowEvent e) {
+ glad.windowResizedOp(window.getWidth(), window.getHeight());
+ }
+ });
+ window.addWindowListener(wl);
+
+ return glad;
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2WindowSingleContextGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testSwitch2WindowSingleContextImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2WindowSingleContextGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testSwitch2WindowSingleContextImpl(reqGLCaps);
+ }
+
+ private void testSwitch2WindowSingleContextImpl(GLCapabilities caps) throws InterruptedException {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter);
+ GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
+
+ // create single context using glad1 and assign it to glad1,
+ // destroy the prev. context afterwards.
+ {
+ final GLContext newCtx = glad1.createContext(null);
+ Assert.assertNotNull(newCtx);
+ final GLContext oldCtx = glad1.setContext(newCtx, true);
+ Assert.assertNotNull(oldCtx);
+ Assert.assertFalse(oldCtx.isCreated());
+ final int res = newCtx.makeCurrent();
+ Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res);
+ newCtx.release();
+ }
+
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ GearsES2 gears = new GearsES2(1);
+ glad1.addGLEventListener(gears);
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Animator animator = new Animator();
+ animator.add(glad1);
+ animator.add(glad2);
+ animator.start();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+
+ // switch context _and_ the demo synchronously
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glad1, glad2);
+
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ glad1.destroy();
+ glad2.destroy();
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowOneDemoGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowOneDemoImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowOneDemoGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowOneDemoImpl(reqGLCaps);
+ }
+
+ private void testSwitch2GLWindowOneDemoImpl(GLCapabilities caps) throws InterruptedException {
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GearsES2 gears = new GearsES2(1);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+
+ GLWindow glWindow1 = GLWindow.create(caps);
+ glWindow1.setTitle("win1");
+ glWindow1.setSize(width, height);
+ glWindow1.setPosition(64, 64);
+ glWindow1.addGLEventListener(0, gears);
+ glWindow1.addGLEventListener(snapshotGLEventListener);
+ glWindow1.addWindowListener(quitAdapter);
+
+ GLWindow glWindow2 = GLWindow.create(caps);
+ glWindow2.setTitle("win2");
+ glWindow2.setSize(width+100, height+100);
+ glWindow2.setPosition(2*64+width, 64);
+ glWindow2.addWindowListener(quitAdapter);
+
+ Animator animator = new Animator();
+ animator.add(glWindow1);
+ animator.add(glWindow2);
+ animator.start();
+
+ glWindow1.setVisible(true);
+ glWindow2.setVisible(true);
+
+ snapshotGLEventListener.setMakeSnapshot();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+ System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+
+ // switch context _and_ the demo synchronously
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
+
+ System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+
+ snapshotGLEventListener.setMakeSnapshot();
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ glWindow1.destroy();
+ glWindow2.destroy();
+
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowEachWithOwnDemoGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void testSwitch2GLWindowEachWithOwnDemoGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testSwitch2GLWindowEachWithOwnDemoImpl(reqGLCaps);
+ }
+
+ public void testSwitch2GLWindowEachWithOwnDemoImpl(GLCapabilities caps) throws InterruptedException {
+ final GearsES2 gears = new GearsES2(1);
+ final RedSquareES2 rsquare = new RedSquareES2(1);
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ final SnapshotGLEventListener snapshotGLEventListener1 = new SnapshotGLEventListener();
+ final SnapshotGLEventListener snapshotGLEventListener2 = new SnapshotGLEventListener();
+
+ GLWindow glWindow1 = GLWindow.create(caps);
+ glWindow1.setTitle("win1");
+ glWindow1.setSize(width, height);
+ glWindow1.setPosition(64, 64);
+ glWindow1.addGLEventListener(0, gears);
+ glWindow1.addGLEventListener(snapshotGLEventListener1);
+ glWindow1.addWindowListener(quitAdapter);
+
+ GLWindow glWindow2 = GLWindow.create(caps);
+ glWindow2.setTitle("win2");
+ glWindow2.setSize(width+100, height+100);
+ glWindow2.setPosition(2*64+width, 64);
+ glWindow2.addGLEventListener(0, rsquare);
+ glWindow2.addGLEventListener(snapshotGLEventListener2);
+ glWindow2.addWindowListener(quitAdapter);
+
+ Animator animator = new Animator();
+ animator.add(glWindow1);
+ animator.add(glWindow2);
+ animator.start();
+
+ glWindow1.setVisible(true);
+ glWindow2.setVisible(true);
+
+ snapshotGLEventListener1.setMakeSnapshot();
+ snapshotGLEventListener2.setMakeSnapshot();
+
+ int s = 0;
+ long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ if( ( t1 - t0 ) / period > s) {
+ s++;
+ System.err.println(s+" - switch - START "+ ( t1 - t0 ));
+ System.err.println(s+" - A w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - A w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ GLDrawableUtil.swapGLContextAndAllGLEventListener(glWindow1, glWindow2);
+ System.err.println(s+" - B w1-h 0x"+Long.toHexString(glWindow1.getHandle())+",-ctx 0x"+Long.toHexString(glWindow1.getContext().getHandle()));
+ System.err.println(s+" - B w2-h 0x"+Long.toHexString(glWindow2.getHandle())+",-ctx 0x"+Long.toHexString(glWindow2.getContext().getHandle()));
+ System.err.println(s+" - switch - END "+ ( t1 - t0 ));
+ snapshotGLEventListener1.setMakeSnapshot();
+ snapshotGLEventListener2.setMakeSnapshot();
+ }
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ animator.stop();
+ // System.err.println("pre -del-w1: w1: "+glWindow1);
+ // System.err.println("pre -del-w1: w2: "+glWindow2);
+ glWindow1.destroy();
+ // System.err.println("post-del-w1: w1: "+glWindow1);
+ // System.err.println("post-del-w1: w2: "+glWindow2);
+ glWindow2.destroy();
+
+ }
+
+ // default timing for 2 switches
+ static long duration = 2200; // ms
+ static long period = 1000; // ms
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i
+ * Test utilizes {@link GLEventListenerState} for preserving the
+ * GLAutoDrawable state, i.e. GLContext, all GLEventListener
+ * and the GLAnimatorControl association.
+ *
+ *
+ * This test is using NEWT's plain Window w/ GLAutoDrawableDelegate.
+ *
+ *
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ *
+ */
+public class TestGLContextDrawableSwitch10NEWT extends UITestCase {
+ // default period for 1 GLAD cycle
+ static long duration = 1000; // ms
+
+ static int width, height;
+
+ static GLCapabilities getCaps(String profile) {
+ if( !GLProfile.isAvailable(profile) ) {
+ System.err.println("Profile "+profile+" n/a");
+ return null;
+ }
+ return new GLCapabilities(GLProfile.get(profile));
+ }
+
+ @BeforeClass
+ public static void initClass() {
+ width = 256;
+ height = 256;
+ }
+
+ private GLAutoDrawable createGLAutoDrawableWithoutContext(GLCapabilities caps, int x, int y, int width, int height, WindowListener wl) throws InterruptedException {
+ final Window window = NewtFactory.createWindow(caps);
+ Assert.assertNotNull(window);
+ window.setPosition(x, y);
+ window.setSize(width, height);
+ window.setVisible(true);
+ Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true));
+ Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true));
+
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
+ final GLDrawable drawable = factory.createGLDrawable(window);
+ Assert.assertNotNull(drawable);
+
+ drawable.setRealized(true);
+ Assert.assertTrue(drawable.isRealized());
+
+ final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false, null) {
+ @Override
+ protected void destroyImplInLock() {
+ super.destroyImplInLock();
+ window.destroy(); // destroys the actual window
+ }
+ };
+
+ window.setWindowDestroyNotifyAction( new Runnable() {
+ public void run() {
+ glad.windowDestroyNotifyOp();
+ } } );
+
+ // add basic window interaction
+ window.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowRepaint(WindowUpdateEvent e) {
+ glad.windowRepaintOp();
+ }
+ @Override
+ public void windowResized(WindowEvent e) {
+ glad.windowResizedOp(window.getWidth(), window.getHeight());
+ }
+ });
+ window.addWindowListener(wl);
+
+ return glad;
+ }
+
+ @Test(timeout=30000)
+ public void test01GLADDelegateGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLADDelegateImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void test02GLADDelegateGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLADDelegateImpl(reqGLCaps);
+ }
+
+ private void testGLADDelegateImpl(GLCapabilities caps) throws InterruptedException {
+ final GLEventListenerCounter glelCounter = new GLEventListenerCounter();
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final GLEventListenerState glls1;
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ final GLAutoDrawable glad1 = createGLAutoDrawableWithoutContext(caps, 64, 64, width, height, quitAdapter);
+ final GLContext context1 = glad1.createContext(null);
+ glad1.setContext(context1, true);
+ animator.add(glad1);
+
+ glad1.addGLEventListener(glelCounter);
+ glad1.addGLEventListener(new GearsES2(1));
+ glad1.addGLEventListener(snapshotGLEventListener);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(context1, glad1.getContext());
+ Assert.assertEquals(3, glad1.getGLEventListenerCount());
+ Assert.assertEquals(context1.getGLReadDrawable(), glad1.getDelegatedDrawable());
+ Assert.assertEquals(context1.getGLDrawable(), glad1.getDelegatedDrawable());
+
+ // - dis-associate context from glad1
+ // - destroy glad1
+ glls1 = GLEventListenerState.moveFrom(glad1);
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(context1, glls1.context);
+ Assert.assertNull(context1.getGLReadDrawable());
+ Assert.assertNull(context1.getGLDrawable());
+ Assert.assertEquals(3, glls1.listenerCount());
+ Assert.assertEquals(true, glls1.isOwner());
+ Assert.assertEquals(null, glad1.getContext());
+ Assert.assertEquals(0, glad1.getGLEventListenerCount());
+
+ glad1.destroy();
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ final QuitAdapter quitAdapter = new QuitAdapter();
+ final GLAutoDrawable glad2 = createGLAutoDrawableWithoutContext(caps, 2*64+width, 64, width+100, height+100, quitAdapter);
+ snapshotGLEventListener.setMakeSnapshot();
+
+ Assert.assertEquals(null, glad2.getContext());
+ Assert.assertEquals(0, glad2.getGLEventListenerCount());
+
+ glls1.moveTo(glad2);
+
+ Assert.assertTrue(glad2.isRealized());
+
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(0, glelCounter.disposeCount);
+ Assert.assertEquals(glls1.context, glad2.getContext());
+ Assert.assertEquals(3, glad2.getGLEventListenerCount());
+ Assert.assertEquals(glls1.context.getGLReadDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(glls1.context.getGLDrawable(), glad2.getDelegatedDrawable());
+ Assert.assertEquals(false, glls1.isOwner());
+
+ final long t0 = System.currentTimeMillis();
+ long t1 = t0;
+
+ while( !quitAdapter.shouldQuit() && ( t1 - t0 ) < duration ) {
+ Thread.sleep(100);
+ t1 = System.currentTimeMillis();
+ }
+
+ glad2.destroy();
+ Assert.assertEquals(1, glelCounter.initCount);
+ Assert.assertTrue(1 <= glelCounter.reshapeCount);
+ Assert.assertTrue(1 <= glelCounter.displayCount);
+ Assert.assertEquals(1, glelCounter.disposeCount);
+ }
+ animator.stop();
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i
+ * Test utilizes {@link GLEventListenerState} for preserving the
+ * GLAutoDrawable state, i.e. GLContext, all GLEventListener
+ * and the GLAnimatorControl association.
+ *
+ *
+ * This test is using JOGL's NEWT GLWindow.
+ *
+ *
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ *
+ */
+public class TestGLContextDrawableSwitch11NewtAWT extends GLContextDrawableSwitchBase {
+
+ @Test(timeout=30000)
+ public void test21GLWindowGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLWindowImpl(reqGLCaps);
+ }
+
+ @Test(timeout=30000)
+ public void test22GLWindowGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLWindowImpl(reqGLCaps);
+ }
+
+ private void testGLWindowImpl(GLCapabilities caps) throws InterruptedException {
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GLEventListenerCounter glelTracker = new GLEventListenerCounter();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final GLEventListenerState glels[] = new GLEventListenerState[1];
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ testGLADOneLifecycle(caps, GLADType.GLWindow, width, height,
+ glelTracker, snapshotGLEventListener,
+ null,
+ glels, animator);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ testGLADOneLifecycle(caps, GLADType.GLWindow, width+100, height+100,
+ glelTracker, snapshotGLEventListener,
+ glels[0],
+ null, null);
+ }
+ animator.stop();
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i
+ * Test utilizes {@link GLEventListenerState} for preserving the
+ * GLAutoDrawable state, i.e. GLContext, all GLEventListener
+ * and the GLAnimatorControl association.
+ *
+ *
+ * This test is using JOGL's AWT GLCanvas
+ *
+ *
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ *
+ */
+public class TestGLContextDrawableSwitch12AWT extends GLContextDrawableSwitchBase {
+
+ @Test(timeout=30000)
+ public void test01GLCanvasOnscreenGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLCanvasImpl(reqGLCaps, false);
+ }
+
+ @Test(timeout=30000)
+ public void test02GLCanvasOnscreenGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLCanvasImpl(reqGLCaps, false);
+ }
+
+ @Test(timeout=30000)
+ public void test11GLCanvasOffscreenGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLCanvasImpl(reqGLCaps, true);
+ }
+
+ @Test(timeout=30000)
+ public void test12GLCanvasOffscreenGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLCanvasImpl(reqGLCaps, true);
+ }
+
+ private void testGLCanvasImpl(GLCapabilities caps, boolean offscreenLayer) throws InterruptedException {
+ if( offscreenLayer ) {
+ if( !JAWTUtil.isOffscreenLayerSupported() ) {
+ System.err.println("Platform doesn't support offscreen rendering.");
+ return;
+ }
+ } else {
+ if( JAWTUtil.isOffscreenLayerRequired() ) {
+ System.err.println("Platform requires offscreen rendering.");
+ return;
+ }
+ }
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GLEventListenerCounter glelTracker = new GLEventListenerCounter();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final GLEventListenerState glels[] = new GLEventListenerState[1];
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ testGLADOneLifecycle(caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width, height,
+ glelTracker, snapshotGLEventListener,
+ null,
+ glels, animator);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ testGLADOneLifecycle(caps, offscreenLayer ? GLADType.GLCanvasOffscreen : GLADType.GLCanvasOnscreen, width+100, height+100,
+ glelTracker, snapshotGLEventListener,
+ glels[0],
+ null, null);
+ }
+ animator.stop();
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i
+ * Test utilizes {@link GLEventListenerState} for preserving the
+ * GLAutoDrawable state, i.e. GLContext, all GLEventListener
+ * and the GLAnimatorControl association.
+ *
+ *
+ * This test moves the {@link GLEventListenerState} from a
+ * NEWT GLWindow before it's destruction to an AWT GLCanvas after it's creation
+ * and vice versa
+ *
+ *
+ * See Bug 665 - https://jogamp.org/bugzilla/show_bug.cgi?id=665.
+ *
+ */
+public class TestGLContextDrawableSwitch21Newt2AWT extends GLContextDrawableSwitchBase {
+
+ @Test(timeout=30000)
+ public void test01GLCanvasOnScrn2GLWindowGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow);
+ }
+
+ @Test(timeout=30000)
+ public void test02GLCanvasOnScrn2GLWindowGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOnscreen, GLADType.GLWindow);
+ }
+
+ @Test(timeout=30000)
+ public void test11GLWindow2GLCanvasOnScrnGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen);
+ }
+
+ @Test(timeout=30000)
+ public void test12GLWindow2GLCanvasOnScrnGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOnscreen);
+ }
+
+ @Test(timeout=30000)
+ public void test21GLCanvasOffScrn2GLWindowGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow);
+ }
+
+ @Test(timeout=30000)
+ public void test22GLCanvasOffScrn2GLWindowGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLCanvasOffscreen, GLADType.GLWindow);
+ }
+
+ @Test(timeout=30000)
+ public void test31GLWindow2GLCanvasOffScrnGL2ES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2ES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen);
+ }
+
+ @Test(timeout=30000)
+ public void test32GLWindow2GLCanvasOffScrnGLES2() throws InterruptedException {
+ final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
+ if(null == reqGLCaps) return;
+ testGLCanvas2GLWindowImpl(reqGLCaps, GLADType.GLWindow, GLADType.GLCanvasOffscreen);
+ }
+
+ private void testGLCanvas2GLWindowImpl(GLCapabilities caps, GLADType gladType1, GLADType gladType2) throws InterruptedException {
+ if( !validateOnOffscreenLayer(gladType1, gladType2) ) {
+ return;
+ }
+ final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener();
+ final GLEventListenerCounter glelTracker = new GLEventListenerCounter();
+ final Animator animator = new Animator();
+ animator.start();
+
+ final GLEventListenerState glels[] = new GLEventListenerState[1];
+
+ // - create glad1 w/o context
+ // - create context using glad1 and assign it to glad1
+ {
+ testGLADOneLifecycle(caps, gladType1, width, height,
+ glelTracker, snapshotGLEventListener,
+ null,
+ glels, animator);
+ }
+
+ // - create glad2 w/ survived context
+ {
+ testGLADOneLifecycle(caps, gladType2, width+100, height+100,
+ glelTracker, snapshotGLEventListener,
+ glels[0],
+ null, null);
+ }
+ animator.stop();
+ }
+
+ public static void main(String args[]) throws IOException {
+ for(int i=0; i pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets());
}
- while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()
Date: Tue, 19 Mar 2013 00:22:28 +0100
Subject: OSX/CALayer: OSX/CALayer Threading Part3 - Run CALayer ops in a
streaming design on main-thread w/o [infinitive] blocking
History:
Part1 commit 896e8b021b39e9415040a57a1d540d7d24b02db1 (Run CALayer Ops on current thread to avoid blocking)
Part2 commit 28c6472335b924080d638b33a28f8f4eedb459b1 (Run CALayer Ops on main-thread w/o blocking)
Dependency:
GlueGen commit 4becdfa125b07ff969d6540e1112735b53cd15eb (Fix RecursiveLockImpl* Timeout corner case)
Part2 misses essential locking of the OpenGL context (and it's surface upfront) while creating the
NSOpenGLLayer instance. The latter instantiates a OpenGL context shared w/ JOGL's, hence it cannot be locked.
Encapsulating NSOpenGLLayer creation/attachment and it's detachment/release in sub-classes
AttachNSOpenGLLayer and DetachNSOpenGLLayer, where instances will be streamed on main-thread.
Both tasks are triggered at associateDrawable(boolean bound).
The mentioned GL context locking requires disturbs the 'streaming' design considerably in AttachNSOpenGLLayer.
It is solved by attempt to acquire the recursive lock of the surface and the context via 'tryLock(maxwait)'
w/ screen-vSync-period/2. If the locks could not be acquired completly, the AttachNSOpenGLLayer instance
will be re-queued to the main-thread for later execution.
Before DetachNSOpenGLLayer is being streamed, it is validated whether AttachNSOpenGLLayer did run.
A recursive situation does happen w/ resizing an offscreen pbuffer drawable! Hence extra care is being taken.
---
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 2 +-
.../classes/jogamp/opengl/GLDrawableHelper.java | 2 +-
.../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 358 +++++++++++++--------
.../com/jogamp/nativewindow/awt/JAWTWindow.java | 73 ++---
.../media/nativewindow/OffscreenLayerSurface.java | 5 +
.../nativewindow/jawt/macosx/MacOSXJAWTWindow.java | 58 ++--
.../jawt/windows/WindowsJAWTWindow.java | 7 -
.../nativewindow/jawt/x11/X11JAWTWindow.java | 7 -
.../jogamp/nativewindow/macosx/OSXUtil.java | 64 +++-
.../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 9 +-
.../acore/TestAddRemove01GLCanvasSwingAWT.java | 52 ++-
.../TestAddRemove02GLWindowNewtCanvasAWT.java | 47 ++-
...TestSwingAWTRobotUsageBeforeJOGLInitBug411.java | 10 +-
.../junit/newt/parenting/TestParenting04AWT.java | 4 +
14 files changed, 439 insertions(+), 259 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 4121e8f77..64ade3eff 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -367,7 +367,7 @@ public abstract class GLContextImpl extends GLContext {
try {
// release current context
if(lock.getHoldCount() == 1) {
- // needs current context to disable debug handler
+ // needs current context to call associateDrawable(..) and to disable debug handler
makeCurrent();
}
try {
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
index 1caa942ba..9c1cd478b 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java
@@ -190,7 +190,7 @@ public class GLDrawableHelper {
* make context current, if it was current
*
*
- * No locking is being performed, caller is required to take care of it.
+ * Locking is performed via {@link GLContext#makeCurrent()} on the passed context
.
*
*
* @param drawable
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index f01e03a2f..33893e456 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -71,6 +71,7 @@ import com.jogamp.common.nio.Buffers;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
import com.jogamp.opengl.GLExtensions;
@@ -461,10 +462,13 @@ public abstract class MacOSXCGLContext extends GLContextImpl
// NSOpenGLContext-based implementation
class NSOpenGLImpl implements GLBackendImpl {
- private long pixelFormat = 0; // lifecycle: [create - destroy]
- private volatile long nsOpenGLLayer = 0; // lifecycle: [associateDrawable_true - associateDrawable_false]
- private float screenVSyncTimeout = 16666; // microSec - defaults to 1/60s
- private volatile int vsyncTimeout = 16666 + 1000; // microSec - for nsOpenGLLayer mode - defaults to 1/60s + 1ms
+ private OffscreenLayerSurface backingLayerHost = null;
+ /** lifecycle: [create - destroy] */
+ private long pixelFormat = 0;
+ /** microSec - defaults to 1/60s */
+ private int screenVSyncTimeout = 16666;
+ /** microSec - for nsOpenGLLayer mode - defaults to 1/60s + 1ms */
+ private volatile int vsyncTimeout = 16666 + 1000;
private int lastWidth=0, lastHeight=0; // allowing to detect size change
private boolean needsSetContextPBuffer = false;
private ShaderProgram gl3ShaderProgram = null;
@@ -562,7 +566,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
final int sRefreshRate = OSXUtil.GetScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex());
if( 0 < sRefreshRate ) {
- screenVSyncTimeout = 1000000f / sRefreshRate;
+ screenVSyncTimeout = 1000000 / sRefreshRate;
}
if(DEBUG) {
System.err.println("NS create OSX>=lion "+isLionOrLater);
@@ -608,32 +612,147 @@ public abstract class MacOSXCGLContext extends GLContextImpl
return CGL.deleteContext(ctx, true);
}
+ /**
+ * NSOpenGLLayer creation and it's attachment is performed on the main-thread w/o [infinite] blocking.
+ *
+ * Since NSOpenGLLayer creation requires this context for it's shared context creation,
+ * this method attempts to acquire the surface and context lock with {@link #screenVSyncTimeout}/2 maximum wait time.
+ * If the surface and context lock could not be acquired, this runnable is being re-queued for later execution.
+ *
+ *
+ * Hence this method blocks the main-thread only for a short period of time.
+ *
+ */
+ class AttachNSOpenGLLayer implements Runnable {
+ final OffscreenLayerSurface ols;
+ final long ctx;
+ final int shaderProgram;
+ final long pfmt;
+ final long pbuffer;
+ final int texID;
+ final boolean isOpaque;
+ final int width;
+ final int height;
+ /** Synchronized by instance's monitor */
+ long nsOpenGLLayer;
+ /** Synchronized by instance's monitor */
+ boolean valid;
+
+ AttachNSOpenGLLayer(OffscreenLayerSurface ols, long ctx, int shaderProgram, long pfmt, long pbuffer, int texID, boolean isOpaque, int width, int height) {
+ this.ols = ols;
+ this.ctx = ctx;
+ this.shaderProgram = shaderProgram;
+ this.pfmt = pfmt;
+ this.pbuffer = pbuffer;
+ this.texID = texID;
+ this.isOpaque = isOpaque;
+ this.width = width;
+ this.height = height;
+ this.valid = false;
+ this.nsOpenGLLayer = 0;
+ }
+
+ @Override
+ public void run() {
+ synchronized(this) {
+ if( !valid ) {
+ try {
+ final int maxwait = screenVSyncTimeout/2000; // TO 1/2 of current screen-vsync in [ms]
+ final RecursiveLock surfaceLock = ols.getLock();
+ if( surfaceLock.tryLock( maxwait ) ) {
+ try {
+ if( MacOSXCGLContext.this.lock.tryLock( maxwait ) ) {
+ try {
+ nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, shaderProgram, pfmt, pbuffer, texID, isOpaque, width, height);
+ ols.attachSurfaceLayer(nsOpenGLLayer);
+ final int currentInterval = MacOSXCGLContext.this.getSwapInterval();
+ final int interval = 0 <= currentInterval ? currentInterval : 1;
+ setSwapIntervalImpl(nsOpenGLLayer, interval); // enabled per default in layered surface
+ valid = true;
+ if (DEBUG) {
+ System.err.println("NSOpenGLLayer.Attach: OK, layer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(pbuffer)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", drawableHandle "+toHexString(drawable.getHandle())+" - "+Thread.currentThread().getName());
+ }
+ } finally {
+ MacOSXCGLContext.this.lock.unlock();
+ }
+ }
+ } finally {
+ surfaceLock.unlock();
+ }
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if( !valid ) {
+ // could not acquire lock, re-queue
+ if (DEBUG) {
+ System.err.println("NSOpenGLLayer.Attach: Re-Queue, drawableHandle "+toHexString(drawable.getHandle())+" - "+Thread.currentThread().getName());
+ }
+ OSXUtil.RunLater(this, 1);
+ }
+ }
+ }
+ }
+ }
+ AttachNSOpenGLLayer attachCALayerCmd = null;
+
+ class DetachNSOpenGLLayer implements Runnable {
+ final AttachNSOpenGLLayer cmd;
+
+ DetachNSOpenGLLayer(AttachNSOpenGLLayer cmd) {
+ this.cmd = cmd;
+ }
+ @Override
+ public void run() {
+ synchronized( cmd ) {
+ if( cmd.valid ) {
+ // still having a valid OLS attached to surface (parent OLS could have been removed)
+ try {
+ final OffscreenLayerSurface ols = cmd.ols;
+ final long l = ols.getAttachedSurfaceLayer();
+ if( 0 != l ) {
+ ols.detachSurfaceLayer();
+ }
+ } catch(Throwable t) {
+ System.err.println("Catched exception @ "+Thread.currentThread().getName()+": ");
+ t.printStackTrace();
+ }
+ CGL.releaseNSOpenGLLayer(cmd.nsOpenGLLayer);
+ if(DEBUG) {
+ System.err.println("NSOpenGLLayer.Detach: OK, layer "+toHexString(cmd.nsOpenGLLayer)+", drawableHandle "+toHexString(drawable.getHandle())+" - "+Thread.currentThread().getName());
+ }
+ cmd.nsOpenGLLayer = 0;
+ cmd.valid = false;
+ } else if(DEBUG) {
+ System.err.println("NSOpenGLLayer.Detach: Skipped "+toHexString(cmd.nsOpenGLLayer)+", drawableHandle "+toHexString(drawable.getHandle())+" - "+Thread.currentThread().getName());
+ }
+ }
+ }
+ }
+
@Override
public void associateDrawable(boolean bound) {
- final OffscreenLayerSurface backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(drawable.getNativeSurface(), true);
+ backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(drawable.getNativeSurface(), true);
if(DEBUG) {
System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable: "+bound+", ctx "+toHexString(contextHandle)+", hasBackingLayerHost "+(null!=backingLayerHost));
+ // Thread.dumpStack();
}
if( bound ) {
- if( null != backingLayerHost ) {
- if( 0 != nsOpenGLLayer ) { // FIXME: redundant
- throw new InternalError("Lifecycle: bound=true, hasBackingLayerHost=true, but 'nsOpenGLLayer' is already/still set local: "+nsOpenGLLayer+", "+this);
- }
- nsOpenGLLayer = backingLayerHost.getAttachedSurfaceLayer();
- if( 0 != nsOpenGLLayer ) { // FIXME: redundant
- throw new InternalError("Lifecycle: bound=true, hasBackingLayerHost=true, but 'nsOpenGLLayer' is already/still set on backingLayerHost: "+nsOpenGLLayer+", "+this);
- }
+ if( null != backingLayerHost ) {
+ final GLCapabilitiesImmutable chosenCaps;
+ final long ctx;
+ final int texID;
+ final long pbufferHandle;
+ final int gl3ShaderProgramName;
//
// handled layered surface
//
- final GLCapabilitiesImmutable chosenCaps = drawable.getChosenGLCapabilities();
- final long ctx = MacOSXCGLContext.this.getHandle();
- final int texID;
+ chosenCaps = drawable.getChosenGLCapabilities();
+ ctx = MacOSXCGLContext.this.getHandle();
final long drawableHandle = drawable.getHandle();
- final long pbufferHandle;
if(drawable instanceof GLFBODrawableImpl) {
final GLFBODrawableImpl fbod = (GLFBODrawableImpl)drawable;
texID = fbod.getTextureBuffer(GL.GL_FRONT).getName();
@@ -657,7 +776,6 @@ 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);
}
- final int gl3ShaderProgramName;
if( MacOSXCGLContext.this.isGL3core() ) {
if( null == gl3ShaderProgram) {
gl3ShaderProgram = createCALayerShader(MacOSXCGLContext.this.gl.getGL3());
@@ -665,88 +783,42 @@ public abstract class MacOSXCGLContext extends GLContextImpl
gl3ShaderProgramName = gl3ShaderProgram.program();
} else {
gl3ShaderProgramName = 0;
- }
+ }
- /**
- * NSOpenGLLayer creation and it's attachment is performed on the main w/o blocking,
- * due to OSX main-thread requirements.
- * Note: It somewhat works from another thread, however,
- * GC-dealloc of the 'released' resources would happen very late!
- *
- * NSOpenGLLayer initialization creates it's own GL ctx sharing
- * this ctx, hence we have to lock this ctx in the main-thread.
- *
- * Locking of this ctx while creation and attachment
- * also gives us good means of synchronization, i.e. it will be
- * performed after this thread ends it's associateDrawable() [makeCurrent(), setDrawable(..)]
- * and before the next display cycle involving makeCurrent().
- */
- OSXUtil.RunOnMainThread(false, new Runnable() {
- public void run() {
- if (DEBUG) {
- System.err.println("NS create nsOpenGLLayer.0 "+Thread.currentThread().getName());
- }
- final long cglCtx = CGL.getCGLContext(ctx);
- if(0 == cglCtx) {
- throw new GLException("Null CGLContext for: "+MacOSXCGLContext.this);
- }
- if( CGL.kCGLNoError != CGL.CGLLockContext(cglCtx) ) {
- throw new GLException("Could not lock CGLContext for: "+MacOSXCGLContext.this);
- }
- try {
- nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, gl3ShaderProgramName, pixelFormat, pbufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight);
- if (DEBUG) {
- System.err.println("NS create nsOpenGLLayer.2 "+Thread.currentThread().getName()+": "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(pbufferHandle)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", "+drawable);
- }
- backingLayerHost.attachSurfaceLayer(nsOpenGLLayer);
- setSwapInterval(1); // enabled per default in layered surface
- } catch (Throwable t) {
- throw new GLException("createNSOpenGLLayer failed for: "+MacOSXCGLContext.this, t);
- } finally {
- if(CGL.kCGLNoError != CGL.CGLUnlockContext(cglCtx)) {
- throw new GLException("Could not unlock CGLContext for: "+MacOSXCGLContext.this);
- }
- }
- if (DEBUG) {
- System.err.println("NS create nsOpenGLLayer.X "+Thread.currentThread().getName());
- }
- }
- });
- CGL.setContextView(contextHandle, 0); // [ctx clearDrawable]
+ // All CALayer lifecycle ops are deferred on main-thread
+ attachCALayerCmd = new AttachNSOpenGLLayer(
+ backingLayerHost, ctx, gl3ShaderProgramName, pixelFormat, pbufferHandle, texID,
+ chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight );
+ OSXUtil.RunOnMainThread(false, attachCALayerCmd);
} else { // -> null == backingLayerHost
lastWidth = drawable.getWidth();
lastHeight = drawable.getHeight();
boolean[] isPBuffer = { false };
boolean[] isFBO = { false };
- CGL.setContextView(contextHandle, getNSViewHandle(isPBuffer, isFBO)); // will call [ctx clearDrawable] if view == 0, otherwise [ctx setView: view] if valid
+ CGL.setContextView(contextHandle, getNSViewHandle(isPBuffer, isFBO));
}
} else { // -> !bound
- if( 0 != nsOpenGLLayer ) {
- if( null == backingLayerHost ) { // FIXME: redundant
- throw new InternalError("Lifecycle: bound=false, hasNSOpneGLLayer=true, but 'backingLayerHost' is null local: "+nsOpenGLLayer+", "+this);
+ if( null != backingLayerHost ) {
+ final AttachNSOpenGLLayer cmd = attachCALayerCmd;
+ attachCALayerCmd = null;
+ if( 0 != cmd.pbuffer ) {
+ CGL.setContextPBuffer(contextHandle, 0);
}
-
- if (DEBUG) {
- System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", "+drawable);
- }
- if( backingLayerHost.isSurfaceLayerAttached() ) {
- // still having a valid OLS attached to surface (parent OLS could have been removed)
- backingLayerHost.detachSurfaceLayer();
- }
- // All CALayer lifecycle calls are deferred on main-thread, so is this.
- final long _nsOpenGLLayer = nsOpenGLLayer;
- nsOpenGLLayer = 0;
- OSXUtil.RunOnMainThread(false, new Runnable() {
- public void run() {
- CGL.releaseNSOpenGLLayer(_nsOpenGLLayer);
- }
- });
- if( null != gl3ShaderProgram ) {
- gl3ShaderProgram.destroy(MacOSXCGLContext.this.gl.getGL3());
- gl3ShaderProgram = null;
+ synchronized(cmd) {
+ if( !cmd.valid ) {
+ cmd.valid = true; // skip pending creation
+ } else {
+ // All CALayer lifecycle ops are deferred on main-thread
+ OSXUtil.RunOnMainThread(false, new DetachNSOpenGLLayer(cmd));
+ if( null != gl3ShaderProgram ) {
+ gl3ShaderProgram.destroy(MacOSXCGLContext.this.gl.getGL3());
+ gl3ShaderProgram = null;
+ }
+ }
}
}
- CGL.setContextView(contextHandle, 0); // [ctx clearDrawable]
+ CGL.clearDrawable(contextHandle);
+ backingLayerHost = null;
}
}
@@ -832,65 +904,83 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean setSwapInterval(int interval) {
- if(0 != nsOpenGLLayer) {
- CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval);
+ final AttachNSOpenGLLayer cmd = attachCALayerCmd;
+ if(null != cmd) {
+ synchronized(cmd) {
+ if( cmd.valid && 0 != cmd.nsOpenGLLayer) {
+ setSwapIntervalImpl(cmd.nsOpenGLLayer, interval);
+ return true;
+ }
+ }
+ }
+ setSwapIntervalImpl(0, interval);
+ return true;
+ }
+
+ private void setSwapIntervalImpl(final long l, int interval) {
+ if( 0 != l ) {
+ CGL.setNSOpenGLLayerSwapInterval(l, interval);
if( 0 < interval ) {
- vsyncTimeout = interval * (int)screenVSyncTimeout + 1000; // +1ms
+ vsyncTimeout = interval * screenVSyncTimeout + 1000; // +1ms
}
if(DEBUG) { System.err.println("NS setSwapInterval: "+interval+" -> "+vsyncTimeout+" micros"); }
}
+ if(DEBUG) { System.err.println("CGL setSwapInterval: "+interval); }
CGL.setSwapInterval(contextHandle, interval);
- return true;
}
-
+
private int skipSync=0;
@Override
public boolean swapBuffers() {
- final boolean res;
- if( 0 != nsOpenGLLayer ) {
- if( validateDrawableSizeConfig(contextHandle) ) {
- // skip wait-for-vsync for a few frames if size has changed,
- // allowing to update the texture IDs ASAP.
- skipSync = 10;
- }
-
- final int texID;
- final boolean valid;
- final boolean isFBO = drawable instanceof GLFBODrawableImpl;
- if( isFBO ){
- texID = ((GLFBODrawableImpl)drawable).getTextureBuffer(GL.GL_FRONT).getName();
- valid = 0 != texID;
- } else {
- texID = 0;
- valid = 0 != drawable.getHandle();
- }
- if(valid) {
- if(0 == skipSync) {
- // If v-sync is disabled, frames will be drawn as quickly as possible w/o delay,
- // while still synchronizing w/ CALayer.
- // If v-sync is enabled wait until next swap interval (v-sync).
- CGL.waitUntilNSOpenGLLayerIsReady(nsOpenGLLayer, vsyncTimeout);
- } else {
- skipSync--;
- }
- res = CGL.flushBuffer(contextHandle);
- if(res) {
- if(isFBO) {
- // trigger CALayer to update incl. possible surface change (texture)
- CGL.setNSOpenGLLayerNeedsDisplayFBO(nsOpenGLLayer, texID);
+ final AttachNSOpenGLLayer cmd = attachCALayerCmd;
+ if(null != cmd) {
+ synchronized(cmd) {
+ if( cmd.valid && 0 != cmd.nsOpenGLLayer) {
+ if( validateDrawableSizeConfig(contextHandle) ) {
+ // skip wait-for-vsync for a few frames if size has changed,
+ // allowing to update the texture IDs ASAP.
+ skipSync = 10;
+ }
+
+ final boolean res;
+ final int texID;
+ final boolean valid;
+ final boolean isFBO = drawable instanceof GLFBODrawableImpl;
+ if( isFBO ){
+ texID = ((GLFBODrawableImpl)drawable).getTextureBuffer(GL.GL_FRONT).getName();
+ valid = 0 != texID;
+ } else {
+ texID = 0;
+ valid = 0 != drawable.getHandle();
+ }
+ if(valid) {
+ res = CGL.flushBuffer(contextHandle);
+ if(res) {
+ if(0 == skipSync) {
+ // If v-sync is disabled, frames will be drawn as quickly as possible w/o delay,
+ // while still synchronizing w/ CALayer.
+ // If v-sync is enabled wait until next swap interval (v-sync).
+ CGL.waitUntilNSOpenGLLayerIsReady(cmd.nsOpenGLLayer, vsyncTimeout);
+ } else {
+ skipSync--;
+ }
+ if(isFBO) {
+ // trigger CALayer to update incl. possible surface change (texture)
+ CGL.setNSOpenGLLayerNeedsDisplayFBO(cmd.nsOpenGLLayer, texID);
+ } else {
+ // trigger CALayer to update incl. possible surface change (new pbuffer handle)
+ CGL.setNSOpenGLLayerNeedsDisplayPBuffer(cmd.nsOpenGLLayer, drawable.getHandle());
+ }
+ }
} else {
- // trigger CALayer to update incl. possible surface change (new pbuffer handle)
- CGL.setNSOpenGLLayerNeedsDisplayPBuffer(nsOpenGLLayer, drawable.getHandle());
+ res = true;
}
+ return res;
}
- } else {
- res = true;
}
- } else {
- res = CGL.flushBuffer(contextHandle);
}
- return res;
+ return CGL.flushBuffer(contextHandle);
}
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
index 15a0f550f..16d4a07ef 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -85,7 +85,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
protected long drawable;
protected Rectangle bounds;
protected Insets insets;
- private long offscreenSurfaceLayer;
+ private volatile long offscreenSurfaceLayer;
private long drawable_old;
@@ -135,12 +135,12 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
protected synchronized void invalidate() {
if(DEBUG) {
- System.err.println("JAWTWindow.invalidate()");
+ System.err.println("JAWTWindow.invalidate() - "+Thread.currentThread().getName());
+ if( isSurfaceLayerAttached() ) {
+ System.err.println("OffscreenSurfaceLayer still attached: 0x"+Long.toHexString(offscreenSurfaceLayer));
+ }
// Thread.dumpStack();
}
- if( isSurfaceLayerAttached() ) {
- detachSurfaceLayer();
- }
invalidateNative();
jawt = null;
isOffscreenLayerSurface = false;
@@ -227,21 +227,16 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
if( !isOffscreenLayerSurfaceEnabled() ) {
throw new NativeWindowException("Not an offscreen layer surface");
}
- int lockRes = lockSurface();
- if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
- throw new NativeWindowException("Could not lock (offscreen layer): "+this);
- }
- try {
- if(DEBUG) {
- System.err.println("JAWTWindow.attachSurfaceHandle: "+toHexString(layerHandle) + ", bounds "+bounds);
- }
- attachSurfaceLayerImpl(layerHandle);
- offscreenSurfaceLayer = layerHandle;
- } finally {
- unlockSurface();
+ if(DEBUG) {
+ System.err.println("JAWTWindow.attachSurfaceHandle: "+toHexString(layerHandle) + ", bounds "+bounds);
}
+ attachSurfaceLayerImpl(layerHandle);
+ offscreenSurfaceLayer = layerHandle;
+ layoutSurfaceLayerImpl(layerHandle, getWidth(), getHeight());
+ }
+ protected void attachSurfaceLayerImpl(final long layerHandle) {
+ throw new UnsupportedOperationException("offscreen layer not supported");
}
- protected abstract void attachSurfaceLayerImpl(final long layerHandle);
/**
* Layout the offscreen layer according to the implementing class's constraints.
@@ -256,38 +251,39 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
* @see #isOffscreenLayerSurfaceEnabled()
* @throws NativeWindowException if {@link #isOffscreenLayerSurfaceEnabled()} == false
*/
- protected void layoutSurfaceLayerImpl() {}
+ protected void layoutSurfaceLayerImpl(long layerHandle, int width, int height) {}
private final void layoutSurfaceLayerIfEnabled() throws NativeWindowException {
if( isOffscreenLayerSurfaceEnabled() && 0 != offscreenSurfaceLayer ) {
- layoutSurfaceLayerImpl();
+ layoutSurfaceLayerImpl(offscreenSurfaceLayer, getWidth(), getHeight());
}
}
@Override
public final void detachSurfaceLayer() throws NativeWindowException {
- if( !isOffscreenLayerSurfaceEnabled() ) {
- throw new java.lang.UnsupportedOperationException("Not an offscreen layer surface");
- }
if( 0 == offscreenSurfaceLayer) {
throw new NativeWindowException("No offscreen layer attached: "+this);
}
- int lockRes = lockSurface();
- if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
- throw new NativeWindowException("Could not lock (offscreen layer): "+this);
- }
- try {
- if(DEBUG) {
- System.err.println("JAWTWindow.detachSurfaceHandle(): osh "+toHexString(offscreenSurfaceLayer));
- }
- detachSurfaceLayerImpl(offscreenSurfaceLayer);
- offscreenSurfaceLayer = 0;
- } finally {
- unlockSurface();
+ if(DEBUG) {
+ System.err.println("JAWTWindow.detachSurfaceHandle(): osh "+toHexString(offscreenSurfaceLayer));
}
+ detachSurfaceLayerImpl(offscreenSurfaceLayer, detachSurfaceLayerNotify);
}
- protected abstract void detachSurfaceLayerImpl(final long layerHandle);
+ private final Runnable detachSurfaceLayerNotify = new Runnable() {
+ @Override
+ public void run() {
+ offscreenSurfaceLayer = 0;
+ }
+ };
+
+ /**
+ * @param detachNotify Runnable to be called before native detachment
+ */
+ protected void detachSurfaceLayerImpl(final long layerHandle, final Runnable detachNotify) {
+ throw new UnsupportedOperationException("offscreen layer not supported");
+ }
+
@Override
public final long getAttachedSurfaceLayer() {
@@ -305,6 +301,11 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
getPrivateGraphicsConfiguration().setChosenCapabilities(caps);
}
+ @Override
+ public final RecursiveLock getLock() {
+ return surfaceLock;
+ }
+
//
// SurfaceUpdateListener
//
diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
index 8c02a68bb..1826008ad 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
@@ -27,6 +27,8 @@
*/
package javax.media.nativewindow;
+import com.jogamp.common.util.locks.RecursiveLock;
+
/**
* Interface specifying the offscreen layer surface protocol.
*/
@@ -60,4 +62,7 @@ public interface OffscreenLayerSurface {
/** Sets the capabilities of this instance, allowing upstream API's to refine it, i.e. OpenGL related settings. */
public void setChosenCapabilities(CapabilitiesImmutable caps);
+ /** Returns the recursive lock object of this surface, which synchronizes multithreaded access. */
+ public RecursiveLock getLock();
+
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
index d11d24664..9f76392a9 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java
@@ -69,16 +69,18 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
}
}
+ @Override
protected void invalidateNative() {
if(DEBUG) {
System.err.println("MacOSXJAWTWindow.invalidateNative(): osh-enabled "+isOffscreenLayerSurfaceEnabled()+
- ", osh-set "+offscreenSurfaceHandleSet+
- ", osh "+toHexString(offscreenSurfaceHandle)+
- ", rsh "+toHexString(rootSurfaceLayer)+
+ ", osd-set "+offscreenSurfaceDrawableSet+
+ ", osd "+toHexString(offscreenSurfaceDrawable)+
+ ", osl "+toHexString(getAttachedSurfaceLayer())+
+ ", rsl "+toHexString(rootSurfaceLayer)+
", wh "+toHexString(windowHandle)+" - "+Thread.currentThread().getName());
}
- offscreenSurfaceHandle=0;
- offscreenSurfaceHandleSet=false;
+ offscreenSurfaceDrawable=0;
+ offscreenSurfaceDrawableSet=false;
if( isOffscreenLayerSurfaceEnabled() ) {
if(0 != windowHandle) {
OSXUtil.DestroyNSWindow(windowHandle);
@@ -108,29 +110,41 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
jawt.FreeDrawingSurface(ds);
}
}
- OSXUtil.DestroyCALayer(rootSurfaceLayer);
- rootSurfaceLayer = 0;
+
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ public void run() {
+ OSXUtil.DestroyCALayer(rootSurfaceLayer, false);
+ rootSurfaceLayer = 0;
+ }
+ });
}
}
windowHandle=0;
}
+ @Override
protected void attachSurfaceLayerImpl(final long layerHandle) {
OSXUtil.AddCASublayer(rootSurfaceLayer, layerHandle, getWidth(), getHeight());
}
- protected void layoutSurfaceLayerImpl() {
- final long osl = getAttachedSurfaceLayer();
- final int w = getWidth();
- final int h = getHeight();
+ @Override
+ protected void layoutSurfaceLayerImpl(long layerHandle, int width, int height) {
if(DEBUG) {
- System.err.println("JAWTWindow.fixSurfaceLayerLayout: "+toHexString(osl) + ", bounds "+bounds+", "+w+"x"+h);
+ System.err.println("JAWTWindow.layoutSurfaceLayerImpl: "+toHexString(layerHandle) + ", "+width+"x"+height+"; "+this);
}
- OSXUtil.FixCALayerLayout(rootSurfaceLayer, osl, w, h);
+ OSXUtil.FixCALayerLayout(rootSurfaceLayer, layerHandle, width, height);
}
- protected void detachSurfaceLayerImpl(final long layerHandle) {
- OSXUtil.RemoveCASublayer(rootSurfaceLayer, layerHandle);
+ @Override
+ protected void detachSurfaceLayerImpl(final long layerHandle, final Runnable detachNotify) {
+ OSXUtil.RunOnMainThread(false, new Runnable() {
+ public void run() {
+ final long l = MacOSXJAWTWindow.this.getAttachedSurfaceLayer();
+ if( 0 != l ) {
+ detachNotify.run();
+ OSXUtil.RemoveCASublayer(rootSurfaceLayer, layerHandle, false);
+ }
+ } } );
}
@Override
@@ -140,7 +154,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
@Override
public final long getSurfaceHandle() {
- return offscreenSurfaceHandleSet ? offscreenSurfaceHandle : drawable /* super.getSurfaceHandle() */ ;
+ return offscreenSurfaceDrawableSet ? offscreenSurfaceDrawable : drawable /* super.getSurfaceHandle() */ ;
}
public void setSurfaceHandle(long surfaceHandle) {
@@ -150,8 +164,8 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
if(DEBUG) {
System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): "+toHexString(surfaceHandle));
}
- this.offscreenSurfaceHandle = surfaceHandle;
- this.offscreenSurfaceHandleSet = true;
+ this.offscreenSurfaceDrawable = surfaceHandle;
+ this.offscreenSurfaceDrawableSet = true;
}
protected JAWT fetchJAWTImpl() throws NativeWindowException {
@@ -257,7 +271,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
}
if(null != errMsg) {
if(0 != rootSurfaceLayer) {
- OSXUtil.DestroyCALayer(rootSurfaceLayer);
+ OSXUtil.DestroyCALayer(rootSurfaceLayer, true);
rootSurfaceLayer = 0;
}
if(0 != windowHandle) {
@@ -329,11 +343,11 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface {
private JAWT_MacOSXDrawingSurfaceInfo macosxdsi;
- private long rootSurfaceLayer = 0; // attached to the JAWT_SurfaceLayer
+ private volatile long rootSurfaceLayer = 0; // attached to the JAWT_SurfaceLayer
private long windowHandle = 0;
- private long offscreenSurfaceHandle = 0;
- private boolean offscreenSurfaceHandleSet = false;
+ private long offscreenSurfaceDrawable = 0;
+ private boolean offscreenSurfaceDrawableSet = false;
// Workaround for instance of 4796548
private boolean firstLock = true;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
index 5d1d43792..905a313d5 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/windows/WindowsJAWTWindow.java
@@ -64,13 +64,6 @@ public class WindowsJAWTWindow extends JAWTWindow {
windowHandle = 0;
}
- protected void attachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
- protected void detachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
-
protected JAWT fetchJAWTImpl() throws NativeWindowException {
return JAWTUtil.getJAWT(false); // no offscreen
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
index 467809284..2e5dc7fb5 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/x11/X11JAWTWindow.java
@@ -59,13 +59,6 @@ public class X11JAWTWindow extends JAWTWindow {
protected void invalidateNative() { }
- protected void attachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
- protected void detachSurfaceLayerImpl(final long layerHandle) {
- throw new UnsupportedOperationException("offscreen layer not supported");
- }
-
protected JAWT fetchJAWTImpl() throws NativeWindowException {
return JAWTUtil.getJAWT(false); // no offscreen
}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
index 703c3d972..4b102be00 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java
@@ -138,11 +138,15 @@ public class OSXUtil implements ToolkitProperties {
/**
* Create a CALayer suitable to act as a root CALayer.
- * @see #DestroyCALayer(long)
+ * @see #DestroyCALayer(long, boolean)
* @see #AddCASublayer(long, long)
*/
public static long CreateCALayer(final int x, final int y, final int width, final int height) {
- return CreateCALayer0(x, y, width, height);
+ final long l = CreateCALayer0(x, y, width, height);
+ if(DEBUG) {
+ System.err.println("OSXUtil.CreateCALayer: 0x"+Long.toHexString(l)+" - "+Thread.currentThread().getName());
+ }
+ return l;
}
/**
@@ -156,7 +160,7 @@ public class OSXUtil implements ToolkitProperties {
* they will be used for creation.
*
* @see #CreateCALayer(int, int, int, int)
- * @see #RemoveCASublayer(long, long)
+ * @see #RemoveCASublayer(long, long, boolean)
*/
public static void AddCASublayer(final long rootCALayer, final long subCALayer, final int width, final int height) {
if(0==rootCALayer || 0==subCALayer) {
@@ -164,6 +168,9 @@ public class OSXUtil implements ToolkitProperties {
}
RunOnMainThread(false, new Runnable() {
public void run() {
+ if(DEBUG) {
+ System.err.println("OSXUtil.AttachCALayer: 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
+ }
AddCASublayer0(rootCALayer, subCALayer, width, height);
}
});
@@ -193,32 +200,48 @@ public class OSXUtil implements ToolkitProperties {
}
/**
- * Detach a sub CALayer from the root CALayer on the main-thread w/o blocking.
+ * Detach a sub CALayer from the root CALayer.
+ * @param onMainThread if true
method will be performed on the main-thread w/o blocking.
*/
- public static void RemoveCASublayer(final long rootCALayer, final long subCALayer) {
+ public static void RemoveCASublayer(final long rootCALayer, final long subCALayer, boolean onMainThread) {
if(0==rootCALayer || 0==subCALayer) {
throw new IllegalArgumentException("rootCALayer 0x"+Long.toHexString(rootCALayer)+", subCALayer 0x"+Long.toHexString(subCALayer));
}
- RunOnMainThread(false, new Runnable() {
+ final Runnable action = new Runnable() {
public void run() {
+ if(DEBUG) {
+ System.err.println("OSXUtil.DetachCALayer: 0x"+Long.toHexString(subCALayer)+" - "+Thread.currentThread().getName());
+ }
RemoveCASublayer0(rootCALayer, subCALayer);
- }
- });
+ } };
+ if( onMainThread ) {
+ RunOnMainThread(false, action);
+ } else {
+ action.run();
+ }
}
/**
- * Destroy a CALayer on main-thread w/o blocking.
+ * Destroy a CALayer.
+ * @param onMainThread if true
method will be performed on the main-thread w/o blocking.
* @see #CreateCALayer(int, int, int, int)
*/
- public static void DestroyCALayer(final long caLayer) {
+ public static void DestroyCALayer(final long caLayer, boolean onMainThread) {
if(0==caLayer) {
throw new IllegalArgumentException("caLayer 0x"+Long.toHexString(caLayer));
}
- RunOnMainThread(false, new Runnable() {
+ final Runnable action = new Runnable() {
public void run() {
+ if(DEBUG) {
+ System.err.println("OSXUtil.DestroyCALayer: 0x"+Long.toHexString(caLayer)+" - "+Thread.currentThread().getName());
+ }
DestroyCALayer0(caLayer);
- }
- });
+ } };
+ if( onMainThread ) {
+ RunOnMainThread(false, action);
+ } else {
+ action.run();
+ }
}
/**
@@ -238,7 +261,7 @@ public class OSXUtil implements ToolkitProperties {
// otherwise we may freeze the OSX main thread.
Throwable throwable = null;
final Object sync = new Object();
- final RunnableTask rt = new RunnableTask( runnable, waitUntilDone ? sync : null, true );
+ final RunnableTask rt = new RunnableTask( runnable, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err );
synchronized(sync) {
RunOnMainThread0(rt);
if( waitUntilDone ) {
@@ -258,6 +281,16 @@ public class OSXUtil implements ToolkitProperties {
}
}
+ /**
+ * Run later on current OSX thread.
+ *
+ * @param runnable
+ * @param delay delay to run the runnable in milliseconds
+ */
+ public static void RunLater(Runnable runnable, int delay) {
+ RunLater0(new RunnableTask( runnable, null, true, System.err ), delay);
+ }
+
private static Runnable _nop = new Runnable() { public void run() {}; };
/** Issues a {@link #RunOnMainThread(boolean, Runnable)} w/ an NOP runnable, while waiting until done. */
@@ -282,7 +315,7 @@ public class OSXUtil implements ToolkitProperties {
// otherwise we may freeze the OSX main thread.
Throwable throwable = null;
final Object sync = new Object();
- final FunctionTask rt = new FunctionTask( func, waitUntilDone ? sync : null, true );
+ final FunctionTask rt = new FunctionTask( func, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err );
synchronized(sync) {
rt.setArgs(args);
RunOnMainThread0(rt);
@@ -349,6 +382,7 @@ public class OSXUtil implements ToolkitProperties {
private static native void RemoveCASublayer0(long rootCALayer, long subCALayer);
private static native void DestroyCALayer0(long caLayer);
private static native void RunOnMainThread0(Runnable runnable);
+ private static native void RunLater0(Runnable runnable, int delay);
private static native boolean IsMainThread0();
private static native int GetScreenRefreshRate0(int scrn_idx);
}
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index d902b0f09..a3c2a5dc8 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -43,9 +43,7 @@ import java.security.PrivilegedAction;
import java.util.Set;
import javax.media.nativewindow.NativeWindow;
-import javax.media.nativewindow.NativeWindowFactory;
import javax.media.nativewindow.OffscreenLayerOption;
-import javax.media.nativewindow.OffscreenLayerSurface;
import javax.media.nativewindow.WindowClosingProtocol;
import javax.swing.MenuSelectionManager;
@@ -615,12 +613,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
configureNewtChild(false);
newtChild.setVisible(false);
- // Detach OLS early..
- final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(newtChild, true);
- if(null != ols && ols.isSurfaceLayerAttached()) {
- ols.detachSurfaceLayer();
- }
- newtChild.reparentWindow(null); // will destroy context (offscreen -> onscreen) and implicit detachSurfaceLayer (if still attached)
+ newtChild.reparentWindow(null); // will destroy context (offscreen -> onscreen) and implicit detachSurfaceLayer
if(DEBUG) {
System.err.println("NewtCanvasAWT.detachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java
index 48c3c89b3..c2eebbfd8 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestAddRemove01GLCanvasSwingAWT.java
@@ -55,13 +55,14 @@ import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
public class TestAddRemove01GLCanvasSwingAWT extends UITestCase {
- static long durationPerTest = 50;
+ static long durationPerTest = 100;
static int addRemoveCount = 15;
static int pauseEach = 0;
static int pauseDuration = 500;
static boolean noOnscreenTest = false;
static boolean noOffscreenTest = false;
- static boolean shallUseOffscreenPBufferLayer = false;
+ static boolean offscreenPBufferOnly = false;
+ static boolean offscreenFBOOnly = false;
static GLProfile glp;
static int width, height;
static boolean waitForKey = false;
@@ -143,6 +144,9 @@ public class TestAddRemove01GLCanvasSwingAWT extends UITestCase {
throws AWTException, InterruptedException, InvocationTargetException
{
+ if(waitForKey) {
+ UITestCase.waitForKey("Start");
+ }
for(int i=0; i w1. free g1 of w1
canvas2.setNEWTChild(glWindow1); // put g1 -> w2
+ frame1.invalidate();
+ frame2.invalidate();
frame1.validate();
frame2.validate();
}
@@ -176,6 +178,8 @@ public class TestParenting04AWT extends UITestCase {
}
canvas1.setNEWTChild(glWindow1);
canvas2.setNEWTChild(glWindow2);
+ frame1.invalidate();
+ frame2.invalidate();
frame1.validate();
frame2.validate();
}
--
cgit v1.2.3
From 7978096bdaac4c4bd14187382bb1f8ab9d082ebe Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Wed, 10 Apr 2013 03:22:19 +0200
Subject: GLDrawable: Refine API doc; GLDrawableImpl: Balance
createHandle()/destroyHandle(); Handle LOCK_SURFACE_CHANGED in lockSurface()
; GLContextImpl.makeCurrent(): Fix drawable handle validation.
GLDrawable: Refine API doc (realized/handle)
- Lifecycle of the drawable handle was not clear
- Ephasizing handle's dependency on NativeSurface's lock state and drawable's realization
GLDrawableImpl: Balance createHandle()/destroyHandle()
- updateHandle() -> createHandle()
- ensure both are balance, see below
GLDrawableImpl: Handle LOCK_SURFACE_CHANGED in GLDrawableImpl's lockSurface()
- call destroyHandle() and createHandle()
GLContextImpl.makeCurrent(): Validate drawable handle if realized only.
- it is valid to have an invalid drawable handle if not realized (see above)
---
.../classes/javax/media/opengl/GLDrawable.java | 70 +++++++++++++--------
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 12 ++--
src/jogl/classes/jogamp/opengl/GLDrawableImpl.java | 72 +++++++++++++++++-----
.../classes/jogamp/opengl/egl/EGLDrawable.java | 4 +-
.../opengl/x11/glx/X11OnscreenGLXDrawable.java | 4 +-
5 files changed, 107 insertions(+), 55 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawable.java b/src/jogl/classes/javax/media/opengl/GLDrawable.java
index 95c314a48..65c8b2ea5 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawable.java
@@ -65,29 +65,31 @@ public interface GLDrawable {
public GLContext createContext(GLContext shareWith);
/**
- * Indicates to on-screen GLDrawable implementations whether the
- * underlying window has been created and can be drawn into. End
- * users do not need to call this method; it is not necessary to
- * call setRealized
on a GLCanvas, a GLJPanel, or a
- * GLPbuffer, as these perform the appropriate calls on their
- * underlying GLDrawables internally.
- *
- *
- *
+ * Indicates to GLDrawable implementations whether the
+ * underlying {@link NativeSurface surface} has been created and can be drawn into.
+ *
+ * If realized, the {@link #getHandle() drawable handle} may become
+ * valid while it's {@link NativeSurface surface} is being {@link NativeSurface#lockSurface() locked}.
+ *
+ *
+ * End users do not need to call this method; it is not necessary to
+ * call setRealized
on a {@link GLAutoDrawable}
+ * as these perform the appropriate calls on their underlying GLDrawables internally.
+ *
+ *
* Developers implementing new OpenGL components for various window
* toolkits need to call this method against GLDrawables obtained
- * from the GLDrawableFactory via the {@link
- * GLDrawableFactory#getGLDrawable
- * GLDrawableFactory.getGLDrawable()} method. It must typically be
+ * from the GLDrawableFactory via the
+ * {@link GLDrawableFactory#createGLDrawable(NativeSurface)} method.
+ * It must typically be
* called with an argument of true
when the component
* associated with the GLDrawable is realized and with an argument
* of false
just before the component is unrealized.
* For the AWT, this means calling setRealized(true)
in
* the addNotify
method and with an argument of
* false
in the removeNotify
method.
- *
- *
- *
+ *
+ *
* GLDrawable
implementations should handle multiple
* cycles of setRealized(true)
/
* setRealized(false)
calls. Most, if not all, Java
@@ -101,12 +103,11 @@ public interface GLDrawable {
* GLDrawable
to re-initialize and destroy any
* associated resources as the component becomes realized and
* unrealized, respectively.
- *
- *
- *
+ *
+ *
* With an argument of true
,
* the minimum implementation shall call
- * {@link NativeSurface#lockSurface() NativeSurface's lockSurface()} and if successfull:
+ * {@link NativeSurface#lockSurface() NativeSurface's lockSurface()} and if successful:
*
* - Update the {@link GLCapabilities}, which are associated with
* the attached {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.
@@ -115,14 +116,17 @@ public interface GLDrawable {
* This is important since {@link NativeSurface#lockSurface() NativeSurface's lockSurface()}
* ensures resolving the window/surface handles, and the drawable's {@link GLCapabilities}
* might have changed.
- *
- *
- *
+ *
+ *
* Calling this method has no other effects. For example, if
* removeNotify
is called on a Canvas implementation
* for which a GLDrawable has been created, it is also necessary to
* destroy all OpenGL contexts associated with that GLDrawable. This
* is not done automatically by the implementation.
+ *
+ * @see #isRealized()
+ * @see #getHandle()
+ * @see NativeSurface#lockSurface()
*/
public void setRealized(boolean realized);
@@ -131,6 +135,7 @@ public interface GLDrawable {
*
* A drawable can be realized and unrealized via {@link #setRealized(boolean)}.
*
+ * @see #setRealized(boolean)
*/
public boolean isRealized();
@@ -172,11 +177,22 @@ public interface GLDrawable {
public NativeSurface getNativeSurface();
/**
- * This is the GL/Windowing drawable handle.
- * It is usually the {@link javax.media.nativewindow.NativeSurface#getSurfaceHandle()},
- * ie the native surface handle of the underlying windowing toolkit.
- * However, on X11/GLX this reflects a GLXDrawable, which represents a GLXWindow, GLXPixmap, or GLXPbuffer.
- * On EGL, this represents the EGLSurface.
+ * Returns the GL drawable handle,
+ * guaranteed to be valid after {@link #setRealized(boolean) realization}
+ * and while it's {@link NativeSurface surface} is being {@link NativeSurface#lockSurface() locked}.
+ *
+ * It is usually identical to the underlying windowing toolkit {@link NativeSurface surface}'s
+ * {@link javax.media.nativewindow.NativeSurface#getSurfaceHandle() handle}
+ * or an intermediate layer to suite GL, e.g. an EGL surface.
+ *
+ *
+ * On EGL it is represented by the EGLSurface.
+ * On X11/GLX it is represented by either the Window XID, GLXPixmap, or GLXPbuffer.
+ * On Windows it is represented by the HDC, which may change with each {@link #lockSurface()}.
+ *
+ * @see #setRealized(boolean)
+ * @see NativeSurface#lockSurface()
+ * @see NativeSurface#unlockSurface()
*/
public long getHandle();
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 64ade3eff..90f5a9907 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -258,7 +258,7 @@ public abstract class GLContextImpl extends GLContext {
if(DEBUG) {
String sgl1 = (null!=this.gl)?this.gl.getClass().getSimpleName()+", "+this.gl.toString():"";
String sgl2 = (null!=gl)?gl.getClass().getSimpleName()+", "+gl.toString():"";
- Exception e = new Exception("Info: setGL (OpenGL "+getGLVersion()+"): "+Thread.currentThread().getName()+", "+sgl1+" -> "+sgl2);
+ Exception e = new Exception("Info: setGL (OpenGL "+getGLVersion()+"): "+getThreadName()+", "+sgl1+" -> "+sgl2);
e.printStackTrace();
}
this.gl = gl;
@@ -495,14 +495,10 @@ public abstract class GLContextImpl extends GLContext {
boolean unlockContextAndSurface = true; // Must be cleared if successful, otherwise finally block will release context and surface!
int res = CONTEXT_NOT_CURRENT;
try {
- if (0 == drawable.getHandle()) {
- throw new GLException("drawable has invalid handle: "+drawable);
- }
- if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) {
- drawable.updateHandle();
- }
-
if ( drawable.isRealized() ) {
+ if ( 0 == drawable.getHandle() ) {
+ throw new GLException("drawable has invalid handle: "+drawable);
+ }
lock.lock();
try {
// One context can only be current by one thread,
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index d0c1461a9..a2b99c7da 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -79,14 +79,11 @@ public abstract class GLDrawableImpl implements GLDrawable {
if( !realized ) { // volatile OK (locked below)
return; // destroyed already
}
- int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release]
+ final int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release]
if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) {
return;
}
try {
- if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) {
- updateHandle();
- }
if( realized ) { // volatile OK
final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities();
if ( caps.getDoubleBuffered() ) {
@@ -145,11 +142,21 @@ public abstract class GLDrawableImpl implements GLDrawable {
return surface;
}
- /** called with locked surface @ setRealized(false) */
+ /**
+ * called with locked surface @ setRealized(false) or @ lockSurface(..) when surface changed
+ *
+ * Must be paired w/ {@link #createHandle()}.
+ *
+ */
protected void destroyHandle() {}
- /** called with locked surface @ setRealized(true) or @ lockSurface(..) when surface changed */
- protected void updateHandle() {}
+ /**
+ * called with locked surface @ setRealized(true) or @ lockSurface(..) when surface changed
+ *
+ * Must be paired w/ {@link #destroyHandle()}.
+ *
+ */
+ protected void createHandle() {}
@Override
public long getHandle() {
@@ -174,7 +181,7 @@ public abstract class GLDrawableImpl implements GLDrawable {
if(isProxySurface) {
((ProxySurface)surface).createNotify();
}
- if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) {
+ if(NativeSurface.LOCK_SURFACE_NOT_READY >= surface.lockSurface()) {
throw new GLException("GLDrawableImpl.setRealized(true): Surface not ready (lockSurface)");
}
} else {
@@ -185,7 +192,7 @@ public abstract class GLDrawableImpl implements GLDrawable {
realized = realizedArg;
if(realizedArg) {
setRealizedImpl();
- updateHandle();
+ createHandle();
} else {
destroyHandle();
setRealizedImpl();
@@ -193,7 +200,7 @@ public abstract class GLDrawableImpl implements GLDrawable {
}
} finally {
if(realizedArg) {
- unlockSurface();
+ surface.unlockSurface();
} else {
aDevice.unlock();
if(isProxySurface) {
@@ -276,12 +283,47 @@ public abstract class GLDrawableImpl implements GLDrawable {
return surface.getHeight();
}
- /** @see NativeSurface#lockSurface() */
+ /**
+ * {@link NativeSurface#lockSurface() Locks} the underlying windowing toolkit's {@link NativeSurface surface}.
+ *
+ * If drawable is {@link #setRealized(boolean) realized},
+ * the {@link #getHandle() drawable handle} is valid after successfully {@link NativeSurface#lockSurface() locking}
+ * it's {@link NativeSurface surface} until being {@link #unlockSurface() unlocked}.
+ *
+ *
+ * In case the {@link NativeSurface surface} has changed as indicated by it's
+ * {@link NativeSurface#lockSurface() lock} result {@link NativeSurface#LOCK_SURFACE_CHANGED},
+ * the implementation is required to update this information as needed within it's implementation.
+ *
+ *
+ * @see NativeSurface#lockSurface()
+ * @see #getHandle()
+ */
public final int lockSurface() throws GLException {
- return surface.lockSurface();
+ final int lockRes = surface.lockSurface();
+ if ( NativeSurface.LOCK_SURFACE_CHANGED == lockRes && realized ) {
+ // Update the drawable handle, in case the surface handle has changed.
+ final long _handle1 = getHandle();
+ destroyHandle();
+ createHandle();
+ final long _handle2 = getHandle();
+ if(DEBUG) {
+ if( _handle1 != _handle2) {
+ System.err.println(getThreadName() + ": Drawable handle changed: "+toHexString(_handle1)+" -> "+toHexString(_handle2));
+ }
+ }
+ }
+ return lockRes;
+
}
- /** @see NativeSurface#unlockSurface() */
+ /**
+ * {@link NativeSurface#unlockSurface() Unlocks} the underlying windowing toolkit {@link NativeSurface surface},
+ * which may render the {@link #getHandle() drawable handle} invalid.
+ *
+ * @see NativeSurface#unlockSurface()
+ * @see #getHandle()
+ */
public final void unlockSurface() {
surface.unlockSurface();
}
@@ -294,9 +336,7 @@ public abstract class GLDrawableImpl implements GLDrawable {
",\n\tSurface "+getNativeSurface()+"]";
}
- protected static String getThreadName() {
- return Thread.currentThread().getName();
- }
+ protected static String getThreadName() { return Thread.currentThread().getName(); }
protected GLDrawableFactory factory;
protected NativeSurface surface;
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
index 167eebf3a..2edf26145 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java
@@ -100,10 +100,10 @@ public abstract class EGLDrawable extends GLDrawableImpl {
}
@Override
- protected final void updateHandle() {
+ protected final void createHandle() {
final EGLWrappedSurface eglws = (EGLWrappedSurface) surface;
if(DEBUG) {
- System.err.println(getThreadName() + ": updateHandle of "+eglws);
+ System.err.println(getThreadName() + ": createHandle of "+eglws);
}
if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
if( EGL.EGL_NO_SURFACE != eglws.getSurfaceHandle() ) {
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
index c15065cfa..6b239a43d 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
@@ -56,7 +56,7 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
glXWindow=0;
useGLXWindow=false;
if(realized) {
- updateHandle();
+ createHandle();
}
}
@@ -82,7 +82,7 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
}
@Override
- protected final void updateHandle() {
+ protected final void createHandle() {
if(USE_GLXWINDOW) {
X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeSurface().getGraphicsConfiguration();
if(config.getFBConfig()>=0) {
--
cgit v1.2.3
From f3e0f109ac7f03ef803523af8e965d713b6044db Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Wed, 10 Apr 2013 04:08:57 +0200
Subject: GLContextImpl.destroy(): Fail fast in case of invalid dawable [null,
!realized] and makeCurrent() failure.
---
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 35 ++++++++++++++---------
1 file changed, 21 insertions(+), 14 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 90f5a9907..0d8b193af 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -342,18 +342,24 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final void destroy() {
+ if ( null == drawable ) {
+ throw new GLException("Drawable is null: "+toString());
+ }
if ( DEBUG_TRACE_SWITCH ) {
System.err.println(getThreadName() + ": GLContextImpl.destroy.0: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
", surf "+toHexString(drawable.getHandle())+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
- if (contextHandle != 0) {
+ if ( 0 != contextHandle ) {
final int lockRes = drawable.lockSurface();
- if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) {
+ if ( NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes ) {
// this would be odd ..
throw new GLException("Surface not ready to lock: "+drawable);
}
Throwable drawableContextRealizedException = null;
try {
+ if ( !drawable.isRealized() ) {
+ throw new GLException("Drawable not realized: "+toString());
+ }
// Must hold the lock around the destroy operation to make sure we
// don't destroy the context while another thread renders to it.
lock.lock(); // holdCount++ -> 1 - n (1: not locked, 2-n: destroy while rendering)
@@ -365,17 +371,18 @@ public abstract class GLContextImpl extends GLContext {
}
}
try {
- // release current context
- if(lock.getHoldCount() == 1) {
- // needs current context to call associateDrawable(..) and to disable debug handler
- makeCurrent();
+ // if not current, makeCurrent(), to call associateDrawable(..) and to disable debug handler
+ if ( lock.getHoldCount() == 1 ) {
+ if ( GLContext.CONTEXT_NOT_CURRENT == makeCurrent() ) {
+ throw new GLException("GLContext.makeCurrent() failed: "+toString());
+ }
}
try {
associateDrawable(false);
} catch (Throwable t) {
drawableContextRealizedException = t;
}
- if(0 != defaultVAO) {
+ if ( 0 != defaultVAO ) {
int[] tmp = new int[] { defaultVAO };
gl.getGL2GL3().glBindVertexArray(0);
gl.getGL2GL3().glDeleteVertexArrays(1, tmp, 0);
@@ -492,7 +499,7 @@ public abstract class GLContextImpl extends GLContext {
return CONTEXT_NOT_CURRENT;
}
- boolean unlockContextAndSurface = true; // Must be cleared if successful, otherwise finally block will release context and surface!
+ boolean unlockResources = true; // Must be cleared if successful, otherwise finally block will release context and/or surface!
int res = CONTEXT_NOT_CURRENT;
try {
if ( drawable.isRealized() ) {
@@ -509,7 +516,7 @@ public abstract class GLContextImpl extends GLContext {
// Assume we don't need to make this context current again
// For Mac OS X, however, we need to update the context to track resizes
drawableUpdatedNotify();
- unlockContextAndSurface = false; // success
+ unlockResources = false; // success
if( TRACE_SWITCH ) {
System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.X2]: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - keep - CONTEXT_CURRENT - "+lock);
}
@@ -519,7 +526,7 @@ public abstract class GLContextImpl extends GLContext {
}
}
res = makeCurrentWithinLock(lockRes);
- unlockContextAndSurface = CONTEXT_NOT_CURRENT == res; // success ?
+ unlockResources = CONTEXT_NOT_CURRENT == res; // success ?
/**
* FIXME: refactor dependence on Java 2D / JOGL bridge
@@ -529,10 +536,10 @@ public abstract class GLContextImpl extends GLContext {
}
*/
} catch (RuntimeException e) {
- unlockContextAndSurface = true;
+ unlockResources = true;
throw e;
} finally {
- if (unlockContextAndSurface) {
+ if (unlockResources) {
if( DEBUG_TRACE_SWITCH ) {
System.err.println(getThreadName() +": GLContext.ContextSwitch[makeCurrent.1]: Context lock.unlock() due to error, res "+makeCurrentResultToString(res)+", "+lock);
}
@@ -541,10 +548,10 @@ public abstract class GLContextImpl extends GLContext {
}
} /* if ( drawable.isRealized() ) */
} catch (RuntimeException e) {
- unlockContextAndSurface = true;
+ unlockResources = true;
throw e;
} finally {
- if (unlockContextAndSurface) {
+ if (unlockResources) {
drawable.unlockSurface();
}
}
--
cgit v1.2.3
From cfe62741e19196d973d9b31f2c8f3873705cb74b Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Fri, 12 Apr 2013 20:27:21 +0200
Subject: GLContextImpl: destroy(): Fix null drawable check;
makeCurrentWithinLock(): Add drawable size validation before attempt to
create context; MacOSXCGLContext: Explicit exception for Null
AttachGLLayerCmd.
GLContextImpl:
- destroy():
- Fix null drawable check
Only if the GLContext isCreated(), we require a drawable to be set.
- Proper name of associateDrawable Exception
- makeCurrentWithinLock():
- Add drawable size validation before attempt to create context.
- 'makeCurrent()' shall never be called w/o proper sized drawable, i.e. > 0x0.
- returns CONTEXT_NOT_CURRENT, if drawable size is <= 0x0
MacOSXCGLContext:
- Explicit exception for Null AttachGLLayerCmd.
In case context creation has failed via makeCurrent(),
AttachGLLayerCmd may never been issued and hence maybe NULL.
Catch this case and send a meaningful exception,
which is catched and fwd in GLContext.destroy().
---
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 28 +++++++----
.../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 54 ++++++++++++++++------
2 files changed, 58 insertions(+), 24 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 0d8b193af..376b3c0e5 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -342,23 +342,24 @@ public abstract class GLContextImpl extends GLContext {
@Override
public final void destroy() {
- if ( null == drawable ) {
- throw new GLException("Drawable is null: "+toString());
- }
if ( DEBUG_TRACE_SWITCH ) {
+ final long drawH = null != drawable ? drawable.getHandle() : 0;
System.err.println(getThreadName() + ": GLContextImpl.destroy.0: obj " + toHexString(hashCode()) + ", ctx " + toHexString(contextHandle) +
- ", surf "+toHexString(drawable.getHandle())+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
+ ", surf "+toHexString(drawH)+", isShared "+GLContextShareSet.isShared(this)+" - "+lock);
}
- if ( 0 != contextHandle ) {
+ if ( 0 != contextHandle ) { // isCreated() ?
+ if ( null == drawable ) {
+ throw new GLException("GLContext created but drawable is null: "+toString());
+ }
final int lockRes = drawable.lockSurface();
if ( NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes ) {
// this would be odd ..
throw new GLException("Surface not ready to lock: "+drawable);
}
- Throwable drawableContextRealizedException = null;
+ Throwable associateDrawableException = null;
try {
if ( !drawable.isRealized() ) {
- throw new GLException("Drawable not realized: "+toString());
+ throw new GLException("GLContext created but drawable not realized: "+toString());
}
// Must hold the lock around the destroy operation to make sure we
// don't destroy the context while another thread renders to it.
@@ -380,7 +381,7 @@ public abstract class GLContextImpl extends GLContext {
try {
associateDrawable(false);
} catch (Throwable t) {
- drawableContextRealizedException = t;
+ associateDrawableException = t;
}
if ( 0 != defaultVAO ) {
int[] tmp = new int[] { defaultVAO };
@@ -410,8 +411,8 @@ public abstract class GLContextImpl extends GLContext {
} finally {
drawable.unlockSurface();
}
- if(null != drawableContextRealizedException) {
- throw new GLException("GLContext.destroy() during GLDrawableImpl.contextRealized(this, false)", drawableContextRealizedException);
+ if( null != associateDrawableException ) {
+ throw new GLException("GLContext.destroy() during associateDrawable(false)", associateDrawableException);
}
}
resetStates();
@@ -601,6 +602,13 @@ public abstract class GLContextImpl extends GLContext {
private final int makeCurrentWithinLock(int surfaceLockRes) throws GLException {
if (!isCreated()) {
+ if( 0 >= drawable.getWidth() || 0 >= drawable.getHeight() ) {
+ if ( DEBUG_TRACE_SWITCH ) {
+ System.err.println(getThreadName() + ": Create GL context REJECTED (zero surface size) obj " + toHexString(hashCode()) + ", surf "+toHexString(drawable.getHandle())+" for " + getClass().getName());
+ System.err.println(drawable.toString());
+ }
+ return CONTEXT_NOT_CURRENT;
+ }
if(DEBUG_GL) {
// only impacts w/ createContextARB(..)
additionalCtxCreationFlags |= GLContext.CTX_OPTION_DEBUG ;
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index a197bd51f..6cab369cf 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -622,7 +622,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
* Hence this method blocks the main-thread only for a short period of time.
*
*/
- class AttachNSOpenGLLayer implements Runnable {
+ class AttachGLLayerCmd implements Runnable {
final OffscreenLayerSurface ols;
final long ctx;
final int shaderProgram;
@@ -637,7 +637,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
/** Synchronized by instance's monitor */
boolean valid;
- AttachNSOpenGLLayer(OffscreenLayerSurface ols, long ctx, int shaderProgram, long pfmt, long pbuffer, int texID, boolean isOpaque, int width, int height) {
+ AttachGLLayerCmd(OffscreenLayerSurface ols, long ctx, int shaderProgram, long pfmt, long pbuffer, int texID, boolean isOpaque, int width, int height) {
this.ols = ols;
this.ctx = ctx;
this.shaderProgram = shaderProgram;
@@ -651,6 +651,15 @@ public abstract class MacOSXCGLContext extends GLContextImpl
this.nsOpenGLLayer = 0;
}
+ public final String contentToString() {
+ return "valid "+valid+", size "+width+"x"+height+", ctx "+toHexString(ctx)+", opaque "+isOpaque+", texID "+texID+", pbuffer "+toHexString(pbuffer)+", nsOpenGLLayer "+toHexString(nsOpenGLLayer);
+ }
+
+ @Override
+ public final String toString() {
+ return "AttachGLLayerCmd["+contentToString()+"]";
+ }
+
@Override
public void run() {
synchronized(this) {
@@ -693,14 +702,20 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
}
}
- AttachNSOpenGLLayer attachCALayerCmd = null;
+ AttachGLLayerCmd attachGLLayerCmd = null;
- class DetachNSOpenGLLayer implements Runnable {
- final AttachNSOpenGLLayer cmd;
+ class DetachGLLayerCmd implements Runnable {
+ final AttachGLLayerCmd cmd;
- DetachNSOpenGLLayer(AttachNSOpenGLLayer cmd) {
+ DetachGLLayerCmd(AttachGLLayerCmd cmd) {
this.cmd = cmd;
}
+
+ @Override
+ public final String toString() {
+ return "DetachGLLayerCmd["+cmd.contentToString()+"]";
+ }
+
@Override
public void run() {
synchronized( cmd ) {
@@ -734,7 +749,8 @@ public abstract class MacOSXCGLContext extends GLContextImpl
backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(drawable.getNativeSurface(), true);
if(DEBUG) {
- System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable: "+bound+", ctx "+toHexString(contextHandle)+", hasBackingLayerHost "+(null!=backingLayerHost));
+ System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable: "+bound+", ctx "+toHexString(contextHandle)+
+ ", hasBackingLayerHost "+(null!=backingLayerHost)+", attachGLLayerCmd "+attachGLLayerCmd);
// Thread.dumpStack();
}
@@ -785,10 +801,13 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
// All CALayer lifecycle ops are deferred on main-thread
- attachCALayerCmd = new AttachNSOpenGLLayer(
+ attachGLLayerCmd = new AttachGLLayerCmd(
backingLayerHost, ctx, gl3ShaderProgramName, pixelFormat, pbufferHandle, texID,
chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight );
- OSXUtil.RunOnMainThread(false, attachCALayerCmd);
+ if(DEBUG) {
+ System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable(true): "+attachGLLayerCmd);
+ }
+ OSXUtil.RunOnMainThread(false, attachGLLayerCmd);
} else { // -> null == backingLayerHost
lastWidth = drawable.getWidth();
lastHeight = drawable.getHeight();
@@ -798,8 +817,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl
}
} else { // -> !bound
if( null != backingLayerHost ) {
- final AttachNSOpenGLLayer cmd = attachCALayerCmd;
- attachCALayerCmd = null;
+ final AttachGLLayerCmd cmd = attachGLLayerCmd;
+ attachGLLayerCmd = null;
+ if( null == cmd ) {
+ throw new GLException("Null attachGLLayerCmd: "+drawable);
+ }
if( 0 != cmd.pbuffer ) {
CGL.setContextPBuffer(contextHandle, 0);
}
@@ -808,7 +830,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl
cmd.valid = true; // skip pending creation
} else {
// All CALayer lifecycle ops are deferred on main-thread
- OSXUtil.RunOnMainThread(false, new DetachNSOpenGLLayer(cmd));
+ final DetachGLLayerCmd dCmd = new DetachGLLayerCmd(cmd);
+ if(DEBUG) {
+ System.err.println("MaxOSXCGLContext.NSOpenGLImpl.associateDrawable(false): "+dCmd);
+ }
+ OSXUtil.RunOnMainThread(false, dCmd);
if( null != gl3ShaderProgram ) {
gl3ShaderProgram.destroy(MacOSXCGLContext.this.gl.getGL3());
gl3ShaderProgram = null;
@@ -903,7 +929,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean setSwapInterval(int interval) {
- final AttachNSOpenGLLayer cmd = attachCALayerCmd;
+ final AttachGLLayerCmd cmd = attachGLLayerCmd;
if(null != cmd) {
synchronized(cmd) {
if( cmd.valid && 0 != cmd.nsOpenGLLayer) {
@@ -932,7 +958,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
public boolean swapBuffers() {
- final AttachNSOpenGLLayer cmd = attachCALayerCmd;
+ final AttachGLLayerCmd cmd = attachGLLayerCmd;
if(null != cmd) {
synchronized(cmd) {
if( cmd.valid && 0 != cmd.nsOpenGLLayer) {
--
cgit v1.2.3
From b414c4b1be05249590138e73558ada82bd170f15 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Sun, 14 Apr 2013 06:28:44 +0200
Subject: Fix Bug 692: Add tracking of VERTEX_ARRAY_BINDING, and enable
allowing a bound non default VAO to pass VBO enabled test, even if VBO is
disabled.
VAO is available if: GL >= 3.0 or is having GL_ARB_vertex_array_object extension.
checkBufferObject(..) checks whether VERTEX_ARRAY_BINDING has a non default VAO bound in case
no VBO is being bound and VAO is allowed.
glBindVertexArray(int) is being tracked, i.e. on state VERTEX_ARRAY_BINDING
---
make/config/jogl/gl-common.cfg | 1 +
make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java | 138 +++++++++++----------
make/scripts/java-win64-dbg.bat | 2 +-
make/scripts/tests-x64.bat | 5 +-
make/scripts/tests.sh | 14 +--
.../jogamp/opengl/GLBufferStateTracker.java | 2 +
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 4 +
7 files changed, 87 insertions(+), 79 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/make/config/jogl/gl-common.cfg b/make/config/jogl/gl-common.cfg
index f8f4f07f5..a57400217 100644
--- a/make/config/jogl/gl-common.cfg
+++ b/make/config/jogl/gl-common.cfg
@@ -515,6 +515,7 @@ JavaPrologue glBegin inBeginEndPair = true;
JavaEpilogue glEnd inBeginEndPair = false;
JavaEpilogue glBindBuffer bufferStateTracker.setBoundBufferObject({0}, {1});
JavaEpilogue glBindBufferARB bufferStateTracker.setBoundBufferObject({0}, {1});
+JavaEpilogue glBindVertexArray bufferStateTracker.setBoundBufferObject(GL2GL3.GL_VERTEX_ARRAY_BINDING, {0});
JavaEpilogue glPushClientAttrib bufferStateTracker.clearBufferObjectState();
JavaEpilogue glPushClientAttrib glStateTracker.pushAttrib(mask);
JavaEpilogue glPopClientAttrib bufferStateTracker.clearBufferObjectState();
diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java
index e079a1a24..bfe2759c0 100644
--- a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java
+++ b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java
@@ -51,133 +51,135 @@ private boolean haveEXTPixelBufferObject;
private boolean haveGL15;
private boolean haveGL21;
private boolean haveARBVertexBufferObject;
+private boolean haveARBVertexArrayObject;
private final void initBufferObjectExtensionChecks() {
- if (bufferObjectExtensionsInitialized)
+ if ( bufferObjectExtensionsInitialized ) {
return;
+ }
bufferObjectExtensionsInitialized = true;
haveARBPixelBufferObject = isExtensionAvailable("GL_ARB_pixel_buffer_object");
haveEXTPixelBufferObject = isExtensionAvailable("GL_EXT_pixel_buffer_object");
haveGL15 = isExtensionAvailable("GL_VERSION_1_5");
haveGL21 = isExtensionAvailable("GL_VERSION_2_1");
haveARBVertexBufferObject = isExtensionAvailable("GL_ARB_vertex_buffer_object");
+ haveARBVertexArrayObject = _context.getGLVersionNumber().compareTo(GLContext.Version30) >= 0 ||
+ isExtensionAvailable("GL_ARB_vertex_array_object");
}
-private final boolean checkBufferObject(boolean extension1,
- boolean extension2,
- boolean extension3,
+private final boolean checkBufferObject(boolean extensionAvail,
+ boolean allowVAO,
boolean enabled,
int state,
String kind, boolean throwException) {
- if (inBeginEndPair) {
+ if ( inBeginEndPair ) {
throw new GLException("May not call this between glBegin and glEnd");
}
- boolean avail = (extension1 || extension2 || extension3);
- if (!avail) {
- if (!enabled)
+ if ( !extensionAvail ) {
+ if ( !enabled ) {
return true;
+ }
if(throwException) {
throw new GLException("Required extensions not available to call this function");
}
return false;
}
int buffer = bufferStateTracker.getBoundBufferObject(state, this);
- if (enabled) {
- if (buffer == 0) {
- if(throwException) {
- throw new GLException(kind + " must be enabled to call this method");
- }
- return false;
+ if ( enabled ) {
+ if ( 0 != buffer ) {
+ return true;
+ }
+ if ( allowVAO ) {
+ buffer = bufferStateTracker.getBoundBufferObject(GL2GL3.GL_VERTEX_ARRAY_BINDING, this);
+ if( 0 != buffer && !_context.isDefaultVAO(buffer) ) {
+ return true;
+ }
+ }
+ if ( throwException ) {
+ throw new GLException(kind + " must be enabled to call this method");
}
+ return false;
} else {
- if (buffer != 0) {
- if(throwException) {
- throw new GLException(kind + " must be disabled to call this method");
- }
- return false;
+ if ( 0 == buffer ) {
+ return true;
}
+ if ( throwException ) {
+ throw new GLException(kind + " must be disabled to call this method");
+ }
+ return false;
}
- return true;
}
private final boolean checkArrayVBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
- return checkBufferObject(haveGL15,
- haveARBVertexBufferObject,
- false,
- false,
- GL.GL_ARRAY_BUFFER,
- "array vertex_buffer_object", throwException);
+ return checkBufferObject(haveGL15 || haveARBVertexBufferObject,
+ haveARBVertexArrayObject, // allowVAO
+ false, // enable
+ GL.GL_ARRAY_BUFFER,
+ "array vertex_buffer_object", throwException);
}
private final boolean checkArrayVBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
- return checkBufferObject(haveGL15,
- haveARBVertexBufferObject,
- false,
- true,
- GL.GL_ARRAY_BUFFER,
- "array vertex_buffer_object", throwException);
+ return checkBufferObject(haveGL15 || haveARBVertexBufferObject,
+ haveARBVertexArrayObject, // allowVAO
+ true, // enable
+ GL.GL_ARRAY_BUFFER,
+ "array vertex_buffer_object", throwException);
}
private final boolean checkElementVBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
- return checkBufferObject(haveGL15,
- haveARBVertexBufferObject,
- false,
- false,
- GL.GL_ELEMENT_ARRAY_BUFFER,
- "element vertex_buffer_object", throwException);
+ return checkBufferObject(haveGL15 || haveARBVertexBufferObject,
+ haveARBVertexArrayObject, // allowVAO
+ false, // enable
+ GL.GL_ELEMENT_ARRAY_BUFFER,
+ "element vertex_buffer_object", throwException);
}
private final boolean checkElementVBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
- return checkBufferObject(haveGL15,
- haveARBVertexBufferObject,
- false,
- true,
- GL.GL_ELEMENT_ARRAY_BUFFER,
- "element vertex_buffer_object", throwException);
+ return checkBufferObject(haveGL15 || haveARBVertexBufferObject,
+ haveARBVertexArrayObject, // allowVAO
+ true, // enable
+ GL.GL_ELEMENT_ARRAY_BUFFER,
+ "element vertex_buffer_object", throwException);
}
private final boolean checkUnpackPBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
- return checkBufferObject(haveARBPixelBufferObject,
- haveEXTPixelBufferObject,
- haveGL21,
- false,
- GL2.GL_PIXEL_UNPACK_BUFFER,
- "unpack pixel_buffer_object", throwException);
+ return checkBufferObject(haveGL21 || haveARBPixelBufferObject || haveEXTPixelBufferObject,
+ false, // allowVAO
+ false, // enable
+ GL2.GL_PIXEL_UNPACK_BUFFER,
+ "unpack pixel_buffer_object", throwException);
}
private final boolean checkUnpackPBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
- return checkBufferObject(haveARBPixelBufferObject,
- haveEXTPixelBufferObject,
- haveGL21,
- true,
- GL2.GL_PIXEL_UNPACK_BUFFER,
- "unpack pixel_buffer_object", throwException);
+ return checkBufferObject(haveGL21 || haveARBPixelBufferObject || haveEXTPixelBufferObject,
+ false, // allowVAO
+ true, // enable
+ GL2.GL_PIXEL_UNPACK_BUFFER,
+ "unpack pixel_buffer_object", throwException);
}
private final boolean checkPackPBODisabled(boolean throwException) {
initBufferObjectExtensionChecks();
- return checkBufferObject(haveARBPixelBufferObject,
- haveEXTPixelBufferObject,
- haveGL21,
- false,
- GL2.GL_PIXEL_PACK_BUFFER,
- "pack pixel_buffer_object", throwException);
+ return checkBufferObject(haveGL21 || haveARBPixelBufferObject || haveEXTPixelBufferObject,
+ false, // allowVAO
+ false, // enable
+ GL2.GL_PIXEL_PACK_BUFFER,
+ "pack pixel_buffer_object", throwException);
}
private final boolean checkPackPBOEnabled(boolean throwException) {
initBufferObjectExtensionChecks();
- return checkBufferObject(haveARBPixelBufferObject,
- haveEXTPixelBufferObject,
- haveGL21,
- true,
- GL2.GL_PIXEL_PACK_BUFFER,
- "pack pixel_buffer_object", throwException);
+ return checkBufferObject(haveGL21 || haveARBPixelBufferObject || haveEXTPixelBufferObject,
+ false, // allowVAO
+ true, // enable
+ GL2.GL_PIXEL_PACK_BUFFER,
+ "pack pixel_buffer_object", throwException);
}
@Override
diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/java-win64-dbg.bat
index 48653d907..c14385fc7 100755
--- a/make/scripts/java-win64-dbg.bat
+++ b/make/scripts/java-win64-dbg.bat
@@ -39,7 +39,7 @@ REM set D_ARGS="-Djogl.debug=all"
REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL"
REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.windows.useWGLVersionOf5WGLGDIFuncSet"
REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch"
-set D_ARGS="-Dnewt.debug.Window"
+REM set D_ARGS="-Dnewt.debug.Window"
REM set D_ARGS="-Dnewt.debug.Window.KeyEvent"
REM set D_ARGS="-Dnewt.debug.Window.MouseEvent"
REM set D_ARGS="-Dnewt.debug.Window.MouseEvent" "-Dnewt.debug.Window.KeyEvent"
diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat
index 7d1380287..d647c2d4a 100755
--- a/make/scripts/tests-x64.bat
+++ b/make/scripts/tests-x64.bat
@@ -19,6 +19,9 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDeb
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT %*
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT
+REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext01NEWT %*
+REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext02NEWT %*
+scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestBug692GL3VAO %*
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimNEWT %*
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext01VSyncAnimAWT %*
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclusiveContext02FPSAnimNEWT %*
@@ -47,7 +50,7 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestJScroll
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug642JSplitPaneMixHwLw01AWT %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestIsRealizedConcurrency01AWT %*
-scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %*
+REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestGearsES1NEWT %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT %*
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 2974658a8..17b3187e6 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -177,7 +177,7 @@ function jrun() {
#D_ARGS="-Dnewt.debug.Window -Dnativewindow.debug=all"
#D_ARGS="-Dnewt.debug.Window -Dnativewindow.debug.JAWT -Djogl.debug.Animator"
#D_ARGS="-Dnewt.debug.Window -Djogl.debug.GLDrawable"
- D_ARGS="-Dnewt.debug.Window"
+ #D_ARGS="-Dnewt.debug.Window"
#D_ARGS="-Xprof"
#D_ARGS="-Dnativewindow.debug=all"
#D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.Java2D -Djogl.debug.GLJPanel"
@@ -290,7 +290,7 @@ function testawtswt() {
#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWTAnalyzeBug455 $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWTBug450 $*
-testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper $*
+#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestTeapotNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.gl3.newt.TestGeomShader01TextureGL3NEWT $*
@@ -315,9 +315,11 @@ testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextSurfaceLockNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMapBufferRead01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext02NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug692GL3VAO $*
+testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug692GL3VAO $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT2 $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES1NEWT $*
@@ -543,12 +545,6 @@ testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper
#testnoawt com.jogamp.opengl.test.junit.graph.demos.GPUUISceneNewtDemo01 $*
#testnoawt com.jogamp.opengl.test.junit.graph.demos.GPUUISceneNewtDemo02 $*
-#
-# Security
-#
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMapBufferRead01NEWT $*
-
#
# OSX bugs
#
diff --git a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
index 4a1a81bcb..7f5316fbd 100644
--- a/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
+++ b/src/jogl/classes/jogamp/opengl/GLBufferStateTracker.java
@@ -91,6 +91,7 @@ public class GLBufferStateTracker {
bindingMap.setKeyNotFoundValue(0xFFFFFFFF);
// Start with known unbound targets for known keys
+ // setBoundBufferObject(GL2GL3.GL_VERTEX_ARRAY_BINDING, 0); // not using default VAO (removed in GL3 core) - only explicit
setBoundBufferObject(GL.GL_ARRAY_BUFFER, 0);
setBoundBufferObject(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
setBoundBufferObject(GL2.GL_PIXEL_PACK_BUFFER, 0);
@@ -120,6 +121,7 @@ public class GLBufferStateTracker {
boolean gotQueryTarget = true;
int queryTarget = 0;
switch (target) {
+ case GL2GL3.GL_VERTEX_ARRAY_BINDING: queryTarget = GL2GL3.GL_VERTEX_ARRAY_BINDING; break;
case GL.GL_ARRAY_BUFFER: queryTarget = GL.GL_ARRAY_BUFFER_BINDING; break;
case GL.GL_ELEMENT_ARRAY_BUFFER: queryTarget = GL.GL_ELEMENT_ARRAY_BUFFER_BINDING; break;
case GL2.GL_PIXEL_PACK_BUFFER: queryTarget = GL2.GL_PIXEL_PACK_BUFFER_BINDING; break;
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 376b3c0e5..9f7c9cf57 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1790,6 +1790,10 @@ public abstract class GLContextImpl extends GLContext {
public final GLStateTracker getGLStateTracker() {
return glStateTracker;
}
+
+ public final boolean isDefaultVAO(int vao) {
+ return defaultVAO == vao;
+ }
//---------------------------------------------------------------------------
// Helpers for context optimization where the last context is left
--
cgit v1.2.3
From 5b47372590ec715647ebbd75d70c41ec7a64485a Mon Sep 17 00:00:00 2001
From: Martin Hegedus
Date: Tue, 2 Apr 2013 09:31:41 -0700
Subject: Fix Bug 705 - Make Mesa X11 driver < 8.0 use new Quirk
DontCloseX11DisplayConnection
---
.../com/jogamp/opengl/GLRendererQuirks.java | 33 +++++++++++++++++--
src/jogl/classes/javax/media/opengl/GLProfile.java | 25 +++++++++++++++
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 32 +++++++++++++++++++
.../classes/jogamp/nativewindow/x11/X11Util.java | 37 +++++++++++++++++++---
4 files changed, 121 insertions(+), 6 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
index 715511d1b..7203ba214 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
@@ -81,12 +81,41 @@ public class GLRendererQuirks {
*/
public static final int GLFlushBeforeRelease = 7;
+ //
+ // The JVM for the following system crashes on the second call to glXDestroyContext after
+ // XCloseDisplay has been called once.
+ //
+ // The following will crash the system:
+ // XOpenDisplay(A), glXCreateNewContext(A), XOpenDisplay(B), glXCreateNewContext(B),
+ // glXDestroyContext(A/B), XCloseDisplay(A/B), glXDestroyContext(B/A) (crash)
+ //
+ // Dell Latitude D520
+ // Intel(R) Core(TM)2 CPU T7200
+ // i810 Monitor driver
+ // Platform LINUX / Linux 2.6.18.8-0.3-default (os), i386 (arch), GENERIC_ABI, 2 cores
+ // Platform Java Version: 1.6.0_18, VM: Java HotSpot(TM) Server VM, Runtime: Java(TM) SE Runtime Environment
+ // Platform Java Vendor: Sun Microsystems Inc., http://java.sun.com/, JavaSE: true, Java6: true, AWT enabled: true
+ // GL Profile GLProfile[GL2/GL2.sw]
+ // CTX VERSION 2.1 (Compatibility profile, FBO, software) - 2.1 Mesa 7.8.2
+ // GL jogamp.opengl.gl4.GL4bcImpl@472d48
+ // GL_VENDOR Brian Paul
+ // GL_RENDERER Mesa X11
+ // GL_VERSION 2.1 Mesa 7.8.2
+ //
+ // The error can be reproduced using a C code, thus the error is indpendent of Java and JOGL.
+ // The work around is to close all the X11 displays upon exit for a "Mesa X11" version < 8.
+ // At this moment, it is unknown if the error exists in versions greater than 7.
+ //
+ // Martin C. Hegedus, March 30, 2013
+ //
+ public static final int DontCloseX11DisplayConnection = 8;
+
/** Number of quirks known. */
- public static final int COUNT = 8;
+ public static final int COUNT = 9;
private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval",
"NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard",
- "GLNonCompliant", "GLFlushBeforeRelease"
+ "GLNonCompliant", "GLFlushBeforeRelease", "DontCloseX11DisplayConnection"
};
private final int _bitmask;
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index 25bba1725..54ed479a9 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -64,6 +64,11 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+// Added to check if X11 Displays should be closed on exit
+// Martin C. Hegedus, March 30, 2013
+import com.jogamp.opengl.GLRendererQuirks;
+import jogamp.nativewindow.x11.X11Util;
+
/**
* Specifies the the OpenGL profile.
*
@@ -1524,6 +1529,26 @@ public class GLProfile {
final boolean addedEGLProfile = null != defaultEGLDevice ? initProfilesForDevice(defaultEGLDevice) : false;
final boolean addedDesktopProfile = null != defaultDesktopDevice ? initProfilesForDevice(defaultDesktopDevice) : false;
final boolean addedAnyProfile = addedEGLProfile || addedDesktopProfile ;
+
+ // Added to check if X11 Displays should be closed on exit
+ // NOTE: This checks defaultEGLDevice and defaultDesktopDevice to determine if XCloseDisplay should be called on exit
+ // NOTE: These checks must be done after initProfilesForDevice since GLContext must set up the renderer quirks.
+ // NOTE: At this point the shared resource has already opened a display, created a new context, made it current, and
+ // released it. Let's cross our fingers that at this point in the code the context will not be destroyed and
+ // the display closed under any circumstances.
+ // NOTE: The checks can be tricked if the default screen is using a driver other than X11 and later a X11 Display,
+ // such as a remote display, is opened. If this occurs then markAllDisplaysUnclosable will not have been
+ // correctly set. Something to deal with at a later date.
+ //
+ // Martin C. Hegedus, March 30, 2013
+ if (eglFactory != null && defaultEGLDevice != null &&
+ eglFactory.hasRendererQuirk(defaultEGLDevice,GLRendererQuirks.DontCloseX11DisplayConnection) &&
+ NativeWindowFactory.getNativeWindowType(true) == NativeWindowFactory.TYPE_X11)
+ X11Util.markAllDisplaysUnclosable();
+ if (desktopFactory != null && defaultDesktopDevice != null &&
+ desktopFactory.hasRendererQuirk(defaultDesktopDevice,GLRendererQuirks.DontCloseX11DisplayConnection) &&
+ NativeWindowFactory.getNativeWindowType(true) == NativeWindowFactory.TYPE_X11)
+ X11Util.markAllDisplaysUnclosable();
if(DEBUG) {
System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 9f7c9cf57..74bc59c7c 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1562,9 +1562,41 @@ public abstract class GLContextImpl extends GLContext {
quirks[i++] = quirk;
}
}
+
+ //
+ // Mesa RENDERER related quirks
+ //
+ if( glRendererLowerCase.contains("mesa") ) {
+ // Added March 30, 2013
+ // Martin C. Hegedus
+ if ( glRendererLowerCase.contains("x11") && getMesaMajorVersion(glVersion) < 8.0 ) {
+ final int quirk = GLRendererQuirks.DontCloseX11DisplayConnection;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Mesa X11 < 8 : Renderer=" + glRenderer + ", Version=" +glVersion);
+ }
+ quirks[i++] = quirk;
+ }
+ }
glRendererQuirks = new GLRendererQuirks(quirks, 0, i);
}
+
+ // Added by Martin C. Hegedus, March 30, 2013
+ private static final int getMesaMajorVersion(String version) {
+ if (version == null || version.length() <= 0) return -1;
+ String[] strings = version.trim().split("\\s+");
+ if (strings.length <= 0) return -1;
+ version = strings[strings.length-1];
+ int index = version.indexOf(".");
+ if (index == 0) return -1;
+ if (index != -1) version = version.substring(0,index);
+ try {
+ Integer iNumber = new Integer(version);
+ return (iNumber == null) ? -1 : iNumber.intValue();
+ } catch (Throwable t) {
+ return -1;
+ }
+ }
private static final boolean hasFBOImpl(int major, int ctp, ExtensionAvailabilityCache extCache) {
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index c771cd67a..2fb780fa2 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -138,7 +138,13 @@ public class X11Util implements ToolkitProperties {
hasX11_EXTENSION_ATIFGLEXTENSION = false;
}
hasThreadingIssues = ATI_HAS_MULTITHREADING_BUG && ( hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION );
- markAllDisplaysUnclosable = ATI_HAS_XCLOSEDISPLAY_BUG && ( hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION );
+ // A check on nativewindow.debug.X11Util.HasX11CloseDisplayBug added March 30, 2013
+ // Martin C. Hegedus
+ if (!markAllDisplaysUnclosable) {
+ markAllDisplaysUnclosable = ATI_HAS_XCLOSEDISPLAY_BUG && ( hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION );
+ if (Debug.isPropertyDefined("nativewindow.debug.X11Util.HasX11CloseDisplayBug", true))
+ markAllDisplaysUnclosable = true;
+ }
if(DEBUG) {
System.err.println("X11Util.initSingleton(): OK "+isInitOK+"]"+
@@ -178,7 +184,10 @@ public class X11Util implements ToolkitProperties {
synchronized(X11Util.class) {
if(isInit) {
final boolean isJVMShuttingDown = NativeWindowFactory.isJVMShuttingDown() ;
- if(DEBUG || openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0) {
+ // Modified March 30, 2013 so output is not created under "expected" circumstances
+ // Martin C. Hegedus
+ if(DEBUG || ((openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0) &&
+ !(reusableDisplayList.size() == pendingDisplayList.size() && markAllDisplaysUnclosable))) {
System.err.println("X11Util.Display: Shutdown (JVM shutdown: "+isJVMShuttingDown+
", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+
", reusable (open, marked uncloseable): "+reusableDisplayList.size()+
@@ -242,6 +251,20 @@ public class X11Util implements ToolkitProperties {
return nullDisplayName;
}
+ // Added March 30, 2013
+ // Martin C. Hegedus
+ public static void markAllDisplaysUnclosable() {
+ synchronized(globalLock) {
+ markAllDisplaysUnclosable = true;
+ for(int i=0; i
Date: Tue, 16 Apr 2013 05:50:55 +0200
Subject: Fix Bug 705 - Cleanup & Generalize Commit
5b47372590ec715647ebbd75d70c41ec7a64485a ; Close X11 Display in
isDeviceSupported()
- Moved GL vendor version parsing to GLVersionNumber
- Moved X11Util.markAllDisplaysUnclosable() trigger into SharedResource creation of
- X11GLXDrawableFactory
- EGLDrawableFactory
- GLProfile is back to pre 5b47372590ec715647ebbd75d70c41ec7a64485a,
i.e. contains no quirk artifact (clean)
- Close X11 Display in X11GLXDrawableFactory.isDeviceSupported()
Regression of 9a4fcc7ea4ec61e4ceed791acced734ac04ea270
- TODO: Remove X11Util markAllDisplaysUnclosable detection code ?
Notes to Martin:
- Use TAB == 4 SPACES
- No author names into source code, git commit log is enough.
- No need to tag your edits, the diff is enough.
---
make/scripts/tests.sh | 4 +-
.../com/jogamp/opengl/GLRendererQuirks.java | 66 ++++++++++---------
.../classes/com/jogamp/opengl/JoglVersion.java | 6 +-
src/jogl/classes/javax/media/opengl/GLContext.java | 18 ++---
src/jogl/classes/javax/media/opengl/GLProfile.java | 25 -------
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 62 ++++++++---------
.../classes/jogamp/opengl/GLVersionNumber.java | 77 +++++++++++++++-------
.../jogamp/opengl/egl/EGLDrawableFactory.java | 12 ++++
.../opengl/x11/glx/X11GLXDrawableFactory.java | 5 ++
.../classes/jogamp/nativewindow/x11/X11Util.java | 73 ++++++++++----------
src/test-native/make.sh | 2 +
11 files changed, 186 insertions(+), 164 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 17b3187e6..fa965d83b 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -306,7 +306,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestPMVMatrix01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestPMVMatrix02NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestNEWTCloseX11DisplayBug565 $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT $*
+testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT $*
@@ -319,7 +319,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMapBufferRead01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug669RecursiveGLContext02NEWT $*
-testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug692GL3VAO $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestBug692GL3VAO $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT2 $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES1NEWT $*
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
index 7203ba214..0b136d460 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
@@ -59,7 +59,7 @@ public class GLRendererQuirks {
/** SIGSEGV on setSwapInterval() after changing the context's drawable w/ 'Mesa 8.0.4' dri2SetSwapInterval/DRI2 (soft & intel) */
public static final int NoSetSwapIntervalPostRetarget = 4;
- /** GLSL discard
command leads to undefined behavior or won't get compiled if being used. Appears to happen on Nvidia Tegra2. FIXME: Constrain version. */
+ /** GLSL discard
command leads to undefined behavior or won't get compiled if being used. Appears to have happened on Nvidia Tegra2, but seems to be fine now. FIXME: Constrain version. */
public static final int GLSLBuggyDiscard = 5;
/**
@@ -81,41 +81,47 @@ public class GLRendererQuirks {
*/
public static final int GLFlushBeforeRelease = 7;
- //
- // The JVM for the following system crashes on the second call to glXDestroyContext after
- // XCloseDisplay has been called once.
- //
- // The following will crash the system:
- // XOpenDisplay(A), glXCreateNewContext(A), XOpenDisplay(B), glXCreateNewContext(B),
- // glXDestroyContext(A/B), XCloseDisplay(A/B), glXDestroyContext(B/A) (crash)
- //
- // Dell Latitude D520
- // Intel(R) Core(TM)2 CPU T7200
- // i810 Monitor driver
- // Platform LINUX / Linux 2.6.18.8-0.3-default (os), i386 (arch), GENERIC_ABI, 2 cores
- // Platform Java Version: 1.6.0_18, VM: Java HotSpot(TM) Server VM, Runtime: Java(TM) SE Runtime Environment
- // Platform Java Vendor: Sun Microsystems Inc., http://java.sun.com/, JavaSE: true, Java6: true, AWT enabled: true
- // GL Profile GLProfile[GL2/GL2.sw]
- // CTX VERSION 2.1 (Compatibility profile, FBO, software) - 2.1 Mesa 7.8.2
- // GL jogamp.opengl.gl4.GL4bcImpl@472d48
- // GL_VENDOR Brian Paul
- // GL_RENDERER Mesa X11
- // GL_VERSION 2.1 Mesa 7.8.2
- //
- // The error can be reproduced using a C code, thus the error is indpendent of Java and JOGL.
- // The work around is to close all the X11 displays upon exit for a "Mesa X11" version < 8.
- // At this moment, it is unknown if the error exists in versions greater than 7.
- //
- // Martin C. Hegedus, March 30, 2013
- //
- public static final int DontCloseX11DisplayConnection = 8;
+ /**
+ * Closing X11 displays may cause JVM crashes or X11 errors with some buggy drivers
+ * while being used in concert w/ OpenGL.
+ *
+ * Some drivers may require X11 displays to be closed in the same order as they were created,
+ * some may not allow them to be closed at all while resources are being used somehow.
+ *
+ *
+ * Drivers known exposing such bug:
+ *
+ * - Mesa < 8.0 _with_ X11 software renderer
Mesa X11
, not with GLX/DRI renderer.
+ * - ATI proprietary Catalyst X11 driver (RENDERER vendor version):
+ *
+ * - 8.78.6
+ * - 8.881
+ * - 8.911
+ * - 9.01.8
+ *
+ *
+ *
+ *
+ * TODO: Validate whether Mesa's X11 driver exposes this bug w/ version >= 8, currently we assume not !
+ * Impact would be to set this quirk on all 'Mesa X11' software renderer!
+ *
+ *
+ *
+ * See Bug 515 - https://jogamp.org/bugzilla/show_bug.cgi?id=515
+ * and {@link jogamp.nativewindow.x11.X11Util#ATI_HAS_XCLOSEDISPLAY_BUG}.
+ *
+ *
+ * See Bug 705 - https://jogamp.org/bugzilla/show_bug.cgi?id=705
+ *
+ */
+ public static final int DontCloseX11Display = 8;
/** Number of quirks known. */
public static final int COUNT = 9;
private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval",
"NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard",
- "GLNonCompliant", "GLFlushBeforeRelease", "DontCloseX11DisplayConnection"
+ "GLNonCompliant", "GLFlushBeforeRelease", "DontCloseX11Display"
};
private final int _bitmask;
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
index 4246d74c7..11e76ef6f 100644
--- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
+++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
@@ -160,9 +160,11 @@ public class JoglVersion extends JogampVersion {
sb.append(Platform.getNewline());
sb.append("GL Profile ").append(gl.getGLProfile());
sb.append(Platform.getNewline());
- sb.append("CTX VERSION ").append(gl.getContext().getGLVersion());
+ sb.append("GL Version ").append(ctx.getGLVersion()).append(" [GL ").append(ctx.getGLVersionNumber()).append(", vendor ").append(ctx.getGLVendorVersionNumber()).append("]");
sb.append(Platform.getNewline());
- sb.append("GL ").append(gl);
+ sb.append("Quirks ").append(ctx.getRendererQuirks());
+ sb.append(Platform.getNewline());
+ sb.append("Impl. class ").append(gl.getClass().getCanonicalName());
sb.append(Platform.getNewline());
sb.append("GL_VENDOR ").append(gl.glGetString(GL.GL_VENDOR));
sb.append(Platform.getNewline());
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index be947e5f5..23ca96504 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -53,6 +53,7 @@ import jogamp.opengl.GLContextImpl;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.VersionNumberString;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.opengl.GLExtensions;
@@ -126,6 +127,8 @@ public abstract class GLContext {
/** Version 3.0. As an OpenGL version, it qualifies for {@link #isGL2()} only */
public static final VersionNumber Version30 = new VersionNumber(3, 0, 0);
+ protected static final VersionNumber Version80 = new VersionNumber(8, 0, 0);
+
/** ARB_create_context
related: created via ARB_create_context. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
protected static final int CTX_IS_ARB_CREATED = 1 << 0;
/** ARB_create_context
related: desktop compatibility profile. Cache key value. See {@link #isGLCompatibilityProfile()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */
@@ -169,9 +172,11 @@ public abstract class GLContext {
protected VersionNumber ctxVersion;
protected int ctxOptions;
protected String ctxVersionString;
+ protected VersionNumberString ctxVendorVersion;
protected VersionNumber ctxGLSLVersion;
private int currentSwapInterval;
protected GLRendererQuirks glRendererQuirks;
+ private static final VersionNumberString nullVersion = new VersionNumberString(-1, -1, -1, "n/a");
/** Did the drawable association changed ? see {@link GLRendererQuirks#NoSetSwapIntervalPostRetarget} */
protected boolean drawableRetargeted;
@@ -181,7 +186,8 @@ public abstract class GLContext {
System.err.println(getThreadName() + ": GLContext.resetStates()");
// Thread.dumpStack();
}
- ctxVersion = new VersionNumber(-1, -1, -1);
+ ctxVersion = nullVersion;
+ ctxVendorVersion = nullVersion;
ctxOptions=0;
ctxVersionString=null;
ctxGLSLVersion=null;
@@ -521,14 +527,9 @@ public abstract class GLContext {
}
public final StringBuilder append(StringBuilder sb) {
- sb.append("OpenGL ");
- sb.append(getGLVersionMajor());
- sb.append(".");
- sb.append(getGLVersionMinor());
- sb.append(", options 0x");
+ sb.append("Version ").append(getGLVersion()).append(" [GL ").append(getGLVersionNumber()).append(", vendor ").append(getGLVendorVersionNumber());
+ sb.append("], options 0x");
sb.append(Integer.toHexString(ctxOptions));
- sb.append(", ");
- sb.append(getGLVersion());
sb.append(", this ");
sb.append(toHexString(hashCode()));
sb.append(", handle ");
@@ -667,6 +668,7 @@ public abstract class GLContext {
* @see #getGLSLVersionNumber()
**/
public final VersionNumber getGLVersionNumber() { return ctxVersion; }
+ public final VersionNumberString getGLVendorVersionNumber() { return ctxVendorVersion; }
public final boolean isGLCompatibilityProfile() { return ( 0 != ( CTX_PROFILE_COMPAT & ctxOptions ) ); }
public final boolean isGLCoreProfile() { return ( 0 != ( CTX_PROFILE_CORE & ctxOptions ) ); }
public final boolean isGLForwardCompatible() { return ( 0 != ( CTX_OPTION_FORWARD & ctxOptions ) ); }
diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java
index 54ed479a9..1b6af22d4 100644
--- a/src/jogl/classes/javax/media/opengl/GLProfile.java
+++ b/src/jogl/classes/javax/media/opengl/GLProfile.java
@@ -64,11 +64,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
-// Added to check if X11 Displays should be closed on exit
-// Martin C. Hegedus, March 30, 2013
-import com.jogamp.opengl.GLRendererQuirks;
-import jogamp.nativewindow.x11.X11Util;
-
/**
* Specifies the the OpenGL profile.
*
@@ -1530,26 +1525,6 @@ public class GLProfile {
final boolean addedDesktopProfile = null != defaultDesktopDevice ? initProfilesForDevice(defaultDesktopDevice) : false;
final boolean addedAnyProfile = addedEGLProfile || addedDesktopProfile ;
- // Added to check if X11 Displays should be closed on exit
- // NOTE: This checks defaultEGLDevice and defaultDesktopDevice to determine if XCloseDisplay should be called on exit
- // NOTE: These checks must be done after initProfilesForDevice since GLContext must set up the renderer quirks.
- // NOTE: At this point the shared resource has already opened a display, created a new context, made it current, and
- // released it. Let's cross our fingers that at this point in the code the context will not be destroyed and
- // the display closed under any circumstances.
- // NOTE: The checks can be tricked if the default screen is using a driver other than X11 and later a X11 Display,
- // such as a remote display, is opened. If this occurs then markAllDisplaysUnclosable will not have been
- // correctly set. Something to deal with at a later date.
- //
- // Martin C. Hegedus, March 30, 2013
- if (eglFactory != null && defaultEGLDevice != null &&
- eglFactory.hasRendererQuirk(defaultEGLDevice,GLRendererQuirks.DontCloseX11DisplayConnection) &&
- NativeWindowFactory.getNativeWindowType(true) == NativeWindowFactory.TYPE_X11)
- X11Util.markAllDisplaysUnclosable();
- if (desktopFactory != null && defaultDesktopDevice != null &&
- desktopFactory.hasRendererQuirk(defaultDesktopDevice,GLRendererQuirks.DontCloseX11DisplayConnection) &&
- NativeWindowFactory.getNativeWindowType(true) == NativeWindowFactory.TYPE_X11)
- X11Util.markAllDisplaysUnclosable();
-
if(DEBUG) {
System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable);
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 74bc59c7c..3657cacda 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -49,6 +49,7 @@ import com.jogamp.common.os.DynamicLookupHelper;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.VersionNumberString;
import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.gluegen.runtime.FunctionAddressResolver;
import com.jogamp.gluegen.runtime.ProcAddressTable;
@@ -1023,7 +1024,7 @@ public abstract class GLContextImpl extends GLContext {
* If major > 0 || minor > 0 : Use passed values, determined at creation time
* Otherwise .. don't touch ..
*/
- private final void setContextVersion(int major, int minor, int ctp, boolean setVersionString) {
+ private final void setContextVersion(int major, int minor, int ctp, VersionNumberString glVendorVersion, boolean useGL) {
if ( 0 == ctp ) {
throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp));
}
@@ -1032,9 +1033,10 @@ public abstract class GLContextImpl extends GLContext {
throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp));
}
ctxVersion = new VersionNumber(major, minor, 0);
+ ctxVersionString = getGLVersion(major, minor, ctxOptions, glVersion);
+ ctxVendorVersion = glVendorVersion;
ctxOptions = ctp;
- if(setVersionString) {
- ctxVersionString = getGLVersion(major, minor, ctxOptions, gl.glGetString(GL.GL_VERSION));
+ if(useGL) {
ctxGLSLVersion = null;
if(major >= 2) { // >= ES2 || GL2.0
final String glslVersion = gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION);
@@ -1192,7 +1194,7 @@ public abstract class GLContextImpl extends GLContext {
*/
private static final VersionNumber getGLVersionNumber(int ctp, String glVersionStr) {
if( null != glVersionStr ) {
- final GLVersionNumber version = new GLVersionNumber(glVersionStr);
+ final GLVersionNumber version = GLVersionNumber.create(glVersionStr);
if ( version.isValid() ) {
int[] major = new int[] { version.getMajor() };
int[] minor = new int[] { version.getMinor() };
@@ -1384,7 +1386,9 @@ public abstract class GLContextImpl extends GLContext {
ctxProfileBits &= ~GLContext.CTX_IMPL_ES2_COMPAT;
}
- setRendererQuirks(major, minor, ctxProfileBits);
+ final VersionNumberString vendorVersion = GLVersionNumber.createVendorVersion(glVersion);
+
+ setRendererQuirks(major, minor, ctxProfileBits, vendorVersion);
if( strictMatch && glRendererQuirks.exist(GLRendererQuirks.GLNonCompliant) ) {
if(DEBUG) {
@@ -1445,7 +1449,7 @@ public abstract class GLContextImpl extends GLContext {
}
} else {
extensionAvailability = new ExtensionAvailabilityCache();
- setContextVersion(major, minor, ctxProfileBits, false); // pre-set of GL version, required for extension cache usage
+ setContextVersion(major, minor, ctxProfileBits, vendorVersion, false); // pre-set of GL version, required for extension cache usage
extensionAvailability.reset(this);
synchronized(mappedContextTypeObjectLock) {
mappedExtensionAvailabilityCache.put(contextFQN, extensionAvailability);
@@ -1469,7 +1473,7 @@ public abstract class GLContextImpl extends GLContext {
//
// Set GL Version (complete w/ version string)
//
- setContextVersion(major, minor, ctxProfileBits, true);
+ setContextVersion(major, minor, ctxProfileBits, vendorVersion, true);
setDefaultSwapInterval();
@@ -1481,7 +1485,7 @@ public abstract class GLContextImpl extends GLContext {
return true;
}
- private final void setRendererQuirks(int major, int minor, int ctp) {
+ private final void setRendererQuirks(int major, int minor, int ctp, VersionNumberString vendorVersion) {
int[] quirks = new int[GLRendererQuirks.COUNT];
int i = 0;
@@ -1555,6 +1559,7 @@ public abstract class GLContextImpl extends GLContext {
}
if( glRendererLowerCase.contains("intel(r)") && compatCtx && ( major>3 || major==3 && minor>=1 ) )
{
+ // FIXME: Apply vendor version constraints!
final int quirk = GLRendererQuirks.GLNonCompliant;
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer " + glRenderer);
@@ -1562,43 +1567,28 @@ public abstract class GLContextImpl extends GLContext {
quirks[i++] = quirk;
}
}
-
- //
- // Mesa RENDERER related quirks
- //
if( glRendererLowerCase.contains("mesa") ) {
- // Added March 30, 2013
- // Martin C. Hegedus
- if ( glRendererLowerCase.contains("x11") && getMesaMajorVersion(glVersion) < 8.0 ) {
- final int quirk = GLRendererQuirks.DontCloseX11DisplayConnection;
+ if ( glRendererLowerCase.contains("x11") && vendorVersion.compareTo(Version80) < 0 ) {
+ final int quirk = GLRendererQuirks.DontCloseX11Display;
if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Mesa X11 < 8 : Renderer=" + glRenderer + ", Version=" +glVersion);
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer=" + glRenderer + ", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]");
}
quirks[i++] = quirk;
- }
+ }
+ }
+ if( glRendererLowerCase.contains("ati technologies") || glRendererLowerCase.startsWith("ati ") ) {
+ {
+ final int quirk = GLRendererQuirks.DontCloseX11Display;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer=" + glRenderer);
+ }
+ quirks[i++] = quirk;
+ }
}
glRendererQuirks = new GLRendererQuirks(quirks, 0, i);
}
- // Added by Martin C. Hegedus, March 30, 2013
- private static final int getMesaMajorVersion(String version) {
- if (version == null || version.length() <= 0) return -1;
- String[] strings = version.trim().split("\\s+");
- if (strings.length <= 0) return -1;
- version = strings[strings.length-1];
- int index = version.indexOf(".");
- if (index == 0) return -1;
- if (index != -1) version = version.substring(0,index);
- try {
- Integer iNumber = new Integer(version);
- return (iNumber == null) ? -1 : iNumber.intValue();
- } catch (Throwable t) {
- return -1;
- }
- }
-
-
private static final boolean hasFBOImpl(int major, int ctp, ExtensionAvailabilityCache extCache) {
return ( 0 != (ctp & CTX_PROFILE_ES) && major >= 2 ) || // ES >= 2.0
diff --git a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
index 83815f7a4..1784cd772 100644
--- a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
+++ b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
@@ -32,24 +32,23 @@ import java.util.StringTokenizer;
import javax.media.opengl.GLContext;
-import com.jogamp.common.util.VersionNumber;
+import com.jogamp.common.util.VersionNumberString;
/**
* A class for storing and comparing OpenGL version numbers.
* This only works for desktop OpenGL at the moment.
*/
-class GLVersionNumber extends VersionNumber {
+class GLVersionNumber extends VersionNumberString {
- protected boolean valid;
+ private final boolean valid;
- public GLVersionNumber(int majorRev, int minorRev, int subMinorRev) {
- super(majorRev, minorRev, subMinorRev);
- valid = true;
+ private GLVersionNumber(int[] val, String versionString, boolean valid) {
+ super(val[0], val[1], val[2], versionString);
+ this.valid = valid;
}
-
- public GLVersionNumber(String versionString) {
- super();
- valid = false;
+
+ public static GLVersionNumber create(String versionString) {
+ int[] val = new int[] { 0, 0, 0 };
try {
if (versionString.startsWith("GL_VERSION_")) {
StringTokenizer tok = new StringTokenizer(versionString, "_");
@@ -57,19 +56,19 @@ class GLVersionNumber extends VersionNumber {
tok.nextToken(); // VERSION_
if (!tok.hasMoreTokens()) {
val[0] = 0;
- return;
- }
- val[0] = Integer.valueOf(tok.nextToken()).intValue();
- if (!tok.hasMoreTokens()) {
- val[1] = 0;
- return;
- }
- val[1] = Integer.valueOf(tok.nextToken()).intValue();
- if (!tok.hasMoreTokens()) {
- val[2] = 0;
- return;
+ } else {
+ val[0] = Integer.valueOf(tok.nextToken()).intValue();
+ if (!tok.hasMoreTokens()) {
+ val[1] = 0;
+ } else {
+ val[1] = Integer.valueOf(tok.nextToken()).intValue();
+ if (!tok.hasMoreTokens()) {
+ val[2] = 0;
+ } else {
+ val[2] = Integer.valueOf(tok.nextToken()).intValue();
+ }
+ }
}
- val[2] = Integer.valueOf(tok.nextToken()).intValue();
} else {
int radix = 10;
if (versionString.length() > 2) {
@@ -105,7 +104,7 @@ class GLVersionNumber extends VersionNumber {
}
}
}
- valid = true;
+ return new GLVersionNumber(val, versionString, true);
} catch (Exception e) {
e.printStackTrace();
// FIXME: refactor desktop OpenGL dependencies and make this
@@ -118,11 +117,41 @@ class GLVersionNumber extends VersionNumber {
new IllegalArgumentException(
"Illegally formatted version identifier: \"" + versionString + "\"")
.initCause(e);
- */
+ */
}
+ return new GLVersionNumber(val, versionString, false);
}
public final boolean isValid() {
return valid;
}
+
+ /**
+ * Returns the optional vendor version at the end of the
+ * GL_VERSION
string if exists, otherwise null
.
+ *
+ * 2.1 Mesa 7.0.3-rc2 -> 7.0.3 (7.0.3-rc2)
+ * 4.2.12171 Compatibility Profile Context 9.01.8 -> 9.1.8 (9.01.8)
+ * 4.3.0 NVIDIA 310.32 -> 310.32 (310.32)
+ *
+ */
+ public static final VersionNumberString createVendorVersion(String versionString) {
+ if (versionString == null || versionString.length() <= 0) {
+ return null;
+ }
+ final String[] strings = versionString.trim().split("\\s+");
+ if ( strings.length <= 0 ) {
+ return null;
+ }
+ // Test all segments backwards from [len-1..1], skipping the 1st entry (GL version)
+ // If a segment represents a valid VersionNumber - use it.
+ for(int i=strings.length-1; i>=1; i--) {
+ final String s = strings[i];
+ final VersionNumberString version = new VersionNumberString(s, ".");
+ if( !version.isZero() ) {
+ return version;
+ }
+ }
+ return null;
+ }
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index be3729a7d..9b87860cb 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -113,6 +113,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
// Check for other underlying stuff ..
if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true)) {
+ hasX11 = true;
try {
ReflectionUtil.createInstance("jogamp.opengl.x11.glx.X11GLXGraphicsConfigurationFactory", EGLDrawableFactory.class.getClassLoader());
} catch (Exception jre) { /* n/a .. */ }
@@ -262,6 +263,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
private EGLGraphicsDevice defaultDevice = null;
private SharedResource defaultSharedResource = null;
private boolean isANGLE = false;
+ private boolean hasX11 = false;
static class SharedResource {
private final EGLGraphicsDevice device;
@@ -568,6 +570,10 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
// avoid exception due to double 'set' - carefull exception of the rule.
EGLContext.setAvailableGLVersionsSet(adevice);
}
+ if( hasX11 ) {
+ handleDontCloseX11DisplayQuirk(rendererQuirksES1[0]);
+ handleDontCloseX11DisplayQuirk(rendererQuirksES2[0]);
+ }
final SharedResource sr = new SharedResource(defaultDevice, madeCurrentES1, hasPBufferES1[0], rendererQuirksES1[0], ctpES1[0],
madeCurrentES2, hasPBufferES2[0], rendererQuirksES2[0], ctpES2[0]);
@@ -582,6 +588,12 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
return sr;
}
+
+ private void handleDontCloseX11DisplayQuirk(GLRendererQuirks quirks) {
+ if( null != quirks && quirks.exist( GLRendererQuirks.DontCloseX11Display ) ) {
+ jogamp.nativewindow.x11.X11Util.markAllDisplaysUnclosable();
+ }
+ }
@Override
protected final Thread getSharedResourceThread() {
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index 2f3940baa..9486b5875 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -73,6 +73,7 @@ import jogamp.opengl.SharedResourceRunner;
import com.jogamp.common.util.VersionNumber;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
+import com.jogamp.opengl.GLRendererQuirks;
public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
@@ -236,6 +237,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
res = GLXUtil.isGLXAvailableOnServer(x11Device);
} finally {
x11Device.unlock();
+ x11Device.close();
}
if(DEBUG) {
System.err.println("GLX "+(res ? "is" : "not")+" available on device/server: "+x11Device);
@@ -276,6 +278,9 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
} finally {
sharedContext.release();
}
+ if( sharedContext.hasRendererQuirk( GLRendererQuirks.DontCloseX11Display ) ) {
+ X11Util.markAllDisplaysUnclosable();
+ }
if (DEBUG) {
System.err.println("SharedDevice: " + sharedDevice);
System.err.println("SharedScreen: " + sharedScreen);
diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
index 2fb780fa2..e28aff116 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11Util.java
@@ -82,6 +82,9 @@ public class X11Util implements ToolkitProperties {
*
*/
public static final boolean ATI_HAS_XCLOSEDISPLAY_BUG = !Debug.isPropertyDefined("nativewindow.debug.X11Util.ATI_HAS_NO_XCLOSEDISPLAY_BUG", true);
+
+ /** See {@link #ATI_HAS_XCLOSEDISPLAY_BUG}. */
+ public static final boolean HAS_XCLOSEDISPLAY_BUG = Debug.isPropertyDefined("nativewindow.debug.X11Util.HAS_XCLOSEDISPLAY_BUG", true);
/**
* See Bug 623 - https://jogamp.org/bugzilla/show_bug.cgi?id=623
@@ -137,14 +140,11 @@ public class X11Util implements ToolkitProperties {
hasX11_EXTENSION_ATIFGLRXDRI = false;
hasX11_EXTENSION_ATIFGLEXTENSION = false;
}
- hasThreadingIssues = ATI_HAS_MULTITHREADING_BUG && ( hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION );
- // A check on nativewindow.debug.X11Util.HasX11CloseDisplayBug added March 30, 2013
- // Martin C. Hegedus
- if (!markAllDisplaysUnclosable) {
- markAllDisplaysUnclosable = ATI_HAS_XCLOSEDISPLAY_BUG && ( hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION );
- if (Debug.isPropertyDefined("nativewindow.debug.X11Util.HasX11CloseDisplayBug", true))
- markAllDisplaysUnclosable = true;
- }
+ final boolean isATIFGLRX = hasX11_EXTENSION_ATIFGLRXDRI || hasX11_EXTENSION_ATIFGLEXTENSION ;
+ hasThreadingIssues = ATI_HAS_MULTITHREADING_BUG && isATIFGLRX;
+ if ( !markAllDisplaysUnclosable ) {
+ markAllDisplaysUnclosable = ( ATI_HAS_XCLOSEDISPLAY_BUG && isATIFGLRX ) || HAS_XCLOSEDISPLAY_BUG;
+ }
if(DEBUG) {
System.err.println("X11Util.initSingleton(): OK "+isInitOK+"]"+
@@ -184,10 +184,10 @@ public class X11Util implements ToolkitProperties {
synchronized(X11Util.class) {
if(isInit) {
final boolean isJVMShuttingDown = NativeWindowFactory.isJVMShuttingDown() ;
- // Modified March 30, 2013 so output is not created under "expected" circumstances
- // Martin C. Hegedus
- if(DEBUG || ((openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0) &&
- !(reusableDisplayList.size() == pendingDisplayList.size() && markAllDisplaysUnclosable))) {
+ if( DEBUG ||
+ ( ( openDisplayMap.size() > 0 || reusableDisplayList.size() > 0 || pendingDisplayList.size() > 0 ) &&
+ ( reusableDisplayList.size() != pendingDisplayList.size() || !markAllDisplaysUnclosable )
+ ) ) {
System.err.println("X11Util.Display: Shutdown (JVM shutdown: "+isJVMShuttingDown+
", open (no close attempt): "+openDisplayMap.size()+"/"+openDisplayList.size()+
", reusable (open, marked uncloseable): "+reusableDisplayList.size()+
@@ -250,21 +250,22 @@ public class X11Util implements ToolkitProperties {
public static String getNullDisplayName() {
return nullDisplayName;
}
-
- // Added March 30, 2013
- // Martin C. Hegedus
+
public static void markAllDisplaysUnclosable() {
synchronized(globalLock) {
- markAllDisplaysUnclosable = true;
- for(int i=0; i
Date: Tue, 16 Apr 2013 06:19:08 +0200
Subject: Fix Bug 705 - Set Quirk DontCloseX11Display also if using X11 and
X11Util has set 'markAllDisplaysUnclosable' (Down -> Upstream)
---
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 40 +++++++++++++++--------
1 file changed, 26 insertions(+), 14 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 3657cacda..7b760ed0e 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -61,6 +61,7 @@ import com.jogamp.opengl.GLRendererQuirks;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.NativeWindowFactory;
import javax.media.opengl.GL;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
@@ -1567,22 +1568,33 @@ public abstract class GLContextImpl extends GLContext {
quirks[i++] = quirk;
}
}
- if( glRendererLowerCase.contains("mesa") ) {
- if ( glRendererLowerCase.contains("x11") && vendorVersion.compareTo(Version80) < 0 ) {
- final int quirk = GLRendererQuirks.DontCloseX11Display;
- if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer=" + glRenderer + ", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]");
+
+ //
+ // Quirk: DontCloseX11Display
+ //
+ {
+ final int quirk = GLRendererQuirks.DontCloseX11Display;
+ if( glRendererLowerCase.contains("mesa") ) {
+ if ( glRendererLowerCase.contains("x11") && vendorVersion.compareTo(Version80) < 0 ) {
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer=" + glRenderer + ", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]");
+ }
+ quirks[i++] = quirk;
+ }
+ } else if( glRendererLowerCase.contains("ati technologies") || glRendererLowerCase.startsWith("ati ") ) {
+ {
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer=" + glRenderer);
+ }
+ quirks[i++] = quirk;
}
- quirks[i++] = quirk;
- }
- }
- if( glRendererLowerCase.contains("ati technologies") || glRendererLowerCase.startsWith("ati ") ) {
- {
- final int quirk = GLRendererQuirks.DontCloseX11Display;
- if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer=" + glRenderer);
+ } else if( NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
+ if( jogamp.nativewindow.x11.X11Util.getMarkAllDisplaysUnclosable() ) {
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11Util Downstream");
+ }
+ quirks[i++] = quirk;
}
- quirks[i++] = quirk;
}
}
--
cgit v1.2.3
From fd418a69eca7b8c1bb74244982305fc6004d0a52 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Thu, 18 Apr 2013 03:16:33 +0200
Subject: Fix Bug 720: Unify all platform specific GLContextImpl
specializations; Fix Bug 719 - Windows BITMAP Offscreen Orientation is not
propagated through API
Fix Bug 719 - Windows BITMAP Offscreen Orientation is not propagated through API
Depends on Bug 720, since cleaning up GLContextImpl* is required to move
property 'GLContext.isGLOrientationFlippedVertical()'
to 'GLDrawable.isGLOriented()' where it belongs!
Windows BITMAP GLDrawable impl. isGLOriented() shall return false,
while we keep the BITMAPINFOHEADER's height field negative
to remove the need for vertical flip when used w/ AWT or Windows, ..
Then property 'GLDrawable.isGLOriented()' has to be recognized throughout the
utility functions, i.e. TextureData's mustFlipVertically and hence TextureIO writer.
Fix Bug 720: Unify all platform specific GLContextImpl specializations
GLContextImpl shall have only _one_ unique platform derivative
to allow proper swapping of GLDrawables of any type via:
- 'GLAutoDrawable.setContext(GLContext newCtx, boolean destroyPrevCtx)', which calls
- 'GLContext.setGLDrawable(GLDrawable readWrite, boolean setWriteOnly)'
Exception: External context may be specialized.
All drawable specific property handling shall be provided
and implemented (if possible) via GLDrawable specializations.
- GLContext.isGLOrientationFlippedVertical() -> GLDrawable.isGLOriented()
- PNGImage.createFromData() takes 'isGLOriented' to properly handle vertical flipping simply by line ordering
- TextureIO's PNG writer passes TextureData's getMustFlipVertically() as isGLOriented to PNGImage.createFromData()
- GLReadBufferUtil respects GLDrawable's isGLOriented() when creating TextureData instance.
- Screenshot respects GLDrawable's isGLOriented()
- Screenshot is deprecated, use GLReadBufferUtil.
- Removed all PBuffer attributes, i.e. floatingPoint, RenderToTexture and RenderToTextureRectangle.
- Allows removal of special pbuffer handling in GLContext* implementations.
- Removed also from GLCapabilities*
- Removed from deprecated GLPbuffer
Impact:
- Low, users who desire to render into a texture shall use our FBO GLOffscreenDrawable.
- Only use case was the deprecated GLPbuffer
- floating point framebuffer technology is still patented anyways :)
- Removed Java2DGLContext, which was only used for OSX's GLJPanel Java2D bridge,
which is no more supported anyways.
---
make/scripts/tests-x64.bat | 4 +-
make/scripts/tests.sh | 4 +-
.../classes/com/jogamp/opengl/swt/GLCanvas.java | 6 +
.../com/jogamp/opengl/util/GLReadBufferUtil.java | 17 ++-
.../com/jogamp/opengl/util/awt/Screenshot.java | 36 +++--
.../com/jogamp/opengl/util/texture/TextureIO.java | 2 +-
.../jogamp/opengl/util/texture/spi/PNGImage.java | 121 +++++++++++-----
.../classes/javax/media/opengl/GLCapabilities.java | 55 +-------
.../media/opengl/GLCapabilitiesImmutable.java | 27 ----
src/jogl/classes/javax/media/opengl/GLContext.java | 10 --
.../classes/javax/media/opengl/GLDrawable.java | 14 ++
.../javax/media/opengl/GLDrawableFactory.java | 9 +-
src/jogl/classes/javax/media/opengl/GLPbuffer.java | 34 -----
.../classes/javax/media/opengl/awt/GLCanvas.java | 6 +
.../classes/javax/media/opengl/awt/GLJPanel.java | 40 ++----
.../classes/jogamp/opengl/GLAutoDrawableBase.java | 6 +
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 7 +-
.../jogamp/opengl/GLDrawableFactoryImpl.java | 11 --
src/jogl/classes/jogamp/opengl/GLDrawableImpl.java | 5 +
src/jogl/classes/jogamp/opengl/GLPbufferImpl.java | 37 +----
.../classes/jogamp/opengl/awt/Java2DGLContext.java | 52 -------
src/jogl/classes/jogamp/opengl/egl/EGLContext.java | 2 +-
.../jogamp/opengl/egl/EGLDrawableFactory.java | 11 --
.../jogamp/opengl/egl/EGLOnscreenContext.java | 45 ------
.../jogamp/opengl/egl/EGLOnscreenDrawable.java | 2 +-
.../jogamp/opengl/egl/EGLPbufferContext.java | 50 -------
.../jogamp/opengl/egl/EGLPbufferDrawable.java | 2 +-
.../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 61 +++++++-
.../macosx/cgl/MacOSXCGLDrawableFactory.java | 11 --
.../macosx/cgl/MacOSXCGLGraphicsConfiguration.java | 8 +-
.../macosx/cgl/MacOSXOffscreenCGLContext.java | 56 --------
.../macosx/cgl/MacOSXOffscreenCGLDrawable.java | 2 +-
.../macosx/cgl/MacOSXOnscreenCGLContext.java | 115 ---------------
.../macosx/cgl/MacOSXOnscreenCGLDrawable.java | 2 +-
.../opengl/macosx/cgl/MacOSXPbufferCGLContext.java | 95 -------------
.../macosx/cgl/MacOSXPbufferCGLDrawable.java | 24 +---
.../cgl/awt/MacOSXAWTCGLDrawableFactory.java | 60 --------
.../macosx/cgl/awt/MacOSXJava2DCGLContext.java | 121 ----------------
.../opengl/windows/wgl/WGLGLCapabilities.java | 10 +-
.../windows/wgl/WindowsBitmapWGLContext.java | 61 --------
.../windows/wgl/WindowsBitmapWGLDrawable.java | 13 +-
.../windows/wgl/WindowsOnscreenWGLContext.java | 49 -------
.../windows/wgl/WindowsOnscreenWGLDrawable.java | 2 +-
.../windows/wgl/WindowsPbufferWGLContext.java | 156 ---------------------
.../windows/wgl/WindowsPbufferWGLDrawable.java | 39 +-----
.../opengl/windows/wgl/WindowsWGLContext.java | 11 --
.../windows/wgl/WindowsWGLDrawableFactory.java | 11 --
.../wgl/WindowsWGLGraphicsConfiguration.java | 93 +-----------
.../jogamp/opengl/x11/glx/X11GLXContext.java | 12 +-
.../opengl/x11/glx/X11GLXDrawableFactory.java | 11 --
.../x11/glx/X11GLXGraphicsConfiguration.java | 15 --
.../opengl/x11/glx/X11OnscreenGLXContext.java | 48 -------
.../opengl/x11/glx/X11OnscreenGLXDrawable.java | 2 +-
.../opengl/x11/glx/X11PbufferGLXContext.java | 67 ---------
.../opengl/x11/glx/X11PbufferGLXDrawable.java | 20 +--
.../jogamp/opengl/x11/glx/X11PixmapGLXContext.java | 58 --------
.../opengl/x11/glx/X11PixmapGLXDrawable.java | 2 +-
.../jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java | 47 ++++++-
.../jogl/util/texture/TestPNGImage01NEWT.java | 41 ++++--
59 files changed, 347 insertions(+), 1591 deletions(-)
delete mode 100644 src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java
delete mode 100644 src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java
delete mode 100644 src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat
index 3990fb7b2..05b1414d6 100755
--- a/make/scripts/tests-x64.bat
+++ b/make/scripts/tests-x64.bat
@@ -32,7 +32,7 @@ REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.ect.TestExclu
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $*
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT $*
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT $*
-scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT $*
+REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT $*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryES2OffscrnCapsNEWT $*
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableFactoryNEWT $*
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableOffThreadSharedContextES2NEWT $*
@@ -58,7 +58,7 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 4000 -x 10 -y 10 -width 100 -height 100 -screen 0
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT -vsync -time 40000 -width 100 -height 100 -screen 0 %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT -time 5000
-REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWT -time 5000
+scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWT %*
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %*
REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.demos.gl3.newt.TestGeomShader01TextureGL3NEWT %*
REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.newt.TestSwingAWTRobotUsageBeforeJOGLInitBug411
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 18ff8e756..23dbf3fd0 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -289,7 +289,7 @@ function testawtswt() {
#testswt com.jogamp.opengl.test.junit.jogl.demos.es2.swt.TestGearsES2SWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWTAnalyzeBug455 $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWT $*
+testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsGLJPanelAWTBug450 $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT $*
@@ -339,7 +339,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $*
-testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryES2OffscrnCapsNEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT $*
diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
index 169266152..ff764d849 100644
--- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -588,6 +588,12 @@ public class GLCanvas extends Canvas implements GLAutoDrawable {
return clientArea.height;
}
+ @Override
+ public boolean isGLOriented() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.isGLOriented() : true;
+ }
+
@Override
public void addGLEventListener(final GLEventListener listener) {
helper.addGLEventListener(listener);
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
index b8709f31c..1345d29bd 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLReadBufferUtil.java
@@ -111,11 +111,15 @@ public class GLReadBufferUtil {
*
* @param gl the current GL context object. It's read drawable is being used as the pixel source.
* @param drawable the drawable to read from
- * @param flip weather to flip the data vertically or not
+ * @param mustFlipVertically indicates weather to flip the data vertically or not.
+ * The context's drawable {@link GLDrawable#isGLOriented()} state
+ * is taken into account.
+ * Vertical flipping is propagated to TextureData
+ * and handled in a efficient manner there (TextureCoordinates and TextureIO writer).
*
* @see #GLReadBufferUtil(boolean, boolean)
*/
- public boolean readPixels(GL gl, boolean flip) {
+ public boolean readPixels(GL gl, boolean mustFlipVertically) {
final int glerr0 = gl.glGetError();
if(GL.GL_NO_ERROR != glerr0) {
System.err.println("Info: GLReadBufferUtil.readPixels: pre-exisiting GL error 0x"+Integer.toHexString(glerr0));
@@ -124,6 +128,13 @@ public class GLReadBufferUtil {
final int textureInternalFormat, textureDataFormat, textureDataType;
final int[] glImplColorReadVals = new int[] { 0, 0 };
+ final boolean flipVertically;
+ if( drawable.isGLOriented() ) {
+ flipVertically = mustFlipVertically;
+ } else {
+ flipVertically = !mustFlipVertically;
+ }
+
if(gl.isGL2GL3() && 3 == components) {
textureInternalFormat=GL.GL_RGB;
textureDataFormat=GL.GL_RGB;
@@ -158,7 +169,7 @@ public class GLReadBufferUtil {
textureDataFormat,
textureDataType,
false, false,
- flip,
+ flipVertically,
readPixelBuffer,
null /* Flusher */);
newData = true;
diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
index 0022d5c2d..0eab65380 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2013 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -43,17 +44,24 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
+import javax.media.opengl.GL;
import javax.media.opengl.GL2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLException;
-import javax.media.opengl.glu.gl2.GLUgl2;
import com.jogamp.common.util.IOUtil;
import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.util.GLPixelStorageModes;
import com.jogamp.opengl.util.TGAWriter;
-/** Utilities for taking screenshots of OpenGL applications. */
-
+/**
+ * Utilities for taking screenshots of OpenGL applications.
+ * @deprecated Please consider using {@link com.jogamp.opengl.util.GLReadBufferUtil},
+ * which is AWT independent and does not require a CPU based vertical image flip
+ * in case drawable {@link GLDrawable#isGLOriented() is in OpenGL orientation}.
+ */
public class Screenshot {
private Screenshot() {}
@@ -149,17 +157,17 @@ public class Screenshot {
writer.open(file, width, height, alpha);
ByteBuffer bgr = writer.getImageData();
- GL2 gl = GLUgl2.getCurrentGL2();
+ GL gl = GLContext.getCurrentGL();
// Set up pixel storage modes
GLPixelStorageModes psm = new GLPixelStorageModes();
psm.setPackAlignment(gl, 1);
- int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2.GL_BGR);
+ int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2GL3.GL_BGR);
// read the BGR values into the image buffer
gl.glReadPixels(x, y, width, height, readbackType,
- GL2.GL_UNSIGNED_BYTE, bgr);
+ GL.GL_UNSIGNED_BYTE, bgr);
// Restore pixel storage modes
psm.restore(gl);
@@ -247,7 +255,7 @@ public class Screenshot {
int height,
boolean alpha) throws GLException {
int bufImgType = (alpha ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR);
- int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2.GL_BGR);
+ int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2GL3.GL_BGR);
if (alpha) {
checkExtABGR();
@@ -256,7 +264,8 @@ public class Screenshot {
// Allocate necessary storage
BufferedImage image = new BufferedImage(width, height, bufImgType);
- GL2 gl = GLUgl2.getCurrentGL2();
+ GLContext glc = GLContext.getCurrent();
+ GL gl = glc.getGL();
// Set up pixel storage modes
GLPixelStorageModes psm = new GLPixelStorageModes();
@@ -264,14 +273,16 @@ public class Screenshot {
// read the BGR values into the image
gl.glReadPixels(x, y, width, height, readbackType,
- GL2.GL_UNSIGNED_BYTE,
+ GL.GL_UNSIGNED_BYTE,
ByteBuffer.wrap(((DataBufferByte) image.getRaster().getDataBuffer()).getData()));
// Restore pixel storage modes
psm.restore(gl);
- // Must flip BufferedImage vertically for correct results
- ImageUtil.flipImageVertically(image);
+ if( glc.getGLDrawable().isGLOriented() ) {
+ // Must flip BufferedImage vertically for correct results
+ ImageUtil.flipImageVertically(image);
+ }
return image;
}
@@ -392,7 +403,8 @@ public class Screenshot {
}
private static void checkExtABGR() {
- GL2 gl = GLUgl2.getCurrentGL2();
+ GL gl = GLContext.getCurrentGL();
+
if (!gl.isExtensionAvailable(GLExtensions.EXT_abgr)) {
throw new IllegalArgumentException("Saving alpha channel requires GL_EXT_abgr");
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
index 0b0af5625..14ceb6421 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
@@ -1408,7 +1408,7 @@ public class TextureIO {
buf.rewind();
PNGImage image = PNGImage.createFromData(data.getWidth(), data.getHeight(), -1f, -1f,
- bytesPerPixel, reversedChannels, buf);
+ bytesPerPixel, reversedChannels, !data.getMustFlipVertically(), buf);
image.write(file, true);
return true;
}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
index 847451b41..b4b00e744 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
@@ -53,20 +53,39 @@ import com.jogamp.common.util.IOUtil;
public class PNGImage {
private static final boolean DEBUG = Debug.debug("PNGImage");
- /** Creates a PNGImage from data supplied by the end user. Shares
- data with the passed ByteBuffer. Assumes the data is already in
- the correct byte order for writing to disk, i.e., LUMINANCE, RGB or RGBA bottom-to-top (OpenGL coord). */
+ /**
+ * Creates a PNGImage from data supplied by the end user. Shares
+ * data with the passed ByteBuffer. Assumes the data is already in
+ * the correct byte order for writing to disk, i.e., LUMINANCE, RGB or RGBA.
+ * Orientation is bottom-to-top (OpenGL coord. default)
+ * or top-to-bottom depending on isGLOriented
.
+ *
+ * @param width
+ * @param height
+ * @param dpiX
+ * @param dpiY
+ * @param bytesPerPixel
+ * @param reversedChannels
+ * @param isGLOriented see {@link #isGLOriented()}.
+ * @param data
+ * @return
+ */
public static PNGImage createFromData(int width, int height, double dpiX, double dpiY,
- int bytesPerPixel, boolean reversedChannels, ByteBuffer data) {
- return new PNGImage(width, height, dpiX, dpiY, bytesPerPixel, reversedChannels, data);
+ int bytesPerPixel, boolean reversedChannels, boolean isGLOriented, ByteBuffer data) {
+ return new PNGImage(width, height, dpiX, dpiY, bytesPerPixel, reversedChannels, isGLOriented, data);
}
- /** Reads a PNG image from the specified InputStream. */
+ /**
+ * Reads a PNG image from the specified InputStream.
+ *
+ * Implicitly flip image to GL orientation, see {@link #isGLOriented()}.
+ *
+ */
public static PNGImage read(InputStream in) throws IOException {
return new PNGImage(in);
}
- /** Reverse read and store, implicitly flip image to GL coords. */
+ /** Reverse read and store, implicitly flip image to GL orientation, see {@link #isGLOriented()}. */
private static final int getPixelRGBA8(ByteBuffer d, int dOff, int[] scanline, int lineOff, boolean hasAlpha) {
if(hasAlpha) {
d.put(dOff--, (byte)scanline[lineOff + 3]); // A
@@ -76,27 +95,28 @@ public class PNGImage {
d.put(dOff--, (byte)scanline[lineOff ]); // R
return dOff;
}
- /** Reverse read and store, implicitly flip image from GL coords. Handle reversed channels (BGR[A])*/
- private static int setPixelRGBA8(ImageLine line, int lineOff, ByteBuffer d, int dOff, boolean hasAlpha, boolean reversedChannels) {
- if(reversedChannels) {
- line.scanline[lineOff ] = d.get(dOff--); // R, A
- line.scanline[lineOff + 1] = d.get(dOff--); // G, B
- line.scanline[lineOff + 2] = d.get(dOff--); // B, G
+
+ /** Reverse write and store, implicitly flip image from current orientation, see {@link #isGLOriented()}. Handle reversed channels (BGR[A]). */
+ private int setPixelRGBA8(ImageLine line, int lineOff, ByteBuffer d, int dOff, boolean hasAlpha) {
+ if( reversedChannels ) {
if(hasAlpha) {
- line.scanline[lineOff + 3] = d.get(dOff--);// R
+ line.scanline[lineOff + 3] = d.get(dOff++); // A
}
+ line.scanline[lineOff + 2] = d.get(dOff++); // R
+ line.scanline[lineOff + 1] = d.get(dOff++); // G
+ line.scanline[lineOff ] = d.get(dOff++); // B
} else {
+ line.scanline[lineOff ] = d.get(dOff++); // R
+ line.scanline[lineOff + 1] = d.get(dOff++); // G
+ line.scanline[lineOff + 2] = d.get(dOff++); // B
if(hasAlpha) {
- line.scanline[lineOff + 3] = d.get(dOff--); // A
+ line.scanline[lineOff + 3] = d.get(dOff++); // A
}
- line.scanline[lineOff + 2] = d.get(dOff--); // B
- line.scanline[lineOff + 1] = d.get(dOff--); // G
- line.scanline[lineOff ] = d.get(dOff--); // R
}
- return dOff;
+ return isGLOriented ? dOff - bytesPerPixel - bytesPerPixel : dOff;
}
- private PNGImage(int width, int height, double dpiX, double dpiY, int bytesPerPixel, boolean reversedChannels, ByteBuffer data) {
+ private PNGImage(int width, int height, double dpiX, double dpiY, int bytesPerPixel, boolean reversedChannels, boolean isGLOriented, ByteBuffer data) {
pixelWidth=width;
pixelHeight=height;
dpi = new double[] { dpiX, dpiY };
@@ -109,6 +129,7 @@ public class PNGImage {
}
this.bytesPerPixel = bytesPerPixel;
this.reversedChannels = reversedChannels;
+ this.isGLOriented = isGLOriented;
this.data = data;
}
@@ -162,13 +183,14 @@ public class PNGImage {
data = Buffers.newDirectByteBuffer(bytesPerPixel * pixelWidth * pixelHeight);
reversedChannels = false; // RGB[A]
+ isGLOriented = true;
int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse store
int[] rgbaScanline = indexed ? new int[imgInfo.cols * channels] : null;
for (int row = 0; row < pixelHeight; row++) {
final ImageLine l1 = pngr.readRow(row);
- int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse read
+ int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse read (PNG top-left -> OpenGL bottom-left origin)
if( indexed ) {
for (int j = pixelWidth - 1; j >= 0; j--) {
rgbaScanline = ImageLineHelper.palette2rgb(l1, plte, trns, rgbaScanline); // reuse rgbaScanline and update if resized
@@ -189,7 +211,8 @@ public class PNGImage {
pngr.end();
}
private final int pixelWidth, pixelHeight, glFormat, bytesPerPixel;
- private boolean reversedChannels;
+ private final boolean reversedChannels;
+ private final boolean isGLOriented;
private final double[] dpi;
private final ByteBuffer data;
@@ -202,6 +225,16 @@ public class PNGImage {
/** Returns true if data has the channels reversed to BGR or BGRA, otherwise RGB or RGBA is expected. */
public boolean getHasReversedChannels() { return reversedChannels; }
+ /**
+ * Returns true
if the drawable is rendered in
+ * OpenGL's coordinate system, origin at bottom left.
+ * Otherwise returns false
, i.e. origin at top left.
+ *
+ * Default impl. is true
, i.e. OpenGL coordinate system.
+ *
+ */
+ public boolean isGLOriented() { return isGLOriented; }
+
/** Returns the dpi of the image. */
public double[] getDpi() { return dpi; }
@@ -231,20 +264,40 @@ public class PNGImage {
// png.getMetadata().setText("my key", "my text");
final boolean hasAlpha = 4 == bytesPerPixel;
final ImageLine l1 = new ImageLine(imi);
- int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse read
- for (int row = 0; row < pixelHeight; row++) {
- int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse store
- if(1 == bytesPerPixel) {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- l1.scanline[lineOff--] = data.get(dataOff--); // // Luminance, 1 bytesPerPixel
- }
- } else {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha, reversedChannels);
- lineOff -= bytesPerPixel;
+ if( isGLOriented ) {
+ // start at last pixel at end-of-buffer, reverse read (OpenGL bottom-left -> PNG top-left origin)
+ int dataOff = ( pixelWidth * bytesPerPixel * ( pixelHeight - 1 ) ) + // full lines - 1 line
+ ( ( pixelWidth - 1 ) * bytesPerPixel ); // one line - 1 pixel
+ for (int row = 0; row < pixelHeight; row++) {
+ int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse store (OpenGL bottom-left -> PNG top-left origin)
+ if(1 == bytesPerPixel) {
+ for (int j = pixelWidth - 1; j >= 0; j--) {
+ l1.scanline[lineOff--] = data.get(dataOff--); // // Luminance, 1 bytesPerPixel
+ }
+ } else {
+ for (int j = pixelWidth - 1; j >= 0; j--) {
+ dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha);
+ lineOff -= bytesPerPixel;
+ }
}
+ png.writeRow(l1, row);
}
- png.writeRow(l1, row);
+ } else {
+ int dataOff = 0; // start at first pixel at start-of-buffer, normal read (same origin: top-left)
+ for (int row = 0; row < pixelHeight; row++) {
+ int lineOff = 0; // start w/ first pixel in line, normal store (same origin: top-left)
+ if(1 == bytesPerPixel) {
+ for (int j = pixelWidth - 1; j >= 0; j--) {
+ l1.scanline[lineOff++] = data.get(dataOff++); // // Luminance, 1 bytesPerPixel
+ }
+ } else {
+ for (int j = pixelWidth - 1; j >= 0; j--) {
+ dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha);
+ lineOff += bytesPerPixel;
+ }
+ }
+ png.writeRow(l1, row);
+ }
}
png.end();
} finally {
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilities.java b/src/jogl/classes/javax/media/opengl/GLCapabilities.java
index 09db70f64..5b3eb9119 100644
--- a/src/jogl/classes/javax/media/opengl/GLCapabilities.java
+++ b/src/jogl/classes/javax/media/opengl/GLCapabilities.java
@@ -75,11 +75,6 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
private boolean sampleBuffers = false;
private int numSamples = 2;
- // Bits for pbuffer creation
- private boolean pbufferFloatingPointBuffers;
- private boolean pbufferRenderToTexture;
- private boolean pbufferRenderToTextureRectangle;
-
/** Creates a GLCapabilities object. All attributes are in a default state.
* @param glp GLProfile, or null for the default GLProfile
* @throws GLException if no profile is given and no default profile is available for the default device.
@@ -122,9 +117,6 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
accumBlueBits = source.getAccumBlueBits();
accumAlphaBits = source.getAccumAlphaBits();
sampleBuffers = source.getSampleBuffers();
- pbufferFloatingPointBuffers = source.getPbufferFloatingPointBuffers();
- pbufferRenderToTexture = source.getPbufferRenderToTexture();
- pbufferRenderToTextureRectangle = source.getPbufferRenderToTextureRectangle();
numSamples = source.getNumSamples();
sampleExtension = source.getSampleExtension();
return this;
@@ -148,9 +140,6 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
hash = ((hash << 5) - hash) + this.accumGreenBits;
hash = ((hash << 5) - hash) + this.accumBlueBits;
hash = ((hash << 5) - hash) + this.accumAlphaBits;
- hash = ((hash << 5) - hash) + ( this.pbufferFloatingPointBuffers ? 1 : 0 );
- hash = ((hash << 5) - hash) + ( this.pbufferRenderToTexture ? 1 : 0 );
- hash = ((hash << 5) - hash) + ( this.pbufferRenderToTextureRectangle ? 1 : 0 );
return hash;
}
@@ -174,10 +163,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
other.getAccumGreenBits()==accumGreenBits &&
other.getAccumBlueBits()==accumBlueBits &&
other.getAccumAlphaBits()==accumAlphaBits &&
- other.getSampleBuffers()==sampleBuffers &&
- other.getPbufferFloatingPointBuffers()==pbufferFloatingPointBuffers &&
- other.getPbufferRenderToTexture()==pbufferRenderToTexture &&
- other.getPbufferRenderToTextureRectangle()==pbufferRenderToTextureRectangle;
+ other.getSampleBuffers()==sampleBuffers;
if(res && sampleBuffers) {
res = other.getNumSamples()==getNumSamples() &&
other.getSampleExtension().equals(sampleExtension) ;
@@ -449,40 +435,6 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
return sampleBuffers ? numSamples : 0;
}
- /** For pbuffers only, indicates whether floating-point buffers
- should be used if available. Defaults to false. */
- public void setPbufferFloatingPointBuffers(boolean enable) {
- pbufferFloatingPointBuffers = enable;
- }
-
- @Override
- public final boolean getPbufferFloatingPointBuffers() {
- return pbufferFloatingPointBuffers;
- }
-
- /** For pbuffers only, indicates whether the render-to-texture
- extension should be used if available. Defaults to false. */
- public void setPbufferRenderToTexture(boolean enable) {
- pbufferRenderToTexture = enable;
- }
-
- @Override
- public final boolean getPbufferRenderToTexture() {
- return pbufferRenderToTexture;
- }
-
- /** For pbuffers only, indicates whether the
- render-to-texture-rectangle extension should be used if
- available. Defaults to false. */
- public void setPbufferRenderToTextureRectangle(boolean enable) {
- pbufferRenderToTextureRectangle = enable;
- }
-
- @Override
- public final boolean getPbufferRenderToTextureRectangle() {
- return pbufferRenderToTextureRectangle;
- }
-
@Override
public StringBuilder toString(StringBuilder sink) {
if(null == sink) {
@@ -526,10 +478,7 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil
}
if(isPBuffer()) {
if(ns) { sink.append(CSEP); }
- sink.append("pbuffer [r2t ").append(pbufferRenderToTexture?1:0)
- .append(", r2tr ").append(pbufferRenderToTextureRectangle?1:0)
- .append(", float ").append(pbufferFloatingPointBuffers?1:0)
- .append("]");
+ sink.append("pbuffer");
ns = true;
}
if(isBitmap()) {
diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
index ee261ca01..6af35021f 100644
--- a/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
+++ b/src/jogl/classes/javax/media/opengl/GLCapabilitiesImmutable.java
@@ -129,33 +129,6 @@ public interface GLCapabilitiesImmutable extends CapabilitiesImmutable {
*/
int getNumSamples();
- /**
- * For pbuffers only, returns whether floating-point buffers should
- * be used if available.
- *
- * Default is false.
- *
- */
- boolean getPbufferFloatingPointBuffers();
-
- /**
- * For pbuffers only, returns whether the render-to-texture
- * extension should be used if available.
- *
- * Default is false.
- *
- */
- boolean getPbufferRenderToTexture();
-
- /**
- * For pbuffers only, returns whether the render-to-texture
- * extension should be used.
- *
- * Default is false.
- *
- */
- boolean getPbufferRenderToTextureRectangle();
-
/**
* Returns the number of stencil buffer bits.
*
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 23ca96504..d26076344 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -1026,16 +1026,6 @@ public abstract class GLContext {
*/
public abstract int getDefaultReadBuffer();
- /** On some platforms the mismatch between OpenGL's coordinate
- system (origin at bottom left) and the window system's
- coordinate system (origin at top left) necessitates a vertical
- flip of pixels read from offscreen contexts.
-
- Default impl. is true
.
-
- */
- public abstract boolean isGLOrientationFlippedVertical();
-
/** Get the default pixel data type, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}. */
public abstract int getDefaultPixelDataType();
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawable.java b/src/jogl/classes/javax/media/opengl/GLDrawable.java
index 65c8b2ea5..369ea6d2b 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawable.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawable.java
@@ -145,6 +145,20 @@ public interface GLDrawable {
/** Returns the current height of this GLDrawable. */
public int getHeight();
+ /**
+ * Returns true
if the drawable is rendered in
+ * OpenGL's coordinate system, origin at bottom left.
+ * Otherwise returns false
, i.e. origin at top left.
+ *
+ * Default impl. is true
, i.e. OpenGL coordinate system.
+ *
+ *
+ * Currently only MS-Windows bitmap offscreen drawable uses a non OpenGL orientation and hence returns false
.
+ * This removes the need of a vertical flip when used in AWT or Windows applications.
+ *
+ */
+ public boolean isGLOriented();
+
/** Swaps the front and back buffers of this drawable. For {@link
GLAutoDrawable} implementations, when automatic buffer swapping
is enabled (as is the default), this method is called
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index e775afbff..9feb54a46 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -114,9 +114,6 @@ public abstract class GLDrawableFactory {
*/
protected static final boolean disableOpenGLES = Debug.isPropertyDefined("jogl.disable.opengles", true);
- static final String macosxFactoryClassNameCGL = "jogamp.opengl.macosx.cgl.MacOSXCGLDrawableFactory";
- static final String macosxFactoryClassNameAWTCGL = "jogamp.opengl.macosx.cgl.awt.MacOSXAWTCGLDrawableFactory";
-
private static volatile boolean isInit = false;
private static GLDrawableFactory eglFactory;
private static GLDrawableFactory nativeOSFactory;
@@ -154,11 +151,7 @@ public abstract class GLDrawableFactory {
} else if ( nwt == NativeWindowFactory.TYPE_WINDOWS ) {
factoryClassName = "jogamp.opengl.windows.wgl.WindowsWGLDrawableFactory";
} else if ( nwt == NativeWindowFactory.TYPE_MACOSX ) {
- if(ReflectionUtil.isClassAvailable(macosxFactoryClassNameAWTCGL, cl)) {
- factoryClassName = macosxFactoryClassNameAWTCGL;
- } else {
- factoryClassName = macosxFactoryClassNameCGL;
- }
+ factoryClassName = "jogamp.opengl.macosx.cgl.MacOSXCGLDrawableFactory";
} else {
// may use egl*Factory ..
if (DEBUG || GLProfile.DEBUG) {
diff --git a/src/jogl/classes/javax/media/opengl/GLPbuffer.java b/src/jogl/classes/javax/media/opengl/GLPbuffer.java
index de7731a3b..12f57fcd8 100644
--- a/src/jogl/classes/javax/media/opengl/GLPbuffer.java
+++ b/src/jogl/classes/javax/media/opengl/GLPbuffer.java
@@ -50,32 +50,7 @@ package javax.media.opengl;
@deprecated Use {@link GLOffscreenAutoDrawable} w/ {@link GLCapabilities#setFBO(boolean)}
via {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) GLDrawableFactory.createOffscreenAutoDrawable(..)}.
*/
-
public interface GLPbuffer extends GLAutoDrawable {
- /** Indicates the GL_APPLE_float_pixels extension is being used for this pbuffer. */
- public static final int APPLE_FLOAT = 1;
-
- /** Indicates the GL_ATI_texture_float extension is being used for this pbuffer. */
- public static final int ATI_FLOAT = 2;
-
- /** Indicates the GL_NV_float_buffer extension is being used for this pbuffer. */
- public static final int NV_FLOAT = 3;
-
- /** Binds this pbuffer to its internal texture target. Only valid to
- call if offscreen render-to-texture has been specified in the
- NWCapabilities for this GLPbuffer. If the
- render-to-texture-rectangle capability has also been specified,
- this will use e.g. wglBindTexImageARB as its implementation and
- cause the texture to be bound to e.g. the
- GL_TEXTURE_RECTANGLE_NV state; otherwise, during the display()
- phase the pixels will have been copied into an internal texture
- target and this will cause that to be bound to the GL_TEXTURE_2D
- state. */
- public void bindTexture();
-
- /** Unbinds the pbuffer from its internal texture target. */
- public void releaseTexture();
-
/** Destroys the native resources associated with this pbuffer. It
is not valid to call display() or any other routines on this
pbuffer after it has been destroyed. Before destroying the
@@ -84,13 +59,4 @@ public interface GLPbuffer extends GLAutoDrawable {
#createContext}. */
@Override
public void destroy();
-
- /** Indicates which vendor's extension is being used to support
- floating point channels in this pbuffer if that capability was
- requested in the NWCapabilities during pbuffer creation. Returns
- one of NV_FLOAT, ATI_FLOAT or APPLE_FLOAT, or throws GLException
- if floating-point channels were not requested for this pbuffer.
- This function may only be called once the init method for this
- pbuffer's GLEventListener has been called. */
- public int getFloatingPointMode();
}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
index c1d5fb1d2..b7a24a777 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java
@@ -886,6 +886,12 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing
return (GLCapabilitiesImmutable)awtConfig.getRequestedCapabilities();
}
+ @Override
+ public boolean isGLOriented() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.isGLOriented() : true;
+ }
+
@Override
public NativeSurface getNativeSurface() {
final GLDrawable _drawable = drawable;
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index e82ad54c3..6ef695319 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -83,17 +83,12 @@ import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableHelper;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.awt.Java2D;
-import jogamp.opengl.awt.Java2DGLContext;
import jogamp.opengl.util.glsl.GLSLTextureRaster;
import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.util.GLPixelStorageModes;
-// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
-// context whenever the displayChanged() function is called on their
-// GLEventListeners
-
/** A lightweight Swing component which provides OpenGL rendering
support. Provided for compatibility with Swing user interfaces
when adding a heavyweight doesn't work either because of
@@ -626,6 +621,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
return oglPipelineUsable;
}
+ @Override
+ public boolean isGLOriented() {
+ if(null != backend) {
+ return backend.getDrawable().isGLOriented();
+ }
+ return true;
+ }
+
@Override
public GLCapabilitiesImmutable getChosenGLCapabilities() {
return backend.getChosenGLCapabilities();
@@ -916,7 +919,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
private final int fboTextureUnit = 0;
private GLContextImpl offscreenContext;
- private boolean flippedVertical;
+ private boolean flipVertical;
// For saving/restoring of OpenGL state during ReadPixels
private final GLPixelStorageModes psm = new GLPixelStorageModes();
@@ -941,9 +944,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) {
isInitialized = true;
final GL gl = offscreenContext.getGL();
- flippedVertical = offscreenContext.isGLOrientationFlippedVertical();
+ flipVertical = offscreenDrawable.isGLOriented();
final GLCapabilitiesImmutable chosenCaps = offscreenDrawable.getChosenGLCapabilities();
- if( USE_GLSL_TEXTURE_RASTERIZER && chosenCaps.isFBO() && flippedVertical && gl.isGL2ES2() ) {
+ if( USE_GLSL_TEXTURE_RASTERIZER && chosenCaps.isFBO() && flipVertical && gl.isGL2ES2() ) {
final boolean _autoSwapBufferMode = helper.getAutoSwapBufferMode();
helper.setAutoSwapBufferMode(false);
final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable;
@@ -1054,14 +1057,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
glType = GL.GL_UNSIGNED_BYTE; // offscreenContext.getDefaultPixelDataType();
offscreenImage = new BufferedImage(panelWidth, panelHeight, withAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
- if(!flippedVertical || null != glslTextureRaster) {
+ if(!flipVertical || null != glslTextureRaster) {
final int[] readBackIntBuffer = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData();
readBackInts = IntBuffer.wrap(readBackIntBuffer);
} else {
readBackInts = IntBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels);
}
if(DEBUG) {
- System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: flippedVertical "+flippedVertical+", glslTextureRaster "+(null!=glslTextureRaster));
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: flippedVertical "+flipVertical+", glslTextureRaster "+(null!=glslTextureRaster));
System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: panelSize "+panelWidth+"x"+panelHeight +", readBackSizeInPixels "+readBackWidthInPixels+"x"+readBackHeightInPixels);
System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: offscreenImage "+offscreenImage.getWidth()+"x"+offscreenImage.getHeight());
}
@@ -1101,7 +1104,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
} else {
gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackInts);
- if ( flippedVertical ) {
+ if ( flipVertical ) {
// Copy temporary data into raster of BufferedImage for faster
// blitting Note that we could avoid this copy in the cases
// where !offscreenContext.offscreenImageNeedsVerticalFlip(),
@@ -1641,28 +1644,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
System.err.println("-- Created External Drawable: "+joglDrawable);
System.err.println("-- Created Context: "+joglContext);
}
- } else if (factory.canCreateContextOnJava2DSurface(device)) {
- // Mac OS X code path
- joglContext = factory.createContextOnJava2DSurface(g, j2dContext);
- if (DEBUG) {
- System.err.println("-- Created Context: "+joglContext);
- }
}
- /*if (DEBUG) {
- joglContext.setGL(new DebugGL2(joglContext.getGL().getGL2()));
- }*/
-
if (Java2D.isFBOEnabled() &&
Java2D.getOGLSurfaceType(g) == Java2D.FBOBJECT &&
fbObjectWorkarounds) {
createNewDepthBuffer = true;
}
}
- if (joglContext instanceof Java2DGLContext) {
- // Mac OS X code path
- ((Java2DGLContext) joglContext).setGraphics(g);
- }
-
helper.invokeGL(joglDrawable, joglContext, updaterDisplayAction, updaterInitAction);
}
} finally {
diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
index 705f8b94e..53fe6c3c9 100644
--- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
+++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java
@@ -654,6 +654,12 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe
return null != _drawable ? _drawable.getHeight() : 0;
}
+ @Override
+ public boolean isGLOriented() {
+ final GLDrawable _drawable = drawable;
+ return null != _drawable ? _drawable.isGLOriented() : true;
+ }
+
@Override
public final GLCapabilitiesImmutable getChosenGLCapabilities() {
final GLDrawable _drawable = drawable;
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 7b760ed0e..883f90591 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1765,11 +1765,6 @@ public abstract class GLContextImpl extends GLContext {
throw new GLException("Not supported on non-pbuffer contexts");
}
- @Override
- public boolean isGLOrientationFlippedVertical() {
- return true;
- }
-
@Override
public int getDefaultPixelDataType() {
if(!pixelDataTypeEvaluated) {
@@ -1804,6 +1799,8 @@ public abstract class GLContextImpl extends GLContext {
pixelDataFormat=GL.GL_RGBA;
pixelDataType = GL.GL_UNSIGNED_BYTE;
}
+ // TODO: Consider:
+ // return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
}
//----------------------------------------------------------------------
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index 92ec96ad7..7ef99b241 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -469,17 +469,6 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
return (GLDrawableFactoryImpl) getFactory(glp);
}
- //---------------------------------------------------------------------------
- // Support for Java2D/JOGL bridge on Mac OS X; the external
- // GLDrawable mechanism in the public API is sufficient to
- // implement this functionality on all other platforms
- //
-
- public abstract boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device);
-
- public abstract GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException;
-
//----------------------------------------------------------------------
// Gamma adjustment support
// Thanks to the LWJGL team for illustrating how to make these
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
index a2b99c7da..877e7b60b 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java
@@ -283,6 +283,11 @@ public abstract class GLDrawableImpl implements GLDrawable {
return surface.getHeight();
}
+ @Override
+ public boolean isGLOriented() {
+ return true;
+ }
+
/**
* {@link NativeSurface#lockSurface() Locks} the underlying windowing toolkit's {@link NativeSurface surface}.
*
diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
index ddc6d5917..b8841d6e2 100644
--- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java
@@ -49,7 +49,6 @@ import com.jogamp.common.util.locks.RecursiveLock;
@SuppressWarnings("deprecation")
public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
- private int floatMode;
public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContextImpl pbufferContext) {
super(pbufferDrawable, pbufferContext, true); // drawable := pbufferDrawable, context := pbufferContext
@@ -59,28 +58,6 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
// pbuffer specifics
//
- @Override
- public void bindTexture() {
- // Doesn't make much sense to try to do this on the event dispatch
- // thread given that it has to be called while the context is current
- context.bindPbufferToTexture();
- }
-
- @Override
- public void releaseTexture() {
- // Doesn't make much sense to try to do this on the event dispatch
- // thread given that it has to be called while the context is current
- context.releasePbufferFromTexture();
- }
-
- @Override
- public int getFloatingPointMode() {
- if (floatMode == 0) {
- throw new GLException("Pbuffer not initialized, or floating-point support not requested");
- }
- return floatMode;
- }
-
//
// GLDrawable delegation
//
@@ -119,22 +96,10 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer {
_lock.lock(); // sync: context/drawable could been recreated/destroyed while animating
try {
if( null != context ) {
- helper.invokeGL(drawable, context, defaultDisplayAction, initAction);
+ helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction);
}
} finally {
_lock.unlock();
}
}
-
- //----------------------------------------------------------------------
- // Internals only below this point
- //
-
- protected final Runnable initAction = new Runnable() {
- @Override
- public final void run() {
- floatMode = context.getFloatingPointMode();
- defaultInitAction.run();
- } };
-
}
diff --git a/src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java b/src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java
deleted file mode 100644
index 4a5b1db54..000000000
--- a/src/jogl/classes/jogamp/opengl/awt/Java2DGLContext.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.awt;
-
-import jogamp.opengl.*;
-import java.awt.Graphics;
-
-/** Provides a construct by which the shared GLJPanel code can
- * interact with a few methods in the Mac OS X-specific Java2D/JOGL
- * bridge implementation.
- */
-
-public interface Java2DGLContext {
- public void setGraphics(Graphics g);
-}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
index 1c0cd0d3c..2b8ca31c9 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java
@@ -56,7 +56,7 @@ import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
import com.jogamp.opengl.GLRendererQuirks;
-public abstract class EGLContext extends GLContextImpl {
+public class EGLContext extends GLContextImpl {
private boolean eglQueryStringInitialized;
private boolean eglQueryStringAvailable;
private EGLExt _eglExt;
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index 9b87860cb..431de5159 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -779,15 +779,4 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
protected GLDrawable createExternalGLDrawableImpl() {
throw new GLException("Not yet implemented");
}
-
- @Override
- public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- @Override
- public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- throw new GLException("Unimplemented on this platform");
- }
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java
deleted file mode 100644
index 325ad6142..000000000
--- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.egl;
-
-import javax.media.opengl.*;
-
-public class EGLOnscreenContext extends EGLContext {
- public EGLOnscreenContext(EGLOnscreenDrawable drawable, GLContext shareWith) {
- super(drawable, shareWith);
- }
-}
-
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
index 6440cf1e5..19084ba19 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java
@@ -50,7 +50,7 @@ public class EGLOnscreenDrawable extends EGLDrawable {
@Override
public GLContext createContext(GLContext shareWith) {
- return new EGLOnscreenContext(this, shareWith);
+ return new EGLContext(this, shareWith);
}
@Override
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java
deleted file mode 100644
index bb9eeb892..000000000
--- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.egl;
-
-import javax.media.opengl.*;
-
-public class EGLPbufferContext extends EGLContext {
- public EGLPbufferContext(EGLPbufferDrawable drawable, GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public int getFloatingPointMode() {
- return 0; // FIXME ??
- }
-}
-
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
index 9e5d9327b..45e39f5d1 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java
@@ -57,7 +57,7 @@ public class EGLPbufferDrawable extends EGLDrawable {
@Override
public GLContext createContext(GLContext shareWith) {
- return new EGLPbufferContext(this, shareWith);
+ return new EGLContext(this, shareWith);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index 6cab369cf..666cd30af 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -80,7 +80,7 @@ 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
+public class MacOSXCGLContext extends GLContextImpl
{
// Abstract interface for implementation of this context (either
// NSOpenGL-based or CGL-based)
@@ -184,6 +184,9 @@ public abstract class MacOSXCGLContext extends GLContextImpl
// CGL extension functions.
private CGLExtProcAddressTable cglExtProcAddressTable;
+ private long updateHandle = 0;
+ private int lastWidth, lastHeight;
+
protected MacOSXCGLContext(GLDrawableImpl drawable,
GLContext shareWith) {
super(drawable, shareWith);
@@ -280,9 +283,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl
MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
GLCapabilitiesImmutable capabilitiesChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
- if (capabilitiesChosen.getPbufferFloatingPointBuffers() && !isTigerOrLater) {
- throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later");
- }
GLProfile glp = capabilitiesChosen.getGLProfile();
if(glp.isGLES1() || glp.isGLES2() || glp.isGL4() || glp.isGL3() && !isLionOrLater) {
throw new GLException("OpenGL profile not supported on MacOSX "+Platform.getOSVersionNumber()+": "+glp);
@@ -311,6 +311,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl
if (!impl.makeCurrent(contextHandle)) {
throw new GLException("Error making Context current: "+this);
}
+ drawableUpdatedNotify();
}
@Override
@@ -322,18 +323,70 @@ public abstract class MacOSXCGLContext extends GLContextImpl
@Override
protected void destroyImpl() throws GLException {
+ releaseUpdateHandle();
if(!impl.destroy(contextHandle)) {
throw new GLException("Error destroying OpenGL Context: "+this);
}
}
+ private final long getUpdateHandle() {
+ if( 0 == updateHandle ) {
+ lastWidth = -1;
+ lastHeight = -1;
+ if( isCreated() && drawable.getChosenGLCapabilities().isOnscreen() && isNSContext() ) {
+ final boolean incompleteView;
+ final NativeSurface surface = drawable.getNativeSurface();
+ if( surface instanceof ProxySurface ) {
+ incompleteView = ((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE );
+ } else {
+ incompleteView = false;
+ }
+ if(!incompleteView) {
+ updateHandle = CGL.updateContextRegister(contextHandle, drawable.getHandle());
+ if(0 == updateHandle) {
+ throw new InternalError("XXX2");
+ }
+ }
+ }
+ }
+ return updateHandle;
+ }
+
+ private final void releaseUpdateHandle() {
+ if ( 0 != updateHandle ) {
+ CGL.updateContextUnregister(updateHandle);
+ updateHandle = 0;
+ }
+ }
+
+ @Override
+ protected void drawableUpdatedNotify() throws GLException {
+ if( drawable.getChosenGLCapabilities().isOnscreen() ) {
+ final long _updateHandle = getUpdateHandle();
+ final int w = drawable.getWidth();
+ final int h = drawable.getHeight();
+ final boolean updateContext = ( 0!=_updateHandle && CGL.updateContextNeedsUpdate(_updateHandle) ) ||
+ w != lastWidth || h != lastHeight;
+ if(updateContext) {
+ lastWidth = w;
+ lastHeight = h;
+ if (contextHandle == 0) {
+ throw new GLException("Context not created");
+ }
+ CGL.updateContext(contextHandle);
+ }
+ }
+ }
+
@Override
protected void associateDrawable(boolean bound) {
// context stuff depends on drawable stuff
if(bound) {
super.associateDrawable(true); // 1) init drawable stuff
impl.associateDrawable(true); // 2) init context stuff
+ getUpdateHandle();
} else {
+ releaseUpdateHandle();
impl.associateDrawable(false); // 1) free context stuff
super.associateDrawable(false); // 2) free drawable stuff
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index 6c647108f..39178290a 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -405,17 +405,6 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
throw new GLException("Not yet implemented");
}
- @Override
- public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- @Override
- public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- throw new GLException("not supported in non AWT enviroment");
- }
-
//------------------------------------------------------
// Gamma-related functionality
//
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
index fa8e8d468..86e1ef481 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
@@ -104,7 +104,8 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
break;
case CGL.kCGLPFAColorFloat:
- ivalues.put(idx, ( !caps.isOnscreen() && caps.isPBuffer() && caps.getPbufferFloatingPointBuffers() ) ? 1 : 0);
+ // ivalues.put(idx, ( !caps.isOnscreen() && caps.isPBuffer() && caps.getPbufferFloatingPointBuffers() ) ? 1 : 0);
+ ivalues.put(idx, 0);
break;
case CGL.NSOpenGLPFAPixelBuffer:
@@ -176,12 +177,13 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
attrs.put(i++, CGL.kCGLPFAOpenGLProfile);
attrs.put(i++, MacOSXCGLContext.GLProfile2CGLOGLProfileValue(ctp, major, minor));
}
+ /**
if(!caps.isOnscreen() && caps.isPBuffer()) {
attrs.put(i++, CGL.kCGLPFAPBuffer);
if (caps.getPbufferFloatingPointBuffers()) {
attrs.put(i++, CGL.kCGLPFAColorFloat);
}
- }
+ } */
if (caps.getDoubleBuffered()) {
attrs.put(i++, CGL.kCGLPFADoubleBuffer);
}
@@ -284,7 +286,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
break;
case CGL.kCGLPFAColorFloat:
- caps.setPbufferFloatingPointBuffers(ivalue != 0);
+ // caps.setPbufferFloatingPointBuffers(ivalue != 0);
break;
case CGL.NSOpenGLPFAPixelBuffer:
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java
deleted file mode 100644
index f2e636796..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.macosx.cgl;
-
-import javax.media.opengl.*;
-
-public class MacOSXOffscreenCGLContext extends MacOSXPbufferCGLContext
-{
- public MacOSXOffscreenCGLContext(MacOSXPbufferCGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public int getDefaultPixelDataType() {
- final GL gl = getGL();
- return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java
index 4f9005504..446a834b9 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLDrawable.java
@@ -53,6 +53,6 @@ public class MacOSXOffscreenCGLDrawable extends MacOSXPbufferCGLDrawable {
@Override
public GLContext createContext(GLContext shareWith) {
- return new MacOSXOffscreenCGLContext(this, shareWith);
+ return new MacOSXCGLContext(this, shareWith);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java
deleted file mode 100644
index 447d18f68..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLContext.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.macosx.cgl;
-
-import javax.media.nativewindow.NativeSurface;
-import javax.media.nativewindow.ProxySurface;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
-
-import jogamp.opengl.GLContextImpl;
-
-public class MacOSXOnscreenCGLContext extends MacOSXCGLContext {
-
- public MacOSXOnscreenCGLContext(MacOSXOnscreenCGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- protected void makeCurrentImpl() throws GLException {
- super.makeCurrentImpl();
- drawableUpdatedNotify();
- }
-
- @Override
- protected void drawableUpdatedNotify() throws GLException {
- final int w = drawable.getWidth();
- final int h = drawable.getHeight();
- final boolean updateContext = ( 0!=updateHandle && CGL.updateContextNeedsUpdate(updateHandle) ) ||
- w != lastWidth || h != lastHeight;
- if(updateContext) {
- lastWidth = w;
- lastHeight = h;
- if (contextHandle == 0) {
- throw new GLException("Context not created");
- }
- CGL.updateContext(contextHandle);
- }
- }
-
- @Override
- protected boolean createImpl(GLContextImpl sharedWith) {
- boolean res = super.createImpl(sharedWith);
- lastWidth = -1;
- lastHeight = -1;
- if(res && isNSContext()) {
- if(0 != updateHandle) {
- throw new InternalError("XXX1");
- }
- final boolean incompleteView;
- final NativeSurface surface = drawable.getNativeSurface();
- if( surface instanceof ProxySurface ) {
- incompleteView = ((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE );
- } else {
- incompleteView = false;
- }
- if(!incompleteView) {
- updateHandle = CGL.updateContextRegister(contextHandle, drawable.getHandle());
- if(0 == updateHandle) {
- throw new InternalError("XXX2");
- }
- }
- }
- return res;
- }
-
- @Override
- protected void destroyImpl() throws GLException {
- if ( 0 != updateHandle ) {
- CGL.updateContextUnregister(updateHandle);
- updateHandle = 0;
- }
- super.destroyImpl();
- }
-
- private long updateHandle = 0;
- private int lastWidth, lastHeight;
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java
index ec9628004..c6f0c1383 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java
@@ -52,7 +52,7 @@ public class MacOSXOnscreenCGLDrawable extends MacOSXCGLDrawable {
@Override
public GLContext createContext(GLContext shareWith) {
- return new MacOSXOnscreenCGLContext(this, shareWith);
+ return new MacOSXCGLContext(this, shareWith);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java
deleted file mode 100644
index 7e2d8cf10..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- */
-
-package jogamp.opengl.macosx.cgl;
-
-import javax.media.opengl.GL;
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLPbuffer;
-
-import jogamp.opengl.GLContextImpl;
-
-@SuppressWarnings("deprecation")
-public class MacOSXPbufferCGLContext extends MacOSXCGLContext {
-
- // State for render-to-texture and render-to-texture-rectangle support
- private int texture; // actual texture object
-
- public MacOSXPbufferCGLContext(MacOSXPbufferCGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public void bindPbufferToTexture() {
- GL gl = getGL();
- gl.glBindTexture(((MacOSXPbufferCGLDrawable)drawable).getTextureTarget(), texture);
- // FIXME: not clear whether this is really necessary, but since
- // the API docs seem to imply it is and since it doesn't seem to
- // impact performance, leaving it in
- CGL.setContextTextureImageToPBuffer(contextHandle, drawable.getHandle(), GL.GL_FRONT);
- }
-
- @Override
- public void releasePbufferFromTexture() {
- }
-
- @Override
- protected boolean createImpl(GLContextImpl shareWith) {
- boolean res = super.createImpl(shareWith);
- if(res) {
- // Initialize render-to-texture support if requested
- final GL gl = getGL();
- final MacOSXPbufferCGLDrawable osxPDrawable = (MacOSXPbufferCGLDrawable)drawable;
- final int textureTarget = osxPDrawable.getTextureTarget();
-
- int[] tmp = new int[1];
- gl.glGenTextures(1, tmp, 0);
- texture = tmp[0];
- gl.glBindTexture(textureTarget, texture);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
- gl.glTexImage2D(textureTarget, 0, GL.GL_RGB, osxPDrawable.getTextureWidth(), osxPDrawable.getTextureHeight(),
- 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, null);
- gl.glCopyTexSubImage2D(textureTarget, 0, 0, 0, 0, 0, drawable.getWidth(), drawable.getHeight());
- }
- return res;
- }
-
- @Override
- public int getFloatingPointMode() {
- return GLPbuffer.APPLE_FLOAT;
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
index 1e845d179..982bb57e1 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
@@ -47,7 +47,6 @@ import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.MutableSurface;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
-import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
@@ -89,7 +88,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
@Override
public GLContext createContext(GLContext shareWith) {
- return new MacOSXPbufferCGLContext(this, shareWith);
+ return new MacOSXCGLContext(this, shareWith);
}
protected int getTextureTarget() { return pBufferTexTarget; }
@@ -134,12 +133,8 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
}
}
- if ( capabilities.getPbufferRenderToTextureRectangle() && null!=sr && sr.isRECTTextureAvailable() ) {
- pBufferTexTarget = GL2GL3.GL_TEXTURE_RECTANGLE;
- } else {
- pBufferTexTarget = GL.GL_TEXTURE_2D;
- }
- if ( GL2GL3.GL_TEXTURE_RECTANGLE == pBufferTexTarget || ( null!=sr && sr.isNPOTTextureAvailable() ) ) {
+ pBufferTexTarget = GL.GL_TEXTURE_2D;
+ if ( null!=sr && sr.isNPOTTextureAvailable() ) {
pBufferTexWidth = getWidth();
pBufferTexHeight = getHeight();
} else {
@@ -147,18 +142,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
pBufferTexHeight = GLBuffers.getNextPowerOf2(getHeight());
}
- int internalFormat = GL.GL_RGBA;
- if (capabilities.getPbufferFloatingPointBuffers()) {
- if(!glProfile.isGL2GL3() || null==sr || sr.isAppleFloatPixelsAvailable()) {
- throw new GLException("Floating-point support (GL_APPLE_float_pixels) not available");
- }
- switch (capabilities.getRedBits()) {
- case 16: internalFormat = GL2.GL_RGBA_FLOAT16_APPLE; break;
- case 32: internalFormat = GL2.GL_RGBA_FLOAT32_APPLE; break;
- default: throw new GLException("Invalid floating-point bit depth (only 16 and 32 supported)");
- }
- }
-
+ final int internalFormat = GL.GL_RGBA;
final long pBuffer = impl.create(pBufferTexTarget, internalFormat, getWidth(), getHeight());
if(DEBUG) {
System.err.println("MacOSXPbufferCGLDrawable tex: target "+toHexString(pBufferTexTarget)+
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java
deleted file mode 100644
index fe60710f0..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.macosx.cgl.awt;
-
-import javax.media.nativewindow.*;
-import javax.media.opengl.*;
-import jogamp.opengl.macosx.cgl.*;
-
-public class MacOSXAWTCGLDrawableFactory extends MacOSXCGLDrawableFactory {
-
- public MacOSXAWTCGLDrawableFactory() {
- super();
- }
-
- public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return true;
- }
-
- public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- return new MacOSXJava2DCGLContext(shareWith);
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java
deleted file mode 100644
index bd183b900..000000000
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.macosx.cgl.awt;
-
-import java.awt.Graphics;
-
-import javax.media.opengl.GLContext;
-import javax.media.opengl.GLException;
-
-import jogamp.opengl.GLContextImpl;
-import jogamp.opengl.awt.Java2D;
-import jogamp.opengl.awt.Java2DGLContext;
-import jogamp.opengl.macosx.cgl.MacOSXCGLContext;
-import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType;
-
-
-/** MacOSXCGLContext implementation supporting the Java2D/JOGL bridge
- * on Mac OS X. The external GLDrawable mechanism does not work on Mac
- * OS X due to how drawables and contexts are operated upon on this
- * platform, so it is necessary to supply an alternative means to
- * create, make current, and destroy contexts on the Java2D "drawable"
- * on the Mac platform.
- */
-
-public class MacOSXJava2DCGLContext extends MacOSXCGLContext implements Java2DGLContext {
- private Graphics graphics;
-
- // FIXME: ignoring context sharing for the time being; will need to
- // rethink this in particular if using FBOs to implement the
- // Java2D/OpenGL pipeline on Mac OS X
-
- MacOSXJava2DCGLContext(GLContext shareWith) {
- super(null, shareWith);
- }
-
- public void setGraphics(Graphics g) {
- this.graphics = g;
- }
-
- protected void makeCurrentImpl() throws GLException {
- if (!Java2D.makeOGLContextCurrentOnSurface(graphics, contextHandle)) {
- throw new GLException("Error making context current");
- }
- }
-
- protected boolean createImpl(GLContextImpl shareWith) {
- long share = createImplPreset(shareWith);
-
- long ctx = Java2D.createOGLContextOnSurface(graphics, share);
- if (ctx == 0) {
- if(DEBUG) {
- System.err.println("Error creating current: "+this);
- }
- return false;
- }
- if (!Java2D.makeOGLContextCurrentOnSurface(graphics, contextHandle)) {
- Java2D.destroyOGLContext(ctx);
- if(DEBUG) {
- System.err.println("Error making created context current: "+this);
- }
- return false;
- }
- setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION
- contextHandle = ctx;
- return true;
- }
-
- protected void releaseImpl() throws GLException {
- // FIXME: would need another primitive in the Java2D class in
- // order to implement this; hopefully should not matter for
- // correctness
- }
-
- protected void destroyImpl() throws GLException {
- Java2D.destroyOGLContext(contextHandle);
- }
-
- public void setOpenGLMode(GLBackendType mode) {
- if (mode != GLBackendType.CGL) {
- throw new GLException("OpenGL mode switching not supported for Java2D GLContexts");
- }
- super.setOpenGLMode(mode);
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
index 10a4b56d5..4444e9d63 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WGLGLCapabilities.java
@@ -32,9 +32,7 @@ import java.nio.IntBuffer;
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
-import jogamp.opengl.GLGraphicsConfigurationUtil;
-import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilities;
@@ -161,19 +159,13 @@ public class WGLGLCapabilities extends GLCapabilities {
}
if (res == WGLExt.WGL_TYPE_RGBA_FLOAT_ARB) {
- setPbufferFloatingPointBuffers(true);
+ return false; // not supported
}
// normal RGBA FB: WGLExt.WGL_TYPE_RGBA_ARB
// ignore unknown results here
break;
- case WGLExt.WGL_FLOAT_COMPONENTS_NV:
- if (res != 0) {
- setPbufferFloatingPointBuffers(true);
- }
- break;
-
case WGLExt.WGL_RED_BITS_ARB:
setRedBits(res);
break;
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java
deleted file mode 100644
index c8aac7f7b..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.windows.wgl;
-
-import javax.media.opengl.*;
-
-public class WindowsBitmapWGLContext extends WindowsWGLContext {
- public WindowsBitmapWGLContext(WindowsBitmapWGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public int getDefaultPixelDataType() {
- return GL.GL_UNSIGNED_BYTE;
- }
-
- @Override
- public boolean isGLOrientationFlippedVertical() {
- // We can take care of this in the DIB creation (see below)
- return false;
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
index bd018105a..a7f62fccf 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java
@@ -73,9 +73,14 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
@Override
public GLContext createContext(GLContext shareWith) {
- return new WindowsBitmapWGLContext(this, shareWith);
+ return new WindowsWGLContext(this, shareWith);
}
+ @Override
+ public boolean isGLOriented() {
+ return false;
+ }
+
private void createBitmap() {
int werr;
final NativeSurface ns = getNativeSurface();
@@ -111,9 +116,9 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable {
bitsPerPixel = 24; // RGB888 only!
header.setBiSize(BITMAPINFOHEADER.size());
header.setBiWidth(width);
- // NOTE: negating the height causes the DIB to be in top-down row
- // order rather than bottom-up; ends up being correct during pixel
- // readback
+ // NOTE: Positive height causes the DIB's origin at bottom-left (OpenGL),
+ // a negative height causes the DIB's origin at top-left (Java AWT, Windows, ..).
+ // We use !OpenGL origin to remove the need for vertical flip, see 'isGLOriented()' above.
header.setBiHeight(-1 * height);
header.setBiPlanes((short) 1);
header.setBiBitCount((short) bitsPerPixel);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java
deleted file mode 100644
index aef55efc6..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLContext.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.windows.wgl;
-
-import javax.media.opengl.*;
-
-public class WindowsOnscreenWGLContext extends WindowsWGLContext {
- public WindowsOnscreenWGLContext(WindowsOnscreenWGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java
index ddbb29d51..61fb787c6 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsOnscreenWGLDrawable.java
@@ -51,7 +51,7 @@ public class WindowsOnscreenWGLDrawable extends WindowsWGLDrawable {
@Override
public GLContext createContext(GLContext shareWith) {
- return new WindowsOnscreenWGLContext(this, shareWith);
+ return new WindowsWGLContext(this, shareWith);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
deleted file mode 100644
index 7dda6a1f1..000000000
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLContext.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.windows.wgl;
-
-import javax.media.opengl.*;
-
-import com.jogamp.opengl.GLExtensions;
-
-import jogamp.opengl.GLContextImpl;
-
-public class WindowsPbufferWGLContext extends WindowsWGLContext {
- // State for render-to-texture and render-to-texture-rectangle support
- private boolean rtt; // render-to-texture?
- private boolean hasRTT; // render-to-texture extension available?
- private boolean rect; // render-to-texture-rectangle?
- private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV
- private int texture; // actual texture object
-
- protected WindowsPbufferWGLContext(WindowsPbufferWGLDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public void bindPbufferToTexture() {
- if (!rtt) {
- throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " +
- "specified in its GLCapabilities");
- }
- GL gl = getGL();
- WGLExt wglExt = getWGLExt();
- gl.glBindTexture(textureTarget, texture);
- if (rtt && hasRTT) {
- if (!wglExt.wglBindTexImageARB(((WindowsPbufferWGLDrawable)drawable).getPbufferHandle(), WGLExt.WGL_FRONT_LEFT_ARB)) {
- throw new GLException("Binding of pbuffer to texture failed: " + wglGetLastError());
- }
- }
- // FIXME: comment is wrong now
- // Note that if the render-to-texture extension is not supported,
- // we perform a glCopyTexImage2D in swapBuffers().
- }
-
- @Override
- public void releasePbufferFromTexture() {
- if (!rtt) {
- throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " +
- "specified in its GLCapabilities");
- }
- if (rtt && hasRTT) {
- WGLExt wglExt = getWGLExt();
- if (!wglExt.wglReleaseTexImageARB(((WindowsPbufferWGLDrawable)drawable).getPbufferHandle(), WGLExt.WGL_FRONT_LEFT_ARB)) {
- throw new GLException("Releasing of pbuffer from texture failed: " + wglGetLastError());
- }
- }
- }
-
- @Override
- protected boolean createImpl(GLContextImpl shareWith) {
- boolean res = super.createImpl(shareWith);
- if(res) {
- GLCapabilitiesImmutable capabilities = drawable.getChosenGLCapabilities();
-
- // Initialize render-to-texture support if requested
- GL gl = getGL();
- rtt = capabilities.getPbufferRenderToTexture();
- rect = gl.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle();
-
- if (rtt) {
- if (DEBUG) {
- System.err.println("Initializing render-to-texture support");
- }
-
- if (!gl.isExtensionAvailable("WGL_ARB_render_texture")) {
- System.err.println("WindowsPbufferWGLContext: WARNING: WGL_ARB_render_texture extension not " +
- "supported; implementing render_to_texture support using slow texture readback");
- } else {
- hasRTT = true;
-
- if (rect && !gl.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) {
- System.err.println("WindowsPbufferWGLContext: WARNING: GL_NV_texture_rectangle extension not " +
- "supported; skipping requested render_to_texture_rectangle support for pbuffer");
- rect = false;
- }
- if (rect) {
- if (DEBUG) {
- System.err.println(" Using render-to-texture-rectangle");
- }
- textureTarget = GL2GL3.GL_TEXTURE_RECTANGLE_ARB;
- } else {
- if (DEBUG) {
- System.err.println(" Using vanilla render-to-texture");
- }
- textureTarget = GL.GL_TEXTURE_2D;
- }
- int[] tmp = new int[1];
- gl.glGenTextures(1, tmp, 0);
- texture = tmp[0];
- gl.glBindTexture(textureTarget, texture);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
- gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
- gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0);
- }
- }
- }
- return res;
- }
-
- @Override
- public int getFloatingPointMode() {
- return ((WindowsPbufferWGLDrawable)drawable).getFloatingPointMode();
- }
-
- private static String wglGetLastError() {
- return WindowsWGLDrawableFactory.wglGetLastError();
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
index b65f5dd2f..2a0f2596e 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
@@ -47,7 +47,6 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.MutableSurface;
-import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
@@ -60,15 +59,12 @@ import jogamp.nativewindow.windows.GDI;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.windows.wgl.WindowsWGLDrawableFactory.SharedResource;
-// import javax.media.opengl.GLPbuffer;
public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
private WGLExt cachedWGLExt; // cached WGLExt instance from parent GLCanvas,
// needed to destroy pbuffer
private long buffer; // pbuffer handle
- private int floatMode;
-
protected WindowsPbufferWGLDrawable(GLDrawableFactory factory, NativeSurface target) {
super(factory, target, false);
}
@@ -84,7 +80,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
@Override
public GLContext createContext(GLContext shareWith) {
- return new WindowsPbufferWGLContext(this, shareWith);
+ return new WindowsWGLContext(this, shareWith);
}
protected void destroyPbuffer() {
@@ -115,10 +111,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
return buffer;
}
- public int getFloatingPointMode() {
- return floatMode;
- }
-
private void createPbuffer() {
WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration();
SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResource(config.getScreen().getDevice());
@@ -155,17 +147,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
throw new GLException("Pbuffer-related extensions not supported");
}
- floatMode = floatModeTmp[0];
- boolean rtt = chosenCaps.getPbufferRenderToTexture();
- boolean rect = chosenCaps.getPbufferRenderToTextureRectangle();
- boolean useFloat = chosenCaps.getPbufferFloatingPointBuffers();
- // boolean ati = false;
-
- /**
- if (useFloat) {
- ati = (floatMode == GLPbuffer.ATI_FLOAT);
- } */
-
final IntBuffer pformats = Buffers.newDirectIntBuffer(WindowsWGLGraphicsConfiguration.MAX_PFORMATS);
final IntBuffer nformatsTmp = Buffers.newDirectIntBuffer(1);
if (!wglExt.wglChoosePixelFormatARB(sharedHdc,
@@ -198,24 +179,6 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
// Create the p-buffer.
niattribs = 0;
- if (rtt) {
- iattributes.put(niattribs++, WGLExt.WGL_TEXTURE_FORMAT_ARB);
- if (useFloat) {
- iattributes.put(niattribs++, WGLExt.WGL_TEXTURE_FLOAT_RGB_NV);
- } else {
- iattributes.put(niattribs++, WGLExt.WGL_TEXTURE_RGBA_ARB);
- }
-
- iattributes.put(niattribs++, WGLExt.WGL_TEXTURE_TARGET_ARB);
- iattributes.put(niattribs++, rect ? WGLExt.WGL_TEXTURE_RECTANGLE_NV : WGLExt.WGL_TEXTURE_2D_ARB);
-
- iattributes.put(niattribs++, WGLExt.WGL_MIPMAP_TEXTURE_ARB);
- iattributes.put(niattribs++, GL.GL_FALSE);
-
- iattributes.put(niattribs++, WGLExt.WGL_PBUFFER_LARGEST_ARB); // exact
- iattributes.put(niattribs++, GL.GL_FALSE);
- }
-
iattributes.put(niattribs++, 0);
tmpBuffer = wglExt.wglCreatePbufferARB(sharedHdc, format, getWidth(), getHeight(), iattributes);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
index 9f034adb1..1f41563ba 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
@@ -540,15 +540,4 @@ public class WindowsWGLContext extends GLContextImpl {
public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) {
return getWGLExt().wglAllocateMemoryNV(arg0, arg1, arg2, arg3);
}
-
- @Override
- public void bindPbufferToTexture() {
- throw new GLException("Should not call this");
- }
-
- @Override
- public void releasePbufferFromTexture() {
- throw new GLException("Should not call this");
- }
-
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index d7d6ceab4..26d73638f 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
@@ -617,17 +617,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
return detail;
}
- @Override
- public final boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- @Override
- public final GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- throw new GLException("Unimplemented on this platform");
- }
-
//------------------------------------------------------
// Gamma-related functionality
//
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
index fdff20daa..3b71c4462 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
@@ -46,12 +46,10 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
-import javax.media.opengl.GLPbuffer;
import javax.media.opengl.GLProfile;
import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
-import com.jogamp.opengl.GLExtensions;
import jogamp.nativewindow.windows.DWM_BLURBEHIND;
import jogamp.nativewindow.windows.GDI;
@@ -61,7 +59,6 @@ import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLGraphicsConfigurationUtil;
-@SuppressWarnings("deprecation")
public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable {
protected static final int MAX_PFORMATS = 256;
protected static final int MAX_ATTRIBS = 256;
@@ -257,15 +254,6 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
iattributes.put(niattribs++, WGLExt.WGL_SAMPLE_BUFFERS_ARB);
iattributes.put(niattribs++, WGLExt.WGL_SAMPLES_ARB);
}
-
- if(sharedResource.hasARBPBuffer()) {
- GLContextImpl sharedCtx = sharedResource.getContext();
- if(null != sharedCtx && sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer)) {
- // pbo float buffer
- iattributes.put(niattribs++, WGLExt.WGL_FLOAT_COMPONENTS_NV); // nvidia
- }
- }
-
return niattribs;
}
@@ -511,85 +499,8 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
iattributes.put(niattribs++, caps.getNumSamples());
}
- boolean rtt = caps.getPbufferRenderToTexture();
- boolean rect = caps.getPbufferRenderToTextureRectangle();
- boolean useFloat = caps.getPbufferFloatingPointBuffers();
- boolean ati = false;
- boolean nvidia = false;
- if ( usePBuffer ) {
- // Check some invariants and set up some state
- if (rect && !rtt) {
- throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified");
- }
-
- GLContextImpl sharedCtx = sharedResource.getContext();
- if (rect) {
- if (!sharedCtx.isExtensionAvailable(GLExtensions.NV_texture_rectangle)) {
- throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension");
- }
- }
-
- if (useFloat) {
- // Prefer NVidia extension over ATI
- nvidia = sharedCtx.isExtensionAvailable(WindowsWGLDrawableFactory.WGL_NV_float_buffer);
- if(nvidia) {
- floatMode[0] = GLPbuffer.NV_FLOAT;
- } else {
- ati = sharedCtx.isExtensionAvailable("WGL_ATI_pixel_format_float");
- if(ati) {
- floatMode[0] = GLPbuffer.ATI_FLOAT;
- } else {
- throw new GLException("Floating-point pbuffers not supported by this hardware");
- }
- }
-
- if (DEBUG) {
- System.err.println("Using " + (ati ? "ATI" : ( nvidia ? "NVidia" : "NONE" ) ) + " floating-point extension");
- }
- }
-
- // See whether we need to change the pixel type to support ATI's
- // floating-point pbuffers
- if (useFloat && ati) {
- if (rtt) {
- throw new GLException("Render-to-floating-point-texture not supported on ATI hardware");
- } else {
- iattributes.put(niattribs++, WGLExt.WGL_PIXEL_TYPE_ARB);
- iattributes.put(niattribs++, WGLExt.WGL_TYPE_RGBA_FLOAT_ARB);
- }
- } else {
- if (!rtt) {
- // Currently we don't support non-truecolor visuals in the
- // GLCapabilities, so we don't offer the option of making
- // color-index pbuffers.
- iattributes.put(niattribs++, WGLExt.WGL_PIXEL_TYPE_ARB);
- iattributes.put(niattribs++, WGLExt.WGL_TYPE_RGBA_ARB);
- }
- }
-
- if (useFloat && nvidia) {
- iattributes.put(niattribs++, WGLExt.WGL_FLOAT_COMPONENTS_NV);
- iattributes.put(niattribs++, GL.GL_TRUE);
- }
-
- if (rtt) {
- if (useFloat) {
- assert(!ati);
- assert(nvidia);
- if (!rect) {
- throw new GLException("Render-to-floating-point-texture only supported on NVidia hardware with render-to-texture-rectangle");
- }
- iattributes.put(niattribs++, WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV);
- iattributes.put(niattribs++, GL.GL_TRUE);
- } else {
- iattributes.put(niattribs++, rect ? WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV : WGLExt.WGL_BIND_TO_TEXTURE_RGB_ARB);
- iattributes.put(niattribs++, GL.GL_TRUE);
- }
- }
- } else {
- iattributes.put(niattribs++, WGLExt.WGL_PIXEL_TYPE_ARB);
- iattributes.put(niattribs++, WGLExt.WGL_TYPE_RGBA_ARB);
- }
+ iattributes.put(niattribs++, WGLExt.WGL_PIXEL_TYPE_ARB);
+ iattributes.put(niattribs++, WGLExt.WGL_TYPE_RGBA_ARB);
iattributes.put(niattribs++, 0);
return true;
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index 575ff51b8..c60619452 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -65,7 +65,7 @@ import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.opengl.GLExtensions;
-public abstract class X11GLXContext extends GLContextImpl {
+public class X11GLXContext extends GLContextImpl {
private static final Map functionNameMap;
private static final Map extensionNameMap;
private GLXExt _glXExt;
@@ -623,16 +623,6 @@ public abstract class X11GLXContext extends GLContextImpl {
return getGLXExt().glXAllocateMemoryNV(arg0, arg1, arg2, arg3);
}
- @Override
- public void bindPbufferToTexture() {
- throw new GLException("Should not call this");
- }
-
- @Override
- public void releasePbufferFromTexture() {
- throw new GLException("Should not call this");
- }
-
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index 9486b5875..19005e48c 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -571,17 +571,6 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
return X11ExternalGLXDrawable.create(this, null);
}
- @Override
- public final boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) {
- return false;
- }
-
- @Override
- public final GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith)
- throws GLException {
- throw new GLException("Unimplemented on this platform");
- }
-
//----------------------------------------------------------------------
// Gamma-related functionality
//
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
index 12ce22392..523364389 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java
@@ -225,17 +225,6 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
res.put(idx++, GLX.GLX_SAMPLES);
res.put(idx++, caps.getNumSamples());
}
- if (caps.isPBuffer()) {
- if (caps.getPbufferFloatingPointBuffers()) {
- String glXExtensions = GLX.glXQueryExtensionsString(display, screen);
- if (glXExtensions == null ||
- glXExtensions.indexOf("GLX_NV_float_buffer") < 0) {
- throw new GLException("Floating-point pbuffers on X11 currently require NVidia hardware: "+glXExtensions);
- }
- res.put(idx++, GLXExt.GLX_FLOAT_COMPONENTS_NV);
- res.put(idx++, GL.GL_TRUE);
- }
- }
res.put(idx++, 0);
return res;
}
@@ -341,10 +330,6 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem
res.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp));
res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp));
- try {
- res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp) != GL.GL_FALSE);
- } catch (Exception e) {}
-
return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res);
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java
deleted file mode 100644
index 460dc10ca..000000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXContext.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-package jogamp.opengl.x11.glx;
-
-import javax.media.opengl.*;
-
-public class X11OnscreenGLXContext extends X11GLXContext {
-
- public X11OnscreenGLXContext(X11OnscreenGLXDrawable drawable, GLContext shareWith) {
- super(drawable, shareWith);
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
index 6b239a43d..9da189290 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11OnscreenGLXDrawable.java
@@ -104,6 +104,6 @@ public class X11OnscreenGLXDrawable extends X11GLXDrawable {
@Override
public GLContext createContext(GLContext shareWith) {
- return new X11OnscreenGLXContext(this, shareWith);
+ return new X11GLXContext(this, shareWith);
}
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java
deleted file mode 100644
index a34e050cd..000000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXContext.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.x11.glx;
-
-import javax.media.opengl.*;
-
-public class X11PbufferGLXContext extends X11GLXContext {
-
- public X11PbufferGLXContext(X11PbufferGLXDrawable drawable, GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public void bindPbufferToTexture() {
- // FIXME: figure out how to implement this
- throw new GLException("Not yet implemented");
- }
-
- @Override
- public void releasePbufferFromTexture() {
- // FIXME: figure out how to implement this
- throw new GLException("Not yet implemented");
- }
-
-
- @Override
- public int getFloatingPointMode() {
- return ((X11PbufferGLXDrawable)drawable).getFloatingPointMode();
- }
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
index d2d0c6789..0e771fd0f 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java
@@ -46,15 +46,12 @@ import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.MutableSurface;
-import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLException;
-import javax.media.opengl.GLPbuffer;
import com.jogamp.common.nio.Buffers;
-@SuppressWarnings("deprecation")
public class X11PbufferGLXDrawable extends X11GLXDrawable {
protected X11PbufferGLXDrawable(GLDrawableFactory factory, NativeSurface target) {
/* GLCapabilities caps,
@@ -74,7 +71,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
@Override
public GLContext createContext(GLContext shareWith) {
- return new X11PbufferGLXContext(this, shareWith);
+ return new X11GLXContext(this, shareWith);
}
protected void destroyPbuffer() {
@@ -103,16 +100,6 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
throw new GLException("Null display");
}
- GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
-
- if (chosenCaps.getPbufferRenderToTexture()) {
- throw new GLException("Render-to-texture pbuffers not supported yet on X11");
- }
-
- if (chosenCaps.getPbufferRenderToTextureRectangle()) {
- throw new GLException("Render-to-texture-rectangle pbuffers not supported yet on X11");
- }
-
// Create the p-buffer.
int niattribs = 0;
IntBuffer iattributes = Buffers.newDirectIntBuffer(7);
@@ -138,9 +125,4 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable {
System.err.println(getThreadName()+": Created pbuffer " + this);
}
}
-
- public int getFloatingPointMode() {
- // Floating-point pbuffers currently require NVidia hardware on X11
- return GLPbuffer.NV_FLOAT;
- }
}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java
deleted file mode 100644
index 1cfb7e427..000000000
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-
-package jogamp.opengl.x11.glx;
-
-import javax.media.opengl.*;
-
-public class X11PixmapGLXContext extends X11GLXContext {
-
- public X11PixmapGLXContext(X11PixmapGLXDrawable drawable,
- GLContext shareWith) {
- super(drawable, shareWith);
- }
-
- @Override
- public int getDefaultPixelDataType() {
- GL gl = getGL();
- return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
- }
-
-}
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
index ab25e4ef4..c1388db8a 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java
@@ -69,7 +69,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable {
@Override
public GLContext createContext(GLContext shareWith) {
- return new X11PixmapGLXContext(this, shareWith);
+ return new X11GLXContext(this, shareWith);
}
private void createPixmap() {
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java
index 6221a1029..728b040af 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWT.java
@@ -107,7 +107,7 @@ public class TestGearsGLJPanelAWT extends UITestCase {
} } ) ;
if( useAnimator ) {
- animator.setUpdateFPSFrames(1, null);
+ animator.setUpdateFPSFrames(60, System.err);
animator.start();
Assert.assertEquals(true, animator.isAnimating());
}
@@ -117,13 +117,18 @@ public class TestGearsGLJPanelAWT extends UITestCase {
new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glJPanel);
new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame);
- snap.setMakeSnapshot();
-
final long t0 = System.currentTimeMillis();
long t1 = t0;
+ boolean triggerSnap = false;
while(!quitAdapter.shouldQuit() && t1 - t0 < duration) {
Thread.sleep(100);
t1 = System.currentTimeMillis();
+ snap.getDisplayCount();
+ if( !triggerSnap && snap.getDisplayCount() > 1 ) {
+ // Snapshot only after one frame has been rendered to suite FBO MSAA!
+ snap.setMakeSnapshot();
+ triggerSnap = true;
+ }
}
Assert.assertNotNull(frame);
@@ -145,7 +150,7 @@ public class TestGearsGLJPanelAWT extends UITestCase {
}
@Test
- public void test01_default()
+ public void test01_DefaultNorm()
throws AWTException, InterruptedException, InvocationTargetException
{
GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
@@ -163,7 +168,7 @@ public class TestGearsGLJPanelAWT extends UITestCase {
}
@Test
- public void test02_msaa()
+ public void test02_DefaultMsaa()
throws AWTException, InterruptedException, InvocationTargetException
{
if( manualTest ) {
@@ -176,25 +181,53 @@ public class TestGearsGLJPanelAWT extends UITestCase {
}
@Test
- public void test03_pbuffer()
+ public void test03_PbufferNorm()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setPBuffer(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test04_PbufferMsaa()
throws AWTException, InterruptedException, InvocationTargetException
{
if( manualTest ) {
return;
}
GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
caps.setPBuffer(true);
runTestGL(caps);
}
@Test
- public void test04_bitmap()
+ public void test05_BitmapNorm()
+ throws AWTException, InterruptedException, InvocationTargetException
+ {
+ if( manualTest ) {
+ return;
+ }
+ GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setBitmap(true);
+ runTestGL(caps);
+ }
+
+ @Test
+ public void test06_BitmapMsaa()
throws AWTException, InterruptedException, InvocationTargetException
{
if( manualTest ) {
return;
}
GLCapabilities caps = new GLCapabilities(GLProfile.getDefault());
+ caps.setNumSamples(4);
+ caps.setSampleBuffers(true);
caps.setBitmap(true);
runTestGL(caps);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java
index 743d682c8..7b53d973c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java
@@ -17,22 +17,43 @@ public class TestPNGImage01NEWT extends UITestCase {
public void testPNGReadWriteAndCompare() throws InterruptedException, IOException, MalformedURLException {
final File out1_f=new File(getSimpleTestName(".")+"-PNGImageTest1.png");
final File out2_f=new File(getSimpleTestName(".")+"-PNGImageTest2.png");
+ final File out2F_f=new File(getSimpleTestName(".")+"-PNGImageTest2Flipped.png");
+ final File out2R_f=new File(getSimpleTestName(".")+"-PNGImageTest2Reversed.png");
+ final File out2RF_f=new File(getSimpleTestName(".")+"-PNGImageTest2ReversedFlipped.png");
final String url_s="jogl/util/data/av/test-ntsc01-160x90.png";
URLConnection urlConn = IOUtil.getResource(url_s, this.getClass().getClassLoader());
- PNGImage image0 = PNGImage.read(urlConn.getInputStream());
- System.err.println("PNGImage - Orig: "+image0);
- image0.write(out1_f, true);
+ PNGImage image1 = PNGImage.read(urlConn.getInputStream());
+ System.err.println("PNGImage - Orig: "+image1);
+ image1.write(out1_f, true);
{
- Assert.assertEquals(image0.getData(), PNGImage.read(IOUtil.toURL(out1_f).openStream()).getData());
+ Assert.assertEquals(image1.getData(), PNGImage.read(IOUtil.toURL(out1_f).openStream()).getData());
}
- final PNGImage image1 = PNGImage.createFromData(image0.getWidth(), image0.getHeight(),
- image0.getDpi()[0], image0.getDpi()[1],
- image0.getBytesPerPixel(), false, image0.getData());
- image1.write(out2_f, true);
+ final PNGImage image2 = PNGImage.createFromData(image1.getWidth(), image1.getHeight(),
+ image1.getDpi()[0], image1.getDpi()[1],
+ image1.getBytesPerPixel(), false /* reverseChannels */, image1.isGLOriented(), image1.getData());
+ image2.write(out2_f, true);
{
- Assert.assertEquals(image0.getData(), PNGImage.read(IOUtil.toURL(out2_f).openStream()).getData());
- }
+ Assert.assertEquals(image1.getData(), PNGImage.read(IOUtil.toURL(out2_f).openStream()).getData());
+ }
+
+ // flipped
+ final PNGImage image2F = PNGImage.createFromData(image1.getWidth(), image1.getHeight(),
+ image1.getDpi()[0], image1.getDpi()[1],
+ image1.getBytesPerPixel(), false /* reverseChannels */, !image1.isGLOriented(), image1.getData());
+ image2F.write(out2F_f, true);
+
+ // reversed channels
+ final PNGImage image2R = PNGImage.createFromData(image1.getWidth(), image1.getHeight(),
+ image1.getDpi()[0], image1.getDpi()[1],
+ image1.getBytesPerPixel(), true /* reverseChannels */, image1.isGLOriented(), image1.getData());
+ image2R.write(out2R_f, true);
+
+ // reversed channels and flipped
+ final PNGImage image2RF = PNGImage.createFromData(image1.getWidth(), image1.getHeight(),
+ image1.getDpi()[0], image1.getDpi()[1],
+ image1.getBytesPerPixel(), true /* reverseChannels */, !image1.isGLOriented(), image1.getData());
+ image2RF.write(out2RF_f, true);
}
public static void main(String args[]) {
--
cgit v1.2.3
From e2323aea92dc8d47f583002921287a06230b2d93 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Wed, 24 Apr 2013 21:49:40 +0200
Subject: Quirk DontCloseX11Display: Only detect w/ X11 NativeWindow System.
---
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 883f90591..66e3efc4d 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1572,24 +1572,24 @@ public abstract class GLContextImpl extends GLContext {
//
// Quirk: DontCloseX11Display
//
- {
+ if( NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
final int quirk = GLRendererQuirks.DontCloseX11Display;
if( glRendererLowerCase.contains("mesa") ) {
if ( glRendererLowerCase.contains("x11") && vendorVersion.compareTo(Version80) < 0 ) {
if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer=" + glRenderer + ", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]");
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer + ", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]");
}
quirks[i++] = quirk;
}
} else if( glRendererLowerCase.contains("ati technologies") || glRendererLowerCase.startsWith("ati ") ) {
{
if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: Renderer=" + glRenderer);
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer);
}
quirks[i++] = quirk;
}
- } else if( NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
- if( jogamp.nativewindow.x11.X11Util.getMarkAllDisplaysUnclosable() ) {
+ } else if( jogamp.nativewindow.x11.X11Util.getMarkAllDisplaysUnclosable() ) {
+ {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11Util Downstream");
}
--
cgit v1.2.3
From 36dc4f5ab6957a4078842c488afb51df2fdc0630 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Fri, 26 Apr 2013 05:38:24 +0200
Subject: Simplify GLDrawableFactory's SharedResource Query Methods; Move
WindowsWGLDrawableFactory Quirks to GLRendererQuirks
(NeedCurrCtx4ARBPixFmtQueries, NeedCurrCtx4ARBCreateContext); Bug 706:
Confine NeedCurrCtx4ARBCreateContext to [Windows, ATI, driver < 12.102.3);
Avoid possible NPE @ GLContext.getGLVendorVersionNumber()
- Simplify GLDrawableFactory's SharedResource Query Methods
- Moving common methods to GLDrawableFactory/GLDrawableFactoryImpl
while reusing common methods to SharedResourceRunner.Resource.
- All factories SharedResources impl. SharedResourceRunner.Resource.
- Move WindowsWGLDrawableFactory Quirks to GLRendererQuirks (NeedCurrCtx4ARBPixFmtQueries, NeedCurrCtx4ARBCreateContext)
- For better maintenance, move the mentioned quirks from the windows factory to our common place,
being detected within GLContextImpl after each context creation.
- Bug 706: Confine NeedCurrCtx4ARBCreateContext to [Windows, ATI, driver < 12.102.3)
- Before we added this quirk if [Windows, ATI],
however, we have hopes that the new drivers will suffice for all
as tested successful on my test machine (AMD Radeon HD 6300M Series, amd_catalyst_13.5_mobility_beta2).
- Avoid possible NPE @ GLContext.getGLVendorVersionNumber()
- GLContext.getGLVendorVersionNumber() never returns 'null' but a zero version instance instead!
- Add API doc.
- Use mixed case names in GLContextImpl.setRendererQuirks(..).
---
.../com/jogamp/opengl/GLRendererQuirks.java | 48 +++++++-
src/jogl/classes/javax/media/opengl/GLContext.java | 15 ++-
.../javax/media/opengl/GLDrawableFactory.java | 9 +-
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 82 +++++++++----
.../jogamp/opengl/GLDrawableFactoryImpl.java | 61 +++++++---
.../classes/jogamp/opengl/GLVersionNumber.java | 7 +-
.../jogamp/opengl/SharedResourceRunner.java | 4 +
.../jogamp/opengl/egl/EGLDrawableFactory.java | 84 +++++---------
.../egl/EGLGraphicsConfigurationFactory.java | 2 +-
.../macosx/cgl/MacOSXCGLDrawableFactory.java | 87 ++++++--------
.../macosx/cgl/MacOSXCGLGraphicsConfiguration.java | 2 +-
.../macosx/cgl/MacOSXPbufferCGLDrawable.java | 2 +-
.../windows/wgl/WindowsPbufferWGLDrawable.java | 2 +-
.../opengl/windows/wgl/WindowsWGLContext.java | 6 +-
.../windows/wgl/WindowsWGLDrawableFactory.java | 129 ++++-----------------
.../wgl/WindowsWGLGraphicsConfiguration.java | 3 +-
.../WindowsWGLGraphicsConfigurationFactory.java | 21 ++--
.../jogamp/opengl/x11/glx/X11GLXContext.java | 2 +-
.../opengl/x11/glx/X11GLXDrawableFactory.java | 47 ++------
.../glx/X11GLXGraphicsConfigurationFactory.java | 2 +-
20 files changed, 296 insertions(+), 319 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
index 4c068414c..01d2b30a0 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
@@ -34,6 +34,10 @@ package com.jogamp.opengl;
* Using centralized quirk identifier enables us to
* locate code dealing w/ it and hence eases it's maintenance.
*
+ *
+ * Some GL_VENDOR
and GL_RENDERER
strings are
+ * listed here .
+ *
*/
public class GLRendererQuirks {
/**
@@ -92,7 +96,7 @@ public class GLRendererQuirks {
* Drivers known exposing such bug:
*
* - Mesa < 8.0 _with_ X11 software renderer
Mesa X11
, not with GLX/DRI renderer.
- * - ATI proprietary Catalyst X11 driver (RENDERER vendor version):
+ *
- ATI proprietary Catalyst X11 driver versions:
*
* - 8.78.6
* - 8.881
@@ -111,12 +115,50 @@ public class GLRendererQuirks {
*/
public static final int DontCloseX11Display = 8;
+ /**
+ * Need current GL Context when calling new ARB pixel format query functions,
+ * otherwise driver crashes the VM.
+ *
+ * Drivers known exposing such bug:
+ *
+ * - ATI proprietary Catalyst driver on Windows version ≤ XP.
+ * TODO: Validate if bug actually relates to 'old' ATI Windows drivers for old GPU's like X300
+ * regardless of the Windows version.
+ *
+ *
+ * See Bug 480 - https://jogamp.org/bugzilla/show_bug.cgi?id=480
+ *
+ */
+ public static final int NeedCurrCtx4ARBPixFmtQueries = 9;
+
+ /**
+ * Need current GL Context when calling new ARB CreateContext function,
+ * otherwise driver crashes the VM.
+ *
+ * Drivers known exposing such bug:
+ *
+ * - ATI proprietary Catalyst Windows driver on laptops with a driver version as reported in GL_VERSION:
+ *
+ * - null
+ * - <
12.102.3.0
( amd_catalyst_13.5_mobility_beta2 )
+ *
+ *
+ *
+ *
+ * See Bug 706 - https://jogamp.org/bugzilla/show_bug.cgi?id=706
+ * See Bug 520 - https://jogamp.org/bugzilla/show_bug.cgi?id=520
+ *
+ */
+ public static final int NeedCurrCtx4ARBCreateContext = 10;
+
+
/** Number of quirks known. */
- public static final int COUNT = 9;
+ public static final int COUNT = 11;
private static final String[] _names = new String[] { "NoDoubleBufferedPBuffer", "NoDoubleBufferedBitmap", "NoSetSwapInterval",
"NoOffscreenBitmap", "NoSetSwapIntervalPostRetarget", "GLSLBuggyDiscard",
- "GLNonCompliant", "GLFlushBeforeRelease", "DontCloseX11Display"
+ "GLNonCompliant", "GLFlushBeforeRelease", "DontCloseX11Display",
+ "NeedCurrCtx4ARBPixFmtQueries", "NeedCurrCtx4ARBCreateContext"
};
private final int _bitmask;
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index d26076344..f303c5b1c 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -176,7 +176,6 @@ public abstract class GLContext {
protected VersionNumber ctxGLSLVersion;
private int currentSwapInterval;
protected GLRendererQuirks glRendererQuirks;
- private static final VersionNumberString nullVersion = new VersionNumberString(-1, -1, -1, "n/a");
/** Did the drawable association changed ? see {@link GLRendererQuirks#NoSetSwapIntervalPostRetarget} */
protected boolean drawableRetargeted;
@@ -186,8 +185,8 @@ public abstract class GLContext {
System.err.println(getThreadName() + ": GLContext.resetStates()");
// Thread.dumpStack();
}
- ctxVersion = nullVersion;
- ctxVendorVersion = nullVersion;
+ ctxVersion = VersionNumberString.zeroVersion;
+ ctxVendorVersion = VersionNumberString.zeroVersion;
ctxOptions=0;
ctxVersionString=null;
ctxGLSLVersion=null;
@@ -668,6 +667,16 @@ public abstract class GLContext {
* @see #getGLSLVersionNumber()
**/
public final VersionNumber getGLVersionNumber() { return ctxVersion; }
+ /**
+ * Returns the vendor's version, i.e. version number at the end of GL_VERSION
not being the GL version.
+ *
+ * In case no such version exists within GL_VERSION
,
+ * the {@link VersionNumberString#zeroVersion zero version} instance is being returned.
+ *
+ *
+ * The vendor's version is usually the vendor's OpenGL driver version.
+ *
+ */
public final VersionNumberString getGLVendorVersionNumber() { return ctxVendorVersion; }
public final boolean isGLCompatibilityProfile() { return ( 0 != ( CTX_PROFILE_COMPAT & ctxOptions ) ); }
public final boolean isGLCoreProfile() { return ( 0 != ( CTX_PROFILE_CORE & ctxOptions ) ); }
diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
index 9feb54a46..dbf6df0de 100644
--- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
@@ -285,7 +285,7 @@ public abstract class GLDrawableFactory {
if(null==device) {
device = getDefaultDevice();
if(null==device) {
- throw new InternalError("no default device");
+ throw new InternalError("no default device available");
}
if (GLProfile.DEBUG) {
System.err.println("Info: "+getClass().getSimpleName()+".validateDevice: using default device : "+device);
@@ -322,7 +322,10 @@ public abstract class GLDrawableFactory {
* @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null
for the platform's default device.
* @return true if a shared resource could been created, otherwise false.
*/
- protected abstract boolean createSharedResource(AbstractGraphicsDevice device);
+ protected final boolean createSharedResource(AbstractGraphicsDevice device) {
+ return createSharedResourceImpl(device);
+ }
+ protected abstract boolean createSharedResourceImpl(AbstractGraphicsDevice device);
/**
* Returns true if the quirk
exist in the shared resource's context {@link GLRendererQuirks}.
@@ -419,7 +422,7 @@ public abstract class GLDrawableFactory {
public final List getAvailableCapabilities(AbstractGraphicsDevice device) {
device = validateDevice(device);
if(null!=device) {
- return getAvailableCapabilitiesImpl(device);
+ return getAvailableCapabilitiesImpl(device);
}
return null;
}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 66e3efc4d..1b8b0316c 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -90,6 +90,7 @@ public abstract class GLContextImpl extends GLContext {
// OpenGL functions.
private ProcAddressTable glProcAddressTable;
+ private String glVendor;
private String glRenderer;
private String glRendererLowerCase;
private String glVersion;
@@ -165,8 +166,10 @@ public abstract class GLContextImpl extends GLContext {
contextFQN = null;
additionalCtxCreationFlags = 0;
- glRenderer = "";
- glRendererLowerCase = glRenderer;
+ glVendor = "";
+ glRenderer = glVendor;
+ glRendererLowerCase = glRenderer;
+ glVersion = glVendor;
if (boundFBOTarget != null) { //
boundFBOTarget[0] = 0; // draw
@@ -1152,6 +1155,16 @@ public abstract class GLContextImpl extends GLContext {
}
return false;
} else {
+ final String _glVendor = glGetStringInt(GL.GL_VENDOR, _glGetString);
+ if(null == _glVendor) {
+ if(DEBUG) {
+ System.err.println("Warning: GL_VENDOR is NULL.");
+ Thread.dumpStack();
+ }
+ return false;
+ }
+ glVendor = _glVendor;
+
final String _glRenderer = glGetStringInt(GL.GL_RENDERER, _glGetString);
if(null == _glRenderer) {
if(DEBUG) {
@@ -1173,6 +1186,7 @@ public abstract class GLContextImpl extends GLContext {
return false;
}
glVersion = _glVersion;
+
return true;
}
}
@@ -1389,7 +1403,7 @@ public abstract class GLContextImpl extends GLContext {
final VersionNumberString vendorVersion = GLVersionNumber.createVendorVersion(glVersion);
- setRendererQuirks(major, minor, ctxProfileBits, vendorVersion);
+ setRendererQuirks(adevice, major, minor, ctxProfileBits, vendorVersion);
if( strictMatch && glRendererQuirks.exist(GLRendererQuirks.GLNonCompliant) ) {
if(DEBUG) {
@@ -1486,13 +1500,16 @@ public abstract class GLContextImpl extends GLContext {
return true;
}
- private final void setRendererQuirks(int major, int minor, int ctp, VersionNumberString vendorVersion) {
+ private final void setRendererQuirks(final AbstractGraphicsDevice adevice, int major, int minor, int ctp, final VersionNumberString vendorVersion) {
int[] quirks = new int[GLRendererQuirks.COUNT];
int i = 0;
+ final String MesaSP = "Mesa ";
final boolean hwAccel = 0 == ( ctp & GLContext.CTX_IMPL_ACCEL_SOFT );
final boolean compatCtx = 0 != ( ctp & GLContext.CTX_PROFILE_COMPAT );
-
+ final boolean isDriverMesa = glRenderer.contains(MesaSP) || glRenderer.contains("Gallium ");
+ final boolean isDriverATICatalyst = !isDriverMesa && ( glVendor.contains("ATI Technologies") || glRenderer.startsWith("ATI ") );
+ final boolean isDriverNVIDIAGeForce = !isDriverMesa && ( glVendor.contains("NVIDIA Corporation") || glRenderer.contains("NVIDIA ") );
//
// OS related quirks
//
@@ -1509,28 +1526,51 @@ public abstract class GLContextImpl extends GLContext {
}
final VersionNumber OSXVersion173 = new VersionNumber(1,7,3);
- if( Platform.getOSVersionNumber().compareTo(OSXVersion173) < 0 && glRendererLowerCase.contains("nvidia") ) {
+ if( Platform.getOSVersionNumber().compareTo(OSXVersion173) < 0 && isDriverNVIDIAGeForce ) {
final int quirk = GLRendererQuirks.GLFlushBeforeRelease;
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", Renderer "+glRenderer);
}
quirks[i++] = quirk;
}
- } else if( Platform.getOSType() == Platform.OSType.WINDOWS ) {
+ } else if( Platform.getOSType() == Platform.OSType.WINDOWS ) {
//
// WINDOWS
//
- final int quirk = GLRendererQuirks.NoDoubleBufferedBitmap;
- if(DEBUG) {
- System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
+ {
+ final int quirk = GLRendererQuirks.NoDoubleBufferedBitmap;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType());
+ }
+ quirks[i++] = quirk;
+ }
+
+ if( isDriverATICatalyst ) {
+ final VersionNumber winXPVersionNumber = new VersionNumber ( 5, 1, 0);
+ final VersionNumber amdSafeMobilityVersion = new VersionNumber(12, 102, 3);
+
+ if ( vendorVersion.compareTo(amdSafeMobilityVersion) < 0 ) { // includes: vendorVersion.isZero()
+ final int quirk = GLRendererQuirks.NeedCurrCtx4ARBCreateContext;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", [Vendor "+glVendor+" or Renderer "+glRenderer+"], driverVersion "+vendorVersion);
+ }
+ quirks[i++] = quirk;
+ }
+
+ if( Platform.getOSVersionNumber().compareTo(winXPVersionNumber) <= 0 ) {
+ final int quirk = GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries;
+ if(DEBUG) {
+ System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS-Version "+Platform.getOSType()+" "+Platform.getOSVersionNumber()+", [Vendor "+glVendor+" or Renderer "+glRenderer+"]");
+ }
+ quirks[i++] = quirk;
+ }
}
- quirks[i++] = quirk;
} else if( Platform.OSType.ANDROID == Platform.getOSType() ) {
//
// ANDROID
//
// Renderer related quirks, may also involve OS
- if( glRendererLowerCase.contains("powervr") ) {
+ if( glRenderer.contains("PowerVR") ) {
final int quirk = GLRendererQuirks.NoSetSwapInterval;
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType() + " / Renderer " + glRenderer);
@@ -1542,7 +1582,7 @@ public abstract class GLContextImpl extends GLContext {
//
// RENDERER related quirks
//
- if( glRendererLowerCase.contains("mesa") || glRendererLowerCase.contains("gallium") ) {
+ if( isDriverMesa ) {
{
final int quirk = GLRendererQuirks.NoSetSwapIntervalPostRetarget;
if(DEBUG) {
@@ -1550,7 +1590,7 @@ public abstract class GLContextImpl extends GLContext {
}
quirks[i++] = quirk;
}
- if( hwAccel /* glRendererLowerCase.contains("intel(r)") || glRendererLowerCase.contains("amd") */ )
+ if( hwAccel /* glRenderer.contains("Intel(R)") || glRenderer.contains("AMD ") */ )
{
final int quirk = GLRendererQuirks.NoDoubleBufferedPBuffer;
if(DEBUG) {
@@ -1558,7 +1598,7 @@ public abstract class GLContextImpl extends GLContext {
}
quirks[i++] = quirk;
}
- if( glRendererLowerCase.contains("intel(r)") && compatCtx && ( major>3 || major==3 && minor>=1 ) )
+ if( glRenderer.contains("Intel(R)") && compatCtx && ( major>3 || major==3 && minor>=1 ) )
{
// FIXME: Apply vendor version constraints!
final int quirk = GLRendererQuirks.GLNonCompliant;
@@ -1574,14 +1614,14 @@ public abstract class GLContextImpl extends GLContext {
//
if( NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
final int quirk = GLRendererQuirks.DontCloseX11Display;
- if( glRendererLowerCase.contains("mesa") ) {
- if ( glRendererLowerCase.contains("x11") && vendorVersion.compareTo(Version80) < 0 ) {
+ if( glRenderer.contains(MesaSP) ) {
+ if ( glRenderer.contains("X11") && vendorVersion.compareTo(Version80) < 0 ) {
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer + ", Version=[vendor " + vendorVersion + ", GL " + glVersion+"]");
}
quirks[i++] = quirk;
}
- } else if( glRendererLowerCase.contains("ati technologies") || glRendererLowerCase.startsWith("ati ") ) {
+ } else if( isDriverATICatalyst ) {
{
if(DEBUG) {
System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: X11 Renderer=" + glRenderer);
@@ -1597,7 +1637,7 @@ public abstract class GLContextImpl extends GLContext {
}
}
}
-
+
glRendererQuirks = new GLRendererQuirks(quirks, 0, i);
}
@@ -1652,8 +1692,8 @@ public abstract class GLContextImpl extends GLContext {
if(!drawable.getChosenGLCapabilities().getHardwareAccelerated()) {
isHardwareRasterizer = false;
} else {
- isHardwareRasterizer = ! ( glRendererLowerCase.contains("software") /* Mesa3D */ ||
- glRendererLowerCase.contains("mesa x11") /* Mesa3D*/ ||
+ isHardwareRasterizer = ! ( glRendererLowerCase.contains("software") /* Mesa3D */ ||
+ glRendererLowerCase.contains("mesa x11") /* Mesa3D */ ||
glRendererLowerCase.contains("softpipe") /* Gallium */ ||
glRendererLowerCase.contains("llvmpipe") /* Gallium */
);
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index 26b1975ba..06e856d41 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -80,30 +80,61 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
super();
}
- @Override
- public GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device) {
- final GLContext ctx = getOrCreateSharedContextImpl(device);
- if(null != ctx) {
- return ctx.getRendererQuirks();
+ /**
+ * Returns the shared resource mapped to the device
{@link AbstractGraphicsDevice#getConnection()},
+ * either a pre-existing or newly created, or null
if creation failed or not supported.
+ * Creation of the shared resource is tried only once.
+ *
+ * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null
for the platform's default device.
+ */
+ protected final SharedResourceRunner.Resource getOrCreateSharedResource(AbstractGraphicsDevice device) {
+ try {
+ device = validateDevice(device);
+ if( null != device) {
+ return getOrCreateSharedResourceImpl( device );
+ }
+ } catch (GLException gle) {
+ if(DEBUG) {
+ System.err.println("Catched Exception on thread "+getThreadName());
+ gle.printStackTrace();
+ }
}
return null;
}
-
+ protected abstract SharedResourceRunner.Resource getOrCreateSharedResourceImpl(AbstractGraphicsDevice device);
+
/**
* Returns the shared context mapped to the device
{@link AbstractGraphicsDevice#getConnection()},
- * either a pre-existing or newly created, or null
if creation failed or not supported.
+ * either a pre-existing or newly created, or null
if creation failed or not supported.
* Creation of the shared context is tried only once.
*
* @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null
for the platform's default device.
*/
public final GLContext getOrCreateSharedContext(AbstractGraphicsDevice device) {
- device = validateDevice(device);
- if(null!=device) {
- return getOrCreateSharedContextImpl(device);
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+ if(null!=sr) {
+ return sr.getContext();
+ }
+ return null;
+ }
+
+ @Override
+ protected final boolean createSharedResourceImpl(AbstractGraphicsDevice device) {
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+ if(null!=sr) {
+ return sr.isValid();
+ }
+ return false;
+ }
+
+ @Override
+ public final GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device) {
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+ if(null!=sr) {
+ return sr.getRendererQuirks();
}
return null;
}
- protected abstract GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device);
/**
* Returns the shared device mapped to the device
{@link AbstractGraphicsDevice#getConnection()},
@@ -113,15 +144,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
* @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be null
for the platform's default device.
*/
protected final AbstractGraphicsDevice getOrCreateSharedDevice(AbstractGraphicsDevice device) {
- device = validateDevice(device);
- if( null != device) {
- return getOrCreateSharedDeviceImpl(device);
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
+ if(null!=sr) {
+ return sr.getDevice();
}
return null;
}
- protected abstract AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device);
-
/**
* Returns the GLDynamicLookupHelper
* @param profile if EGL/ES, profile 1
refers to ES1 and 2
to ES2,
diff --git a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
index 1784cd772..990698667 100644
--- a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
+++ b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
@@ -128,12 +128,13 @@ class GLVersionNumber extends VersionNumberString {
/**
* Returns the optional vendor version at the end of the
- * GL_VERSION
string if exists, otherwise null
.
+ * GL_VERSION
string if exists, otherwise the {@link VersionNumberString#zeroVersion zero version} instance.
*
* 2.1 Mesa 7.0.3-rc2 -> 7.0.3 (7.0.3-rc2)
* 4.2.12171 Compatibility Profile Context 9.01.8 -> 9.1.8 (9.01.8)
+ * 4.2.12198 Compatibility Profile Context 12.102.3.0 -> 12.102.3 (12.102.3.0)
* 4.3.0 NVIDIA 310.32 -> 310.32 (310.32)
- *
+ *
*/
public static final VersionNumberString createVendorVersion(String versionString) {
if (versionString == null || versionString.length() <= 0) {
@@ -152,6 +153,6 @@ class GLVersionNumber extends VersionNumberString {
return version;
}
}
- return null;
+ return VersionNumberString.zeroVersion;
}
}
diff --git a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
index 91187cc26..f454904a2 100644
--- a/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
+++ b/src/jogl/classes/jogamp/opengl/SharedResourceRunner.java
@@ -33,14 +33,18 @@ import java.util.Iterator;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.AbstractGraphicsScreen;
+import com.jogamp.opengl.GLRendererQuirks;
+
public class SharedResourceRunner implements Runnable {
protected static final boolean DEBUG = GLDrawableImpl.DEBUG;
public static interface Resource {
+ boolean isValid();
AbstractGraphicsDevice getDevice();
AbstractGraphicsScreen getScreen();
GLDrawableImpl getDrawable();
GLContextImpl getContext();
+ GLRendererQuirks getRendererQuirks();
}
public static interface Implementation {
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
index 431de5159..adb78b3b9 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java
@@ -67,10 +67,12 @@ import javax.media.opengl.GLProfile;
import jogamp.nativewindow.WrappedSurface;
import jogamp.opengl.Debug;
+import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
import jogamp.opengl.GLGraphicsConfigurationUtil;
+import jogamp.opengl.SharedResourceRunner;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.nio.PointerBuffer;
@@ -251,8 +253,8 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
String key = keyI.next();
SharedResource sr = sharedMap.get(key);
System.err.println("EGLDrawableFactory.map["+i+"] "+key+" -> "+sr.getDevice()+", "+
- "es1 [avail "+sr.wasES1ContextAvailable()+", pbuffer "+sr.hasES1PBuffer()+", quirks "+sr.getGLRendererQuirksES1()+", ctp "+EGLContext.getGLVersion(1, 0, sr.getCtpES1(), null)+"], "+
- "es2 [avail "+sr.wasES2ContextAvailable()+", pbuffer "+sr.hasES2PBuffer()+", quirks "+sr.getGLRendererQuirksES1()+", ctp "+EGLContext.getGLVersion(2, 0, sr.getCtpES2(), null)+"]");
+ "es1 [avail "+sr.wasES1ContextCreated+", pbuffer "+sr.hasPBufferES1+", quirks "+sr.rendererQuirksES1+", ctp "+EGLContext.getGLVersion(1, 0, sr.ctpES1, null)+"], "+
+ "es2 [avail "+sr.wasES2ContextCreated+", pbuffer "+sr.hasPBufferES2+", quirks "+sr.rendererQuirksES2+", ctp "+EGLContext.getGLVersion(2, 0, sr.ctpES2, null)+"]");
}
;
}
@@ -265,7 +267,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
private boolean isANGLE = false;
private boolean hasX11 = false;
- static class SharedResource {
+ static class SharedResource implements SharedResourceRunner.Resource {
private final EGLGraphicsDevice device;
// private final EGLContext contextES1;
// private final EGLContext contextES2;
@@ -293,17 +295,31 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
this.hasPBufferES1= hasPBufferES1;
this.hasPBufferES2= hasPBufferES2;
}
- final EGLGraphicsDevice getDevice() { return device; }
+ @Override
+ public final boolean isValid() {
+ return wasES1ContextCreated || wasES2ContextCreated;
+ }
+ @Override
+ public final EGLGraphicsDevice getDevice() { return device; }
// final EGLContext getContextES1() { return contextES1; }
// final EGLContext getContextES2() { return contextES2; }
- final GLRendererQuirks getGLRendererQuirksES1() { return rendererQuirksES1; }
- final GLRendererQuirks getGLRendererQuirksES2() { return rendererQuirksES2; }
- final int getCtpES1() { return ctpES1; }
- final int getCtpES2() { return ctpES2; }
- final boolean wasES1ContextAvailable() { return wasES1ContextCreated; }
- final boolean wasES2ContextAvailable() { return wasES2ContextCreated; }
- final boolean hasES1PBuffer() { return hasPBufferES1; }
- final boolean hasES2PBuffer() { return hasPBufferES2; }
+
+ @Override
+ public AbstractGraphicsScreen getScreen() {
+ return null;
+ }
+ @Override
+ public GLDrawableImpl getDrawable() {
+ return null;
+ }
+ @Override
+ public GLContextImpl getContext() {
+ return null;
+ }
+ @Override
+ public GLRendererQuirks getRendererQuirks() {
+ return null != rendererQuirksES2 ? rendererQuirksES2 : rendererQuirksES1 ;
+ }
}
@Override
@@ -504,7 +520,8 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
}
}
- /* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) {
+ @Override
+ protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice adevice) {
if(null == sharedMap) { // null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper
return null;
}
@@ -600,46 +617,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl {
return null;
}
- @Override
- protected final boolean createSharedResource(AbstractGraphicsDevice device) {
- try {
- SharedResource sr = getOrCreateEGLSharedResource(device);
- if(null!=sr) {
- return sr.wasES1ContextAvailable() || sr.wasES2ContextAvailable();
- }
- } catch (GLException gle) {
- if(DEBUG) {
- System.err.println("Catched Exception on thread "+getThreadName());
- gle.printStackTrace();
- }
- }
- return false;
- }
-
- @Override
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- return null; // FIXME: n/a ..
- }
-
- @Override
- public GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device) {
- SharedResource sr = getOrCreateEGLSharedResource(device);
- if(null!=sr) {
- return null != sr.getGLRendererQuirksES2() ? sr.getGLRendererQuirksES2() : sr.getGLRendererQuirksES1() ;
- }
- return null;
- }
-
- @Override
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResource sr = getOrCreateEGLSharedResource(device);
- if(null!=sr) {
- return sr.getDevice();
- }
- return null;
- }
-
- public boolean isANGLE() {
+ public final boolean isANGLE() {
return isANGLE;
}
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
index 7e1f8a5a2..b44e08500 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java
@@ -181,7 +181,7 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact
}
protected static List getAvailableCapabilities(EGLDrawableFactory factory, AbstractGraphicsDevice device) {
- EGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateEGLSharedResource(device);
+ EGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
index 39178290a..c9402b33d 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java
@@ -64,10 +64,12 @@ import javax.media.opengl.GLProfile;
import jogamp.nativewindow.WrappedSurface;
import jogamp.nativewindow.macosx.OSXDummyUpstreamSurfaceHook;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
+import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
import jogamp.opengl.GLDrawableImpl;
import jogamp.opengl.GLDynamicLookupHelper;
import jogamp.opengl.GLGraphicsConfigurationUtil;
+import jogamp.opengl.SharedResourceRunner;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.ReflectionUtil;
@@ -146,35 +148,54 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
private HashMap sharedMap = new HashMap();
private MacOSXGraphicsDevice defaultDevice;
- static class SharedResource {
+ static class SharedResource implements SharedResourceRunner.Resource {
// private MacOSXCGLDrawable drawable;
// private MacOSXCGLContext context;
private GLRendererQuirks glRendererQuirks;
MacOSXGraphicsDevice device;
- boolean wasContextCreated;
+ boolean valid;
boolean hasNPOTTextures;
boolean hasRECTTextures;
boolean hasAppleFloatPixels;
- SharedResource(MacOSXGraphicsDevice device, boolean wasContextCreated,
+ SharedResource(MacOSXGraphicsDevice device, boolean valid,
boolean hasNPOTTextures, boolean hasRECTTextures, boolean hasAppletFloatPixels
/* MacOSXCGLDrawable draw, MacOSXCGLContext ctx */, GLRendererQuirks glRendererQuirks) {
// drawable = draw;
// this.context = ctx;
this.glRendererQuirks = glRendererQuirks;
this.device = device;
- this.wasContextCreated = wasContextCreated;
+ this.valid = valid;
this.hasNPOTTextures = hasNPOTTextures;
this.hasRECTTextures = hasRECTTextures;
this.hasAppleFloatPixels = hasAppletFloatPixels;
}
- final MacOSXGraphicsDevice getDevice() { return device; }
+ @Override
+ public final boolean isValid() {
+ return valid;
+ }
+ @Override
+ public final MacOSXGraphicsDevice getDevice() { return device; }
// final MacOSXCGLContext getContext() { return context; }
- final GLRendererQuirks getGLRendererQuirks() { return glRendererQuirks; }
- final boolean wasContextAvailable() { return wasContextCreated; }
final boolean isNPOTTextureAvailable() { return hasNPOTTextures; }
final boolean isRECTTextureAvailable() { return hasRECTTextures; }
final boolean isAppleFloatPixelsAvailable() { return hasAppleFloatPixels; }
+ @Override
+ public final AbstractGraphicsScreen getScreen() {
+ return null;
+ }
+ @Override
+ public final GLDrawableImpl getDrawable() {
+ return null;
+ }
+ @Override
+ public GLContextImpl getContext() {
+ return null;
+ }
+ @Override
+ public GLRendererQuirks getRendererQuirks() {
+ return glRendererQuirks;
+ }
}
@Override
@@ -208,7 +229,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
}
- /* package */ SharedResource getOrCreateOSXSharedResource(AbstractGraphicsDevice adevice) {
+ protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice adevice) {
final String connection = adevice.getConnection();
SharedResource sr;
synchronized(sharedMap) {
@@ -218,7 +239,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
addDeviceTried(connection);
final MacOSXGraphicsDevice sharedDevice = new MacOSXGraphicsDevice(adevice.getUnitID());
GLRendererQuirks glRendererQuirks = null;
- boolean madeCurrent = false;
+ boolean isValid = false;
boolean hasNPOTTextures = false;
boolean hasRECTTextures = false;
boolean hasAppleFloatPixels = false;
@@ -238,8 +259,8 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
try {
sharedContext.makeCurrent(); // could cause exception
- madeCurrent = sharedContext.isCurrent();
- if(madeCurrent) {
+ isValid = sharedContext.isCurrent();
+ if(isValid) {
GL gl = sharedContext.getGL();
hasNPOTTextures = gl.isNPOTTextureAvailable();
hasRECTTextures = gl.isExtensionAvailable(GLExtensions.EXT_texture_rectangle);
@@ -263,14 +284,14 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
}
sharedDrawable.setRealized(false);
}
- sr = new SharedResource(sharedDevice, madeCurrent, hasNPOTTextures, hasRECTTextures, hasAppleFloatPixels, glRendererQuirks);
+ sr = new SharedResource(sharedDevice, isValid, hasNPOTTextures, hasRECTTextures, hasAppleFloatPixels, glRendererQuirks);
synchronized(sharedMap) {
sharedMap.put(connection, sr);
}
removeDeviceTried(connection);
if (DEBUG) {
System.err.println("MacOSXCGLDrawableFactory.createShared: device: " + sharedDevice);
- System.err.println("MacOSXCGLDrawableFactory.createShared: context: madeCurrent " + madeCurrent + ", NPOT "+hasNPOTTextures+
+ System.err.println("MacOSXCGLDrawableFactory.createShared: context: madeCurrent " + isValid + ", NPOT "+hasNPOTTextures+
", RECT "+hasRECTTextures+", FloatPixels "+hasAppleFloatPixels+", "+glRendererQuirks);
}
}
@@ -282,46 +303,6 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl {
return null;
}
- @Override
- protected final boolean createSharedResource(AbstractGraphicsDevice device) {
- try {
- SharedResource sr = getOrCreateOSXSharedResource(device);
- if(null!=sr) {
- return sr.wasContextAvailable();
- }
- } catch (GLException gle) {
- if(DEBUG) {
- System.err.println("Catched Exception on thread "+getThreadName());
- gle.printStackTrace();
- }
- }
- return false;
- }
-
- @Override
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- // FIXME: no more available
- return null;
- }
-
- @Override
- public GLRendererQuirks getRendererQuirks(AbstractGraphicsDevice device) {
- SharedResource sr = getOrCreateOSXSharedResource(device);
- if(null!=sr) {
- return sr.getGLRendererQuirks();
- }
- return null;
- }
-
- @Override
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResource sr = getOrCreateOSXSharedResource(device);
- if(null!=sr) {
- return sr.getDevice();
- }
- return null;
- }
-
@Override
protected List getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
return MacOSXCGLGraphicsConfiguration.getAvailableCapabilities(this, device);
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
index 86e1ef481..5eb11c6a4 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java
@@ -64,7 +64,7 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration
}
protected static List getAvailableCapabilities(MacOSXCGLDrawableFactory factory, AbstractGraphicsDevice device) {
- MacOSXCGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateOSXSharedResource(device);
+ MacOSXCGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
index 982bb57e1..4e791cb5f 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java
@@ -121,7 +121,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable {
final DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ms.getGraphicsConfiguration();
final GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getChosenCapabilities();
final GLProfile glProfile = capabilities.getGLProfile();
- MacOSXCGLDrawableFactory.SharedResource sr = ((MacOSXCGLDrawableFactory)factory).getOrCreateOSXSharedResource(config.getScreen().getDevice());
+ MacOSXCGLDrawableFactory.SharedResource sr = ((MacOSXCGLDrawableFactory)factory).getOrCreateSharedResourceImpl(config.getScreen().getDevice());
if (DEBUG) {
System.out.println(getThreadName()+": Pbuffer config: " + config);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
index 2a0f2596e..217ca18e8 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java
@@ -113,7 +113,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable {
private void createPbuffer() {
WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration();
- SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResource(config.getScreen().getDevice());
+ SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResourceImpl(config.getScreen().getDevice());
NativeSurface sharedSurface = sharedResource.getDrawable().getNativeSurface();
if (NativeSurface.LOCK_SURFACE_NOT_READY >= sharedSurface.lockSurface()) {
throw new NativeWindowException("Could not lock (sharedSurface): "+this);
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
index 92b12a7ff..94153d96d 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java
@@ -56,6 +56,7 @@ import com.jogamp.common.nio.Buffers;
import com.jogamp.gluegen.runtime.ProcAddressTable;
import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
import jogamp.nativewindow.windows.GDI;
import jogamp.opengl.GLContextImpl;
@@ -271,8 +272,7 @@ public class WindowsWGLContext extends GLContextImpl {
final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice device = config.getScreen().getDevice();
final WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl();
- final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
- final WindowsWGLContext sharedContext = (WindowsWGLContext) ( null != sharedResource ? sharedResource.getContext() : null );
+ final WindowsWGLContext sharedContext = (WindowsWGLContext) factory.getOrCreateSharedContext(device);
final GLCapabilitiesImmutable glCaps = drawable.getChosenGLCapabilities();
isGLReadDrawableAvailable(); // trigger setup wglGLReadDrawableAvailable
@@ -296,7 +296,7 @@ public class WindowsWGLContext extends GLContextImpl {
// utilize the shared context's GLXExt in case it was using the ARB method and it already exists ; exclude BITMAP
if( null != sharedContext && sharedContext.isCreatedWithARBMethod() && !glCaps.isBitmap() ) {
- if ( sharedResource.needsCurrenContext4ARBCreateContextAttribs() ) {
+ if ( sharedContext.getRendererQuirks().exist( GLRendererQuirks.NeedCurrCtx4ARBCreateContext ) ) {
if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) {
throw new GLException("Could not make Shared Context current: "+sharedContext);
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index 483e31611..5fb01d1a3 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
@@ -41,6 +41,7 @@
package jogamp.opengl.windows.wgl;
import java.nio.Buffer;
+
import java.nio.ShortBuffer;
import java.util.Collection;
import java.util.HashMap;
@@ -53,7 +54,6 @@ import javax.media.nativewindow.DefaultGraphicsScreen;
import javax.media.nativewindow.NativeSurface;
import javax.media.nativewindow.ProxySurface;
import javax.media.nativewindow.UpstreamSurfaceHook;
-import javax.media.opengl.GL;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLCapabilitiesChooser;
import javax.media.opengl.GLCapabilitiesImmutable;
@@ -76,11 +76,10 @@ import jogamp.opengl.GLGraphicsConfigurationUtil;
import jogamp.opengl.SharedResourceRunner;
import com.jogamp.common.nio.PointerBuffer;
-import com.jogamp.common.os.Platform;
import com.jogamp.common.util.ReflectionUtil;
-import com.jogamp.common.util.VersionNumber;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
private static DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper = null;
@@ -201,29 +200,18 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
}
- /**
- * http://msdn.microsoft.com/en-us/library/ms724832%28v=vs.85%29.aspx
- * Windows XP 5.1
- */
- static final VersionNumber winXPVersionNumber = new VersionNumber ( 5, 1, 0);
-
static class SharedResource implements SharedResourceRunner.Resource {
private final boolean hasARBPixelFormat;
private final boolean hasARBMultisample;
private final boolean hasARBPBuffer;
private final boolean hasARBReadDrawable;
- private final String vendor;
- private final boolean isVendorATI;
- private final boolean isVendorNVIDIA;
- private final boolean needsCurrenContext4ARBPFDQueries;
- private final boolean needsCurrenContext4ARBCreateContextAttribs;
private WindowsGraphicsDevice device;
private AbstractGraphicsScreen screen;
private GLDrawableImpl drawable;
private GLContextImpl context;
-
+
SharedResource(WindowsGraphicsDevice dev, AbstractGraphicsScreen scrn, GLDrawableImpl draw, GLContextImpl ctx,
- boolean arbPixelFormat, boolean arbMultisample, boolean arbPBuffer, boolean arbReadDrawable, String glVendor) {
+ boolean arbPixelFormat, boolean arbMultisample, boolean arbPBuffer, boolean arbReadDrawable) {
device = dev;
screen = scrn;
drawable = draw;
@@ -232,33 +220,12 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
hasARBMultisample = arbMultisample;
hasARBPBuffer = arbPBuffer;
hasARBReadDrawable = arbReadDrawable;
- vendor = glVendor;
- if(null != vendor) {
- isVendorNVIDIA = vendor.startsWith("NVIDIA") ;
- isVendorATI = vendor.startsWith("ATI") ;
- } else {
- isVendorNVIDIA = false;
- isVendorATI = false;
- }
-
- if ( isVendorATI ) {
- needsCurrenContext4ARBCreateContextAttribs = true;
- final VersionNumber winVersion = Platform.getOSVersionNumber();
- final boolean isWinXPOrLess = winVersion.compareTo(winXPVersionNumber) <= 0;
- needsCurrenContext4ARBPFDQueries = isWinXPOrLess;
- if(DEBUG) {
- System.err.println("ATI && isWinXPOrLess = "+winVersion+" <= "+winXPVersionNumber+" = "+isWinXPOrLess+" - "+Platform.getOSVersion());
- }
- } else {
- needsCurrenContext4ARBPFDQueries = false;
- needsCurrenContext4ARBCreateContextAttribs = false;
- }
- if(DEBUG) {
- System.err.println("needsCurrenContext4ARBCreateContextAttribs: "+needsCurrenContext4ARBCreateContextAttribs);
- System.err.println("needsCurrenContext4ARBPFDQueries: "+needsCurrenContext4ARBPFDQueries);
- }
}
+ @Override
+ public final boolean isValid() {
+ return null != context;
+ }
@Override
final public AbstractGraphicsDevice getDevice() { return device; }
@Override
@@ -267,35 +234,15 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
final public GLDrawableImpl getDrawable() { return drawable; }
@Override
final public GLContextImpl getContext() { return context; }
+ @Override
+ public GLRendererQuirks getRendererQuirks() {
+ return null != context ? context.getRendererQuirks() : null;
+ }
final boolean hasARBPixelFormat() { return hasARBPixelFormat; }
final boolean hasARBMultisample() { return hasARBMultisample; }
final boolean hasARBPBuffer() { return hasARBPBuffer; }
final boolean hasReadDrawable() { return hasARBReadDrawable; }
-
- final String vendor() { return vendor; }
- final boolean isVendorATI() { return isVendorATI; }
- final boolean isVendorNVIDIA() { return isVendorNVIDIA; }
-
- /**
- * Solves bug #480
- *
- * TODO: Validate if bug actually relates to the 'old' ATI Windows driver for old GPU's like X300 etc
- * and not to the Windows version !
- *
- * @return true if GL_VENDOR is ATI _and_ platform is Windows version XP or less!
- */
- final boolean needsCurrentContext4ARBPFDQueries() { return needsCurrenContext4ARBPFDQueries; }
-
- /**
- * Solves bug #706 and bug #520
- *
- * TODO: Validate if quirk can be reduced to a certain range of GPUs and/or driver versions,
- * where we would also need a method to query the latter (-> jogl/src/nativewindow/native/win32/DeviceDriverQuery.txt).
- *
- * @return true if GL_VENDOR is ATI
- */
- final boolean needsCurrenContext4ARBCreateContextAttribs() { return needsCurrenContext4ARBCreateContextAttribs; }
}
class SharedResourceImplementation implements SharedResourceRunner.Implementation {
@@ -351,7 +298,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
boolean hasARBMultisample;
boolean hasARBPBuffer;
boolean hasARBReadDrawableAvailable;
- String vendor;
sharedContext.makeCurrent();
try {
hasARBPixelFormat = sharedContext.isExtensionAvailable(WGL_ARB_pixel_format);
@@ -359,7 +305,6 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
hasARBPBuffer = sharedContext.isExtensionAvailable(GLExtensions.ARB_pbuffer);
hasARBReadDrawableAvailable = sharedContext.isExtensionAvailable(WGL_ARB_make_current_read) &&
sharedContext.isFunctionAvailable(wglMakeContextCurrent);
- vendor = sharedContext.getGL().glGetString(GL.GL_VENDOR);
} finally {
sharedContext.release();
}
@@ -371,11 +316,10 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
System.err.println("multisample: " + hasARBMultisample);
System.err.println("pbuffer: " + hasARBPBuffer);
System.err.println("readDrawable: " + hasARBReadDrawableAvailable);
- System.err.println("vendor: " + vendor);
}
return new SharedResource(sharedDevice, absScreen, sharedDrawable, sharedContext,
hasARBPixelFormat, hasARBMultisample,
- hasARBPBuffer, hasARBReadDrawableAvailable, vendor);
+ hasARBPBuffer, hasARBReadDrawableAvailable);
} catch (Throwable t) {
throw new GLException("WindowsWGLDrawableFactory - Could not initialize shared resources for "+connection, t);
} finally {
@@ -441,51 +385,18 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final boolean createSharedResource(AbstractGraphicsDevice device) {
- try {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return null != sr.getContext();
- }
- } catch (GLException gle) {
- if(DEBUG) {
- System.err.println("Catched Exception on thread "+getThreadName());
- gle.printStackTrace();
- }
- }
- return false;
- }
-
- @Override
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getContext();
- }
- return null;
- }
-
- @Override
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getDevice();
- }
- return null;
+ protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice device) {
+ return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
}
- protected WindowsWGLDrawable getOrCreateSharedDrawable(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
+ protected final WindowsWGLDrawable getOrCreateSharedDrawable(AbstractGraphicsDevice device) {
+ SharedResourceRunner.Resource sr = getOrCreateSharedResourceImpl(device);
if(null!=sr) {
return (WindowsWGLDrawable) sr.getDrawable();
}
return null;
}
- SharedResource getOrCreateSharedResource(AbstractGraphicsDevice device) {
- return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
- }
-
@Override
protected List getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
return WindowsWGLGraphicsConfigurationFactory.getAvailableCapabilities(this, device);
@@ -518,7 +429,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
* Similar to ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277,
* we need to have a context current on the same Display to create a PBuffer.
*/
- final SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared(device);
+ final SharedResource sr = getOrCreateSharedResourceImpl(device);
if(null!=sr) {
GLContext lastContext = GLContext.getCurrent();
if (lastContext != null) {
@@ -544,7 +455,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
* and -1 if undefined yet, ie no shared device exist at this point.
*/
public final int isReadDrawableAvailable(AbstractGraphicsDevice device) {
- SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice);
+ SharedResource sr = getOrCreateSharedResourceImpl( ( null != device ) ? device : defaultDevice );
if(null!=sr) {
return sr.hasReadDrawable() ? 1 : 0 ;
}
@@ -553,7 +464,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
@Override
public final boolean canCreateGLPbuffer(AbstractGraphicsDevice device) {
- SharedResource sr = (SharedResource) sharedResourceRunner.getOrCreateShared((null!=device)?device:defaultDevice);
+ SharedResource sr = getOrCreateSharedResourceImpl( ( null != device ) ? device : defaultDevice );
if(null!=sr) {
return sr.hasARBPBuffer();
}
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
index 017f8c40b..42b92305a 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java
@@ -56,7 +56,6 @@ import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.GDIUtil;
import jogamp.nativewindow.windows.MARGINS;
import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
-import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLGraphicsConfigurationUtil;
public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable {
@@ -100,7 +99,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio
}
WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory;
AbstractGraphicsDevice device = screen.getDevice();
- WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+ WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
boolean hasARB = null != sharedResource && sharedResource.hasARBPixelFormat();
WGLGLCapabilities caps = null;
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
index 1e72e312b..3d093b972 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java
@@ -51,6 +51,7 @@ import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.GLRendererQuirks;
import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.PIXELFORMATDESCRIPTOR;
@@ -114,21 +115,23 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
}
protected static List getAvailableCapabilities(WindowsWGLDrawableFactory factory, AbstractGraphicsDevice device) {
- final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+ final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
final GLDrawableImpl sharedDrawable = sharedResource.getDrawable();
- final GLContext sharedContext = sharedResource.getContext();
final GLProfile glp = GLProfile.getDefault(device);
List availableCaps = null;
- if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) {
+ final GLContext sharedContext;
+ if ( factory.hasRendererQuirk(device, GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries) ) {
+ sharedContext = sharedResource.getContext();
if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) {
throw new GLException("Could not make Shared Context current: "+device);
}
} else {
+ sharedContext = null;
sharedDrawable.lockSurface();
}
try {
@@ -147,7 +150,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
availableCaps.addAll(availableCapsGDI);
}
} finally {
- if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) {
+ if ( null != sharedContext ) {
sharedContext.release();
} else {
sharedDrawable.unlockSurface();
@@ -281,13 +284,15 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
System.err.println("user chosen caps " + config.getChosenCapabilities());
}
AbstractGraphicsDevice device = config.getScreen().getDevice();
- WindowsWGLDrawableFactory.SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResource(device);
- GLContext sharedContext = null;
- if (null != sharedResource && sharedResource.needsCurrentContext4ARBPFDQueries()) {
+ WindowsWGLDrawableFactory.SharedResource sharedResource = ((WindowsWGLDrawableFactory)factory).getOrCreateSharedResourceImpl(device);
+ final GLContext sharedContext;
+ if ( factory.hasRendererQuirk(device, GLRendererQuirks.NeedCurrCtx4ARBPixFmtQueries) ) {
sharedContext = sharedResource.getContext();
if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) {
throw new GLException("Could not make Shared Context current: "+device);
}
+ } else {
+ sharedContext = null;
}
try {
final GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities();
@@ -308,7 +313,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat
private static boolean updateGraphicsConfigurationARB(WindowsWGLDrawableFactory factory, WindowsWGLGraphicsConfiguration config, CapabilitiesChooser chooser,
long hdc, boolean extHDC, int[] pformats) {
final AbstractGraphicsDevice device = config.getScreen().getDevice();
- final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+ final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if (null == sharedResource) {
if (DEBUG) {
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
index 9df042ba8..0d56bcde1 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java
@@ -283,7 +283,7 @@ public class X11GLXContext extends GLContextImpl {
final X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl();
final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeSurface().getGraphicsConfiguration();
final AbstractGraphicsDevice device = config.getScreen().getDevice();
- final X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContextImpl(device);
+ final X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContext(device);
long display = device.getHandle();
final long share;
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
index 0d89468a9..e44be7509 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java
@@ -185,6 +185,10 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
glXMultisampleAvailable = glXServerMultisampleAvail;
}
@Override
+ public final boolean isValid() {
+ return null != context;
+ }
+ @Override
final public AbstractGraphicsDevice getDevice() { return device; }
@Override
final public AbstractGraphicsScreen getScreen() { return screen; }
@@ -192,6 +196,10 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
final public GLDrawableImpl getDrawable() { return drawable; }
@Override
final public GLContextImpl getContext() { return context; }
+ @Override
+ public GLRendererQuirks getRendererQuirks() {
+ return null != context ? context.getRendererQuirks() : null;
+ }
final String getGLXVendorName() { return glXServerVendorName; }
final boolean isGLXVendorATI() { return isGLXServerVendorATI; }
@@ -357,51 +365,18 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl {
}
@Override
- protected final boolean createSharedResource(AbstractGraphicsDevice device) {
- try {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return null != sr.getContext();
- }
- } catch (GLException gle) {
- if(DEBUG) {
- System.err.println("Catched Exception on thread "+getThreadName());
- gle.printStackTrace();
- }
- }
- return false;
- }
-
- @Override
- protected final GLContext getOrCreateSharedContextImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getContext();
- }
- return null;
- }
-
- @Override
- protected AbstractGraphicsDevice getOrCreateSharedDeviceImpl(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
- if(null!=sr) {
- return sr.getDevice();
- }
- return null;
+ protected final SharedResource getOrCreateSharedResourceImpl(AbstractGraphicsDevice device) {
+ return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
}
protected final long getOrCreateSharedDpy(AbstractGraphicsDevice device) {
- SharedResourceRunner.Resource sr = sharedResourceRunner.getOrCreateShared(device);
+ final SharedResourceRunner.Resource sr = getOrCreateSharedResource( device );
if(null!=sr) {
return sr.getDevice().getHandle();
}
return 0;
}
- SharedResource getOrCreateSharedResource(AbstractGraphicsDevice device) {
- return (SharedResource) sharedResourceRunner.getOrCreateShared(device);
- }
-
@Override
protected List getAvailableCapabilitiesImpl(AbstractGraphicsDevice device) {
return X11GLXGraphicsConfigurationFactory.getAvailableCapabilities(this, device);
diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
index e62dcadcb..a7c7d3fe6 100644
--- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
+++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java
@@ -124,7 +124,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF
}
protected static List getAvailableCapabilities(X11GLXDrawableFactory factory, AbstractGraphicsDevice device) {
- X11GLXDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device);
+ X11GLXDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
if(null == sharedResource) {
throw new GLException("Shared resource for device n/a: "+device);
}
--
cgit v1.2.3
From ff9fb2d0adc81fdf25d6e26b91e1f67d8241e3e4 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Fri, 26 Apr 2013 07:41:12 +0200
Subject: GLContext*'s ctxGLSLVersion: Use zeroVersion to denominate
uninitialized VersionNumber instead of null, it's get*string returns a zero
length string instead of null.
---
src/jogl/classes/javax/media/opengl/GLContext.java | 20 +++++++++++---------
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 6 +++---
2 files changed, 14 insertions(+), 12 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index f303c5b1c..288329310 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -189,7 +189,7 @@ public abstract class GLContext {
ctxVendorVersion = VersionNumberString.zeroVersion;
ctxOptions=0;
ctxVersionString=null;
- ctxGLSLVersion=null;
+ ctxGLSLVersion = VersionNumber.zeroVersion;
attachedObjects.clear();
contextHandle=0;
currentSwapInterval = -1;
@@ -671,7 +671,7 @@ public abstract class GLContext {
* Returns the vendor's version, i.e. version number at the end of GL_VERSION
not being the GL version.
*
* In case no such version exists within GL_VERSION
,
- * the {@link VersionNumberString#zeroVersion zero version} instance is being returned.
+ * the {@link VersionNumberString#zeroVersion zero version} instance is returned.
*
*
* The vendor's version is usually the vendor's OpenGL driver version.
@@ -689,13 +689,14 @@ public abstract class GLContext {
* via {@link GL2ES2#GL_SHADING_LANGUAGE_VERSION} if ≥ ES2.0 or GL2.0,
* otherwise a static match is being utilized.
*
- * The context must have been current once, otherwise null
is returned.
+ * The context must have been current once,
+ * otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned.
*
*
* Examples w/ major.minor
:
*
- * 1.00 (ES2.0), 1.10 (GL2.0), 1.20 (GL2.1), 1.50 GL(3.2),
- * 3.30 (GL3.3), 4.40 (GL4.0)
+ * 1.00 (ES 2.0), 1.10 (GL 2.0), 1.20 (GL 2.1), 1.50 (GL 3.2),
+ * 3.30 (GL 3.3), 4.00 (GL 4.0), 4.10 (GL 4.1), 4.20 (GL 4.2)
*
*
*
@@ -704,7 +705,8 @@ public abstract class GLContext {
* The latter is not true on OSX w/ a GL3 context.
*
*
- * @param GLSL version number if context has been made current at least once, otherwise null
.
+ * @return GLSL version number if context has been made current at least once,
+ * otherwise the {@link VersionNumberString#zeroVersion zero version} instance is returned.
*
* @see #getGLVersionNumber()
*/
@@ -719,13 +721,13 @@ public abstract class GLContext {
* #version 110
*
*
- * If context has not been made current, null
is returned.
+ * If context has not been made current yet, a string of zero length is returned.
*
* @see #getGLSLVersionNumber()
*/
public final String getGLSLVersionString() {
- if(null == ctxGLSLVersion) {
- return null;
+ if( ctxGLSLVersion.isZero() ) {
+ return "";
}
final int minor = ctxGLSLVersion.getMinor();
return "#version " + ctxGLSLVersion.getMajor() + ( minor < 10 ? "0"+minor : minor ) + "\n" ;
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 1b8b0316c..b947bd693 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1041,17 +1041,17 @@ public abstract class GLContextImpl extends GLContext {
ctxVendorVersion = glVendorVersion;
ctxOptions = ctp;
if(useGL) {
- ctxGLSLVersion = null;
+ ctxGLSLVersion = VersionNumber.zeroVersion;
if(major >= 2) { // >= ES2 || GL2.0
final String glslVersion = gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION);
if( null != glslVersion ) {
ctxGLSLVersion = new VersionNumber(glslVersion, ".");
if( ctxGLSLVersion.getMajor() < 1 ) {
- ctxGLSLVersion = null; // failed ..
+ ctxGLSLVersion = VersionNumber.zeroVersion; // failed ..
}
}
}
- if( null == ctxGLSLVersion ){
+ if( ctxGLSLVersion.isZero() ) {
final int[] sver = new int[2];
getStaticGLSLVersionNumber(major, minor, ctxOptions, sver);
ctxGLSLVersion = new VersionNumber(sver[0], sver[1], 0);
--
cgit v1.2.3
From 29e5caf61c1e09d2b225f4d42f5a384dd6eef9a8 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Sat, 27 Apr 2013 01:45:14 +0200
Subject: Complete commit e7064ece049705e013d80985eae698ce0ee3c4e3: Add
getDefaultPixelDataFormat(), complementing getDefaultPixelDataType()
---
src/jogl/classes/javax/media/opengl/GLContext.java | 3 +
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 66 ++++++++++++----------
2 files changed, 40 insertions(+), 29 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 288329310..95342d455 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -1040,6 +1040,9 @@ public abstract class GLContext {
/** Get the default pixel data type, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}. */
public abstract int getDefaultPixelDataType();
+ /** Get the default pixel data format, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}. */
+ public abstract int getDefaultPixelDataFormat();
+
/**
* @return The extension implementing the GLDebugOutput feature,
* either GL_ARB_debug_output or GL_AMD_debug_output.
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index b947bd693..bd2d21cc9 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -107,6 +107,9 @@ public abstract class GLContextImpl extends GLContext {
protected GLDrawableImpl drawable;
protected GLDrawableImpl drawableRead;
+ private volatile boolean pixelDataEvaluated;
+ private int /* pixelDataInternalFormat, */ pixelDataFormat, pixelDataType;
+
protected GL gl;
protected static final Object mappedContextTypeObjectLock;
@@ -175,6 +178,8 @@ public abstract class GLContextImpl extends GLContext {
boundFBOTarget[0] = 0; // draw
boundFBOTarget[1] = 0; // read
}
+
+ pixelDataEvaluated = false;
super.resetStates();
}
@@ -1807,40 +1812,43 @@ public abstract class GLContextImpl extends GLContext {
@Override
public int getDefaultPixelDataType() {
- if(!pixelDataTypeEvaluated) {
- synchronized(this) {
- if(!pixelDataTypeEvaluated) {
- evalPixelDataType();
- pixelDataTypeEvaluated = true;
- }
- }
- }
+ evalPixelDataType();
return pixelDataType;
}
- private volatile boolean pixelDataTypeEvaluated = false;
- int /* pixelDataInternalFormat, */ pixelDataFormat, pixelDataType;
+ @Override
+ public int getDefaultPixelDataFormat() {
+ evalPixelDataType();
+ return pixelDataFormat;
+ }
private final void evalPixelDataType() {
- /* if(isGL2GL3() && 3 == components) {
- pixelDataInternalFormat=GL.GL_RGB;
- pixelDataFormat=GL.GL_RGB;
- pixelDataType = GL.GL_UNSIGNED_BYTE;
- } else */ if(isGLES2Compatible() || isExtensionAvailable(GLExtensions.OES_read_format)) {
- final int[] glImplColorReadVals = new int[] { 0, 0 };
- gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
- gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);
- // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
- pixelDataFormat = glImplColorReadVals[0];
- pixelDataType = glImplColorReadVals[1];
- } else {
- // RGBA read is safe for all GL profiles
- // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
- pixelDataFormat=GL.GL_RGBA;
- pixelDataType = GL.GL_UNSIGNED_BYTE;
- }
- // TODO: Consider:
- // return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
+ if(!pixelDataEvaluated) {
+ synchronized(this) {
+ if(!pixelDataEvaluated) {
+ /* if(isGL2GL3() && 3 == components) {
+ pixelDataInternalFormat=GL.GL_RGB;
+ pixelDataFormat=GL.GL_RGB;
+ pixelDataType = GL.GL_UNSIGNED_BYTE;
+ } else */ if(isGLES2Compatible() || isExtensionAvailable(GLExtensions.OES_read_format)) {
+ final int[] glImplColorReadVals = new int[] { 0, 0 };
+ gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0);
+ gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1);
+ // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
+ pixelDataFormat = glImplColorReadVals[0];
+ pixelDataType = glImplColorReadVals[1];
+ } else {
+ // RGBA read is safe for all GL profiles
+ // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB;
+ pixelDataFormat=GL.GL_RGBA;
+ pixelDataType = GL.GL_UNSIGNED_BYTE;
+ }
+ // TODO: Consider:
+ // return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1;
+ pixelDataEvaluated = true;
+ }
+ }
+ }
}
//----------------------------------------------------------------------
--
cgit v1.2.3
From 502e1d863e636808b7436354c3b639fc2f92bf29 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Mon, 6 May 2013 17:29:35 +0200
Subject: Fix GLSL Version Exposure: Type in 'static' GL -> GLSL matching,
don't set GLSL version if GLSL is n/a
---
src/jogl/classes/com/jogamp/opengl/JoglVersion.java | 4 ++--
src/jogl/classes/javax/media/opengl/GLContext.java | 4 ++--
.../classes/jogamp/opengl/ExtensionAvailabilityCache.java | 7 +++++--
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 12 ++++++------
.../opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java | 2 +-
.../jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java | 2 +-
.../jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java | 2 +-
.../opengl/test/junit/jogl/demos/es1/RedSquareES1.java | 2 +-
.../jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java | 4 ++--
.../opengl/test/junit/jogl/demos/es2/PointsDemoES2.java | 2 +-
.../opengl/test/junit/jogl/demos/es2/RedSquareES2.java | 2 +-
.../com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java | 2 +-
.../test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java | 2 +-
13 files changed, 25 insertions(+), 22 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
index 11e76ef6f..6cd02b749 100644
--- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
+++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
@@ -172,9 +172,9 @@ public class JoglVersion extends JogampVersion {
sb.append(Platform.getNewline());
sb.append("GL_VERSION ").append(gl.glGetString(GL.GL_VERSION));
sb.append(Platform.getNewline());
- sb.append("GLSL ").append(gl.hasGLSL()).append(", has-compiler: ").append(gl.isFunctionAvailable("glCompileShader"));
+ sb.append("GLSL ").append(gl.hasGLSL()).append(", has-compiler-func: ").append(gl.isFunctionAvailable("glCompileShader"));
if(gl.hasGLSL()) {
- sb.append(", version: ").append(gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION));
+ sb.append(", version: ").append(gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION)).append(" / ").append(ctx.getGLSLVersionNumber());
}
sb.append(Platform.getNewline());
sb.append("GL_EXTENSIONS ").append(ctx.getGLExtensionCount());
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index 95342d455..bbe8d602b 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -737,14 +737,14 @@ public abstract class GLContext {
if( 0 != ( CTX_PROFILE_ES & ctxOptions ) ) {
res[0] = 1; res[1] = 0; // ES 2.0 -> GLSL 1.00
} else if( 1 == glMajorVersion ) {
- res[0] = 1; res[0] = 10; // GL 1.x -> GLSL 1.10
+ res[0] = 1; res[1] = 10; // GL 1.x -> GLSL 1.10
} else if( 2 == glMajorVersion ) {
res[0] = 1;
switch ( glMinorVersion ) {
case 0: res[1] = 10; break; // GL 2.0 -> GLSL 1.10
default: res[1] = 20; break; // GL 2.1 -> GLSL 1.20
}
- } else if( 3 == glMajorVersion && 2 >= glMajorVersion ) {
+ } else if( 3 == glMajorVersion && 2 >= glMinorVersion ) {
res[0] = 1;
switch ( glMinorVersion ) {
case 0: res[1] = 30; break; // GL 3.0 -> GLSL 1.30
diff --git a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
index 1a862a3b7..7c7ea1508 100644
--- a/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
+++ b/src/jogl/classes/jogamp/opengl/ExtensionAvailabilityCache.java
@@ -42,6 +42,8 @@ package jogamp.opengl;
import javax.media.opengl.*;
+import com.jogamp.common.util.VersionNumber;
+
import java.util.*;
/**
@@ -218,8 +220,9 @@ final class ExtensionAvailabilityCache {
}
if(!context.isGLES()) {
- int major[] = new int[] { context.getGLVersionMajor() };
- int minor[] = new int[] { context.getGLVersionMinor() };
+ final VersionNumber version = context.getGLVersionNumber();
+ int major[] = new int[] { version.getMajor() };
+ int minor[] = new int[] { version.getMinor() };
while (GLContext.isValidGLVersion(major[0], minor[0])) {
availableExtensionCache.add("GL_VERSION_" + major[0] + "_" + minor[0]);
if (DEBUG) {
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index bd2d21cc9..f16834d28 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1047,7 +1047,7 @@ public abstract class GLContextImpl extends GLContext {
ctxOptions = ctp;
if(useGL) {
ctxGLSLVersion = VersionNumber.zeroVersion;
- if(major >= 2) { // >= ES2 || GL2.0
+ if( hasGLSL() ) { // >= ES2 || GL2.0
final String glslVersion = gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION);
if( null != glslVersion ) {
ctxGLSLVersion = new VersionNumber(glslVersion, ".");
@@ -1055,12 +1055,12 @@ public abstract class GLContextImpl extends GLContext {
ctxGLSLVersion = VersionNumber.zeroVersion; // failed ..
}
}
+ if( ctxGLSLVersion.isZero() ) {
+ final int[] sver = new int[2];
+ getStaticGLSLVersionNumber(major, minor, ctxOptions, sver);
+ ctxGLSLVersion = new VersionNumber(sver[0], sver[1], 0);
+ }
}
- if( ctxGLSLVersion.isZero() ) {
- final int[] sver = new int[2];
- getStaticGLSLVersionNumber(major, minor, ctxOptions, sver);
- ctxGLSLVersion = new VersionNumber(sver[0], sver[1], 0);
- }
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java
index 90f0c5414..9251120c0 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLMesaBug651NEWT.java
@@ -78,7 +78,7 @@ public class TestGLMesaBug651NEWT extends UITestCase {
System.err.println(" GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
System.err.println(" GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
System.err.println(" GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println(" GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")+", "+gl.getContext().getGLSLVersionNumber());
+ System.err.println(" GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")+", "+gl.getContext().getGLSLVersionNumber());
System.err.println(" GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
System.err.println(" GL Profile: "+gl.getGLProfile());
System.err.println(" GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java
index 5186fd7fd..bf668879a 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/GearsES1.java
@@ -140,7 +140,7 @@ public class GearsES1 implements GLEventListener {
System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
System.err.println("GL Profile: "+gl.getGLProfile());
System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java
index e9ec6898c..04fe26420 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/OlympicES1.java
@@ -124,7 +124,7 @@ public class OlympicES1 implements GLEventListener
System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
System.err.println("GL Profile: "+gl.getGLProfile());
System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java
index 37ed83eb6..97519e7c7 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/RedSquareES1.java
@@ -83,7 +83,7 @@ public class RedSquareES1 implements GLEventListener {
System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
System.err.println("GL Profile: "+gl.getGLProfile());
System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
index 9bbbbce05..4cf6f3764 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
@@ -120,7 +120,7 @@ public class GearsES2 implements GLEventListener {
System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")+", "+gl.getContext().getGLSLVersionNumber());
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")+", "+gl.getContext().getGLSLVersionNumber());
System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
System.err.println("GL Profile: "+gl.getGLProfile());
System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
@@ -508,7 +508,7 @@ public class GearsES2 implements GLEventListener {
}
prevMouseX = x;
prevMouseY = y;
- System.err.println("rotXY.1: "+view_rotx+"/"+view_roty+", source "+e);
+ // System.err.println("rotXY.1: "+view_rotx+"/"+view_roty+", source "+e);
}
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
index 1e0f9596f..43b919e78 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
@@ -85,7 +85,7 @@ public class PointsDemoES2 extends PointsDemo {
System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
System.err.println("GL Profile: "+gl.getGLProfile());
st = new ShaderState();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
index 9b3fe74cd..688653471 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
@@ -72,7 +72,7 @@ public class RedSquareES2 implements GLEventListener {
System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
System.err.println("GL Profile: "+gl.getGLProfile());
System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java
index 6fb0a9ff6..fbcfb26f3 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/Gears.java
@@ -75,7 +75,7 @@ public class Gears implements GLEventListener {
System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")+", "+gl.getContext().getGLSLVersionNumber());
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")+", "+gl.getContext().getGLSLVersionNumber());
System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
System.err.println("GL Profile: "+gl.getGLProfile());
System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java
index 9e1e8c931..c6f4ee0c0 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl3/GeomShader01TextureGL3.java
@@ -90,7 +90,7 @@ public class GeomShader01TextureGL3 implements GLEventListener {
System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
- System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
System.err.println("GL Profile: "+gl.getGLProfile());
System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
--
cgit v1.2.3
From 33abeb8097a8f80acd1a4ce94b4866e5dc41f0c0 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Fri, 17 May 2013 04:52:32 +0200
Subject: Fix Bug 737: Add shader default precision for GLSL [1.30 .. 1.50[ -
See GLSL Spec [1.30 - 1.40].
---
make/scripts/tests.sh | 7 +-
.../com/jogamp/opengl/util/glsl/ShaderCode.java | 120 +++++++++++++++++++--
src/jogl/classes/javax/media/opengl/GLContext.java | 34 +++---
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 4 +-
.../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 4 +-
.../jogamp/opengl/util/glsl/GLSLTextureRaster.java | 4 +-
.../util/glsl/fixedfunc/FixedFuncPipeline.java | 4 +-
.../opengl/test/junit/jogl/demos/es2/GearsES2.java | 4 +-
.../test/junit/jogl/demos/es2/PointsDemoES2.java | 4 +-
.../test/junit/jogl/demos/es2/RedSquareES2.java | 4 +-
.../jogl/demos/es2/TextureDraw01ES2Listener.java | 4 +-
.../junit/jogl/demos/es2/awt/TestGearsES2AWT.java | 26 +++++
.../demos/es2/awt/TestGearsES2GLJPanelAWT.java | 116 +++++++++++++++++---
.../jogl/demos/es2/newt/TestGearsES2NEWT.java | 16 ++-
.../jogl/demos/gl3/GeomShader01TextureGL3.java | 6 +-
.../junit/jogl/glsl/TestGLSLShaderState01NEWT.java | 8 +-
.../junit/jogl/glsl/TestGLSLShaderState02NEWT.java | 6 +-
.../test/junit/jogl/glsl/TestRulerNEWT01.java | 4 +-
18 files changed, 304 insertions(+), 71 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 4ced71d3d..71cf57565 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -88,6 +88,7 @@ function jrun() {
#D_ARGS="-Djogl.debug.FBObject -Djogl.debug.TraceGL -Djogl.debug.GLBufferStateTracker"
#D_ARGS="-Djogl.debug.FBObject"
#D_ARGS="-Djogl.debug.GLSLCode"
+ D_ARGS="-Djogl.debug.GLSLCode"
#D_ARGS="-Djogl.debug.GLSLCode -Djogl.debug.DebugGL -Djogl.debug.TraceGL"
#D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.JAWT -Dnewt.debug.Window"
#D_ARGS="-Dnativewindow.debug.JAWT -Djogamp.debug.TaskBase.TraceSource"
@@ -174,7 +175,7 @@ function jrun() {
#D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.GLContext"
#D_ARGS="-Dnewt.debug.Window -Djogl.debug.Animator -Dnewt.debug.Screen"
#D_ARGS="-Dnativewindow.debug.JAWT -Dnewt.debug.Window"
- D_ARGS="-Dnewt.debug.Window.KeyEvent"
+ #D_ARGS="-Dnewt.debug.Window.KeyEvent"
#D_ARGS="-Dnewt.debug.Window.MouseEvent"
#D_ARGS="-Dnewt.debug.Window.MouseEvent -Dnewt.debug.Window.KeyEvent"
#D_ARGS="-Dnewt.debug.Window -Dnativewindow.debug=all"
@@ -281,10 +282,10 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestOlympicES1NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestRedSquareES1NEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT $*
+testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelsAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $*
-testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
#testawtswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $*
diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
index 1e552c17f..80a7efaec 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java
@@ -54,6 +54,7 @@ import jogamp.opengl.Debug;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.VersionNumber;
/**
* Convenient shader code class to use and instantiate vertex or fragment programs.
@@ -716,6 +717,7 @@ public class ShaderCode {
return -1;
}
+ @SuppressWarnings("resource")
private static int readShaderSource(Class> context, URLConnection conn, StringBuilder result, int lineno) throws IOException {
if(DEBUG_CODE) {
if(0 == lineno) {
@@ -823,11 +825,74 @@ public class ShaderCode {
}
// Shall we use: #ifdef GL_FRAGMENT_PRECISION_HIGH .. #endif for using highp in fragment shader if avail ?
- /** {@value #es2_default_precision_vp} */
+ /** Default precision of {@link GL#isGLES2() ES2} for {@link GL2ES2#GL_VERTEX_SHADER vertex-shader}: {@value #es2_default_precision_vp} */
public static final String es2_default_precision_vp = "\nprecision highp float;\nprecision highp int;\n";
- /** {@value #es2_default_precision_fp} */
+ /** Default precision of {@link GL#isGLES2() ES2} for {@link GL2ES2#GL_FRAGMENT_SHADER fragment-shader}: {@value #es2_default_precision_fp} */
public static final String es2_default_precision_fp = "\nprecision mediump float;\nprecision mediump int;\n/*precision lowp sampler2D;*/\n";
+ /** Default precision of GLSL ≥ 1.30 as required until < 1.50 for {@link GL2ES2#GL_VERTEX_SHADER vertex-shader} or {@link GL3#GL_GEOMETRY_SHADER geometry-shader}: {@value #gl3_default_precision_vp_gp}. See GLSL Spec 1.30-1.50 Section 4.5.3. */
+ public static final String gl3_default_precision_vp_gp = "\nprecision highp float;\nprecision highp int;\n";
+ /** Default precision of GLSL ≥ 1.30 as required until < 1.50 for {@link GL2ES2#GL_FRAGMENT_SHADER fragment-shader}: {@value #gl3_default_precision_fp}. See GLSL Spec 1.30-1.50 Section 4.5.3. */
+ public static final String gl3_default_precision_fp = "\nprecision highp float;\nprecision mediump int;\n";
+
+ /**
+ * Add GLSL version at the head of this shader source code.
+ *
+ * Note: The shader source to be edit must be created using a mutable StringBuilder.
+ *
+ * @param gl a GL context, which must have been made current once
+ * @return the index after the inserted data, maybe 0 if nothing has be inserted.
+ */
+ public final int addGLSLVersion(GL2ES2 gl) {
+ return insertShaderSource(0, 0, gl.getContext().getGLSLVersionString());
+ }
+
+ /**
+ * Adds default precision to source code at given position if required, i.e.
+ * {@link #es2_default_precision_vp}, {@link #es2_default_precision_fp},
+ * {@link #gl3_default_precision_vp_gp}, {@link #gl3_default_precision_fp} or none,
+ * depending on the {@link GLContext#getGLSLVersionNumber() GLSL version} being used.
+ *
+ * Note: The shader source to be edit must be created using a mutable StringBuilder.
+ *
+ * @param gl a GL context, which must have been made current once
+ * @param pos position within this mutable shader source.
+ * @return the index after the inserted data, maybe 0 if nothing has be inserted.
+ */
+ public final int addDefaultShaderPrecision(GL2ES2 gl, int pos) {
+ final VersionNumber glslVersion = gl.getContext().getGLSLVersionNumber();
+ final String defaultPrecision;
+ if( gl.isGLES2() ) {
+ switch ( shaderType ) {
+ case GL2ES2.GL_VERTEX_SHADER:
+ defaultPrecision = es2_default_precision_vp; break;
+ case GL2ES2.GL_FRAGMENT_SHADER:
+ defaultPrecision = es2_default_precision_vp; break;
+ default:
+ defaultPrecision = null;
+ break;
+ }
+ } else if( glslVersion.compareTo(GLContext.Version130) >= 0 && glslVersion.compareTo(GLContext.Version150) < 0 ) {
+ // GLSL [ 1.30 .. 1.50 [ needs at least fragement float default precision!
+ switch ( shaderType ) {
+ case GL2ES2.GL_VERTEX_SHADER:
+ case GL3.GL_GEOMETRY_SHADER:
+ defaultPrecision = gl3_default_precision_vp_gp; break;
+ case GL2ES2.GL_FRAGMENT_SHADER:
+ defaultPrecision = gl3_default_precision_fp; break;
+ default:
+ defaultPrecision = null;
+ break;
+ }
+ } else {
+ defaultPrecision = null;
+ }
+ if( null != defaultPrecision ) {
+ pos = insertShaderSource(0, pos, defaultPrecision);
+ }
+ return pos;
+ }
+
/**
* Default customization of this shader source code.
*
@@ -835,18 +900,51 @@ public class ShaderCode {
*
* @param gl a GL context, which must have been made current once
* @param preludeVersion if true {@link GLContext#getGLSLVersionString()} is preluded, otherwise not.
- * @param es2DefaultPrecision optional default precision source code line(s) preluded if not null and if {@link GL#isGLES()}.
+ * @param addDefaultPrecision if true
default precision source code line(s) are added, i.e.
+ * {@link #es2_default_precision_vp}, {@link #es2_default_precision_fp},
+ * {@link #gl3_default_precision_vp_gp}, {@link #gl3_default_precision_fp} or none,
+ * depending on the {@link GLContext#getGLSLVersionNumber() GLSL version} being used.
+ * @return the index after the inserted data, maybe 0 if nothing has be inserted.
+ * @see #addGLSLVersion(GL2ES2)
+ * @see #addDefaultShaderPrecision(GL2ES2, int)
+ */
+ public final int defaultShaderCustomization(GL2ES2 gl, boolean preludeVersion, boolean addDefaultPrecision) {
+ int pos;
+ if( preludeVersion ) {
+ pos = addGLSLVersion(gl);
+ } else {
+ pos = 0;
+ }
+ if( addDefaultPrecision ) {
+ pos = addDefaultShaderPrecision(gl, pos);
+ }
+ return pos;
+ }
+
+ /**
+ * Default customization of this shader source code.
+ *
+ * Note: The shader source to be edit must be created using a mutable StringBuilder.
+ *
+ * @param gl a GL context, which must have been made current once
+ * @param preludeVersion if true {@link GLContext#getGLSLVersionString()} is preluded, otherwise not.
+ * @param esDefaultPrecision optional default precision source code line(s) preluded if not null and if {@link GL#isGLES()}.
* You may use {@link #es2_default_precision_fp} for fragment shader and {@link #es2_default_precision_vp} for vertex shader.
* @return the index after the inserted data, maybe 0 if nothing has be inserted.
+ * @see #addGLSLVersion(GL2ES2)
+ * @see #addDefaultShaderPrecision(GL2ES2, int)
*/
- public final int defaultShaderCustomization(GL2ES2 gl, boolean preludeVersion, String es2DefaultPrecision) {
- int pos = 0;
- if(preludeVersion) {
- final String glslVersion_prelude = gl.getContext().getGLSLVersionString();
- pos = insertShaderSource(0, pos, glslVersion_prelude);
- }
- if( gl.isGLES() && null != es2DefaultPrecision ) {
- pos = insertShaderSource(0, pos, es2DefaultPrecision);
+ public final int defaultShaderCustomization(GL2ES2 gl, boolean preludeVersion, String esDefaultPrecision) {
+ int pos;
+ if( preludeVersion ) {
+ pos = addGLSLVersion(gl);
+ } else {
+ pos = 0;
+ }
+ if( gl.isGLES2() && null != esDefaultPrecision ) {
+ pos = insertShaderSource(0, pos, esDefaultPrecision);
+ } else {
+ pos = addDefaultShaderPrecision(gl, pos);
}
return pos;
}
diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java
index bbe8d602b..ab966a70d 100644
--- a/src/jogl/classes/javax/media/opengl/GLContext.java
+++ b/src/jogl/classes/javax/media/opengl/GLContext.java
@@ -118,6 +118,19 @@ public abstract class GLContext {
/** Indicates that a newly-created context was made current during the last call to {@link #makeCurrent makeCurrent}. */
public static final int CONTEXT_CURRENT_NEW = 2;
+ /* Version 1.00, i.e. GLSL 1.00 for ES 2.0. */
+ public static final VersionNumber Version100 = new VersionNumber(1, 0, 0);
+ /* Version 1.10, i.e. GLSL 1.10 for GL 2.0. */
+ public static final VersionNumber Version110 = new VersionNumber(1, 10, 0);
+ /* Version 1.20, i.e. GLSL 1.20 for GL 2.1. */
+ public static final VersionNumber Version120 = new VersionNumber(1, 20, 0);
+ /* Version 1.30, i.e. GLSL 1.30 for GL 3.0. */
+ public static final VersionNumber Version130 = new VersionNumber(1, 30, 0);
+ /* Version 1.40, i.e. GLSL 1.40 for GL 3.1. */
+ public static final VersionNumber Version140 = new VersionNumber(1, 40, 0);
+ /* Version 1.50, i.e. GLSL 1.50 for GL 3.2. */
+ public static final VersionNumber Version150 = new VersionNumber(1, 50, 0);
+
/** Version 3.2. As an OpenGL version, it qualifies for geometry shader */
public static final VersionNumber Version32 = new VersionNumber(3, 2, 0);
@@ -733,27 +746,24 @@ public abstract class GLContext {
return "#version " + ctxGLSLVersion.getMajor() + ( minor < 10 ? "0"+minor : minor ) + "\n" ;
}
- protected static final void getStaticGLSLVersionNumber(int glMajorVersion, int glMinorVersion, int ctxOptions, int[] res) {
+ protected static final VersionNumber getStaticGLSLVersionNumber(int glMajorVersion, int glMinorVersion, int ctxOptions) {
if( 0 != ( CTX_PROFILE_ES & ctxOptions ) ) {
- res[0] = 1; res[1] = 0; // ES 2.0 -> GLSL 1.00
+ return Version100; // ES 2.0 -> GLSL 1.00
} else if( 1 == glMajorVersion ) {
- res[0] = 1; res[1] = 10; // GL 1.x -> GLSL 1.10
+ return Version110; // GL 1.x -> GLSL 1.10
} else if( 2 == glMajorVersion ) {
- res[0] = 1;
switch ( glMinorVersion ) {
- case 0: res[1] = 10; break; // GL 2.0 -> GLSL 1.10
- default: res[1] = 20; break; // GL 2.1 -> GLSL 1.20
+ case 0: return Version110; // GL 2.0 -> GLSL 1.10
+ default: return Version120; // GL 2.1 -> GLSL 1.20
}
} else if( 3 == glMajorVersion && 2 >= glMinorVersion ) {
- res[0] = 1;
switch ( glMinorVersion ) {
- case 0: res[1] = 30; break; // GL 3.0 -> GLSL 1.30
- case 1: res[1] = 40; break; // GL 3.1 -> GLSL 1.40
- default: res[1] = 50; break; // GL 3.2 -> GLSL 1.50
+ case 0: return Version130; // GL 3.0 -> GLSL 1.30
+ case 1: return Version140; // GL 3.1 -> GLSL 1.40
+ default: return Version150; // GL 3.2 -> GLSL 1.50
}
} else { // >= 3.3
- res[0] = glMajorVersion; // GL M.N -> GLSL M.N
- res[1] = glMinorVersion * 10;
+ return new VersionNumber(glMajorVersion, glMinorVersion * 10, 0); // GL M.N -> GLSL M.N
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index f16834d28..8c9c12e21 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1056,9 +1056,7 @@ public abstract class GLContextImpl extends GLContext {
}
}
if( ctxGLSLVersion.isZero() ) {
- final int[] sver = new int[2];
- getStaticGLSLVersionNumber(major, minor, ctxOptions, sver);
- ctxGLSLVersion = new VersionNumber(sver[0], sver[1], 0);
+ ctxGLSLVersion = getStaticGLSLVersionNumber(major, minor, ctxOptions);
}
}
}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index 666cd30af..b90609ff1 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -149,8 +149,8 @@ public class MacOSXCGLContext extends GLContextImpl
"../../shader", "../../shader/bin", shaderBasename, true);
final ShaderCode fp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MacOSXCGLContext.class,
"../../shader", "../../shader/bin", shaderBasename, true);
- vp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
- fp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+ vp.defaultShaderCustomization(gl, true, true);
+ fp.defaultShaderCustomization(gl, true, true);
sp.add(vp);
sp.add(fp);
if(!sp.link(gl, System.err)) {
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java
index 20c251635..eaf8dc30a 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java
@@ -69,8 +69,8 @@ public class GLSLTextureRaster {
shaderSrcPath, shaderBinPath, shaderBasename, true);
final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
shaderSrcPath, shaderBinPath, shaderBasename, true);
- rsVp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
- rsFp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+ rsVp.defaultShaderCustomization(gl, true, true);
+ rsFp.defaultShaderCustomization(gl, true, true);
// Create & Link the shader program
sp = new ShaderProgram();
diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
index cc58f2363..f4f20ac7c 100644
--- a/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
+++ b/src/jogl/classes/jogamp/opengl/util/glsl/fixedfunc/FixedFuncPipeline.java
@@ -943,8 +943,8 @@ public class FixedFuncPipeline {
private static final String constMaxTextures8 = "#define MAX_TEXTURE_UNITS 8\n";
private final void customizeShader(GL2ES2 gl, ShaderCode vp, ShaderCode fp, String maxTextureDefine) {
- int rsVpPos = vp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
- int rsFpPos = fp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+ int rsVpPos = vp.defaultShaderCustomization(gl, true, true);
+ int rsFpPos = fp.defaultShaderCustomization(gl, true, true);
vp.insertShaderSource(0, rsVpPos, maxTextureDefine);
fp.insertShaderSource(0, rsFpPos, maxTextureDefine);
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
index f21e767fa..66a8082a6 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
@@ -148,8 +148,8 @@ public class GearsES2 implements GLEventListener {
"shader/bin", "gears", true);
final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
"shader/bin", "gears", true);
- vp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
- fp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp0 = new ShaderProgram();
sp0.add(gl, vp0, System.err);
sp0.add(gl, fp0, System.err);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
index 43b919e78..52af4916c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/PointsDemoES2.java
@@ -94,8 +94,8 @@ public class PointsDemoES2 extends PointsDemo {
"shader/bin", "PointsShader", true);
final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
"shader/bin", "PointsShader", true);
- vp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
- fp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp0 = new ShaderProgram();
sp0.add(gl, vp0, System.err);
sp0.add(gl, fp0, System.err);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
index 688653471..3f092e341 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java
@@ -84,8 +84,8 @@ public class RedSquareES2 implements GLEventListener {
"shader/bin", "RedSquareShader", true);
final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
"shader/bin", "RedSquareShader", true);
- vp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
- fp0.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
final ShaderProgram sp0 = new ShaderProgram();
sp0.add(gl, vp0, System.err);
sp0.add(gl, fp0, System.err);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java
index 4bcb073dc..622df8695 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java
@@ -70,8 +70,8 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A
"shader", "shader/bin", shaderBasename, true);
ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(),
"shader", "shader/bin", shaderBasename, true);
- rsVp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp);
- rsFp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp);
+ rsVp.defaultShaderCustomization(gl, true, true);
+ rsFp.defaultShaderCustomization(gl, true, true);
// Create & Link the shader program
ShaderProgram sp = new ShaderProgram();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java
index a51df5088..a63f2590a 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/awt/TestGearsES2AWT.java
@@ -75,6 +75,7 @@ public class TestGearsES2AWT extends UITestCase {
static boolean forceES2 = false;
static boolean forceGL3 = false;
+ static boolean mainRun = false;
static boolean shallUseOffscreenFBOLayer = false;
static boolean shallUseOffscreenPBufferLayer = false;
static boolean useMSAA = false;
@@ -310,10 +311,35 @@ public class TestGearsES2AWT extends UITestCase {
runTestGL(caps, resizeBy, frameLayout);
}
+ @Test
+ public void test02_GLES2() throws InterruptedException, InvocationTargetException {
+ if(mainRun) return;
+
+ if( !GLProfile.isAvailable(GLProfile.GLES2) ) {
+ System.err.println("GLES2 n/a");
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GLES2);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, resizeBy, frameLayout);
+ }
+
+ @Test
+ public void test03_GL3() throws InterruptedException, InvocationTargetException {
+ if(mainRun) return;
+
+ if( !GLProfile.isAvailable(GLProfile.GL3) ) {
+ System.err.println("GL3 n/a");
+ }
+ final GLProfile glp = GLProfile.get(GLProfile.GL3);
+ final GLCapabilities caps = new GLCapabilities( glp );
+ runTestGL(caps, resizeBy, frameLayout);
+ }
+
public static void main(String args[]) {
boolean waitForKey = false;
int rw=-1, rh=-1;
+ mainRun = true;
for(int i=0; i
Date: Fri, 17 May 2013 07:57:50 +0200
Subject: GLSL version determination: Use static GLSL version mapping in case
of GLES - Mesa 9.1* fails otherwise since it supports ES3/300 which is
returned.
---
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 8c9c12e21..314db292d 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1048,7 +1048,7 @@ public abstract class GLContextImpl extends GLContext {
if(useGL) {
ctxGLSLVersion = VersionNumber.zeroVersion;
if( hasGLSL() ) { // >= ES2 || GL2.0
- final String glslVersion = gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION);
+ final String glslVersion = isGLES() ? null : gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) ; // Use static GLSL version for ES to be safe!
if( null != glslVersion ) {
ctxGLSLVersion = new VersionNumber(glslVersion, ".");
if( ctxGLSLVersion.getMajor() < 1 ) {
--
cgit v1.2.3
From 81afec4e963ac4372dc2b604d6f91237b81ee6f2 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Fri, 31 May 2013 06:34:13 +0200
Subject: GLVersionNumber: Fix vendor version parser; Adapt to GlueGen commit
959d6d83ec26152343d538287c02eeebf0dcf238
Adapt to GlueGen commit 959d6d83ec26152343d538287c02eeebf0dcf238:
- Use only RegExp and cache default (no wrapped whitespace tokenizer)
- String match: Store end-of-match and flag defined components.
- Remove manual parsing, utilize VersionNumber
- No need to look further for 'updated' GL version, (probably the vendor version),
since we utilize the ARB version number as set at creation.
Fix vendor version parser:
- Cut off GL version part of versionString (fixes case where GL version was interpreted as vendor version)
- Loop through remaining string until a valid version number w/ major.minor has been found
---
make/scripts/tests.sh | 5 +-
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 2 +-
.../classes/jogamp/opengl/GLVersionNumber.java | 137 +++++++----------
.../jogl/acore/TestGLVersionParsing00NEWT.java | 170 +++++++++++++++++++++
4 files changed, 226 insertions(+), 88 deletions(-)
create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 840414c54..8fd7d2852 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -87,7 +87,7 @@ function jrun() {
#D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.FBObject"
#D_ARGS="-Djogl.debug.FBObject -Djogl.debug.TraceGL -Djogl.debug.GLBufferStateTracker"
#D_ARGS="-Djogl.debug.FBObject"
- D_ARGS="-Djogl.debug.GLSLCode"
+ #D_ARGS="-Djogl.debug.GLSLCode"
#D_ARGS="-Djogl.debug.GLSLCode -Djogl.debug.DebugGL -Djogl.debug.TraceGL"
#D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.JAWT -Dnewt.debug.Window"
#D_ARGS="-Dnativewindow.debug.JAWT -Djogamp.debug.TaskBase.TraceSource"
@@ -312,6 +312,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFloatUtil01MatrixMatrixMultNOUI $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestPMVMatrix01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestPMVMatrix02NEWT $*
+testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLVersionParsing00NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestNEWTCloseX11DisplayBug565 $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $*
@@ -549,7 +550,7 @@ function testawtswt() {
#
#testnoawt com.jogamp.opengl.test.junit.graph.TestTextRendererNEWT10 $*
#testnoawt com.jogamp.opengl.test.junit.graph.TestTextRendererNEWT00 $*
-testnoawt com.jogamp.opengl.test.junit.graph.TestRegionRendererNEWT01 $*
+#testnoawt com.jogamp.opengl.test.junit.graph.TestRegionRendererNEWT01 $*
#testnoawt com.jogamp.opengl.test.junit.graph.TestTextRendererNEWT01 $*
#testnoawt com.jogamp.opengl.test.junit.graph.demos.ui.UINewtDemo01 $*
#testnoawt com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtDemo01 $*
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 314db292d..e7eef61e7 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -1050,7 +1050,7 @@ public abstract class GLContextImpl extends GLContext {
if( hasGLSL() ) { // >= ES2 || GL2.0
final String glslVersion = isGLES() ? null : gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) ; // Use static GLSL version for ES to be safe!
if( null != glslVersion ) {
- ctxGLSLVersion = new VersionNumber(glslVersion, ".");
+ ctxGLSLVersion = new VersionNumber(glslVersion);
if( ctxGLSLVersion.getMajor() < 1 ) {
ctxGLSLVersion = VersionNumber.zeroVersion; // failed ..
}
diff --git a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
index 990698667..a32fdfa77 100644
--- a/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
+++ b/src/jogl/classes/jogamp/opengl/GLVersionNumber.java
@@ -28,98 +28,62 @@
package jogamp.opengl;
-import java.util.StringTokenizer;
-
-import javax.media.opengl.GLContext;
-
+import com.jogamp.common.util.VersionNumber;
import com.jogamp.common.util.VersionNumberString;
/**
* A class for storing and comparing OpenGL version numbers.
* This only works for desktop OpenGL at the moment.
*/
-class GLVersionNumber extends VersionNumberString {
+public class GLVersionNumber extends VersionNumberString {
private final boolean valid;
- private GLVersionNumber(int[] val, String versionString, boolean valid) {
- super(val[0], val[1], val[2], versionString);
+ private GLVersionNumber(int[] val, int strEnd, short state, String versionString, boolean valid) {
+ super(val[0], val[1], val[2], strEnd, state, versionString);
this.valid = valid;
}
- public static GLVersionNumber create(String versionString) {
+ private static java.util.regex.Pattern getUnderscorePattern() {
+ if( null == _Pattern ) { // volatile dbl-checked-locking OK
+ synchronized( VersionNumber.class ) {
+ if( null == _Pattern ) {
+ _Pattern = getVersionNumberPattern("_");
+ }
+ }
+ }
+ return _Pattern;
+ }
+ private static volatile java.util.regex.Pattern _Pattern = null;
+
+ public static final GLVersionNumber create(String versionString) {
int[] val = new int[] { 0, 0, 0 };
- try {
- if (versionString.startsWith("GL_VERSION_")) {
- StringTokenizer tok = new StringTokenizer(versionString, "_");
- tok.nextToken(); // GL_
- tok.nextToken(); // VERSION_
- if (!tok.hasMoreTokens()) {
- val[0] = 0;
+ int strEnd = 0;
+ short state = 0;
+ if (versionString != null && versionString.length() > 0) {
+ try {
+ final java.util.regex.Pattern versionPattern;
+ if (versionString.startsWith("GL_VERSION_")) {
+ versionPattern = getUnderscorePattern();
} else {
- val[0] = Integer.valueOf(tok.nextToken()).intValue();
- if (!tok.hasMoreTokens()) {
- val[1] = 0;
- } else {
- val[1] = Integer.valueOf(tok.nextToken()).intValue();
- if (!tok.hasMoreTokens()) {
- val[2] = 0;
- } else {
- val[2] = Integer.valueOf(tok.nextToken()).intValue();
- }
- }
+ versionPattern = VersionNumberString.getDefaultVersionNumberPattern();
}
- } else {
- int radix = 10;
- if (versionString.length() > 2) {
- if (Character.isDigit(versionString.charAt(0)) && versionString.charAt(1) == '.' && Character.isDigit(versionString.charAt(2))) {
- val[0] = Character.digit(versionString.charAt(0), radix);
- val[1] = Character.digit(versionString.charAt(2), radix);
- // See if there's version-specific information which might
- // imply a more recent OpenGL version
- StringTokenizer tok = new StringTokenizer(versionString, " ");
- if (tok.hasMoreTokens()) {
- tok.nextToken();
- if (tok.hasMoreTokens()) {
- String token = tok.nextToken();
- int i = 0;
- while (i < token.length() && !Character.isDigit(token.charAt(i))) {
- i++;
- }
- if (i < token.length() - 2 && Character.isDigit(token.charAt(i)) && token.charAt(i + 1) == '.' && Character.isDigit(token.charAt(i + 2))) {
- int altMajor = Character.digit(token.charAt(i), radix);
- int altMinor = Character.digit(token.charAt(i + 2), radix);
- // Avoid possibly confusing situations by putting some
- // constraints on the upgrades we do to the major and
- // minor versions
- if ( (altMajor == val[0] && altMinor > val[1]) || altMajor == val[0] + 1 ) {
- if( GLContext.isValidGLVersion(altMajor, altMinor) ) {
- val[0] = altMajor;
- val[1] = altMinor;
- }
- }
- }
- }
- }
- }
+ final VersionNumberString version = new VersionNumberString(versionString, versionPattern);
+ if( version.hasMajor() && version.hasMinor() ) { // Requires at least a defined major and minor version component!
+ val[0] = version.getMajor();
+ val[1] = version.getMinor();
+ strEnd = version.endOfStringMatch();
+ state = (short) ( ( version.hasMajor() ? VersionNumber.HAS_MAJOR : (short)0 ) |
+ ( version.hasMinor() ? VersionNumber.HAS_MINOR : (short)0 ) );
}
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.err.println("Info: ExtensionAvailabilityCache: FunctionAvailabilityCache.Version.: " + e);
+ val[0] = 1;
+ val[1] = 0;
}
- return new GLVersionNumber(val, versionString, true);
- } catch (Exception e) {
- e.printStackTrace();
- // FIXME: refactor desktop OpenGL dependencies and make this
- // class work properly for OpenGL ES
- System.err.println("Info: ExtensionAvailabilityCache: FunctionAvailabilityCache.Version.: " + e);
- val[0] = 1;
- val[1] = 0;
- /*
- throw (IllegalArgumentException)
- new IllegalArgumentException(
- "Illegally formatted version identifier: \"" + versionString + "\"")
- .initCause(e);
- */
- }
- return new GLVersionNumber(val, versionString, false);
+ }
+ return new GLVersionNumber(val, strEnd, state, versionString, false);
}
public final boolean isValid() {
@@ -131,6 +95,7 @@ class GLVersionNumber extends VersionNumberString {
* GL_VERSION
string if exists, otherwise the {@link VersionNumberString#zeroVersion zero version} instance.
*
* 2.1 Mesa 7.0.3-rc2 -> 7.0.3 (7.0.3-rc2)
+ * 2.1 Mesa 7.12-devel (git-d6c318e) -> 7.12.0 (7.12-devel)
* 4.2.12171 Compatibility Profile Context 9.01.8 -> 9.1.8 (9.01.8)
* 4.2.12198 Compatibility Profile Context 12.102.3.0 -> 12.102.3 (12.102.3.0)
* 4.3.0 NVIDIA 310.32 -> 310.32 (310.32)
@@ -139,19 +104,21 @@ class GLVersionNumber extends VersionNumberString {
public static final VersionNumberString createVendorVersion(String versionString) {
if (versionString == null || versionString.length() <= 0) {
return null;
- }
- final String[] strings = versionString.trim().split("\\s+");
- if ( strings.length <= 0 ) {
- return null;
}
- // Test all segments backwards from [len-1..1], skipping the 1st entry (GL version)
- // If a segment represents a valid VersionNumber - use it.
- for(int i=strings.length-1; i>=1; i--) {
- final String s = strings[i];
- final VersionNumberString version = new VersionNumberString(s, ".");
- if( !version.isZero() ) {
+
+ // Skip the 1st GL version
+ String str;
+ {
+ final GLVersionNumber glv = create(versionString);
+ str = versionString.substring(glv.endOfStringMatch());
+ }
+
+ while ( str.length() > 0 ) {
+ final VersionNumberString version = new VersionNumberString(str, getDefaultVersionNumberPattern());
+ if( version.hasMajor() && version.hasMinor() ) { // Requires at least a defined major and minor version component!
return version;
}
+ str = str.substring(version.endOfStringMatch());
}
return VersionNumberString.zeroVersion;
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java
new file mode 100644
index 000000000..394772135
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLVersionParsing00NEWT.java
@@ -0,0 +1,170 @@
+/**
+ * Copyright 2013 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.opengl.test.junit.jogl.acore;
+
+import java.io.IOException;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import jogamp.opengl.GLVersionNumber;
+
+import com.jogamp.common.util.VersionNumberString;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+public class TestGLVersionParsing00NEWT extends UITestCase {
+
+ public static final String[] glVersionStrings00 = new String[] {
+ "GL_VERSION_2_1 DummyTool 1.2.3", // 0
+ "2.1 Mesa 7.0.3-rc2",
+ "4.2.12171 Compatibility Profile Context 9.01.8",
+ "4.2.12198 Compatibility Profile Context 12.102.3.0",
+ "2.1 Mesa 7.0.3-rc2 post odd",
+ "4.2.12171 Compatibility Profile Context 9.01.8 post odd",
+ "4.2.12198 Compatibility Profile Context 12.102.3.0 post odd",
+ "OpenGL ES 2.0 Mesa 9.1.1", // 7
+ "OpenGL ES 2.0 14.10.1",
+ "OpenGL ES GLSL ES 2.0 14.10.1", // 9
+ "OpenGL ES 2.0 3Com L3 11.33.44" // 10
+ };
+ public static final String[] glVersionStrings01 = new String[] {
+ "GL_VERSION_2_1 Dummy Tool 1.2", // 0
+ "2.1 Mesa 7.12",
+ "2.1 Mesa 7.12-devel",
+ "2.1 Mesa 7.12-devel (git-d6c318e)",
+ "2.1 Mesa 7.12-devel la1 la2 li3",
+ "4.3.0 NVIDIA 310.32",
+ "OpenGL ES 2.0 Mesa 9.1", // 6
+ "OpenGL ES 2.0 14.10",
+ "OpenGL ES GLSL ES 2.0 14.10", // 8
+ "OpenGL ES 2.0 3Com L3 11.33" // 9
+ };
+ public static final String[] glVersionStrings02 = new String[] {
+ "GL_VERSION_2_1", // 0
+ "OpenGL ES 2.0", // 1
+ "OpenGL ES GLSL ES 2.0" // 2
+ };
+
+ public static final VersionNumberString[] glVersionNumbers = new VersionNumberString[] {
+ new VersionNumberString(2, 1, 0, glVersionStrings00[0]),
+ new VersionNumberString(2, 1, 0, glVersionStrings00[1]),
+ new VersionNumberString(4, 2, 0, glVersionStrings00[2]),
+ new VersionNumberString(4, 2, 0, glVersionStrings00[3]),
+ new VersionNumberString(2, 1, 0, glVersionStrings00[4]),
+ new VersionNumberString(4, 2, 0, glVersionStrings00[5]),
+ new VersionNumberString(4, 2, 0, glVersionStrings00[6]),
+ new VersionNumberString(2, 0, 0, glVersionStrings00[7]),
+ new VersionNumberString(2, 0, 0, glVersionStrings00[8]),
+ new VersionNumberString(2, 0, 0, glVersionStrings00[9]),
+ new VersionNumberString(2, 0, 0, glVersionStrings00[10]),
+
+ new VersionNumberString(2, 1, 0, glVersionStrings01[0]),
+ new VersionNumberString(2, 1, 0, glVersionStrings01[1]),
+ new VersionNumberString(2, 1, 0, glVersionStrings01[2]),
+ new VersionNumberString(2, 1, 0, glVersionStrings01[3]),
+ new VersionNumberString(2, 1, 0, glVersionStrings01[4]),
+ new VersionNumberString(4, 3, 0, glVersionStrings01[5]),
+ new VersionNumberString(2, 0, 0, glVersionStrings01[6]),
+ new VersionNumberString(2, 0, 0, glVersionStrings01[7]),
+ new VersionNumberString(2, 0, 0, glVersionStrings01[8]),
+ new VersionNumberString(2, 0, 0, glVersionStrings01[9]),
+
+ new VersionNumberString(2, 1, 0, glVersionStrings02[0]),
+ new VersionNumberString(2, 0, 0, glVersionStrings02[1]),
+ new VersionNumberString(2, 0, 0, glVersionStrings02[1])
+ };
+ public static final VersionNumberString[] glVendorVersionNumbersWithSub = new VersionNumberString[] {
+ new VersionNumberString(1, 2, 3, glVersionStrings00[0]),
+ new VersionNumberString(7, 0, 3, glVersionStrings00[1]),
+ new VersionNumberString(9, 1, 8, glVersionStrings00[2]),
+ new VersionNumberString(12, 102, 3, glVersionStrings00[3]),
+ new VersionNumberString(7, 0, 3, glVersionStrings00[4]),
+ new VersionNumberString(9, 1, 8, glVersionStrings00[5]),
+ new VersionNumberString(12, 102, 3, glVersionStrings00[6]),
+ new VersionNumberString(9, 1, 1, glVersionStrings00[7]),
+ new VersionNumberString(14, 10, 1, glVersionStrings00[8]),
+ new VersionNumberString(14, 10, 1, glVersionStrings00[9]),
+ new VersionNumberString(11, 33, 44, glVersionStrings00[10])
+ };
+ public static final VersionNumberString[] glVendorVersionNumbersNoSub = new VersionNumberString[] {
+ new VersionNumberString(1, 2, 0, glVersionStrings01[0]),
+ new VersionNumberString(7, 12, 0, glVersionStrings01[1]),
+ new VersionNumberString(7, 12, 0, glVersionStrings01[2]),
+ new VersionNumberString(7, 12, 0, glVersionStrings01[3]),
+ new VersionNumberString(7, 12, 0, glVersionStrings01[4]),
+ new VersionNumberString(310, 32, 0, glVersionStrings01[5]),
+ new VersionNumberString(9, 1, 0, glVersionStrings01[6]),
+ new VersionNumberString(14, 10, 0, glVersionStrings01[7]),
+ new VersionNumberString(14, 10, 0, glVersionStrings01[8]),
+ new VersionNumberString(11, 33, 0, glVersionStrings01[9])
+ };
+ public static final VersionNumberString[] glVendorVersionNumbersNone = new VersionNumberString[] {
+ new VersionNumberString(0, 0, 0, glVersionStrings02[0]),
+ new VersionNumberString(0, 0, 0, glVersionStrings02[1]),
+ new VersionNumberString(0, 0, 0, glVersionStrings02[2])
+ };
+
+ @Test
+ public void test01GLVersion() throws InterruptedException {
+ for(int i=0; i "+has+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]");
+ Assert.assertTrue(has.hasMajor());
+ Assert.assertTrue(has.hasMinor());
+ Assert.assertTrue(!has.hasSub());
+ Assert.assertEquals(exp, has);
+ }
+ }
+
+ private void testGLVendorVersionImpl(VersionNumberString[] versionNumberString, boolean withMajor, boolean withMinor, boolean withSub) throws InterruptedException {
+ for(int i=0; i "+has+", define ["+has.hasMajor()+":"+has.hasMinor()+":"+has.hasSub()+"]");
+ Assert.assertEquals(withMajor, has.hasMajor());
+ Assert.assertEquals(withMinor, has.hasMinor());
+ Assert.assertEquals(withSub, has.hasSub());
+ Assert.assertEquals(exp, has);
+ }
+ }
+
+ @Test
+ public void test02GLVendorVersion() throws InterruptedException {
+ testGLVendorVersionImpl(glVendorVersionNumbersWithSub, true, true, true);
+ testGLVendorVersionImpl(glVendorVersionNumbersNoSub, true, true, false);
+ testGLVendorVersionImpl(glVendorVersionNumbersNone, false, false, false);
+ }
+
+ public static void main(String args[]) throws IOException {
+ String tstname = TestGLVersionParsing00NEWT.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}
\ No newline at end of file
--
cgit v1.2.3
From cbd7bf1d65a253381b0775d57c0c949c75aef008 Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Fri, 31 May 2013 11:16:01 +0200
Subject: GLVersionNumber.createVendorVersion(): Only test match result and
potentially continue matching if having a pattern-match (don't loop
for-ever).
---
make/scripts/tests.sh | 4 +-
src/jogl/classes/com/jogamp/opengl/FBObject.java | 15 ++--
.../com/jogamp/opengl/GLRendererQuirks.java | 42 ++++++++++-
src/jogl/classes/javax/media/opengl/GLContext.java | 18 ++---
src/jogl/classes/jogamp/opengl/GLContextImpl.java | 84 +++++++++++++++-------
.../classes/jogamp/opengl/GLVersionNumber.java | 11 ++-
.../jogl/acore/TestGLVersionParsing00NEWT.java | 16 +++--
7 files changed, 133 insertions(+), 57 deletions(-)
(limited to 'src/jogl/classes/jogamp/opengl/GLContextImpl.java')
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index 8fd7d2852..071c56a9b 100755
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -281,7 +281,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestOlympicES1NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es1.newt.TestRedSquareES1NEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT $*
+testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelsAWT $*
#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
@@ -312,7 +312,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFloatUtil01MatrixMatrixMultNOUI $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestPMVMatrix01NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestPMVMatrix02NEWT $*
-testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLVersionParsing00NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLVersionParsing00NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestNEWTCloseX11DisplayBug565 $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $*
diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java
index 6f2ac3e35..7060bb7d1 100644
--- a/src/jogl/classes/com/jogamp/opengl/FBObject.java
+++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java
@@ -60,7 +60,6 @@ import com.jogamp.opengl.FBObject.Attachment.Type;
*/
public class FBObject {
protected static final boolean DEBUG = Debug.debug("FBObject");
- private static final boolean forceMinimumFBOSupport = Debug.isPropertyDefined("jogl.fbo.force.min", true);
private static final boolean FBOResizeQuirk = false;
private static enum DetachAction { NONE, DISPOSE, RECREATE };
@@ -813,6 +812,7 @@ public class FBObject {
maxColorAttachments = 1;
if( fullFBOSupport || NV_fbo_color_attachments ) {
try {
+ val[0] = 0;
gl.glGetIntegerv(GL2ES2.GL_MAX_COLOR_ATTACHMENTS, val, 0);
realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1
} catch (GLException gle) { gle.printStackTrace(); }
@@ -823,15 +823,10 @@ public class FBObject {
colorAttachmentCount = 0;
maxSamples = gl.getMaxRenderbufferSamples();
- if(!forceMinimumFBOSupport) {
- gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0);
- maxTextureSize = val[0];
- gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0);
- maxRenderbufferSize = val[0];
- } else {
- maxTextureSize = 2048;
- maxRenderbufferSize = 2048;
- }
+ gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0);
+ maxTextureSize = val[0];
+ gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0);
+ maxRenderbufferSize = val[0];
checkPreGLError(gl);
diff --git a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
index 78bd62e42..36893f5ec 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLRendererQuirks.java
@@ -27,6 +27,8 @@
*/
package com.jogamp.opengl;
+import java.util.List;
+
/**
* GLRendererQuirks contains information of known bugs of various GL renderer.
* This information allows us to workaround them.
@@ -151,14 +153,36 @@ public class GLRendererQuirks {
*/
public static final int NeedCurrCtx4ARBCreateContext = 10;
+ /**
+ * No full FBO support, i.e. not compliant w/
+ *
+ * - GL_ARB_framebuffer_object
+ * - EXT_framebuffer_object
+ * - EXT_framebuffer_multisample
+ * - EXT_framebuffer_blit
+ * - EXT_packed_depth_stencil
+ *
.
+ * Drivers known exposing such bug:
+ *
+ * - Mesa