JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
GLEventListenerState.java
Go to the documentation of this file.
1/**
2 * Copyright 2013 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.opengl;
29
30import java.util.ArrayList;
31import java.util.List;
32
33import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
34import com.jogamp.nativewindow.AbstractGraphicsDevice;
35import com.jogamp.nativewindow.DefaultGraphicsDevice;
36import com.jogamp.nativewindow.NativeSurface;
37import com.jogamp.nativewindow.ProxySurface;
38import com.jogamp.opengl.GLAnimatorControl;
39import com.jogamp.opengl.GLAutoDrawable;
40import com.jogamp.opengl.GLCapabilitiesImmutable;
41import com.jogamp.opengl.GLContext;
42import com.jogamp.opengl.GLEventListener;
43import com.jogamp.opengl.GLException;
44import com.jogamp.opengl.GLRunnable;
45
46import jogamp.opengl.Debug;
47
48import com.jogamp.common.util.locks.RecursiveLock;
49import com.jogamp.nativewindow.MutableGraphicsConfiguration;
50import com.jogamp.opengl.util.GLDrawableUtil;
51
52/**
53 * GLEventListenerState is holding {@link GLAutoDrawable} components crucial
54 * to relocating all its {@link GLEventListener} w/ their operating {@link GLContext}, etc.
55 * The components are:
56 * <ul>
57 * <li>{@link GLContext}</li>
58 * <li>All {@link GLEventListener}, incl. their init state</li>
59 * <li>{@link GLAnimatorControl}</li>
60 * <!--li>{@link GLCapabilitiesImmutable} for compatibility check</li-->
61 * <li>{@link AbstractGraphicsDevice} for compatibility check and preserving the native device handle incl. ownership</li>
62 * </ul>
63 * <p>
64 * A GLEventListenerState instance can be created while components are {@link #moveFrom(GLAutoDrawable) moved from} a {@link GLAutoDrawable}
65 * to the new instance, which gains {@link #isOwner() ownership} of the moved components.
66 * </p>
67 * <p>
68 * A GLEventListenerState instance's components can be {@link #moveTo(GLAutoDrawable) moved to} a {@link GLAutoDrawable},
69 * while loosing {@link #isOwner() ownership} of the moved components.
70 * </p>
71 */
73 private static final boolean DEBUG = Debug.debug("GLDrawable") || Debug.debug("GLEventListenerState");
74
77 final RecursiveLock upstreamLock, final NativeSurface lockedSurface,
78 final GLContext context, final int count, final GLAnimatorControl anim, final boolean animStarted) {
79 this.upstreamDevice = upstreamDevice;
80 this.proxyOwnsUpstreamDevice = proxyOwnsUpstreamDevice;
81 this.device = device;
82 this.caps = caps;
83 this.upstreamLock = upstreamLock;
84 this.lockedSurface = lockedSurface;
85 this.context = context;
86 this.listeners = new GLEventListener[count];
87 this.listenersInit = new boolean[count];
88 this.anim = anim;
89 this.animStarted = animStarted;
90
91 this.owner = true;
92 }
93 /**
94 * Returns <code>true</code>, if this instance is the current owner of the components,
95 * otherwise <code>false</code>.
96 * <p>
97 * Ownership is lost if {@link #moveTo(GLAutoDrawable)} is being called successfully
98 * and all components are transferred to the new {@link GLAutoDrawable}.
99 * </p>
100 */
101 public final boolean isOwner() { return owner; }
102
103 public final int listenerCount() { return listeners.length; }
104
106 public final boolean proxyOwnsUpstreamDevice;
109 public final GLContext context;
111 public final boolean[] listenersInit;
113 public final boolean animStarted;
114
115 private volatile RecursiveLock upstreamLock;
116 private volatile NativeSurface lockedSurface;
117 private volatile boolean owner;
118
119 /**
120 * Returns a {@link Runnable} {@link NativeSurface#unlockSurface() unlocking} an eventually locked {@link NativeSurface},
121 * see {@link #moveFrom(GLAutoDrawable, boolean)} and {@link #moveTo(GLAutoDrawable, Runnable)}.
122 */
123 public Runnable getUnlockSurfaceOp() { return unlockOp; }
124
125 private final Runnable unlockOp = new Runnable() {
126 public void run() {
127 final RecursiveLock rl = upstreamLock;
128 final NativeSurface ls = lockedSurface;
129 upstreamLock = null;
130 lockedSurface = null;
131 if( null != rl ) {
132 rl.unlock();
133 }
134 if( null != ls ) {
135 ls.unlockSurface();
136 }
137 } };
138
139 /**
140 * Last resort to destroy and loose ownership
141 */
142 public void destroy() {
143 if( owner ) {
144 final int aSz = listenerCount();
145 for(int i=0; i<aSz; i++) {
146 listeners[i] = null;
147 }
148 // context.destroy(); - NPE (null drawable)
149 unlockOp.run();
150 device.close();
151 owner = false;
152 }
153 }
154
155 private static AbstractGraphicsDevice cloneDevice(final AbstractGraphicsDevice aDevice) {
156 return (AbstractGraphicsDevice) aDevice.clone();
157 }
158
159 /**
160 * Moves all GLEventListenerState components from the given {@link GLAutoDrawable}
161 * to a newly created instance.
162 * <p>
163 * Note that all components are removed from the {@link GLAutoDrawable},
164 * i.e. the {@link GLContext}, all {@link GLEventListener}.
165 * </p>
166 * <p>
167 * If the {@link GLAutoDrawable} was added to a {@link GLAnimatorControl}, it is removed
168 * and the {@link GLAnimatorControl} added to the GLEventListenerState.
169 * </p>
170 * <p>
171 * The returned GLEventListenerState instance is the {@link #isOwner() owner of the components}.
172 * </p>
173 * <p>
174 * Locking is performed on the {@link GLAutoDrawable auto-drawable's}
175 * {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface}.
176 * See <a href="../../../com/jogamp/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
177 * </p>
178 *
179 * @param src {@link GLAutoDrawable} source to move components from
180 * @return new GLEventListenerState instance {@link #isOwner() owning} moved components.
181 *
182 * @see #moveTo(GLAutoDrawable)
183 */
185 return GLEventListenerState.moveFrom(src, false);
186 }
187
188 /**
189 * Moves all GLEventListenerState components from the given {@link GLAutoDrawable}
190 * to a newly created instance.
191 * <p>
192 * Note that all components are removed from the {@link GLAutoDrawable},
193 * i.e. the {@link GLContext}, all {@link GLEventListener}.
194 * </p>
195 * <p>
196 * If the {@link GLAutoDrawable} was added to a {@link GLAnimatorControl}, it is removed
197 * and the {@link GLAnimatorControl} added to the GLEventListenerState.
198 * </p>
199 * <p>
200 * The returned GLEventListenerState instance is the {@link #isOwner() owner of the components}.
201 * </p>
202 * <p>
203 * Locking is performed on the {@link GLAutoDrawable auto-drawable's}
204 * {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface},
205 * which is <i>not released</i> if <code>keepLocked</code> is <code>true</code>.
206 * See <a href="../../../com/jogamp/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
207 * </p>
208 * <p>
209 * <code>keepLocked</code> may be utilized if swapping a context between drawables
210 * and to ensure atomicity of operation.
211 * Here, the {@link #getUnlockSurfaceOp()} shall be passed to {@link #moveTo(GLAutoDrawable, Runnable)}.
212 * See {@link GLDrawableUtil#swapGLContextAndAllGLEventListener(GLAutoDrawable, GLAutoDrawable)}.
213 * </p>
214 *
215 * @param src {@link GLAutoDrawable} source to move components from
216 * @param keepLocked keep {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface} locked, see above
217 * @return new GLEventListenerState instance {@link #isOwner() owning} moved components.
218 *
219 * @see #moveTo(GLAutoDrawable, Runnable)
220 */
221 public static GLEventListenerState moveFrom(final GLAutoDrawable src, final boolean keepLocked) {
222 final GLAnimatorControl srcAnim = src.getAnimator();
223 final boolean srcAnimStarted;
224 if( null != srcAnim ) {
225 srcAnimStarted = srcAnim.isStarted();
226 srcAnim.remove(src); // also handles ECT
227 } else {
228 srcAnimStarted = false;
229 }
230
231 final GLEventListenerState glls;
232 final RecursiveLock srcUpstreamLock = src.getUpstreamLock();
233 srcUpstreamLock.lock();
234 try {
235 final NativeSurface srcSurface = src.getNativeSurface();
236 final boolean srcSurfaceLocked = NativeSurface.LOCK_SURFACE_NOT_READY < srcSurface.lockSurface();
237 if( src.isRealized() && !srcSurfaceLocked ) {
238 throw new GLException("Could not lock realized surface "+src);
239 }
240
241 try {
242 final int aSz = src.getGLEventListenerCount();
243
244 // Create new AbstractGraphicsScreen w/ cloned AbstractGraphicsDevice for future GLAutoDrawable
245 // allowing this AbstractGraphicsDevice to loose ownership -> not closing display/device!
248 final AbstractGraphicsDevice aDevice1 = aCfg.getScreen().getDevice();
249 final AbstractGraphicsDevice aDevice2 = cloneDevice(aDevice1);
250 aDevice1.clearHandleOwner(); // don't close device handle
251 if( DEBUG ) {
252 System.err.println("GLEventListenerState.moveFrom.0a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1);
253 System.err.println("GLEventListenerState.moveFrom.0b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2);
254 System.err.println("GLEventListenerState.moveFrom.1: "+srcSurface.getClass().getName()/*+", "+aSurface*/);
255 }
256 final AbstractGraphicsDevice aUpDevice2;
257 final boolean proxyOwnsUpstreamDevice;
258 {
259 AbstractGraphicsDevice _aUpDevice2 = null;
260 if(srcSurface instanceof ProxySurface) {
261 final ProxySurface aProxy = (ProxySurface)srcSurface;
263 final NativeSurface aUpSurface = aProxy.getUpstreamSurface();
264 if(DEBUG && null != aUpSurface) {
265 System.err.println("GLEventListenerState.moveFrom.2: "+aUpSurface.getClass().getName()+", "+aUpSurface);
266 }
267 if(null != aUpSurface) {
268 final AbstractGraphicsDevice aUpDevice1 = aUpSurface.getGraphicsConfiguration().getScreen().getDevice();
269 _aUpDevice2 = cloneDevice(aUpDevice1);
270 aUpDevice1.clearHandleOwner(); // don't close device handle
271 if(DEBUG) {
272 System.err.println("GLEventListenerState.moveFrom.3a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1);
273 System.err.println("GLEventListenerState.moveFrom.3b: up-pres 0x"+Integer.toHexString(_aUpDevice2.hashCode())+", "+_aUpDevice2);
274 System.err.println("GLEventListenerState.moveFrom.3c: "+srcSurface.getClass().getName()+", "+srcSurface);
275 System.err.println("GLEventListenerState.moveFrom.3d: "+aUpSurface.getClass().getName()/*+", "+aUpSurface+", "*/+aProxy.getUpstreamOptionBits(null).toString());
276 }
277 }
278 } else {
280 }
281 aUpDevice2 = _aUpDevice2;
282 }
283
284 glls = new GLEventListenerState(aUpDevice2, proxyOwnsUpstreamDevice, aDevice2, caps,
285 keepLocked ? srcUpstreamLock : null,
286 srcSurfaceLocked && keepLocked ? srcSurface : null,
287 src.getContext(), aSz, srcAnim, srcAnimStarted);
288
289 //
290 // remove and cache all GLEventListener and their init-state
291 //
292 for(int i=0; i<aSz; i++) {
293 final GLEventListener l = src.getGLEventListener(0);
295 glls.listeners[i] = src.removeGLEventListener( l );
296 }
297
298 src.setContext( null, false ); // implicit glFinish() ctx/drawable sync
299
300 } finally {
301 if( srcSurfaceLocked && !keepLocked ) {
302 srcSurface.unlockSurface();
303 }
304 }
305 } finally {
306 if( !keepLocked ) {
307 srcUpstreamLock.unlock();
308 }
309 }
310 return glls;
311 }
312
313 /**
314 * Moves all GLEventListenerState components to the given {@link GLAutoDrawable}
315 * from this instance, while loosing {@link #isOwner() ownership}.
316 * <p>
317 * If the previous {@link GLAutoDrawable} was removed from a {@link GLAnimatorControl} by previous {@link #moveFrom(GLAutoDrawable)},
318 * the given {@link GLAutoDrawable} is added to the cached {@link GLAnimatorControl}.
319 * This operation is skipped, if the given {@link GLAutoDrawable} is already added to a {@link GLAnimatorControl} instance.
320 * </p>
321 * <p>
322 * Locking is performed on the {@link GLAutoDrawable auto-drawable's}
323 * {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface}.
324 * See <a href="../../../com/jogamp/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
325 * </p>
326 * <p>
327 * Note: After this operation, the GLEventListenerState reference should be released.
328 * </p>
329 *
330 * @param dest {@link GLAutoDrawable} destination to move GLEventListenerState components to
331 *
332 * @throws GLException if a realized surface could not be locked.
333 * @throws GLException if this preserved {@link AbstractGraphicsDevice} is incompatible w/ the given destination one.
334 * <!-- @throws GLException if the {@link GLAutoDrawable}'s configuration is incompatible, i.e. different {@link GLCapabilitiesImmutable}. -->
335 *
336 * @see #moveFrom(GLAutoDrawable)
337 * @see #isOwner()
338 */
339 public final void moveTo(final GLAutoDrawable dest) throws GLException {
340 this.moveTo(dest, null);
341 }
342
343 /**
344 * Moves all GLEventListenerState components to the given {@link GLAutoDrawable}
345 * from this instance, while loosing {@link #isOwner() ownership}.
346 * <p>
347 * If the previous {@link GLAutoDrawable} was removed from a {@link GLAnimatorControl} by previous {@link #moveFrom(GLAutoDrawable, boolean)},
348 * the given {@link GLAutoDrawable} is added to the cached {@link GLAnimatorControl}.
349 * This operation is skipped, if the given {@link GLAutoDrawable} is already added to a {@link GLAnimatorControl} instance.
350 * </p>
351 * <p>
352 * Locking is performed on the {@link GLAutoDrawable auto-drawable's}
353 * {@link GLAutoDrawable#getUpstreamLock() upstream-lock} and {@link GLAutoDrawable#getNativeSurface() surface}.
354 * See <a href="../../../com/jogamp/opengl/GLAutoDrawable.html#locking">GLAutoDrawable Locking</a>.</li>
355 * </p>
356 * <p>
357 * If the {@link GLAutoDrawable} <code>dest</code> has been kept locked by {@link #moveFrom(GLAutoDrawable, boolean)},
358 * it's {@link #getUnlockSurfaceOp()} shall be passed here to <code>destUnlockOperation</code> to be unlocked.
359 * </p>
360 * <p>
361 * Note: After this operation, the GLEventListenerState reference should be released.
362 * </p>
363 *
364 * @param dest {@link GLAutoDrawable} destination to move GLEventListenerState components to
365 * @param destUnlockOperation optional unlock operation for <code>dest</code>, see {@link #moveFrom(GLAutoDrawable, boolean)}.
366 *
367 * @throws GLException if a realized surface could not be locked.
368 * @throws GLException if this preserved {@link AbstractGraphicsDevice} is incompatible w/ the given destination one.
369 * <!-- @throws GLException if the {@link GLAutoDrawable}'s configuration is incompatible, i.e. different {@link GLCapabilitiesImmutable}. -->
370 *
371 * @see #moveFrom(GLAutoDrawable, boolean)
372 * @see #isOwner()
373 */
374 public final void moveTo(final GLAutoDrawable dest, final Runnable destUnlockOperation) throws GLException {
375 final GLAnimatorControl destAnim = dest.getAnimator();
376 final boolean destAnimPaused;
377 if( null != destAnim ) {
378 destAnimPaused = destAnim.pause();
379 destAnim.remove(dest); // also handles ECT
380 } else {
381 destAnimPaused = false;
382 }
383
384 final List<GLRunnable> aGLCmds = new ArrayList<GLRunnable>();
385 final int aSz = listenerCount();
386
387 final RecursiveLock destUpstreamLock = dest.getUpstreamLock();
388 destUpstreamLock.lock();
389 final boolean destIsRealized;
390 try {
391 final NativeSurface destSurface = dest.getNativeSurface();
392 final boolean destSurfaceLocked = NativeSurface.LOCK_SURFACE_NOT_READY < destSurface.lockSurface();
393 if( dest.isRealized() && !destSurfaceLocked ) {
394 throw new GLException("Could not lock realized surface "+dest);
395 }
396 try {
397
399 /**
400 final GLCapabilitiesImmutable aCaps = (GLCapabilitiesImmutable) aCfg.getChosenCapabilities();
401 if( caps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) != aCaps.getVisualID(VisualIDHolder.VIDType.INTRINSIC) ||
402 caps.getVisualID(VisualIDHolder.VIDType.NATIVE) != aCaps.getVisualID(VisualIDHolder.VIDType.NATIVE) ) {
403 throw new GLException("Incompatible Capabilities - Prev-Holder: "+caps+", New-Holder "+caps);
404 } */
407 if( !aDevice1.getUniqueID().equals( aDevice2.getUniqueID() ) ) {
408 throw new GLException("Incompatible devices: Preserved <"+aDevice2.getUniqueID()+">, target <"+aDevice1.getUniqueID()+">");
409 }
410
411 // collect optional upstream surface info
412 final ProxySurface aProxy;
413 final NativeSurface aUpSurface;
414 if(destSurface instanceof ProxySurface) {
415 aProxy = (ProxySurface)destSurface;
416 aUpSurface = aProxy.getUpstreamSurface();
417 } else {
418 aProxy = null;
419 aUpSurface = null;
420 }
421 if( DEBUG ) {
422 System.err.println("GLEventListenerState.moveTo.0 : has aProxy "+(null!=aProxy));
423 System.err.println("GLEventListenerState.moveTo.0 : has aUpSurface "+(null!=aUpSurface));
424 }
425 if( null==aUpSurface && null != upstreamDevice ) {
426 throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = true, New-Holder = false");
427 }
428
429 // Destroy and remove currently associated GLContext, if any (will be replaced)
430 dest.setContext( null, true );
431 destIsRealized = dest.isRealized();
432 if( destIsRealized && null != aUpSurface ) {
433 // Unrealize due to device dependencies of an upstream surface, e.g. EGLUpstreamSurfaceHook
434 dest.getDelegatedDrawable().setRealized(false);
435 }
436
437 // Set new Screen and close previous one
438 {
439 if( DEBUG ) {
440 System.err.println("GLEventListenerState.moveTo.0a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1);
441 System.err.println("GLEventListenerState.moveTo.0b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2);
442 }
444 aDevice2.close();
445 if( DEBUG ) {
446 System.err.println("GLEventListenerState.moveTo.1a: orig 0x"+Integer.toHexString(aDevice1.hashCode())+", "+aDevice1);
447 System.err.println("GLEventListenerState.moveTo.1b: pres 0x"+Integer.toHexString(aDevice2.hashCode())+", "+aDevice2);
448 }
449 }
450
451 // If using a ProxySurface w/ an upstream surface, set new Screen and close previous one on it
452 if( null != aUpSurface ) {
454 if( null != upstreamDevice ) {
455 final DefaultGraphicsDevice aUpDevice1 = (DefaultGraphicsDevice) aUpCfg.getScreen().getDevice();
457 if( !aUpDevice1.getUniqueID().equals( aUpDevice2.getUniqueID() ) ) {
458 throw new GLException("Incompatible updtream devices: Preserved <"+aUpDevice2.getUniqueID()+">, target <"+aUpDevice1.getUniqueID()+">");
459 }
460 if( DEBUG ) {
461 System.err.println("GLEventListenerState.moveTo.2a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1);
462 System.err.println("GLEventListenerState.moveTo.2b: up-pres 0x"+Integer.toHexString(aUpDevice2.hashCode())+", "+aUpDevice2);
463 System.err.println("GLEventListenerState.moveTo.2c: "+aUpSurface.getClass().getName()/*+", "+aUpSurface+", "*/+aProxy.getUpstreamOptionBits(null).toString());
464 }
465 DefaultGraphicsDevice.swapHandleAndOwnership(aUpDevice1, aUpDevice2);
466 aUpDevice2.close();
469 }
470 if( DEBUG ) {
471 System.err.println("GLEventListenerState.moveTo.3a: up-orig 0x"+Integer.toHexString(aUpDevice1.hashCode())+", "+aUpDevice1);
472 System.err.println("GLEventListenerState.moveTo.3b: up-pres 0x"+Integer.toHexString(aUpDevice2.hashCode())+", "+aUpDevice2);
473 System.err.println("GLEventListenerState.moveTo.3c: "+aUpSurface.getClass().getName()/*+", "+aUpSurface+", "*/+aProxy.getUpstreamOptionBits(null).toString());
474 }
475 } else {
476 throw new GLException("Incompatible Surface config - Has Upstream-Surface: Prev-Holder = false, New-Holder = true");
477 }
478 }
479
480 if( destIsRealized && null != aUpSurface ) {
481 dest.getDelegatedDrawable().setRealized(true);
482 }
483 if( DEBUG ) {
484 System.err.println("GLEventListenerState.moveTo.X : has aProxy "+(null!=aProxy));
485 System.err.println("GLEventListenerState.moveTo.X : has aUpSurface "+(null!=aUpSurface));
486 }
487 dest.setContext( context, false );
488 } finally {
489 if( destSurfaceLocked ) {
490 destSurface.unlockSurface();
491 }
492 }
493 } finally {
494 destUpstreamLock.unlock();
495 }
496 if( null != destUnlockOperation ) {
497 destUnlockOperation.run();
498 }
499
500 owner = false;
501
502 //
503 // Trigger GL-Viewport reset and reshape of all initialized GLEventListeners
504 //
505 aGLCmds.add(setViewport);
506 for(int i=0; i<aSz; i++) {
507 if( listenersInit[i] ) {
508 aGLCmds.add(new GLDrawableUtil.ReshapeGLEventListener( listeners[i], false ) );
509 }
510 }
511 aGLCmds.add(glFinish);
512 dest.invoke(destIsRealized, aGLCmds); // only wait if already realized
513
514 // add all cached GLEventListener to their destination and fix their init-state
515 for(int i=0; i<aSz; i++) {
516 final GLEventListener l = listeners[i];
517 dest.addGLEventListener( l );
518 dest.setGLEventListenerInitState(l, listenersInit[i]);
519 listeners[i] = null;
520 }
521
522 if( null != destAnim ) {
523 // prefer already bound animator
524 destAnim.add(dest);
525 if( destAnimPaused ) {
526 destAnim.resume();
527 }
528 } else if ( null != anim ) {
529 // use previously bound animator
530 anim.add(dest); // also handles ECT
531 if(animStarted) {
532 anim.start();
533 }
534 }
535 }
536
537 private static final GLRunnable setViewport = new GLRunnable() {
538 @Override
539 public boolean run(final GLAutoDrawable drawable) {
540 drawable.getGL().glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
541 return true;
542 }
543 };
544
545 private static final GLRunnable glFinish = new GLRunnable() {
546 @Override
547 public boolean run(final GLAutoDrawable drawable) {
548 drawable.getGL().glFinish();
549 return true;
550 }
551 };
552}
final AbstractGraphicsScreen getScreen()
Return the screen this graphics configuration is valid for.
boolean close()
Optionally closing the device if handle is not null.
final String getUniqueID()
Returns a unique ID object of this device using type, connection and unitID as it's key components.
static final void swapHandleAndOwnership(final DefaultGraphicsDevice a, final DefaultGraphicsDevice b)
Abstraction for an OpenGL rendering context.
Definition: GLContext.java:74
GLEventListenerState is holding GLAutoDrawable components crucial to relocating all its GLEventListen...
final AbstractGraphicsDevice upstreamDevice
void destroy()
Last resort to destroy and loose ownership.
static GLEventListenerState moveFrom(final GLAutoDrawable src, final boolean keepLocked)
Moves all GLEventListenerState components from the given GLAutoDrawable to a newly created instance.
final void moveTo(final GLAutoDrawable dest, final Runnable destUnlockOperation)
Moves all GLEventListenerState components to the given GLAutoDrawable from this instance,...
final boolean isOwner()
Returns true, if this instance is the current owner of the components, otherwise false.
final void moveTo(final GLAutoDrawable dest)
Moves all GLEventListenerState components to the given GLAutoDrawable from this instance,...
static GLEventListenerState moveFrom(final GLAutoDrawable src)
Moves all GLEventListenerState components from the given GLAutoDrawable to a newly created instance.
Runnable getUnlockSurfaceOp()
Returns a Runnable unlocking an eventually locked NativeSurface, see moveFrom(GLAutoDrawable,...
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
GLRunnable to issue GLEventListener#reshape(GLAutoDrawable, int, int, int, int), returning true on GL...
Providing utility functions dealing w/ GLDrawables, GLAutoDrawable and their GLEventListener.
A marker interface describing a graphics configuration, visual, or pixel format in a toolkit-independ...
CapabilitiesImmutable getChosenCapabilities()
Return the capabilities reflecting this graphics configuration, which may differ from the capabilitie...
AbstractGraphicsScreen getScreen()
Return the screen this graphics configuration is valid for.
A interface describing a graphics device in a toolkit-independent manner.
boolean close()
Optionally closing the device if handle is not null.
AbstractGraphicsDevice getDevice()
Return the device this graphics configuration is valid for.
Provides low-level information required for hardware-accelerated rendering using a surface in a platf...
int lockSurface()
Lock the surface of this native window.
AbstractGraphicsConfiguration getGraphicsConfiguration()
Returns the graphics configuration corresponding to this window.
void unlockSurface()
Unlock the surface of this native window.
Provides a mutable NativeSurface, i.e.
NativeSurface getUpstreamSurface()
Returns the optional upstream NativeSurface if used by implementation, otherwise null.
void addUpstreamOptionBits(int v)
Add the given bit-mask to this instance upstream-option-bits using bit-or w/ v.
boolean containsUpstreamOptionBits(int v)
Returns true if the give bit-mask v is set in this instance upstream-option-bits, otherwise false.
StringBuilder getUpstreamOptionBits(StringBuilder sink)
static final int OPT_PROXY_OWNS_UPSTREAM_DEVICE
Implementation specific bit-value stating this ProxySurface owns the upstream's AbstractGraphicsDevic...
An animator control interface, which implementation may drive a com.jogamp.opengl....
boolean start()
Starts this animator, if not running.
boolean resume()
Resumes animation if paused.
void remove(GLAutoDrawable drawable)
Removes a drawable from the animator's list of rendering drawables.
boolean pause()
Pauses this animator.
boolean isStarted()
Indicates whether this animator has been started.
void add(GLAutoDrawable drawable)
Adds a drawable to this animator's list of rendering drawables.
A higher-level abstraction than GLDrawable which supplies an event based mechanism (GLEventListener) ...
GLEventListener getGLEventListener(int index)
Returns the GLEventListener at the given index of this drawable queue.
GLContext setContext(GLContext newCtx, boolean destroyPrevCtx)
Associate the new context, newtCtx, to this auto-drawable.
GLAnimatorControl getAnimator()
GL getGL()
Returns the GL pipeline object this GLAutoDrawable uses.
RecursiveLock getUpstreamLock()
Returns the recursive lock object of the upstream widget to synchronize multithreaded access on top o...
int getGLEventListenerCount()
Returns the number of GLEventListener of this drawable queue.
GLEventListener removeGLEventListener(GLEventListener listener)
Removes the given listener from this drawable queue.
GLContext getContext()
Returns the context associated with this drawable.
boolean getGLEventListenerInitState(GLEventListener listener)
Retrieves whether the given listener is initialized or not.
Specifies an immutable set of OpenGL capabilities.
int getSurfaceWidth()
Returns the width of this GLDrawable's surface client area in pixel units.
boolean isRealized()
Returns true if this drawable is realized, otherwise false.
NativeSurface getNativeSurface()
Returns the associated NativeSurface of this NativeSurfaceHolder.
int getSurfaceHeight()
Returns the height of this GLDrawable's surface client area in pixel units.
Declares events which client code can use to manage OpenGL rendering into a GLAutoDrawable.
void glViewport(int x, int y, int width, int height)
Entry point to C language function: void {@native glViewport}(GLint x, GLint y, GLsizei width,...