JOGL v2.6.0-rc-20250706
JOGL, High-Performance Graphics Binding for Java™ (public API).
GLCanvas.java
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
3 * Copyright (c) 2010-2023 JogAmp Community. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * - Redistribution of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * - Redistribution in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of Sun Microsystems, Inc. or the names of
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * This software is provided "AS IS," without a warranty of any kind. ALL
21 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
22 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
23 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
24 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
25 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
26 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
27 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
28 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
29 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
30 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
31 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32 *
33 * You acknowledge that this software is not designed or intended for use
34 * in the design, construction, operation or maintenance of any nuclear
35 * facility.
36 *
37 * Sun gratefully acknowledges that this software was originally authored
38 * and developed by Kenneth Bradley Russell and Christopher John Kline.
39 */
40
41package com.jogamp.opengl.awt;
42
43import java.beans.Beans;
44import java.awt.Canvas;
45import java.awt.Color;
46import java.awt.FontMetrics;
47import java.awt.Frame;
48import java.awt.Graphics;
49import java.awt.Graphics2D;
50import java.awt.GraphicsConfiguration;
51import java.awt.GraphicsDevice;
52import java.awt.event.HierarchyEvent;
53import java.awt.event.HierarchyListener;
54import java.awt.geom.NoninvertibleTransformException;
55import java.awt.geom.Rectangle2D;
56import java.awt.EventQueue;
57import java.lang.reflect.InvocationTargetException;
58import java.util.ArrayList;
59import java.util.List;
60
61import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
62import com.jogamp.nativewindow.OffscreenLayerOption;
63import com.jogamp.nativewindow.ScalableSurface;
64import com.jogamp.nativewindow.VisualIDHolder;
65import com.jogamp.nativewindow.WindowClosingProtocol;
66import com.jogamp.nativewindow.AbstractGraphicsDevice;
67import com.jogamp.nativewindow.AbstractGraphicsScreen;
68import com.jogamp.nativewindow.GraphicsConfigurationFactory;
69import com.jogamp.nativewindow.NativeSurface;
70import com.jogamp.nativewindow.NativeWindowFactory;
71import com.jogamp.opengl.GL;
72import com.jogamp.opengl.GLAnimatorControl;
73import com.jogamp.opengl.GLAutoDrawable;
74import com.jogamp.opengl.GLCapabilities;
75import com.jogamp.opengl.GLCapabilitiesChooser;
76import com.jogamp.opengl.GLCapabilitiesImmutable;
77import com.jogamp.opengl.GLContext;
78import com.jogamp.opengl.GLDrawable;
79import com.jogamp.opengl.GLDrawableFactory;
80import com.jogamp.opengl.GLEventListener;
81import com.jogamp.opengl.GLException;
82import com.jogamp.opengl.GLOffscreenAutoDrawable;
83import com.jogamp.opengl.GLProfile;
84import com.jogamp.opengl.GLRunnable;
85import com.jogamp.opengl.GLSharedContextSetter;
86import com.jogamp.opengl.Threading;
87
88import com.jogamp.common.GlueGenVersion;
89import com.jogamp.common.os.Platform;
90import com.jogamp.common.os.Platform.OSType;
91import com.jogamp.common.util.VersionUtil;
92import com.jogamp.common.util.awt.AWTEDTExecutor;
93import com.jogamp.common.util.locks.LockFactory;
94import com.jogamp.common.util.locks.RecursiveLock;
95import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration;
96import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
97import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
98import com.jogamp.nativewindow.awt.AWTPrintLifecycle;
99import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol;
100import com.jogamp.nativewindow.awt.JAWTWindow;
101import com.jogamp.opengl.JoglVersion;
102import com.jogamp.opengl.util.GLDrawableUtil;
103import com.jogamp.opengl.util.TileRenderer;
104
105import jogamp.nativewindow.SurfaceScaleUtils;
106import jogamp.nativewindow.jawt.JAWTUtil;
107import jogamp.opengl.Debug;
108import jogamp.opengl.GLContextImpl;
109import jogamp.opengl.GLDrawableHelper;
110import jogamp.opengl.GLDrawableImpl;
111import jogamp.opengl.awt.AWTTilePainter;
112
113// FIXME: Subclasses need to call resetGLFunctionAvailability() on their
114// context whenever the displayChanged() function is called on our
115// GLEventListeners
116
117/** A heavyweight AWT component which provides OpenGL rendering
118 support. This is the primary implementation of an AWT {@link GLDrawable};
119 {@link GLJPanel} is provided for compatibility with Swing user
120 interfaces when adding a heavyweight doesn't work either because
121 of Z-ordering or LayoutManager problems.
122 *
123 * <h5><a name="offscreenlayer">Offscreen Layer Remarks</a></h5>
124 *
125 * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
126 * maybe called to use an offscreen drawable (FBO or PBuffer) allowing
127 * the underlying JAWT mechanism to composite the image, if supported.
128 * <p>
129 * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)}
130 * is being called if {@link GLCapabilitiesImmutable#isOnscreen()} is <code>false</code>.
131 * </p>
132 *
133 * <h5><a name="java2dgl">Java2D OpenGL Remarks</a></h5>
134 *
135 * To avoid any conflicts with a potential Java2D OpenGL context,<br>
136 * you shall consider setting the following JVM properties:<br>
137 * <ul>
138 * <li><pre>sun.java2d.opengl=false</pre></li>
139 * <li><pre>sun.java2d.noddraw=true</pre></li>
140 * </ul>
141 * This is especially true in case you want to utilize a GLProfile other than
142 * {@link GLProfile#GL2}, eg. using {@link GLProfile#getMaxFixedFunc()}.<br>
143 * On the other hand, if you like to experiment with GLJPanel's utilization
144 * of Java2D's OpenGL pipeline, you have to set them to
145 * <ul>
146 * <li><pre>sun.java2d.opengl=true</pre></li>
147 * <li><pre>sun.java2d.noddraw=true</pre></li>
148 * </ul>
149 *
150 * <h5><a name="backgrounderase">Disable Background Erase</a></h5>
151 *
152 * GLCanvas tries to disable background erase for the AWT Canvas
153 * before native peer creation (X11) and after it (Windows), <br>
154 * utilizing the optional {@link java.awt.Toolkit} method <code>disableBeackgroundErase(java.awt.Canvas)</code>.<br>
155 * However if this does not give you the desired results, you may want to disable AWT background erase in general:
156 * <ul>
157 * <li><pre>sun.awt.noerasebackground=true</pre></li>
158 * </ul>
159 *
160 * <h5><a name="contextSharing">OpenGL Context Sharing</a></h5>
161 *
162 * To share a {@link GLContext} see the following note in the documentation overview:
163 * <a href="../../../../overview-summary.html#SHARING">context sharing</a>
164 * as well as {@link GLSharedContextSetter}.
165 *
166 */
167
168@SuppressWarnings("serial")
171
172 private static final boolean DEBUG = Debug.debug("GLCanvas");
173
174 private static JAWTUtil.BackgroundEraseControl backgroundEraseControl = new JAWTUtil.BackgroundEraseControl();
175
176 private final RecursiveLock lock = LockFactory.createRecursiveLock();
177 private final GLDrawableHelper helper = new GLDrawableHelper();
178 private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
179 private volatile JAWTWindow jawtWindow; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle
180 private volatile GLContextImpl context; // volatile: avoid locking for read-only access
181 private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking
182 private final float[] hasPixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
183
184 // copy of the cstr args, mainly for recreation
185 private final GLCapabilitiesImmutable capsReqUser;
186 private final GLCapabilitiesChooser chooser;
187 private int additionalCtxCreationFlags = 0;
188 private boolean shallUseOffscreenLayer = false;
189
190 private volatile GraphicsDevice awtDeviceReq; // one time user req.
191 private volatile AWTGraphicsConfiguration awtConfig;
192 private volatile boolean isShowing;
193 private final HierarchyListener hierarchyListener = new HierarchyListener() {
194 @Override
195 public void hierarchyChanged(final HierarchyEvent e) {
196 isShowing = GLCanvas.this.isShowing();
197 }
198 };
199
200 private final AWTWindowClosingProtocol awtWindowClosingProtocol =
201 new AWTWindowClosingProtocol(this, new Runnable() {
202 @Override
203 public void run() {
204 GLCanvas.this.destroyImpl( true );
205 }
206 }, null);
207
208 /** Creates a new GLCanvas component with a default set of OpenGL
209 capabilities, using the default OpenGL capabilities selection
210 mechanism, on the default screen device.
211 <p>
212 See details about <a href="#contextSharing">OpenGL context sharing</a>.
213 </p>
214 * @throws GLException if no default profile is available for the default desktop device.
215 */
216 public GLCanvas() throws GLException {
217 this(null);
218 }
219
220 /** Creates a new GLCanvas component with the requested set of
221 OpenGL capabilities, using the default OpenGL capabilities
222 selection mechanism, on the default screen device.
223 <p>
224 See details about <a href="#contextSharing">OpenGL context sharing</a>.
225 </p>
226 * @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
227 * @see GLCanvas#GLCanvas(com.jogamp.opengl.GLCapabilitiesImmutable, com.jogamp.opengl.GLCapabilitiesChooser, com.jogamp.opengl.GLContext, java.awt.GraphicsDevice)
228 */
229 public GLCanvas(final GLCapabilitiesImmutable capsReqUser) throws GLException {
230 this(capsReqUser, null, null);
231 }
232
233 /** Creates a new GLCanvas component. The passed GLCapabilities
234 specifies the OpenGL capabilities for the component; if null, a
235 default set of capabilities is used. The GLCapabilitiesChooser
236 specifies the algorithm for selecting one of the available
237 GLCapabilities for the component; a DefaultGLCapabilitesChooser
238 is used if null is passed for this argument.
239 The passed GraphicsDevice indicates the screen on
240 which to create the GLCanvas; the GLDrawableFactory uses the
241 default screen device of the local GraphicsEnvironment if null
242 is passed for this argument.
243 <p>
244 See details about <a href="#contextSharing">OpenGL context sharing</a>.
245 </p>
246 * @throws GLException if no GLCapabilities are given and no default profile is available for the default desktop device.
247 */
248 public GLCanvas(final GLCapabilitiesImmutable capsReqUser,
249 final GLCapabilitiesChooser chooser,
250 final GraphicsDevice device)
251 throws GLException
252 {
253 /*
254 * Determination of the native window is made in 'super.addNotify()',
255 * which creates the native peer using AWT's GraphicsConfiguration.
256 * GraphicsConfiguration is returned by this class overwritten
257 * 'getGraphicsConfiguration()', which returns our OpenGL compatible
258 * 'chosen' GraphicsConfiguration.
259 */
260 super();
261
262 if(null==capsReqUser) {
264 } else {
265 // don't allow the user to change data
266 this.capsReqUser = (GLCapabilitiesImmutable) capsReqUser.cloneMutable();
267 }
268 if( !this.capsReqUser.isOnscreen() ) {
269 setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported
270 }
271
272 // One time user AWT GraphicsDevice request
273 awtDeviceReq = device;
274
275 // instantiation will be issued in addNotify()
276 this.chooser = chooser;
277
278 this.addHierarchyListener(hierarchyListener);
279 this.isShowing = isShowing();
280 }
281
282 @Override
283 public final void setSharedContext(final GLContext sharedContext) throws IllegalStateException {
284 helper.setSharedContext(this.context, sharedContext);
285 }
286
287 @Override
288 public final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable) throws IllegalStateException {
289 helper.setSharedAutoDrawable(this, sharedAutoDrawable);
290 }
291
292 @Override
293 public final Object getUpstreamWidget() {
294 return this;
295 }
296
297 @Override
298 public final RecursiveLock getUpstreamLock() { return lock; }
299
300 @Override
301 public final boolean isThreadGLCapable() { return Threading.isOpenGLThread(); }
302
303 @Override
304 public void setShallUseOffscreenLayer(final boolean v) {
305 shallUseOffscreenLayer = v;
306 }
307
308 @Override
309 public final boolean getShallUseOffscreenLayer() {
310 return shallUseOffscreenLayer;
311 }
312
313 @Override
314 public final boolean isOffscreenLayerSurfaceEnabled() {
315 final JAWTWindow _jawtWindow = jawtWindow;
316 if(null != _jawtWindow) {
317 return _jawtWindow.isOffscreenLayerSurfaceEnabled();
318 }
319 return false;
320 }
321
322
323 /**
324 * {@inheritDoc}
325 * <p>
326 * Overridden to choose a {@link GraphicsConfiguration} from a parent container's
327 * {@link GraphicsDevice}.
328 * </p>
329 * <p>
330 * Method also intercepts {@link GraphicsConfiguration} changes regarding to
331 * its capabilities and its {@link GraphicsDevice}. This may happen in case
332 * the display changes its configuration or the component is moved to another screen.
333 * </p>
334 */
335 @Override
336 public GraphicsConfiguration getGraphicsConfiguration() {
337 /**
338 * parentGC will be null unless:
339 * - A native peer has assigned it. This means we have a native
340 * peer, and are already committed to a graphics configuration.
341 * - This canvas has been added to a component hierarchy and has
342 * an ancestor with a non-null GC, but the native peer has not
343 * yet been created. This means we can still choose the GC on
344 * all platforms since the peer hasn't been created.
345 */
346 final GraphicsConfiguration parentGC = super.getGraphicsConfiguration();
347
348 if( Beans.isDesignTime() ) {
349 return parentGC;
350 }
351 final GraphicsConfiguration oldGC = null != awtConfig ? awtConfig.getAWTGraphicsConfiguration() : null;
352
353 if ( null != parentGC && null != oldGC && !oldGC.equals(parentGC) ) {
354 // Previous oldGC != parentGC of native peer
355
356 if ( !oldGC.getDevice().getIDstring().equals(parentGC.getDevice().getIDstring()) ) {
357 // Previous oldGC's GraphicsDevice != parentGC's GraphicsDevice of native peer
358
359 /**
360 * Here we select a GraphicsConfiguration on the alternate device.
361 * In case the new configuration differs (-> !equalCaps),
362 * we might need a reconfiguration,
363 */
364 final AWTGraphicsConfiguration newConfig = chooseGraphicsConfiguration( (GLCapabilitiesImmutable)awtConfig.getChosenCapabilities(),
366 chooser, parentGC.getDevice());
367 final GraphicsConfiguration newGC = newConfig.getAWTGraphicsConfiguration();
368 final boolean equalCaps = newConfig.getChosenCapabilities().equals(awtConfig.getChosenCapabilities());
369 if(DEBUG) {
370 System.err.println(getThreadName()+": getGraphicsConfiguration() Info: Changed GC and GD");
371 System.err.println("Created Config (n): Old GC "+oldGC);
372 System.err.println("Created Config (n): Old GD "+oldGC.getDevice().getIDstring());
373 System.err.println("Created Config (n): Parent GC "+parentGC);
374 System.err.println("Created Config (n): Parent GD "+parentGC.getDevice().getIDstring());
375 System.err.println("Created Config (n): New GC "+newGC);
376 System.err.println("Created Config (n): New GD "+newGC.getDevice().getIDstring());
377 System.err.println("Created Config (n): Old CF "+awtConfig);
378 System.err.println("Created Config (n): New CF "+newConfig);
379 System.err.println("Created Config (n): EQUALS CAPS "+equalCaps);
380 // Thread.dumpStack();
381 }
382 if ( null != newGC ) {
383 if( !equalCaps && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) {
384 // complete destruction!
385 destroyImpl( true );
386 // recreation!
387 setAWTGraphicsConfiguration(newConfig);
388 createJAWTDrawableAndContext();
389 validateGLDrawable();
390 } else {
391 setAWTGraphicsConfiguration(newConfig);
392 }
393 /**
394 * Return the newGC, which covers the desired capabilities and is compatible
395 * with the available GC's of its devices.
396 */
397 if(DEBUG) {
398 System.err.println(getThreadName()+": Info: getGraphicsConfiguration - end.01: newGC "+newGC);
399 }
400 return newGC;
401 } else {
402 if(DEBUG) {
403 System.err.println(getThreadName()+": Info: getGraphicsConfiguration - end.00: oldGC "+oldGC);
404 }
405 }
406 }
407 /**
408 * If a new GC was _not_ found/defined above,
409 * method returns oldGC as selected in the constructor or first addNotify().
410 * This may cause an exception in Component.checkGD when adding to a
411 * container, and is the desired behavior.
412 */
413 return oldGC;
414 } else if (null == parentGC) {
415 /**
416 * The parentGC is null, which means we have no native peer, and are not
417 * part of a (realized) component hierarchy. So we return the
418 * desired visual that was selected in the constructor (possibly
419 * null).
420 */
421 return oldGC;
422 } else {
423 /**
424 * Otherwise we have not explicitly selected a GC in the constructor, so
425 * just return what Canvas would have.
426 */
427 return parentGC;
428 }
429 }
430
431 @Override
432 public GLContext createContext(final GLContext shareWith) {
433 final RecursiveLock _lock = lock;
434 _lock.lock();
435 try {
436 if(drawable != null) {
437 final GLContext _ctx = drawable.createContext(shareWith);
438 _ctx.setContextCreationFlags(additionalCtxCreationFlags);
439 return _ctx;
440 }
441 return null;
442 } finally {
443 _lock.unlock();
444 }
445 }
446
447 private final void setRealizedImpl(final boolean realized) {
448 final RecursiveLock _lock = lock;
449 _lock.lock();
450 try {
451 final GLDrawable _drawable = drawable;
452 if( null == _drawable || realized == _drawable.isRealized() ||
453 realized && ( 0 >= _drawable.getSurfaceWidth() || 0 >= _drawable.getSurfaceHeight() ) ) {
454 return;
455 }
456 _drawable.setRealized(realized);
457 if( realized && _drawable.isRealized() ) {
458 sendReshape=true; // ensure a reshape is being send ..
459 }
460 } finally {
461 _lock.unlock();
462 }
463 }
464 private final Runnable realizeOnEDTAction = new Runnable() {
465 @Override
466 public void run() { setRealizedImpl(true); }
467 };
468 private final Runnable unrealizeOnEDTAction = new Runnable() {
469 @Override
470 public void run() { setRealizedImpl(false); }
471 };
472
473 @Override
474 public final void setRealized(final boolean realized) {
475 // Make sure drawable realization happens on AWT-EDT and only there. Consider the AWTTree lock!
476 AWTEDTExecutor.singleton.invoke(getTreeLock(), false /* allowOnNonEDT */, true /* wait */, realized ? realizeOnEDTAction : unrealizeOnEDTAction);
477 }
478
479 @Override
480 public boolean isRealized() {
481 final GLDrawable _drawable = drawable;
482 return ( null != _drawable ) ? _drawable.isRealized() : false;
483 }
484
485 @Override
487 return awtWindowClosingProtocol.getDefaultCloseOperation();
488 }
489
490 @Override
492 return awtWindowClosingProtocol.setDefaultCloseOperation(op);
493 }
494
495 @Override
496 public void display() {
497 if( !validateGLDrawable() ) {
498 if(DEBUG) {
499 System.err.println(getThreadName()+": Info: GLCanvas display - skipped GL render, drawable not valid yet");
500 }
501 return; // not yet available ..
502 }
503 if( isShowing && !printActive ) {
504 Threading.invoke(true, displayOnEDTAction, getTreeLock());
505 }
506 }
507
508 /**
509 * {@inheritDoc}
510 *
511 * <p>
512 * This impl. only destroys all GL related resources.
513 * </p>
514 * <p>
515 * This impl. does not remove the GLCanvas from it's parent AWT container
516 * so this class's {@link #removeNotify()} AWT override won't get called.
517 * To do so, remove this component from it's parent AWT container.
518 * </p>
519 */
520 @Override
521 public void destroy() {
522 destroyImpl( false );
523 }
524
525 protected void destroyImpl(final boolean destroyJAWTWindowAndAWTDevice) {
526 Threading.invoke(true, destroyOnEDTAction, getTreeLock());
527 if( destroyJAWTWindowAndAWTDevice ) {
528 AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, disposeJAWTWindowAndAWTDeviceOnEDT);
529 }
530 }
531
532 /** Overridden to cause OpenGL rendering to be performed during
533 repaint cycles. Subclasses which override this method must call
534 super.paint() in their paint() method in order to function
535 properly.
536 */
537 @Override
538 public void paint(final Graphics g) {
539 if( Beans.isDesignTime() ) {
540 // Make GLCanvas behave better in NetBeans GUI builder
541 g.setColor(Color.BLACK);
542 g.fillRect(0, 0, getWidth(), getHeight());
543 final FontMetrics fm = g.getFontMetrics();
544 String name = getName();
545 if (name == null) {
546 name = getClass().getName();
547 final int idx = name.lastIndexOf('.');
548 if (idx >= 0) {
549 name = name.substring(idx + 1);
550 }
551 }
552 final Rectangle2D bounds = fm.getStringBounds(name, g);
553 g.setColor(Color.WHITE);
554 g.drawString(name,
555 (int) ((getWidth() - bounds.getWidth()) / 2),
556 (int) ((getHeight() + bounds.getHeight()) / 2));
557 } else if( !this.helper.isAnimatorAnimatingOnOtherThread() ) {
558 display();
559 }
560 }
561
562 /** Overridden to track when this component is added to a container.
563 Subclasses which override this method must call
564 super.addNotify() in their addNotify() method in order to
565 function properly. <P>
566
567 <B>Overrides:</B>
568 <DL><DD><CODE>addNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL>
569 */
570 @SuppressWarnings("deprecation")
571 @Override
572 public void addNotify() {
573 final RecursiveLock _lock = lock;
574 _lock.lock();
575 try {
576 final boolean isBeansDesignTime = Beans.isDesignTime();
577
578 if(DEBUG) {
579 System.err.println(getThreadName()+": Info: addNotify - start, bounds: "+this.getBounds()+", isBeansDesignTime "+isBeansDesignTime);
580 // Thread.dumpStack();
581 }
582
583 if( isBeansDesignTime ) {
584 super.addNotify();
585 } else {
586 /**
587 * 'super.addNotify()' determines the GraphicsConfiguration,
588 * while calling this class's overridden 'getGraphicsConfiguration()' method
589 * after which it creates the native peer.
590 * Hence we have to set the 'awtConfig' before since it's GraphicsConfiguration
591 * is being used in getGraphicsConfiguration().
592 * This code order also allows recreation, ie re-adding the GLCanvas.
593 */
594
595 // before native peer is valid: X11
596 if( OSType.WINDOWS != Platform.getOSType() ) {
597 backgroundEraseControl.disable(this);
598 }
599
600 final GraphicsDevice awtDevice;
601 if(null==awtDeviceReq) {
602 // Query AWT GraphicsDevice from parent tree, default
603 final GraphicsConfiguration gc = super.getGraphicsConfiguration();
604 if(null==gc) {
605 throw new GLException("Error: NULL AWT GraphicsConfiguration");
606 }
607 awtDevice = gc.getDevice();
608 } else {
609 // Use one time user AWT GraphicsDevice request
610 awtDevice = awtDeviceReq;
611 awtDeviceReq = null;
612 }
613 final AWTGraphicsConfiguration awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, awtDevice);
614 if(null==awtConfig) {
615 throw new GLException("Error: NULL AWTGraphicsConfiguration");
616 }
617 setAWTGraphicsConfiguration(awtConfig);
618
619 // issues getGraphicsConfiguration() and creates the native peer
620 super.addNotify();
621
622 // after native peer is valid: Windows
623 if( OSType.WINDOWS == Platform.getOSType() ) {
624 backgroundEraseControl.disable(this);
625 }
626
627 createJAWTDrawableAndContext();
628
629 // init drawable by paint/display makes the init sequence more equal
630 // for all launch flavors (applet/javaws/..)
631 // validateGLDrawable();
632 }
633 awtWindowClosingProtocol.addClosingListener();
634
635 if(DEBUG) {
636 System.err.println(getThreadName()+": Info: addNotify - end");
637 }
638 } finally {
639 _lock.unlock();
640 }
641 }
642
643 /**
644 * {@inheritDoc}
645 * <p>
646 * This implementation returns false, i.e. not supporting manual change of pixel-scale.
647 * </p>
648 */
649 @Override
650 public final boolean canSetSurfaceScale() { return false; }
651
652 /**
653 * {@inheritDoc}
654 * <p>
655 * Ignored for an AWT widget since pixelScale is dictated by AWT mechanisms.
656 * </p>
657 */
658 @Override
659 public final boolean setSurfaceScale(final float[] pixelScale) {
660 return false;
661 }
662
663 private final boolean updatePixelScale() {
664 if( jawtWindow.hasPixelScaleChanged() ) {
665 if(DEBUG) {
666 final float[] old = { hasPixelScale[0], hasPixelScale[1] };
667 jawtWindow.getCurrentSurfaceScale(hasPixelScale);
668 System.err.printf("GLCanvas.updatePixelScale hasPixelScale %.2f %.2f -> %.2f %.2f\n", old[0], old[1], hasPixelScale[0], hasPixelScale[1]);
669 } else {
670 jawtWindow.getCurrentSurfaceScale(hasPixelScale);
671 }
672 return true;
673 } else {
674 return false;
675 }
676 }
677
678 /**
679 * {@inheritDoc}
680 * <p>
681 * Returns {@link ScalableSurface#AUTOMAX_PIXELSCALE}, always.
682 * </p>
683 */
684 @Override
685 public final float[] getRequestedSurfaceScale(final float[] result) {
688 return result;
689 }
690
691 @Override
692 public final float[] getCurrentSurfaceScale(final float[] result) {
693 System.arraycopy(hasPixelScale, 0, result, 0, 2);
694 return result;
695 }
696
697 /**
698 * {@inheritDoc}
699 * <p>
700 * Returns 1.0, always.
701 * </p>
702 */
703 @Override
704 public float[] getMinimumSurfaceScale(final float[] result) {
705 result[0] = 1f;
706 result[1] = 1f;
707 return result;
708 }
709
710 /**
711 * {@inheritDoc}
712 * <p>
713 * Returns {@link #getCurrentSurfaceScale(float[])}.
714 * </p>
715 */
716 @Override
717 public float[] getMaximumSurfaceScale(final float[] result) {
718 System.arraycopy(hasPixelScale, 0, result, 0, 2);
719 return result;
720 }
721
722 private void createJAWTDrawableAndContext() {
723 if ( !Beans.isDesignTime() ) {
724
725 /**
726 * FIXME: Bug 1373, 1374: Implement general High-DPI for even non native DPI toolkit aware platforms (Linux, Windows)
727 JAWTUtil.getPixelScale(awtConfig.getAWTGraphicsConfiguration(), minPixelScale, maxPixelScale);
728 SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG ? getClass().getSimpleName() : null);
729 */
730 jawtWindow = (JAWTWindow) NativeWindowFactory.getNativeWindow(this, awtConfig);
731 jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
732 jawtWindow.lockSurface();
733 try {
734 drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow);
735 createContextImpl(drawable);
736 jawtWindow.getCurrentSurfaceScale(hasPixelScale);
737 } finally {
738 jawtWindow.unlockSurface();
739 }
740 }
741 }
742 private boolean createContextImpl(final GLDrawable drawable) {
743 final GLContext[] shareWith = { null };
744 if( !helper.isSharedGLContextPending(shareWith) ) {
745 context = (GLContextImpl) drawable.createContext(shareWith[0]);
746 context.setContextCreationFlags(additionalCtxCreationFlags);
747 if(DEBUG) {
748 System.err.println(getThreadName()+": Context created: has shared "+(null != shareWith[0]));
749 }
750 return true;
751 } else {
752 if(DEBUG) {
753 System.err.println(getThreadName()+": Context !created: pending share");
754 }
755 return false;
756 }
757 }
758
759 private boolean validateGLDrawable() {
760 if( Beans.isDesignTime() || !isDisplayable() ) {
761 return false; // early out!
762 }
763 final GLDrawable _drawable = drawable;
764 if ( null != _drawable ) {
765 boolean res = _drawable.isRealized();
766 if( !res ) {
767 // re-try drawable creation
768 if( 0 >= _drawable.getSurfaceWidth() || 0 >= _drawable.getSurfaceHeight() ) {
769 return false; // early out!
770 }
771 setRealized(true);
772 res = _drawable.isRealized();
773 if(DEBUG) {
774 System.err.println(getThreadName()+": Realized Drawable: isRealized "+res+", "+_drawable.toString());
775 // Thread.dumpStack();
776 }
777 }
778 if( res && null == context ) {
779 // re-try context creation
780 res = createContextImpl(_drawable); // pending creation.
781 }
782 return res;
783 }
784 return false;
785 }
786
787 private void setAWTGraphicsConfiguration(final AWTGraphicsConfiguration config) {
788 // Cache awtConfig
789 awtConfig = config;
790 if( null != jawtWindow ) {
791 // Notify JAWTWindow ..
792 jawtWindow.setAWTGraphicsConfiguration(config);
793 }
794 }
795
796 /** <p>Overridden to track when this component is removed from a
797 container. Subclasses which override this method must call
798 super.removeNotify() in their removeNotify() method in order to
799 function properly. </p>
800 <p>User shall not call this method outside of EDT, read the AWT/Swing specs
801 about this.</p>
802 <B>Overrides:</B>
803 <DL><DD><CODE>removeNotify</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
804 @SuppressWarnings("deprecation")
805 @Override
806 public void removeNotify() {
807 if(DEBUG) {
808 System.err.println(getThreadName()+": Info: removeNotify - start");
809 // Thread.dumpStack();
810 }
811
812 awtWindowClosingProtocol.removeClosingListener();
813
814 if( Beans.isDesignTime() ) {
815 super.removeNotify();
816 } else {
817 try {
818 destroyImpl( true );
819 } finally {
820 super.removeNotify();
821 }
822 }
823 if(DEBUG) {
824 System.err.println(getThreadName()+": Info: removeNotify - end");
825 }
826 }
827
828 /** Overridden to cause {@link GLDrawableHelper#reshape} to be
829 called on all registered {@link GLEventListener}s. Subclasses
830 which override this method must call super.reshape() in
831 their reshape() method in order to function properly. <P>
832
833 <B>Overrides:</B>
834 <DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */
835 @SuppressWarnings("deprecation")
836 @Override
837 public void reshape(final int x, final int y, final int width, final int height) {
838 synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape
839 super.reshape(x, y, width, height);
840 reshapeImpl(width, height);
841 }
842 }
843 private void reshapeImpl(final int width, final int height) {
844 final int scaledWidth = SurfaceScaleUtils.scale(width, hasPixelScale[0]);
845 final int scaledHeight = SurfaceScaleUtils.scale(height, hasPixelScale[1]);
846
847 if(DEBUG) {
848 final NativeSurface ns = getNativeSurface();
849 final long nsH = null != ns ? ns.getSurfaceHandle() : 0;
850 System.err.println(getThreadName()+": GLCanvas.reshape.0 "+this.getName()+" resize"+(printActive?"WithinPrint":"")+
851 " [ this "+getWidth()+"x"+getHeight()+", pixelScale "+getPixelScaleStr()+
852 "] -> "+(printActive?"[skipped] ":"") + width+"x"+height+" * "+getPixelScaleStr()+" -> "+scaledWidth+"x"+scaledHeight+
853 " - surfaceHandle 0x"+Long.toHexString(nsH));
854 // Thread.dumpStack();
855 }
856 if( validateGLDrawable() && !printActive ) {
857 final GLDrawableImpl _drawable = drawable;
858 if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
859 final RecursiveLock _lock = lock;
860 _lock.lock();
861 try {
862 final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, scaledWidth, scaledHeight);
863 if(_drawable != _drawableNew) {
864 // write back
865 drawable = _drawableNew;
866 }
867 } finally {
868 _lock.unlock();
869 }
870 }
871 sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
872 }
873 }
874
875 /**
876 * Overridden from Canvas to prevent the AWT's clearing of the
877 * canvas from interfering with the OpenGL rendering.
878 */
879 @Override
880 public void update(final Graphics g) {
881 paint(g);
882 }
883
884 private volatile boolean printActive = false;
885 private GLAnimatorControl printAnimator = null;
886 private GLAutoDrawable printGLAD = null;
887 private AWTTilePainter printAWTTiles = null;
888
889 @Override
890 public void setupPrint(final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight) {
891 printActive = true;
892 final int componentCount = isOpaque() ? 3 : 4;
893 final TileRenderer printRenderer = new TileRenderer();
894 printAWTTiles = new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight, DEBUG);
895 AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, setupPrintOnEDT);
896 }
897 private final Runnable setupPrintOnEDT = new Runnable() {
898 @Override
899 public void run() {
900 final RecursiveLock _lock = lock;
901 _lock.lock();
902 try {
903 if( !validateGLDrawable() ) {
904 if(DEBUG) {
905 System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, drawable not valid yet");
906 }
907 printActive = false;
908 return; // not yet available ..
909 }
910 if( !isVisible() ) {
911 if(DEBUG) {
912 System.err.println(getThreadName()+": Info: GLCanvas setupPrint - skipped GL render, canvas not visible");
913 }
914 printActive = false;
915 return; // not yet available ..
916 }
917 sendReshape = false; // clear reshape flag
918 printAnimator = helper.getAnimator();
919 if( null != printAnimator ) {
920 printAnimator.remove(GLCanvas.this);
921 }
922 printGLAD = GLCanvas.this; // _not_ default, shall be replaced by offscreen GLAD
923 final GLCapabilitiesImmutable gladCaps = getChosenGLCapabilities();
924 final int printNumSamples = printAWTTiles.getNumSamples(gladCaps);
925 GLDrawable printDrawable = printGLAD.getDelegatedDrawable();
926 final boolean reqNewGLADSamples = printNumSamples != gladCaps.getNumSamples();
927 final boolean reqNewGLADSize = printAWTTiles.customTileWidth != -1 && printAWTTiles.customTileWidth != printDrawable.getSurfaceWidth() ||
928 printAWTTiles.customTileHeight != -1 && printAWTTiles.customTileHeight != printDrawable.getSurfaceHeight();
929 final boolean reqNewGLADOnscrn = gladCaps.isOnscreen();
930
931 final GLCapabilities newGLADCaps = (GLCapabilities)gladCaps.cloneMutable();
932 newGLADCaps.setDoubleBuffered(false);
933 newGLADCaps.setOnscreen(false);
934 if( printNumSamples != newGLADCaps.getNumSamples() ) {
935 newGLADCaps.setSampleBuffers(0 < printNumSamples);
936 newGLADCaps.setNumSamples(printNumSamples);
937 }
938 final boolean reqNewGLADSafe = GLDrawableUtil.isSwapGLContextSafe(getRequestedGLCapabilities(), gladCaps, newGLADCaps);
939
940 final boolean reqNewGLAD = ( reqNewGLADOnscrn || reqNewGLADSamples || reqNewGLADSize ) && reqNewGLADSafe;
941
942 if( DEBUG ) {
943 System.err.println("AWT print.setup: reqNewGLAD "+reqNewGLAD+"[ onscreen "+reqNewGLADOnscrn+", samples "+reqNewGLADSamples+", size "+reqNewGLADSize+", safe "+reqNewGLADSafe+"], "+
944 ", drawableSize "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+
945 ", customTileSize "+printAWTTiles.customTileWidth+"x"+printAWTTiles.customTileHeight+
946 ", scaleMat "+printAWTTiles.scaleMatX+" x "+printAWTTiles.scaleMatY+
947 ", numSamples "+printAWTTiles.customNumSamples+" -> "+printNumSamples+", printAnimator "+printAnimator);
948 }
949 if( reqNewGLAD ) {
950 final GLDrawableFactory factory = GLDrawableFactory.getFactory(newGLADCaps.getGLProfile());
951 GLOffscreenAutoDrawable offGLAD = null;
952 try {
953 offGLAD = factory.createOffscreenAutoDrawable(null, newGLADCaps, null,
954 printAWTTiles.customTileWidth != -1 ? printAWTTiles.customTileWidth : DEFAULT_PRINT_TILE_SIZE,
955 printAWTTiles.customTileHeight != -1 ? printAWTTiles.customTileHeight : DEFAULT_PRINT_TILE_SIZE);
956 } catch (final GLException gle) {
957 if( DEBUG ) {
958 System.err.println("Caught: "+gle.getMessage());
959 gle.printStackTrace();
960 }
961 }
962 if( null != offGLAD ) {
963 printGLAD = offGLAD;
964 GLDrawableUtil.swapGLContextAndAllGLEventListener(GLCanvas.this, printGLAD);
965 printDrawable = printGLAD.getDelegatedDrawable();
966 }
967 }
968 printAWTTiles.setGLOrientation(printGLAD.isGLOriented(), printGLAD.isGLOriented());
969 printAWTTiles.renderer.setTileSize(printDrawable.getSurfaceWidth(), printDrawable.getSurfaceHeight(), 0);
970 printAWTTiles.renderer.attachAutoDrawable(printGLAD);
971 if( DEBUG ) {
972 System.err.println("AWT print.setup "+printAWTTiles);
973 System.err.println("AWT print.setup AA "+printNumSamples+", "+newGLADCaps);
974 System.err.println("AWT print.setup printGLAD: "+printGLAD.getSurfaceWidth()+"x"+printGLAD.getSurfaceHeight()+", "+printGLAD);
975 System.err.println("AWT print.setup printDraw: "+printDrawable.getSurfaceWidth()+"x"+printDrawable.getSurfaceHeight()+", "+printDrawable);
976 }
977 } finally {
978 _lock.unlock();
979 }
980 }
981 };
982
983 @Override
984 public void releasePrint() {
985 if( !printActive || null == printGLAD ) {
986 throw new IllegalStateException("setupPrint() not called");
987 }
988 sendReshape = false; // clear reshape flag
989 AWTEDTExecutor.singleton.invoke(getTreeLock(), true /* allowOnNonEDT */, true /* wait */, releasePrintOnEDT);
990 }
991 private final Runnable releasePrintOnEDT = new Runnable() {
992 @Override
993 public void run() {
994 final RecursiveLock _lock = lock;
995 _lock.lock();
996 try {
997 if( DEBUG ) {
998 System.err.println("AWT print.release "+printAWTTiles);
999 }
1000 printAWTTiles.dispose();
1001 printAWTTiles= null;
1002 if( printGLAD != GLCanvas.this ) {
1003 GLDrawableUtil.swapGLContextAndAllGLEventListener(printGLAD, GLCanvas.this);
1004 printGLAD.destroy();
1005 }
1006 printGLAD = null;
1007 if( null != printAnimator ) {
1008 printAnimator.add(GLCanvas.this);
1009 printAnimator = null;
1010 }
1011 sendReshape = true; // trigger reshape, i.e. gl-viewport and -listener - this component might got resized!
1012 printActive = false;
1013 display();
1014 } finally {
1015 _lock.unlock();
1016 }
1017 }
1018 };
1019
1020 @Override
1021 public void print(final Graphics graphics) {
1022 if( !printActive || null == printGLAD ) {
1023 throw new IllegalStateException("setupPrint() not called");
1024 }
1025 if(DEBUG && !EventQueue.isDispatchThread()) {
1026 System.err.println(getThreadName()+": Warning: GLCanvas print - not called from AWT-EDT");
1027 // we cannot dispatch print on AWT-EDT due to printing internal locking ..
1028 }
1029 sendReshape = false; // clear reshape flag
1030
1031 final Graphics2D g2d = (Graphics2D)graphics;
1032 try {
1033 printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
1034 final TileRenderer tileRenderer = printAWTTiles.renderer;
1035 if( DEBUG ) {
1036 System.err.println("AWT print.0: "+tileRenderer);
1037 }
1038 if( !tileRenderer.eot() ) {
1039 try {
1040 do {
1041 if( printGLAD != GLCanvas.this ) {
1042 tileRenderer.display();
1043 } else {
1044 Threading.invoke(true, displayOnEDTAction, getTreeLock());
1045 }
1046 } while ( !tileRenderer.eot() );
1047 if( DEBUG ) {
1048 System.err.println("AWT print.1: "+printAWTTiles);
1049 }
1050 } finally {
1051 tileRenderer.reset();
1052 printAWTTiles.resetGraphics2D();
1053 }
1054 }
1055 } catch (final NoninvertibleTransformException nte) {
1056 System.err.println("Caught: Inversion failed of: "+g2d.getTransform());
1057 nte.printStackTrace();
1058 }
1059 if( DEBUG ) {
1060 System.err.println("AWT print.X: "+printAWTTiles);
1061 }
1062 }
1063
1064 @Override
1065 public void addGLEventListener(final GLEventListener listener) {
1066 helper.addGLEventListener(listener);
1067 }
1068
1069 @Override
1070 public void addGLEventListener(final int index, final GLEventListener listener) throws IndexOutOfBoundsException {
1071 helper.addGLEventListener(index, listener);
1072 }
1073
1074 @Override
1076 return helper.getGLEventListenerCount();
1077 }
1078
1079 @Override
1080 public GLEventListener getGLEventListener(final int index) throws IndexOutOfBoundsException {
1081 return helper.getGLEventListener(index);
1082 }
1083
1084 @Override
1086 return helper.areAllGLEventListenerInitialized();
1087 }
1088
1089 @Override
1090 public boolean getGLEventListenerInitState(final GLEventListener listener) {
1091 return helper.getGLEventListenerInitState(listener);
1092 }
1093
1094 @Override
1095 public void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized) {
1096 helper.setGLEventListenerInitState(listener, initialized);
1097 }
1098
1099 @Override
1100 public GLEventListener disposeGLEventListener(final GLEventListener listener, final boolean remove) {
1101 final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
1102 Threading.invoke(true, r, getTreeLock());
1103 return r.listener;
1104 }
1105
1106 @Override
1108 return helper.removeGLEventListener(listener);
1109 }
1110
1111 @Override
1112 public void setAnimator(final GLAnimatorControl animatorControl) {
1113 helper.setAnimator(animatorControl);
1114 }
1115
1116 @Override
1118 return helper.getAnimator();
1119 }
1120
1121 @Override
1122 public final Thread setExclusiveContextThread(final Thread t) throws GLException {
1123 return helper.setExclusiveContextThread(t, context);
1124 }
1125
1126 @Override
1127 public final Thread getExclusiveContextThread() {
1128 return helper.getExclusiveContextThread();
1129 }
1130
1131 @Override
1132 public boolean invoke(final boolean wait, final GLRunnable glRunnable) throws IllegalStateException {
1133 return helper.invoke(this, wait, glRunnable);
1134 }
1135
1136 @Override
1137 public boolean invoke(final boolean wait, final List<GLRunnable> glRunnables) throws IllegalStateException {
1138 return helper.invoke(this, wait, glRunnables);
1139 }
1140
1141 @Override
1142 public void flushGLRunnables() {
1143 helper.flushGLRunnables();
1144 }
1145
1146 @Override
1147 public GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx) {
1148 final RecursiveLock _lock = lock;
1149 _lock.lock();
1150 try {
1151 final GLContext oldCtx = context;
1152 GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
1153 context=(GLContextImpl)newCtx;
1154 return oldCtx;
1155 } finally {
1156 _lock.unlock();
1157 }
1158 }
1159
1160 @Override
1162 return drawable;
1163 }
1164
1165 @Override
1167 return context;
1168 }
1169
1170 @Override
1171 public GL getGL() {
1172 if( Beans.isDesignTime() ) {
1173 return null;
1174 }
1175 final GLContext _context = context;
1176 return (_context == null) ? null : _context.getGL();
1177 }
1178
1179 @Override
1180 public GL setGL(final GL gl) {
1181 final GLContext _context = context;
1182 if (_context != null) {
1183 _context.setGL(gl);
1184 return gl;
1185 }
1186 return null;
1187 }
1188
1189
1190 @Override
1191 public void setAutoSwapBufferMode(final boolean onOrOff) {
1192 helper.setAutoSwapBufferMode(onOrOff);
1193 }
1194
1195 @Override
1196 public boolean getAutoSwapBufferMode() {
1197 return helper.getAutoSwapBufferMode();
1198 }
1199
1200 @Override
1201 public void swapBuffers() {
1202 Threading.invoke(true, swapBuffersOnEDTAction, getTreeLock());
1203 }
1204
1205 @Override
1206 public void setContextCreationFlags(final int flags) {
1207 additionalCtxCreationFlags = flags;
1208 final GLContext _context = context;
1209 if(null != _context) {
1210 _context.setContextCreationFlags(additionalCtxCreationFlags);
1211 }
1212 }
1213
1214 @Override
1216 return additionalCtxCreationFlags;
1217 }
1218
1219 @Override
1221 return capsReqUser.getGLProfile();
1222 }
1223
1224 @Override
1226 if( Beans.isDesignTime() ) {
1227 return capsReqUser;
1228 } else if( null == awtConfig ) {
1229 throw new GLException("No AWTGraphicsConfiguration: "+this);
1230 }
1232 }
1233
1234 @Override
1236 if( null == awtConfig ) {
1237 return capsReqUser;
1238 }
1240 }
1241
1242 @Override
1243 public int getSurfaceWidth() {
1244 return SurfaceScaleUtils.scale(getWidth(), hasPixelScale[0]);
1245 }
1246
1247 @Override
1248 public int getSurfaceHeight() {
1249 return SurfaceScaleUtils.scale(getHeight(), hasPixelScale[1]);
1250 }
1251
1252 @Override
1253 public boolean isGLOriented() {
1254 final GLDrawable _drawable = drawable;
1255 return null != _drawable ? _drawable.isGLOriented() : true;
1256 }
1257
1258 @Override
1260 final GLDrawable _drawable = drawable;
1261 return (null != _drawable) ? _drawable.getNativeSurface() : null;
1262 }
1263
1264 @Override
1265 public long getHandle() {
1266 final GLDrawable _drawable = drawable;
1267 return (null != _drawable) ? _drawable.getHandle() : 0;
1268 }
1269
1270 @Override
1272 final GLDrawable _drawable = drawable;
1273 return (null != _drawable) ? _drawable.getFactory() : null;
1274 }
1275
1276 @Override
1277 public String toString() {
1278 final GLDrawable _drawable = drawable;
1279 final int dw = (null!=_drawable) ? _drawable.getSurfaceWidth() : -1;
1280 final int dh = (null!=_drawable) ? _drawable.getSurfaceHeight() : -1;
1281
1282 return "AWT-GLCanvas[Realized "+isRealized()+
1283 ",\n\t"+((null!=_drawable)?_drawable.getClass().getName():"null-drawable")+
1284 ",\n\tFactory "+getFactory()+
1285 ",\n\thandle 0x"+Long.toHexString(getHandle())+
1286 ",\n\tDrawable size "+dw+"x"+dh+" surface["+getSurfaceWidth()+"x"+getSurfaceHeight()+"]"+
1287 ",\n\tAWT[pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+
1288 ",\n\tvisible "+isVisible()+", displayable "+isDisplayable()+", showing "+isShowing+
1289 ",\n\t"+awtConfig+"]]";
1290 }
1291
1292 //----------------------------------------------------------------------
1293 // Internals only below this point
1294 //
1295
1296 private final String getPixelScaleStr() { return "["+hasPixelScale[0]+", "+hasPixelScale[1]+"]"; }
1297
1298 private final Runnable destroyOnEDTAction = new Runnable() {
1299 @Override
1300 public void run() {
1301 final RecursiveLock _lock = lock;
1302 _lock.lock();
1303 try {
1304 final GLAnimatorControl animator = getAnimator();
1305
1306 if(DEBUG) {
1307 System.err.println(getThreadName()+": Info: destroyOnEDTAction() - START, hasContext " +
1308 (null!=context) + ", hasDrawable " + (null!=drawable)+", "+animator);
1309 // Thread.dumpStack();
1310 }
1311
1312 final boolean animatorPaused;
1313 if(null!=animator) {
1314 // can't remove us from animator for recreational addNotify()
1315 animatorPaused = animator.pause();
1316 } else {
1317 animatorPaused = false;
1318 }
1319
1320 GLException exceptionOnDisposeGL = null;
1321
1322 // OLS will be detached by disposeGL's context destruction below
1323 if( null != context ) {
1324 if( context.isCreated() ) {
1325 try {
1326 helper.disposeGL(GLCanvas.this, context, true);
1327 if(DEBUG) {
1328 System.err.println(getThreadName()+": destroyOnEDTAction() - post ctx: "+context);
1329 }
1330 } catch (final GLException gle) {
1331 exceptionOnDisposeGL = gle;
1332 }
1333 }
1334 context = null;
1335 }
1336
1337 Throwable exceptionOnUnrealize = null;
1338 if( null != drawable ) {
1339 try {
1340 drawable.setRealized(false);
1341 if(DEBUG) {
1342 System.err.println(getThreadName()+": destroyOnEDTAction() - post drawable: "+drawable);
1343 }
1344 } catch( final Throwable re ) {
1345 exceptionOnUnrealize = re;
1346 }
1347 drawable = null;
1348 }
1349
1350 if(animatorPaused) {
1351 animator.resume();
1352 }
1353
1354 // throw exception in order of occurrence ..
1355 if( null != exceptionOnDisposeGL ) {
1356 throw exceptionOnDisposeGL;
1357 }
1358 if( null != exceptionOnUnrealize ) {
1359 throw GLException.newGLException(exceptionOnUnrealize);
1360 }
1361
1362 if(DEBUG) {
1363 System.err.println(getThreadName()+": dispose() - END, animator "+animator);
1364 }
1365
1366 } finally {
1367 _lock.unlock();
1368 }
1369 }
1370 };
1371
1372 /**
1373 * Disposes the JAWTWindow and AbstractGraphicsDevice within EDT,
1374 * since resources created (X11: Display), must be destroyed in the same thread, where they have been created.
1375 * <p>
1376 * The drawable and context handle are null'ed as well, assuming {@link #destroy()} has been called already.
1377 * </p>
1378 *
1379 * @see #chooseGraphicsConfiguration(com.jogamp.opengl.GLCapabilitiesImmutable, com.jogamp.opengl.GLCapabilitiesImmutable, com.jogamp.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice)
1380 */
1381 private final Runnable disposeJAWTWindowAndAWTDeviceOnEDT = new Runnable() {
1382 @Override
1383 public void run() {
1384 context=null;
1385 drawable=null;
1386
1387 if( null != jawtWindow ) {
1388 jawtWindow.destroy();
1389 if(DEBUG) {
1390 System.err.println(getThreadName()+": GLCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post JAWTWindow: "+jawtWindow);
1391 }
1392 jawtWindow=null;
1393 }
1394 hasPixelScale[0] = ScalableSurface.IDENTITY_PIXELSCALE;
1395 hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
1396
1397 if(null != awtConfig) {
1398 final AbstractGraphicsConfiguration aconfig = awtConfig.getNativeGraphicsConfiguration();
1399 final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
1400 final String adeviceMsg;
1401 if(DEBUG) {
1402 adeviceMsg = adevice.toString();
1403 } else {
1404 adeviceMsg = null;
1405 }
1406 final boolean closed = adevice.close();
1407 if(DEBUG) {
1408 System.err.println(getThreadName()+": GLCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post GraphicsDevice: "+adeviceMsg+", result: "+closed);
1409 }
1410 }
1411 awtConfig = null;
1412 }
1413 };
1414
1415 private final Runnable initAction = new Runnable() {
1416 @Override
1417 public void run() {
1418 helper.init(GLCanvas.this, !sendReshape);
1419 }
1420 };
1421
1422 private final Runnable displayAction = new Runnable() {
1423 @Override
1424 public void run() {
1425 if (sendReshape) {
1426 if(DEBUG) {
1427 System.err.println(getThreadName()+": Reshape: "+getSurfaceWidth()+"x"+getSurfaceHeight());
1428 }
1429 // Note: we ignore the given x and y within the parent component
1430 // since we are drawing directly into this heavyweight component.
1431 helper.reshape(GLCanvas.this, 0, 0, getSurfaceWidth(), getSurfaceHeight());
1432 sendReshape = false;
1433 }
1434
1435 helper.display(GLCanvas.this);
1436 }
1437 };
1438
1439 private final Runnable displayOnEDTAction = new Runnable() {
1440 @Override
1441 public void run() {
1442 final RecursiveLock _lock = lock;
1443 _lock.lock();
1444 try {
1445 if( null != drawable && drawable.isRealized() ) {
1446 if( GLCanvas.this.updatePixelScale() ) {
1447 GLCanvas.this.reshapeImpl(getWidth(), getHeight());
1448 }
1449 helper.invokeGL(drawable, context, displayAction, initAction);
1450 }
1451 } finally {
1452 _lock.unlock();
1453 }
1454 }
1455 };
1456
1457 private final Runnable swapBuffersOnEDTAction = new Runnable() {
1458 @Override
1459 public void run() {
1460 final RecursiveLock _lock = lock;
1461 _lock.lock();
1462 try {
1463 if( null != drawable && drawable.isRealized() ) {
1464 drawable.swapBuffers();
1465 }
1466 } finally {
1467 _lock.unlock();
1468 }
1469 }
1470 };
1471
1472 private class DisposeGLEventListenerAction implements Runnable {
1473 GLEventListener listener;
1474 private final boolean remove;
1475 private DisposeGLEventListenerAction(final GLEventListener listener, final boolean remove) {
1476 this.listener = listener;
1477 this.remove = remove;
1478 }
1479
1480 @Override
1481 public void run() {
1482 final RecursiveLock _lock = lock;
1483 _lock.lock();
1484 try {
1485 listener = helper.disposeGLEventListener(GLCanvas.this, drawable, context, listener, remove);
1486 } finally {
1487 _lock.unlock();
1488 }
1489 }
1490 };
1491
1492 /**
1493 * Issues the GraphicsConfigurationFactory's choosing facility within EDT,
1494 * since resources created (X11: Display), must be destroyed in the same thread, where they have been created.
1495 *
1496 * @param capsChosen
1497 * @param capsRequested
1498 * @param chooser
1499 * @param device
1500 * @return the chosen AWTGraphicsConfiguration
1501 *
1502 * @see #disposeJAWTWindowAndAWTDeviceOnEDT
1503 */
1504 private AWTGraphicsConfiguration chooseGraphicsConfiguration(final GLCapabilitiesImmutable capsChosen,
1505 final GLCapabilitiesImmutable capsRequested,
1506 final GLCapabilitiesChooser chooser,
1507 final GraphicsDevice device) {
1508 // Make GLCanvas behave better in NetBeans GUI builder
1509 if( Beans.isDesignTime() ) {
1510 return null;
1511 }
1512 if( null == device ) {
1513 throw new GLException("Error: NULL AWT GraphicsDevice");
1514 }
1515 final AbstractGraphicsScreen aScreen = AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT);
1516 AWTGraphicsConfiguration config = null;
1517
1518 if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) {
1519 config = (AWTGraphicsConfiguration)
1520 GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
1521 capsRequested,
1522 chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
1523 } else {
1524 try {
1525 final ArrayList<AWTGraphicsConfiguration> bucket = new ArrayList<AWTGraphicsConfiguration>(1);
1526 EventQueue.invokeAndWait(new Runnable() {
1527 @Override
1528 public void run() {
1529 final AWTGraphicsConfiguration c = (AWTGraphicsConfiguration)
1530 GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
1531 capsRequested,
1532 chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
1533 bucket.add(c);
1534 }
1535 });
1536 config = ( bucket.size() > 0 ) ? bucket.get(0) : null ;
1537 } catch (final InvocationTargetException e) {
1538 throw new GLException(e.getTargetException());
1539 } catch (final InterruptedException e) {
1540 throw new GLException(e);
1541 }
1542 }
1543
1544 if ( null == config ) {
1545 throw new GLException("Error: Couldn't fetch AWTGraphicsConfiguration");
1546 }
1547
1548 return config;
1549 }
1550
1551 protected static String getThreadName() { return Thread.currentThread().getName(); }
1552
1553 /**
1554 * A most simple JOGL AWT test entry
1555 */
1556 public static void main(final String args[]) {
1557 System.err.println(VersionUtil.getPlatformInfo());
1558 System.err.println(GlueGenVersion.getInstance());
1559 // System.err.println(NativeWindowVersion.getInstance());
1560 System.err.println(JoglVersion.getInstance());
1561
1562 System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
1563
1565 final Frame frame = new Frame("JOGL AWT Test");
1566
1567 final GLCanvas glCanvas = new GLCanvas(caps);
1568 frame.add(glCanvas);
1569 frame.setSize(128, 128);
1570
1571 glCanvas.addGLEventListener(new GLEventListener() {
1572 @Override
1573 public void init(final GLAutoDrawable drawable) {
1574 final GL gl = drawable.getGL();
1575 System.err.println(JoglVersion.getGLInfo(gl, null));
1576 }
1577 @Override
1578 public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { }
1579 @Override
1580 public void display(final GLAutoDrawable drawable) { }
1581 @Override
1582 public void dispose(final GLAutoDrawable drawable) { }
1583 });
1584
1585 try {
1586 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
1587 @Override
1588 public void run() {
1589 frame.setVisible(true);
1590 }});
1591 } catch (final Throwable t) {
1592 t.printStackTrace();
1593 }
1594 glCanvas.display();
1595 try {
1596 javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
1597 @Override
1598 public void run() {
1599 frame.dispose();
1600 }});
1601 } catch (final Throwable t) {
1602 t.printStackTrace();
1603 }
1604 }
1605
1606}
final CapabilitiesImmutable getRequestedCapabilities()
Return the capabilities used to choose this graphics configuration.
final CapabilitiesImmutable getChosenCapabilities()
Return the capabilities reflecting this graphics configuration, which may differ from the capabilitie...
Provides a pluggable mechanism for arbitrary window toolkits to adapt their components to the NativeW...
static NativeWindow getNativeWindow(final Object winObj, final AbstractGraphicsConfiguration config)
Converts the given window object and it's AbstractGraphicsConfiguration into a NativeWindow which can...
A wrapper for an AWT GraphicsConfiguration allowing it to be handled in a toolkit-independent manner.
GraphicsConfiguration getAWTGraphicsConfiguration()
Return the AWT GraphicsConfiguration.
AbstractGraphicsConfiguration getNativeGraphicsConfiguration()
In case the implementation utilizes a delegation pattern to wrap abstract toolkits,...
final WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op)
final boolean addClosingListener()
Adds this closing listener to the components Window if exist and only one time.
final float[] getCurrentSurfaceScale(final float[] result)
Returns the current pixel scale of the associated NativeSurface.
void destroy()
Destroys this window incl.
final boolean isOffscreenLayerSurfaceEnabled()
Returns true if this instance uses an offscreen layer, otherwise false.
final int lockSurface()
Lock the surface of this native window.
void setShallUseOffscreenLayer(final boolean v)
Request an offscreen layer, if supported.
final void unlockSurface()
Unlock the surface of this native window.
final void setAWTGraphicsConfiguration(final AWTGraphicsConfiguration config)
Set a new AWTGraphicsConfiguration instance, as required if upstream component's GraphicsConfiguratio...
Specifies a set of OpenGL capabilities.
Abstraction for an OpenGL rendering context.
Definition: GLContext.java:74
abstract void setContextCreationFlags(int flags)
abstract GL setGL(GL gl)
Sets the GL pipeline object for this GLContext.
abstract GL getGL()
Returns the GL pipeline object for this GLContext.
final RecursiveLock lock
Definition: GLContext.java:222
static GLDrawableFactory getFactory(final GLProfile glProfile)
Returns the sole GLDrawableFactory instance.
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
Specifies the the OpenGL profile.
Definition: GLProfile.java:77
static GLProfile getDefault(final AbstractGraphicsDevice device)
Returns a default GLProfile object, reflecting the best for the running platform.
Definition: GLProfile.java:739
static AbstractGraphicsDevice getDefaultDevice()
static JoglVersion getInstance()
static StringBuilder getGLInfo(final GL gl, final StringBuilder sb)
static StringBuilder getDefaultOpenGLInfo(AbstractGraphicsDevice device, StringBuilder sb, final boolean withCapabilitiesInfo)
This API provides access to the threading model for the implementation of the classes in this package...
Definition: Threading.java:119
static final boolean isOpenGLThread()
Indicates whether the current thread is capable of performing OpenGL-related work.
Definition: Threading.java:187
static final void invoke(final boolean wait, final Runnable r, final Object lock)
If not isOpenGLThread() and the lock is not being hold by this thread, invoke Runnable r on the OpenG...
Definition: Threading.java:218
A heavyweight AWT component which provides OpenGL rendering support.
Definition: GLCanvas.java:170
final float[] getRequestedSurfaceScale(final float[] result)
Returns the requested pixel scale of the associated NativeSurface.If canSetSurfaceScale() returns fal...
Definition: GLCanvas.java:685
final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable)
Specifies an GLAutoDrawable, which OpenGL context shall be shared by this GLAutoDrawable's GLContext.
Definition: GLCanvas.java:288
void update(final Graphics g)
Overridden from Canvas to prevent the AWT's clearing of the canvas from interfering with the OpenGL r...
Definition: GLCanvas.java:880
boolean isRealized()
Returns true if this drawable is realized, otherwise false.
Definition: GLCanvas.java:480
void destroyImpl(final boolean destroyJAWTWindowAndAWTDevice)
Definition: GLCanvas.java:525
GLEventListener disposeGLEventListener(final GLEventListener listener, final boolean remove)
Disposes the given listener via dispose(..) if it has been initialized and added to this queue.
Definition: GLCanvas.java:1100
void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized)
Sets the given listener's initialized state.
Definition: GLCanvas.java:1095
GL setGL(final GL gl)
Sets the GL pipeline object this GLAutoDrawable uses.
Definition: GLCanvas.java:1180
final Thread setExclusiveContextThread(final Thread t)
Dedicates this instance's GLContext to the given thread.
Definition: GLCanvas.java:1122
GLCapabilitiesImmutable getRequestedGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the user requested OpenGL capabilities (pixel fo...
Definition: GLCanvas.java:1235
GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx)
Associate the new context, newtCtx, to this auto-drawable.
Definition: GLCanvas.java:1147
WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op)
Definition: GLCanvas.java:491
void addNotify()
Overridden to track when this component is added to a container.
Definition: GLCanvas.java:572
GLDrawableFactory getFactory()
Return the GLDrawableFactory being used to create this instance.
Definition: GLCanvas.java:1271
void print(final Graphics graphics)
Definition: GLCanvas.java:1021
void reshape(final int x, final int y, final int width, final int height)
Overridden to cause GLDrawableHelper#reshape to be called on all registered GLEventListeners.
Definition: GLCanvas.java:837
GLEventListener getGLEventListener(final int index)
Returns the GLEventListener at the given index of this drawable queue.
Definition: GLCanvas.java:1080
GLContext getContext()
Returns the context associated with this drawable.
Definition: GLCanvas.java:1166
GL getGL()
Returns the GL pipeline object this GLAutoDrawable uses.
Definition: GLCanvas.java:1171
GLProfile getGLProfile()
Fetches the GLProfile for this drawable.
Definition: GLCanvas.java:1220
boolean areAllGLEventListenerInitialized()
Returns true if all added GLEventListener are initialized, otherwise false.
Definition: GLCanvas.java:1085
final RecursiveLock getUpstreamLock()
Returns the recursive lock object of the upstream widget to synchronize multithreaded access on top o...
Definition: GLCanvas.java:298
final Thread getExclusiveContextThread()
Definition: GLCanvas.java:1127
void paint(final Graphics g)
Overridden to cause OpenGL rendering to be performed during repaint cycles.
Definition: GLCanvas.java:538
void setAutoSwapBufferMode(final boolean onOrOff)
Enables or disables automatic buffer swapping for this drawable.
Definition: GLCanvas.java:1191
GLCanvas()
Creates a new GLCanvas component with a default set of OpenGL capabilities, using the default OpenGL ...
Definition: GLCanvas.java:216
void flushGLRunnables()
Flushes all enqueued GLRunnable of this GLAutoDrawable including notifying waiting executor.
Definition: GLCanvas.java:1142
final GLDrawable getDelegatedDrawable()
If the implementation uses delegation, return the delegated GLDrawable instance, otherwise return thi...
Definition: GLCanvas.java:1161
final void setSharedContext(final GLContext sharedContext)
Specifies an OpenGL context, which shall be shared by this GLAutoDrawable's GLContext.
Definition: GLCanvas.java:283
boolean getAutoSwapBufferMode()
Indicates whether automatic buffer swapping is enabled for this drawable.
Definition: GLCanvas.java:1196
final boolean setSurfaceScale(final float[] pixelScale)
Request a pixel scale in x- and y-direction for the associated NativeSurface, where size_in_pixel_uni...
Definition: GLCanvas.java:659
static void main(final String args[])
A most simple JOGL AWT test entry.
Definition: GLCanvas.java:1556
void destroy()
Destroys all resources associated with this GLAutoDrawable, inclusive the GLContext....
Definition: GLCanvas.java:521
GLEventListener removeGLEventListener(final GLEventListener listener)
Removes the given listener from this drawable queue.
Definition: GLCanvas.java:1107
final Object getUpstreamWidget()
Method may return the upstream UI toolkit object holding this GLAutoDrawable instance,...
Definition: GLCanvas.java:293
void setupPrint(final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight)
Shall be called before PrinterJob#print().
Definition: GLCanvas.java:890
final boolean isThreadGLCapable()
Indicates whether the current thread is capable of performing OpenGL-related work.
Definition: GLCanvas.java:301
GLCanvas(final GLCapabilitiesImmutable capsReqUser, final GLCapabilitiesChooser chooser, final GraphicsDevice device)
Creates a new GLCanvas component.
Definition: GLCanvas.java:248
int getSurfaceHeight()
Returns the height of this GLDrawable's surface client area in pixel units.
Definition: GLCanvas.java:1248
int getSurfaceWidth()
Returns the width of this GLDrawable's surface client area in pixel units.
Definition: GLCanvas.java:1243
GraphicsConfiguration getGraphicsConfiguration()
Definition: GLCanvas.java:336
void setShallUseOffscreenLayer(final boolean v)
Request an offscreen layer, if supported.
Definition: GLCanvas.java:304
void swapBuffers()
Swaps the front and back buffers of this drawable.
Definition: GLCanvas.java:1201
GLAnimatorControl getAnimator()
Definition: GLCanvas.java:1117
boolean getGLEventListenerInitState(final GLEventListener listener)
Retrieves whether the given listener is initialized or not.
Definition: GLCanvas.java:1090
void releasePrint()
Shall be called after PrinterJob#print().
Definition: GLCanvas.java:984
final boolean canSetSurfaceScale()
Returns true if setSurfaceScale(float[]) is supported, otherwise false.For pure downstream scalable s...
Definition: GLCanvas.java:650
WindowClosingMode getDefaultCloseOperation()
Definition: GLCanvas.java:486
int getGLEventListenerCount()
Returns the number of GLEventListener of this drawable queue.
Definition: GLCanvas.java:1075
final void setRealized(final boolean realized)
Indicates to GLDrawable implementations whether the underlying surface has been created and can be dr...
Definition: GLCanvas.java:474
boolean invoke(final boolean wait, final List< GLRunnable > glRunnables)
Extends invoke(boolean, GLRunnable) functionality allowing to inject a list of GLRunnables.
Definition: GLCanvas.java:1137
float[] getMinimumSurfaceScale(final float[] result)
Returns the minimum pixel scale of the associated NativeSurface.the passed storage containing the min...
Definition: GLCanvas.java:704
boolean isGLOriented()
Returns true if the drawable is rendered in OpenGL's coordinate system, origin at bottom left.
Definition: GLCanvas.java:1253
long getHandle()
Returns the GL drawable handle, guaranteed to be valid after realization and while it's surface is be...
Definition: GLCanvas.java:1265
GLContext createContext(final GLContext shareWith)
Creates a new context for drawing to this drawable that will optionally share buffer objects,...
Definition: GLCanvas.java:432
final boolean isOffscreenLayerSurfaceEnabled()
Returns true if this instance uses an offscreen layer, otherwise false.
Definition: GLCanvas.java:314
NativeSurface getNativeSurface()
Returns the associated NativeSurface of this NativeSurfaceHolder.Returns the underlying NativeSurface...
Definition: GLCanvas.java:1259
void addGLEventListener(final GLEventListener listener)
Adds the given listener to the end of this drawable queue.
Definition: GLCanvas.java:1065
void addGLEventListener(final int index, final GLEventListener listener)
Adds the given listener at the given index of this drawable queue.
Definition: GLCanvas.java:1070
final boolean getShallUseOffscreenLayer()
Returns the property set by setShallUseOffscreenLayer(boolean).
Definition: GLCanvas.java:309
boolean invoke(final boolean wait, final GLRunnable glRunnable)
Enqueues a one-shot GLRunnable, which will be executed within the next display() call after all regis...
Definition: GLCanvas.java:1132
float[] getMaximumSurfaceScale(final float[] result)
Returns the maximum pixel scale of the associated NativeSurface.The maximum pixel scale maybe used to...
Definition: GLCanvas.java:717
GLCapabilitiesImmutable getChosenGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the chosen OpenGL capabilities (pixel format / v...
Definition: GLCanvas.java:1225
void setAnimator(final GLAnimatorControl animatorControl)
Registers the usage of an animator, an com.jogamp.opengl.GLAnimatorControl implementation.
Definition: GLCanvas.java:1112
void setContextCreationFlags(final int flags)
Definition: GLCanvas.java:1206
final float[] getCurrentSurfaceScale(final float[] result)
Returns the current pixel scale of the associated NativeSurface.
Definition: GLCanvas.java:692
GLCanvas(final GLCapabilitiesImmutable capsReqUser)
Creates a new GLCanvas component with the requested set of OpenGL capabilities, using the default Ope...
Definition: GLCanvas.java:229
Providing utility functions dealing w/ GLDrawables, GLAutoDrawable and their GLEventListener.
static final void swapGLContextAndAllGLEventListener(final GLAutoDrawable a, final GLAutoDrawable b)
Swaps the GLContext and all GLEventListener between GLAutoDrawable a and b, while preserving it's ini...
final void display()
Rendering one tile, by simply calling GLAutoDrawable#display().
A fairly direct port of Brian Paul's tile rendering library, found at http://www.mesa3d....
final boolean eot()
Returns true if end of tiling has been reached, otherwise false.end of tiling criteria is implementat...
final void reset()
Method resets implementation's internal state to start of tiling as required for beginTile(GL) if end...
Window closing mode if triggered by toolkit close operation.
AbstractGraphicsScreen getScreen()
Return the screen this graphics configuration is valid for.
boolean close()
Optionally closing the device if handle is not null.
AbstractGraphicsDevice getDevice()
Return the device this graphics configuration is valid for.
boolean isOnscreen()
Returns whether an on- or offscreen surface is requested, available or chosen.
boolean equals(Object obj)
Equality over the immutable attributes of both objects.
Provides low-level information required for hardware-accelerated rendering using a surface in a platf...
long getSurfaceHandle()
Returns the handle to the surface for this NativeSurface.
Handling requests for using an OffscreenLayerSurface within the implementation.
Adding mutable surface pixel scale property to implementing class, usually to a NativeSurface impleme...
static final float IDENTITY_PIXELSCALE
Setting surface-pixel-scale of {@value}, results in same pixel- and window-units.
static final float AUTOMAX_PIXELSCALE
Setting surface-pixel-scale of {@value}, results in maximum platform dependent pixel-scale,...
Protocol for handling window closing events.
Interface describing print lifecycle to support AWT printing, e.g.
An animator control interface, which implementation may drive a com.jogamp.opengl....
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.
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) ...
static final boolean SCREEN_CHANGE_ACTION_ENABLED
Flag reflecting whether the GLDrawable reconfiguration will be issued in case a screen device change ...
GL getGL()
Returns the GL pipeline object this GLAutoDrawable uses.
void destroy()
Destroys all resources associated with this GLAutoDrawable, inclusive the GLContext.
GLDrawable getDelegatedDrawable()
If the implementation uses delegation, return the delegated GLDrawable instance, otherwise return thi...
Provides a mechanism by which applications can customize the window type selection for a given GLCapa...
Specifies an immutable set of OpenGL capabilities.
GLProfile getGLProfile()
Returns the GL profile you desire or used by the drawable.
An abstraction for an OpenGL rendering target.
Definition: GLDrawable.java:51
int getSurfaceWidth()
Returns the width of this GLDrawable's surface client area in pixel units.
long getHandle()
Returns the GL drawable handle, guaranteed to be valid after realization and while it's surface is be...
boolean isRealized()
Returns true if this drawable is realized, otherwise false.
boolean isGLOriented()
Returns true if the drawable is rendered in OpenGL's coordinate system, origin at bottom left.
NativeSurface getNativeSurface()
Returns the associated NativeSurface of this NativeSurfaceHolder.
GLDrawableFactory getFactory()
Return the GLDrawableFactory being used to create this instance.
void setRealized(boolean realized)
Indicates to GLDrawable implementations whether the underlying surface has been created and can be dr...
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.
Adds capabilities to set a shared GLContext directly or via an GLAutoDrawable.