aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-06-17 04:39:58 +0200
committerSven Gothel <[email protected]>2013-06-17 04:39:58 +0200
commitd7e2cb6fdec200d25a9189f7951c5f94c26a1ce4 (patch)
tree21032f1f85d365b5a205ea7296f8ff5f76b2166d /src/jogl
parentc3dc7fbdb9437f773146926b41003df32ba756d1 (diff)
Fix Bug 753: Stuttering caused by lack of GL resource synchronization between Java GL- and CALayer thread ; Simplify / Fix waitUntilRenderSignal().
Stuttering caused by lack of GL resource synchronization between Java GL- and CALayer thread + // Required(?) to finish previous GL rendering to give CALayer proper result, + // i.e. synchronize both threads each w/ their GLContext sharing same resources. + // + // FIXME: IMHO this synchronization should be implicitly performed via 'CGL.flushBuffer(contextHandle)' above, + // in case this will be determined a driver bug - use a QUIRK entry in GLRendererQuirks! + gl.glFinish(); Simplify / Fix waitUntilRenderSignal() - remove loop and 'ready' condition -> nonsense - if too later, i.e. lastWaitTime+TO < now, use now+TO as max. vsync waiting time Bug735 Tests: - Make vsync, wait and ECT (exclusive context thread) configurable via main args. - Inv2*, Inv3* and Inv4*: Fluent Animation - Works w/ ECT
Diffstat (limited to 'src/jogl')
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java52
-rw-r--r--src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m63
2 files changed, 82 insertions, 33 deletions
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
index 976056891..6b086ce44 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java
@@ -81,7 +81,7 @@ import com.jogamp.opengl.util.glsl.ShaderCode;
import com.jogamp.opengl.util.glsl.ShaderProgram;
public class MacOSXCGLContext extends GLContextImpl
-{
+{
// Abstract interface for implementation of this context (either
// NSOpenGL-based or CGL-based)
protected interface GLBackendImpl {
@@ -1000,6 +1000,8 @@ public class MacOSXCGLContext extends GLContextImpl
CGL.setNSOpenGLLayerSwapInterval(l, interval);
if( 0 < interval ) {
vsyncTimeout = interval * screenVSyncTimeout + 1000; // +1ms
+ } else {
+ vsyncTimeout = 1 * screenVSyncTimeout + 1000; // +1ms
}
if(DEBUG) { System.err.println("NS setSwapInterval: "+interval+" -> "+vsyncTimeout+" micros"); }
}
@@ -1008,6 +1010,14 @@ public class MacOSXCGLContext extends GLContextImpl
}
private int skipSync=0;
+ /** TODO: Remove after discussion
+ private boolean perfIterReset = false;
+ private int perfIter = 0;
+ private long waitGLS = 0;
+ private long finishGLS = 0;
+ private long frameXS = 0;
+ private long lastFrameStart = 0;
+ */
@Override
public boolean swapBuffers() {
@@ -1036,6 +1046,45 @@ public class MacOSXCGLContext extends GLContextImpl
res = CGL.flushBuffer(contextHandle);
if(res) {
if(0 == skipSync) {
+ /** TODO: Remove after discussion
+ perfIter++;
+ if( !perfIterReset && 100 == perfIter ) {
+ perfIterReset = true;
+ perfIter = 1;
+ waitGLS = 0;
+ finishGLS = 0;
+ frameXS = 0;
+ }
+ final long lastFramePeriod0 = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+ gl.glFinish(); // Require to finish previous GL rendering to give CALayer proper result
+ final long lastFramePeriod1 = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+
+ // 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);
+ final long lastFramePeriodX = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart;
+
+ final long finishGL = lastFramePeriod1 - lastFramePeriod0;
+ final long waitGL = lastFramePeriodX - lastFramePeriod1;
+ finishGLS += finishGL;
+ waitGLS += waitGL;
+ frameXS += lastFramePeriodX;
+
+ System.err.println("XXX["+perfIter+"] TO "+vsyncTimeout/1000+" ms, "+
+ "lFrame0 "+lastFramePeriod0/1000+" ms, "+
+ "lFrameX "+lastFramePeriodX/1000+" / "+frameXS/1000+" ~"+(frameXS/perfIter)/1000.0+" ms, "+
+ "finishGL "+finishGL/1000+" / "+finishGLS/1000+" ~"+(finishGLS/perfIter)/1000.0+" ms, "+
+ "waitGL "+waitGL/1000+" / "+waitGLS/1000+" ~"+(waitGLS/perfIter)/1000.0+" ms");
+ */
+ //
+ // Required(?) to finish previous GL rendering to give CALayer proper result,
+ // i.e. synchronize both threads each w/ their GLContext sharing same resources.
+ //
+ // FIXME: IMHO this synchronization should be implicitly performed via 'CGL.flushBuffer(contextHandle)' above,
+ // in case this will be determined a driver bug - use a QUIRK entry in GLRendererQuirks!
+ gl.glFinish();
+
// 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).
@@ -1050,6 +1099,7 @@ public class MacOSXCGLContext extends GLContextImpl
// trigger CALayer to update incl. possible surface change (new pbuffer handle)
CGL.setNSOpenGLLayerNeedsDisplayPBuffer(cmd.nsOpenGLLayer, drawable.getHandle());
}
+ // lastFrameStart = TimeUnit.NANOSECONDS.toMicros(System.nanoTime());
}
} else {
res = true;
diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
index 6738364a7..046171efc 100644
--- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
+++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m
@@ -818,40 +818,39 @@ static const GLfloat gl_verts[] = {
- (void)waitUntilRenderSignal: (long) to_micros
{
- BOOL ready = NO;
- int wr = 0;
+ struct timespec t0, to_until;
+ BOOL tooLate;
+ int wr;
+ if( 0 >= to_micros ) {
+ to_micros = 16666 + 1000; // defaults to 1/60s + 1ms
+ NSLog(@"MyNSOpenGLContext::waitUntilRenderSignal: to_micros was zero, using defaults");
+ }
pthread_mutex_lock(&renderLock);
- SYNC_PRINT("{W %ld us", to_micros);
- do {
- if(0 >= swapInterval) {
- ready = YES;
- }
- if(NO == ready) {
- #ifdef DBG_SYNC
- struct timespec t0, t1, td, td2;
- timespec_now(&t0);
- #endif
- if( 0 >= to_micros ) {
- to_micros = 16666 + 1000; // defaults to 1/60s + 1ms
- NSLog(@"MyNSOpenGLContext::waitUntilRenderSignal: to_micros was zero, using defaults");
- }
- struct timespec to_abs = lastWaitTime;
- timespec_addmicros(&to_abs, to_micros);
- #ifdef DBG_SYNC
- timespec_subtract(&td, &to_abs, &t0);
- fprintf(stderr, ", (%ld) / ", timespec_milliseconds(&td));
- #endif
- wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_abs);
- #ifdef DBG_SYNC
- timespec_now(&t1);
- timespec_subtract(&td, &t1, &t0);
- timespec_subtract(&td2, &t1, &lastWaitTime);
- fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
- #endif
- ready = YES;
+ timespec_now(&t0);
+ to_until = lastWaitTime;
+ timespec_addmicros(&to_until, to_micros);
+ tooLate = timespec_compare(&to_until, &t0) < 0;
+ #ifdef DBG_SYNC
+ struct timespec td_until;
+ timespec_subtract(&td_until, &to_until, &t0);
+ SYNC_PRINT("{W %ld ms, to %ld ms, late %d", to_micros/1000, timespec_milliseconds(&td_until), tooLate);
+ #endif
+ if( 0 < swapInterval ) {
+ if( tooLate ) {
+ // adjust!
+ to_until = t0;
+ timespec_addmicros(&to_until, to_micros);
}
- } while (NO == ready && 0 == wr) ;
- SYNC_PRINT("-%d-%d-%d}", shallDraw, wr, ready);
+ wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_until);
+ #ifdef DBG_SYNC
+ struct timespec t1, td, td2;
+ timespec_now(&t1);
+ timespec_subtract(&td, &t1, &t0);
+ timespec_subtract(&td2, &t1, &lastWaitTime);
+ fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2));
+ #endif
+ }
+ SYNC_PRINT("-%d-%d}\n", shallDraw, wr);
timespec_now(&lastWaitTime);
pthread_mutex_unlock(&renderLock);
}