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 2011 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.swt;
29
30import java.util.List;
31
32import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
33import com.jogamp.nativewindow.AbstractGraphicsDevice;
34import com.jogamp.nativewindow.AbstractGraphicsScreen;
35import com.jogamp.nativewindow.GraphicsConfigurationFactory;
36import com.jogamp.nativewindow.NativeSurface;
37import com.jogamp.nativewindow.NativeWindowException;
38import com.jogamp.nativewindow.ProxySurface;
39import com.jogamp.nativewindow.UpstreamSurfaceHook;
40import com.jogamp.nativewindow.VisualIDHolder;
41import com.jogamp.nativewindow.VisualIDHolder.VIDType;
42import com.jogamp.opengl.GL;
43import com.jogamp.opengl.GLAnimatorControl;
44import com.jogamp.opengl.GLAutoDrawable;
45import com.jogamp.opengl.GLCapabilities;
46import com.jogamp.opengl.GLCapabilitiesChooser;
47import com.jogamp.opengl.GLCapabilitiesImmutable;
48import com.jogamp.opengl.GLContext;
49import com.jogamp.opengl.GLDrawable;
50import com.jogamp.opengl.GLDrawableFactory;
51import com.jogamp.opengl.GLEventListener;
52import com.jogamp.opengl.GLException;
53import com.jogamp.opengl.GLProfile;
54import com.jogamp.opengl.GLRunnable;
55import com.jogamp.opengl.GLSharedContextSetter;
56import com.jogamp.opengl.Threading;
57
58import jogamp.nativewindow.macosx.OSXUtil;
59import jogamp.nativewindow.x11.X11Util;
60import jogamp.opengl.Debug;
61import jogamp.opengl.GLContextImpl;
62import jogamp.opengl.GLDrawableHelper;
63import jogamp.opengl.GLDrawableImpl;
64
65import org.eclipse.swt.SWT;
66import org.eclipse.swt.graphics.Color;
67import org.eclipse.swt.graphics.Rectangle;
68import org.eclipse.swt.internal.DPIUtil;
69import org.eclipse.swt.layout.FillLayout;
70import org.eclipse.swt.widgets.Canvas;
71import org.eclipse.swt.widgets.Composite;
72import org.eclipse.swt.widgets.Display;
73import org.eclipse.swt.widgets.Event;
74import org.eclipse.swt.widgets.Listener;
75import org.eclipse.swt.widgets.Shell;
76
77import com.jogamp.common.GlueGenVersion;
78import com.jogamp.common.os.Platform;
79import com.jogamp.common.util.VersionUtil;
80import com.jogamp.common.util.locks.LockFactory;
81import com.jogamp.common.util.locks.RecursiveLock;
82import com.jogamp.nativewindow.swt.SWTAccessor;
83import com.jogamp.nativewindow.x11.X11GraphicsDevice;
84import com.jogamp.opengl.JoglVersion;
85
86/**
87 * Native SWT Canvas implementing GLAutoDrawable
88 * <p>
89 * Implementation allows use of custom {@link GLCapabilities}.
90 * </p>
91 * <p>
92 * <a name="contextSharing"><h5>OpenGL Context Sharing</h5></a>
93 * To share a {@link GLContext} see the following note in the documentation overview:
94 * <a href="../../../../overview-summary.html#SHARING">context sharing</a>
95 * as well as {@link GLSharedContextSetter}.
96 * </p>
97 */
98public class GLCanvas extends Canvas implements GLAutoDrawable, GLSharedContextSetter {
99 private static final boolean DEBUG = Debug.debug("GLCanvas");
100
101 /*
102 * Flag for whether the SWT thread should be used for OpenGL calls when in single-threaded mode. This is controlled
103 * by the setting of the threading mode to worker (do not use SWT thread), awt (use SWT thread), or false (always use
104 * calling thread).
105 *
106 * @see Threading
107 *
108 * Now done dynamically to avoid early loading of gluegen library.
109 */
110 //private static final boolean useSWTThread = ThreadingImpl.getMode() != ThreadingImpl.WORKER;
111
112 /* GL Stuff */
113 private final RecursiveLock lock = LockFactory.createRecursiveLock();
114 private final GLDrawableHelper helper = new GLDrawableHelper();
115
116 private final GLCapabilitiesImmutable capsRequested;
117 private final GLCapabilitiesChooser capsChooser;
118
119 private volatile Rectangle clientAreaPixels, clientAreaWindow;
120 private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access
121 private volatile GLContextImpl context; // volatile: avoid locking for read-only access
122
123 /* Native window surface */
124 private final boolean useX11GTK;
125 private volatile long x11Window; // .. or X11 child window (for GL rendering)
126 private final AbstractGraphicsScreen screen;
127
128 /* Construction parameters stored for GLAutoDrawable accessor methods */
129 private int additionalCtxCreationFlags = 0;
130
131
132 /* Flag indicating whether an unprocessed reshape is pending. */
133 private volatile boolean sendReshape; // volatile: maybe written by WindowManager thread w/o locking
134
135 private static String getThreadName() { return Thread.currentThread().getName(); }
136 private static String toHexString(final int v) { return "0x"+Integer.toHexString(v); }
137 private static String toHexString(final long v) { return "0x"+Long.toHexString(v); }
138
139 /*
140 * Invokes init(...) on all GLEventListeners. Assumes context is current when run.
141 */
142 private final Runnable initAction = new Runnable() {
143 @Override
144 public void run() {
145 helper.init(GLCanvas.this, !sendReshape);
146 }
147 };
148
149 /*
150 * Action to handle display in OpenGL, also processes reshape since they should be done at the same time.
151 *
152 * Assumes GLContext is current when run.
153 */
154 private final Runnable displayAction = new Runnable() {
155 @Override
156 public void run() {
157 if (sendReshape) {
158 helper.reshape(GLCanvas.this, 0, 0, clientAreaPixels.width, clientAreaPixels.height);
159 sendReshape = false;
160 }
161 helper.display(GLCanvas.this);
162 }
163 };
164
165 /* Action to make specified context current prior to running displayAction */
166 private final Runnable makeCurrentAndDisplayOnGLAction = new Runnable() {
167 @Override
168 public void run() {
169 final RecursiveLock _lock = lock;
170 _lock.lock();
171 try {
172 if( !GLCanvas.this.isDisposed() ) {
173 helper.invokeGL(drawable, context, displayAction, initAction);
174 }
175 } finally {
176 _lock.unlock();
177 }
178 }
179 };
180
181 /* Swaps buffers, assuming the GLContext is current */
182 private final Runnable swapBuffersOnGLAction = new Runnable() {
183 @Override
184 public void run() {
185 final RecursiveLock _lock = lock;
186 _lock.lock();
187 try {
188 final boolean drawableOK = null != drawable && drawable.isRealized();
189 if( drawableOK && !GLCanvas.this.isDisposed() ) {
190 drawable.swapBuffers();
191 }
192 } finally {
193 _lock.unlock();
194 }
195 }
196 };
197
198 /*
199 * Disposes of OpenGL resources
200 */
201 private final Runnable disposeOnEDTGLAction = new Runnable() {
202 @Override
203 public void run() {
204 final RecursiveLock _lock = lock;
205 _lock.lock();
206 try {
207 final GLAnimatorControl animator = getAnimator();
208 final boolean animatorPaused;
209 if(null!=animator) {
210 // can't remove us from animator for recreational addNotify()
211 animatorPaused = animator.pause();
212 } else {
213 animatorPaused = false;
214 }
215
216 GLException exceptionOnDisposeGL = null;
217 if( null != context ) {
218 if( context.isCreated() ) {
219 try {
220 if( !GLCanvas.this.isDisposed() ) {
221 helper.disposeGL(GLCanvas.this, context, true);
222 } else {
223 context.destroy();
224 }
225 } catch (final GLException gle) {
226 exceptionOnDisposeGL = gle;
227 }
228 }
229 context = null;
230 }
231
232 Throwable exceptionOnUnrealize = null;
233 if( null != drawable ) {
234 try {
235 drawable.setRealized(false);
236 } catch( final Throwable re ) {
237 exceptionOnUnrealize = re;
238 }
239 drawable = null;
240 }
241
242 Throwable exceptionOnDeviceClose = null;
243 try {
244 if( 0 != x11Window) {
245 SWTAccessor.destroyX11Window(screen.getDevice(), x11Window);
246 x11Window = 0;
247 }
248 screen.getDevice().close();
249 } catch (final Throwable re) {
250 exceptionOnDeviceClose = re;
251 }
252
253 if (animatorPaused) {
254 animator.resume();
255 }
256
257 // throw exception in order of occurrence ..
258 if( null != exceptionOnDisposeGL ) {
259 throw exceptionOnDisposeGL;
260 }
261 if( null != exceptionOnUnrealize ) {
262 throw GLException.newGLException(exceptionOnUnrealize);
263 }
264 if( null != exceptionOnDeviceClose ) {
265 throw GLException.newGLException(exceptionOnDeviceClose);
266 }
267 } finally {
268 _lock.unlock();
269 }
270 }
271 };
272
273 private class DisposeGLEventListenerAction implements Runnable {
274 private GLEventListener listener;
275 private final boolean remove;
276 private DisposeGLEventListenerAction(final GLEventListener listener, final boolean remove) {
277 this.listener = listener;
278 this.remove = remove;
279 }
280
281 @Override
282 public void run() {
283 final RecursiveLock _lock = lock;
284 _lock.lock();
285 try {
286 if( !GLCanvas.this.isDisposed() ) {
287 listener = helper.disposeGLEventListener(GLCanvas.this, drawable, context, listener, remove);
288 }
289 } finally {
290 _lock.unlock();
291 }
292 }
293 };
294
295 /**
296 * Creates an instance using {@link #GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser)}
297 * on the SWT thread.
298 *
299 * @param parent
300 * Required (non-null) parent Composite.
301 * @param style
302 * Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the
303 * Canvas constructor, so OpenGL handles the background.
304 * @param caps
305 * Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the
306 * graphics device determined by the parent Composite are used. Note that the GLCapabilities that are
307 * actually used may differ based on the capabilities of the graphics device.
308 * @param chooser
309 * Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the
310 * requested GLCapabilities, and the available capabilities of the graphics device.
311 * @return a new instance
312 */
313 public static GLCanvas create(final Composite parent, final int style, final GLCapabilitiesImmutable caps,
314 final GLCapabilitiesChooser chooser) {
315 final GLCanvas[] res = new GLCanvas[] { null };
316 parent.getDisplay().syncExec(new Runnable() {
317 @Override
318 public void run() {
319 res[0] = new GLCanvas( parent, style, caps, chooser );
320 }
321 });
322 return res[0];
323 }
324
325 /**
326 * Creates a new SWT GLCanvas.
327 *
328 * @param parent
329 * Required (non-null) parent Composite.
330 * @param style
331 * Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the
332 * Canvas constructor, so OpenGL handles the background.
333 * @param capsReqUser
334 * Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the
335 * graphics device determined by the parent Composite are used. Note that the GLCapabilities that are
336 * actually used may differ based on the capabilities of the graphics device.
337 * @param capsChooser
338 * Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the
339 * requested GLCapabilities, and the available capabilities of the graphics device.
340 */
341 public GLCanvas(final Composite parent, final int style, final GLCapabilitiesImmutable capsReqUser,
342 final GLCapabilitiesChooser capsChooser) {
343 /* NO_BACKGROUND required to avoid clearing bg in native SWT widget (we do this in the GL display) */
344 super(parent, style | SWT.NO_BACKGROUND);
345
346 GLProfile.initSingleton(); // ensure JOGL is completely initialized
347
348 SWTAccessor.setRealized(this, true);
349
350 clientAreaPixels = SWTAccessor.getClientAreaInPixels(this);
351 clientAreaWindow = getClientArea();
352
353 /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
354 * Note: SWT is owner of the native handle, hence closing operation will be a NOP. */
355 final AbstractGraphicsDevice swtDevice = SWTAccessor.getDevice(this);
356
357 useX11GTK = SWTAccessor.useX11GTK();
358 if(useX11GTK) {
359 // Decoupled X11 Device/Screen allowing X11 display lock-free off-thread rendering
360 final long x11DeviceHandle = X11Util.openDisplay(swtDevice.getConnection());
361 if( 0 == x11DeviceHandle ) {
362 throw new RuntimeException("Error creating display(EDT): "+swtDevice.getConnection());
363 }
364 final AbstractGraphicsDevice x11Device = new X11GraphicsDevice(x11DeviceHandle, AbstractGraphicsDevice.DEFAULT_UNIT, true /* owner */);
365 screen = SWTAccessor.getScreen(x11Device, -1 /* default */);
366 } else {
367 screen = SWTAccessor.getScreen(swtDevice, -1 /* default */);
368 }
369
370 /* Select default GLCapabilities if none was provided, otherwise use cloned provided caps */
371 if(null == capsReqUser) {
372 this.capsRequested = new GLCapabilities(GLProfile.getDefault(screen.getDevice()));
373 } else {
374 this.capsRequested = (GLCapabilitiesImmutable) capsReqUser.cloneMutable();
375 }
376 this.capsChooser = capsChooser;
377
378 // post create .. when ready
379 x11Window = 0;
380 drawable = null;
381 context = null;
382
383 // Bug 1362 fix or workaround: Seems SWT/GTK3 at least performs lazy initialization
384 // Minimal action required: setBackground of the parent canvas before reparenting!
385 //
386 // SWT 3.110 (Eclipse 4.10?) would require color to be disposed, hence use pre-allocated.
387 // Since at least 'Eclipse 4.26.0 Release Build: 4.26' no more disposal of Color required.
388 setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WHITE));
389
390 final Listener listener = new Listener () {
391 @Override
392 public void handleEvent (final Event event) {
393 switch (event.type) {
394 case SWT.Paint:
395 displayIfNoAnimatorNoCheck();
396 break;
397 case SWT.Resize:
399 break;
400 case SWT.Dispose:
401 GLCanvas.this.dispose();
402 break;
403 }
404 }
405 };
406 addListener (SWT.Resize, listener);
407 addListener (SWT.Paint, listener);
408 addListener (SWT.Dispose, listener);
409 }
410
411 @Override
412 public final void setSharedContext(final GLContext sharedContext) throws IllegalStateException {
413 helper.setSharedContext(this.context, sharedContext);
414 }
415
416 @Override
417 public final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable) throws IllegalStateException {
418 helper.setSharedAutoDrawable(this, sharedAutoDrawable);
419 }
420
421 private final UpstreamSurfaceHook swtCanvasUpStreamHook = new UpstreamSurfaceHook() {
422 @Override
423 public final void create(final ProxySurface s) { /* nop */ }
424
425 @Override
426 public final void destroy(final ProxySurface s) { /* nop */ }
427
428 @Override
429 public final int getSurfaceWidth(final ProxySurface s) {
430 return clientAreaPixels.width;
431 }
432
433 @Override
434 public final int getSurfaceHeight(final ProxySurface s) {
435 return clientAreaPixels.height;
436 }
437
438 @Override
439 public String toString() {
440 return "SWTCanvasUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+", "+clientAreaPixels.width+"x"+clientAreaPixels.height+" [pixel], "+clientAreaWindow.width+"x"+clientAreaWindow.height+" [win]]";
441 }
442
443 /**
444 * {@inheritDoc}
445 * <p>
446 * Returns <code>null</code>.
447 * </p>
448 */
449 @Override
450 public final NativeSurface getUpstreamSurface() {
451 return null;
452 }
453 };
454
455 protected final void updateSizeCheck() {
456 final Rectangle oClientAreaPixels = clientAreaPixels;
457 final Rectangle nClientAreaPixels = SWTAccessor.getClientAreaInPixels(this);
458
459 if ( nClientAreaPixels != null &&
460 ( nClientAreaPixels.width != oClientAreaPixels.width || nClientAreaPixels.height != oClientAreaPixels.height )
461 ) {
462 clientAreaPixels = nClientAreaPixels; // write back new value
463 clientAreaWindow = getClientArea();
464
465 final GLDrawableImpl _drawable = drawable;
466 final boolean drawableOK = null != _drawable && _drawable.isRealized();
467 if(DEBUG) {
468 final long dh = drawableOK ? _drawable.getHandle() : 0;
469 System.err.println(getThreadName()+": GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientAreaPixels.x+"/"+nClientAreaPixels.y+" "+nClientAreaPixels.width+"x"+nClientAreaPixels.height+" - drawableHandle "+toHexString(dh));
470 }
471 if( drawableOK ) {
472 if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
473 final RecursiveLock _lock = lock;
474 _lock.lock();
475 try {
476 final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, nClientAreaPixels.width, nClientAreaPixels.height);
477 if(_drawable != _drawableNew) {
478 // write back
479 drawable = _drawableNew;
480 }
481 } finally {
482 _lock.unlock();
483 }
484 }
485 }
486 if(0 != x11Window) {
487 SWTAccessor.resizeX11Window(screen.getDevice(), clientAreaPixels, x11Window);
488 }
489 sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock
490 }
491 }
492
493 private boolean isValidAndVisibleOnEDTActionResult;
494 private final Runnable isValidAndVisibleOnEDTAction = new Runnable() {
495 @Override
496 public void run() {
497 isValidAndVisibleOnEDTActionResult = !GLCanvas.this.isDisposed() && GLCanvas.this.isVisible();
498 } };
499
500 private final boolean isValidAndVisibleOnEDT() {
501 synchronized(isValidAndVisibleOnEDTAction) {
502 runOnEDTIfAvail(true, isValidAndVisibleOnEDTAction);
503 return isValidAndVisibleOnEDTActionResult;
504 }
505 }
506
507 /** assumes drawable == null (implying !drawable.isRealized()) ! Checks of !isDispose() and isVisible() */
508 protected final boolean validateDrawableAndContextWithCheck() {
509 if( !isValidAndVisibleOnEDT() ) {
510 return false;
511 }
512 return validateDrawableAndContextPostCheck();
513 }
514
515 private final boolean isDrawableAndContextValid() {
516 // drawable != null implies drawable.isRealized()==true
517 return null != drawable && null != context;
518 }
519
520 /** assumes drawable == null (implying !drawable.isRealized()) || context == null ! No check of !isDispose() and isVisible() */
521 private final boolean validateDrawableAndContextPostCheck() {
522 boolean res;
523 final RecursiveLock _lock = lock;
524 _lock.lock();
525 try {
526 if(null == drawable) {
527 // 'displayable' (isValidAndVisibleOnEDT()) must have been checked upfront if appropriate!
528 createDrawableImpl(); // checks clientArea size (i.e. drawable size) and perf. realization
529 }
530 final GLDrawable _drawable = drawable;
531 if ( null != _drawable ) {
532 // drawable realization goes in-hand w/ it's construction
533 if( null == context ) {
534 // re-try context creation
535 res = createContextImpl(_drawable); // pending creation.
536 } else {
537 res = true;
538 }
539 if(res) {
540 sendReshape = true;
541 }
542 } else {
543 if(DEBUG) {
544 System.err.println(getThreadName()+": SWT.GLCanvas.validate "+toHexString(hashCode())+": null drawable");
545 }
546 res = false;
547 }
548 if(DEBUG) {
549 final boolean isDrawableNull = null == drawable;
550 final boolean isDrawableRealized = !isDrawableNull ? drawable.isRealized() : false;
551 System.err.println(getThreadName()+": SWT.GLCanvas.validate.X "+toHexString(hashCode())+": "+res+", drawable[null "+isDrawableNull+", realized "+isDrawableRealized+"], has context "+(null!=context));
552 }
553 } finally {
554 _lock.unlock();
555 }
556 return res;
557 }
558 private final void createDrawableImpl() {
559 final Rectangle nClientArea = clientAreaPixels;
560 if(0 >= nClientArea.width || 0 >= nClientArea.height) {
561 if(DEBUG) {
562 System.err.println(getThreadName()+": SWT.GLCanvas.validate.X "+toHexString(hashCode())+": drawable could not be created: size < 0x0");
563 }
564 return; // early out
565 }
566 final AbstractGraphicsDevice device = screen.getDevice();
567 device.open();
568
569 final long nativeWindowHandle;
570 if( useX11GTK ) {
571 final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(device, capsRequested);
572 final AbstractGraphicsConfiguration cfg = factory.chooseGraphicsConfiguration(
573 capsRequested, capsRequested, capsChooser, screen, VisualIDHolder.VID_UNDEFINED);
574 if(DEBUG) {
575 System.err.println(getThreadName()+": SWT.GLCanvas.X11 "+toHexString(hashCode())+": factory: "+factory+", chosen config: "+cfg);
576 }
577 if (null == cfg) {
578 throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
579 }
580 final int visualID = cfg.getVisualID(VIDType.NATIVE);
581 if( VisualIDHolder.VID_UNDEFINED != visualID ) {
582 // gdkWindow = SWTAccessor.createCompatibleGDKChildWindow(this, visualID, clientArea.width, clientArea.height);
583 // nativeWindowHandle = SWTAccessor.gdk_window_get_xwindow(gdkWindow);
584 x11Window = SWTAccessor.createCompatibleX11ChildWindow(screen, this, visualID, clientAreaPixels.width, clientAreaPixels.height);
585 nativeWindowHandle = x11Window;
586 } else {
587 throw new GLException("Could not choose valid visualID: "+toHexString(visualID)+", "+this);
588 }
589 } else {
590 nativeWindowHandle = SWTAccessor.getWindowHandle(this);
591 if( SWTAccessor.isOSX ) {
592 final float reqPixelScale = DPIUtil.autoScaleUp(this, 1f);
593 if( DEBUG ) {
594 System.err.println(getThreadName()+": SWT.GLCanvas.OSX "+toHexString(hashCode())+": Scaling: devZoom "+DPIUtil.getDeviceZoom()+", general "+DPIUtil.autoScaleUp(1f)+", onWidged "+reqPixelScale);
595 }
596 if( reqPixelScale > 1f ) {
597 OSXUtil.SetWindowPixelScale(nativeWindowHandle, reqPixelScale);
598 }
599 }
600 }
601 final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(capsRequested.getGLProfile());
602
603 // Create a NativeWindow proxy for the SWT canvas
604 final ProxySurface proxySurface = glFactory.createProxySurface(device, screen.getIndex(), nativeWindowHandle,
605 capsRequested, capsChooser, swtCanvasUpStreamHook);
606 // Associate a GL surface with the proxy
607 final GLDrawableImpl _drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface);
608 _drawable.setRealized(true);
609 if(!_drawable.isRealized()) {
610 // oops
611 if(DEBUG) {
612 System.err.println(getThreadName()+": SWT.GLCanvas.validate.X "+proxySurface);
613 System.err.println(getThreadName()+": SWT.GLCanvas.validate.X "+toHexString(hashCode())+": Drawable could not be realized: "+_drawable);
614 }
615 } else {
616 if(DEBUG) {
617 System.err.println(getThreadName()+": SWT.GLCanvas.validate "+proxySurface);
618 System.err.println(getThreadName()+": SWT.GLCanvas.validate "+toHexString(hashCode())+": Drawable created and realized: "+_drawable);
619 }
620 drawable = _drawable;
621 }
622 }
623 private boolean createContextImpl(final GLDrawable drawable) {
624 final GLContext[] shareWith = { null };
625 if( !helper.isSharedGLContextPending(shareWith) ) {
626 context = (GLContextImpl) drawable.createContext(shareWith[0]);
627 context.setContextCreationFlags(additionalCtxCreationFlags);
628 if(DEBUG) {
629 System.err.println(getThreadName()+": SWT.GLCanvas.validate "+toHexString(hashCode())+": Context created: has shared "+(null != shareWith[0]));
630 }
631 return true;
632 } else {
633 if(DEBUG) {
634 System.err.println(getThreadName()+": SWT.GLCanvas.validate "+toHexString(hashCode())+": Context !created: pending share");
635 }
636 return false;
637 }
638 }
639
640 @Override
641 public void update() {
642 // don't paint background etc .. nop avoids flickering
643 // super.update();
644 }
645
646 /**
647 @Override
648 public boolean forceFocus() {
649 final boolean r = super.forceFocus();
650 if(r && 0 != gdkWindow) {
651 SWTGTKUtil.focusGDKWindow(gdkWindow);
652 }
653 return r;
654 } */
655
656 @Override
657 public void dispose() {
658 runInGLThread(disposeOnEDTGLAction);
659 super.dispose();
660 }
661
662 private final void displayIfNoAnimatorNoCheck() {
663 if ( !helper.isAnimatorAnimatingOnOtherThread() ) {
664 if( isDrawableAndContextValid() || validateDrawableAndContextPostCheck() ) {
665 runInGLThread(makeCurrentAndDisplayOnGLAction);
666 }
667 }
668 }
669
670 //
671 // GL[Auto]Drawable
672 //
673
674 @Override
675 public void display() {
676 if( isDrawableAndContextValid() || validateDrawableAndContextWithCheck() ) {
677 runInGLThread(makeCurrentAndDisplayOnGLAction);
678 }
679 }
680
681 @Override
682 public final Object getUpstreamWidget() {
683 return this;
684 }
685
686 @Override
687 public final RecursiveLock getUpstreamLock() { return lock; }
688
689 @Override
690 public int getSurfaceWidth() {
691 return clientAreaPixels.width;
692 }
693
694 @Override
695 public int getSurfaceHeight() {
696 return clientAreaPixels.height;
697 }
698
699 @Override
700 public boolean isGLOriented() {
701 final GLDrawable _drawable = drawable;
702 return null != _drawable ? _drawable.isGLOriented() : true;
703 }
704
705 @Override
706 public void addGLEventListener(final GLEventListener listener) {
707 helper.addGLEventListener(listener);
708 }
709
710 @Override
711 public void addGLEventListener(final int idx, final GLEventListener listener) throws IndexOutOfBoundsException {
712 helper.addGLEventListener(idx, listener);
713 }
714
715 @Override
717 return helper.getGLEventListenerCount();
718 }
719
720 @Override
721 public GLEventListener getGLEventListener(final int index) throws IndexOutOfBoundsException {
722 return helper.getGLEventListener(index);
723 }
724
725 @Override
727 return helper.areAllGLEventListenerInitialized();
728 }
729
730 @Override
731 public boolean getGLEventListenerInitState(final GLEventListener listener) {
732 return helper.getGLEventListenerInitState(listener);
733 }
734
735 @Override
736 public void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized) {
737 helper.setGLEventListenerInitState(listener, initialized);
738 }
739
740 @Override
741 public GLEventListener disposeGLEventListener(final GLEventListener listener, final boolean remove) {
742 final DisposeGLEventListenerAction r = new DisposeGLEventListenerAction(listener, remove);
743 runInGLThread(r);
744 return r.listener;
745 }
746
747 @Override
749 return helper.removeGLEventListener(listener);
750 }
751
752 /**
753 * {@inheritDoc}
754 *
755 * <p>
756 * This impl. calls this class's {@link #dispose()} SWT override,
757 * where the actual implementation resides.
758 * </p>
759 */
760 @Override
761 public void destroy() {
762 dispose();
763 }
764
765 @Override
767 return helper.getAnimator();
768 }
769
770 @Override
771 public final Thread setExclusiveContextThread(final Thread t) throws GLException {
772 return helper.setExclusiveContextThread(t, context);
773 }
774
775 @Override
776 public final Thread getExclusiveContextThread() {
777 return helper.getExclusiveContextThread();
778 }
779
780 @Override
781 public boolean getAutoSwapBufferMode() {
782 return helper.getAutoSwapBufferMode();
783 }
784
785 @Override
787 return drawable;
788 }
789
790 @Override
792 return context;
793 }
794
795 @Override
797 return additionalCtxCreationFlags;
798 }
799
800 @Override
801 public GL getGL() {
802 final GLContext _context = context;
803 return (null == _context) ? null : _context.getGL();
804 }
805
806 @Override
807 public boolean invoke(final boolean wait, final GLRunnable runnable) throws IllegalStateException {
808 return helper.invoke(this, wait, runnable);
809 }
810
811 @Override
812 public boolean invoke(final boolean wait, final List<GLRunnable> runnables) throws IllegalStateException {
813 return helper.invoke(this, wait, runnables);
814 }
815
816 @Override
817 public void flushGLRunnables() {
818 helper.flushGLRunnables();
819 }
820
821 @Override
822 public void setAnimator(final GLAnimatorControl arg0) throws GLException {
823 helper.setAnimator(arg0);
824 }
825
826 @Override
827 public void setAutoSwapBufferMode(final boolean arg0) {
828 helper.setAutoSwapBufferMode(arg0);
829 }
830
831 @Override
832 public GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx) {
833 final RecursiveLock _lock = lock;
834 _lock.lock();
835 try {
836 final GLContext oldCtx = context;
837 GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
838 context=(GLContextImpl)newCtx;
839 return oldCtx;
840 } finally {
841 _lock.unlock();
842 }
843 }
844
845 @Override
846 public void setContextCreationFlags(final int arg0) {
847 additionalCtxCreationFlags = arg0;
848 final GLContext _context = context;
849 if(null != _context) {
850 _context.setContextCreationFlags(additionalCtxCreationFlags);
851 }
852 }
853
854 @Override
855 public GL setGL(final GL arg0) {
856 final GLContext _context = context;
857 if (null != _context) {
858 _context.setGL(arg0);
859 return arg0;
860 }
861 return null;
862 }
863
864 @Override
865 public GLContext createContext(final GLContext shareWith) {
866 final RecursiveLock _lock = lock;
867 _lock.lock();
868 try {
869 if(drawable != null) {
870 final GLContext _ctx = drawable.createContext(shareWith);
871 _ctx.setContextCreationFlags(additionalCtxCreationFlags);
872 return _ctx;
873 }
874 return null;
875 } finally {
876 _lock.unlock();
877 }
878 }
879
880 @Override
882 final GLDrawable _drawable = drawable;
883 return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getChosenGLCapabilities() : null;
884 }
885
886 @Override
888 final GLDrawable _drawable = drawable;
889 return null != _drawable ? (GLCapabilitiesImmutable)_drawable.getRequestedGLCapabilities() : null;
890 }
891
892 @Override
894 final GLDrawable _drawable = drawable;
895 return (_drawable != null) ? _drawable.getFactory() : null;
896 }
897
898 @Override
900 return capsRequested.getGLProfile();
901 }
902
903 @Override
904 public long getHandle() {
905 final GLDrawable _drawable = drawable;
906 return (_drawable != null) ? _drawable.getHandle() : 0;
907 }
908
909 @Override
911 final GLDrawable _drawable = drawable;
912 return (_drawable != null) ? _drawable.getNativeSurface() : null;
913 }
914
915 @Override
916 public boolean isRealized() {
917 final GLDrawable _drawable = drawable;
918 return (_drawable != null) ? _drawable.isRealized() : false;
919 }
920
921 @Override
922 public void setRealized(final boolean arg0) {
923 /* Intentionally empty */
924 }
925
926 @Override
927 public void swapBuffers() throws GLException {
928 runInGLThread(swapBuffersOnGLAction);
929 }
930
931 /**
932 * {@inheritDoc}
933 * <p>
934 * Implementation always supports multithreading, hence method always returns <code>true</code>.
935 * </p>
936 */
937 @Override
938 public final boolean isThreadGLCapable() { return true; }
939
940 /**
941 * Runs the specified action in an SWT compatible thread, which is:
942 * <ul>
943 * <li>Mac OSX
944 * <ul>
945 * <!--li>AWT EDT: In case AWT is available, the AWT EDT is the OSX UI main thread</li-->
946 * <!--li><i>Main Thread</i>: Run on OSX UI main thread.</li-->
947 * <li>Current thread</li>
948 * </ul></li>
949 * <li>Linux, Windows, ..
950 * <ul>
951 * <!--li>Use {@link Threading#invokeOnOpenGLThread(boolean, Runnable)}</li-->
952 * <li>Current thread</li>
953 * </ul></li>
954 * </ul>
955 * The current thread seems to be valid for all platforms,
956 * since no SWT lifecycle tasks are being performed w/ this call.
957 * Only GL task, which are independent from the SWT threading model.
958 *
959 * @see Platform#AWT_AVAILABLE
960 * @see Platform#getOSType()
961 */
962 private void runInGLThread(final Runnable action) {
963 /**
964 if(Platform.OSType.MACOS == Platform.OS_TYPE) {
965 SWTAccessor.invoke(true, action);
966 } else {
967 Threading.invokeOnOpenGLThread(true, action);
968 } */
969 /**
970 if( !isDisposed() ) {
971 final Display d = getDisplay();
972 if( d.getThread() == Thread.currentThread() ) {
973 action.run();
974 } else {
975 d.syncExec(action);
976 }
977 } */
978 action.run();
979 }
980
981 private void runOnEDTIfAvail(final boolean wait, final Runnable action) {
982 final Display d = isDisposed() ? null : getDisplay();
983 if( null == d || d.isDisposed() || d.getThread() == Thread.currentThread() ) {
984 action.run();
985 } else if(wait) {
986 d.syncExec(action);
987 } else {
988 d.asyncExec(action);
989 }
990 }
991
992 @Override
993 public String toString() {
994 final GLDrawable _drawable = drawable;
995 final int dw = (null!=_drawable) ? _drawable.getSurfaceWidth() : -1;
996 final int dh = (null!=_drawable) ? _drawable.getSurfaceHeight() : -1;
997
998 return "SWT-GLCanvas[Realized "+isRealized()+
999 ",\n\t"+((null!=_drawable)?_drawable.getClass().getName():"null-drawable")+
1000 ",\n\tFactory "+getFactory()+
1001 ",\n\thandle "+toHexString(getHandle())+
1002 ",\n\tDrawable size "+dw+"x"+dh+
1003 ",\n\tSWT size "+getSurfaceWidth()+"x"+getSurfaceHeight()+"]";
1004 }
1005
1006 public static void main(final String[] args) {
1007 System.err.println(VersionUtil.getPlatformInfo());
1008 System.err.println(GlueGenVersion.getInstance());
1009 // System.err.println(NativeWindowVersion.getInstance());
1010 System.err.println(JoglVersion.getInstance());
1011
1012 System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
1013
1015 final Display display = new Display();
1016 final Shell shell = new Shell(display);
1017 shell.setSize(128,128);
1018 shell.setLayout(new FillLayout());
1019
1020 final GLCanvas canvas = new GLCanvas(shell, 0, caps, null);
1021
1022 canvas.addGLEventListener(new GLEventListener() {
1023 @Override
1024 public void init(final GLAutoDrawable drawable) {
1025 final GL gl = drawable.getGL();
1026 System.err.println(JoglVersion.getGLInfo(gl, null));
1027 }
1028 @Override
1029 public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {}
1030 @Override
1031 public void display(final GLAutoDrawable drawable) {}
1032 @Override
1033 public void dispose(final GLAutoDrawable drawable) {}
1034 });
1035 shell.open();
1036 canvas.display();
1037 display.dispose();
1038 }
1039}
static void destroyX11Window(final AbstractGraphicsDevice device, final long x11Window)
static Rectangle getClientAreaInPixels(final Scrollable s)
Returns the unscaled Scrollable#getClientArea() in pixels.
static AbstractGraphicsDevice getDevice(final Control swtControl)
static AbstractGraphicsScreen getScreen(final AbstractGraphicsDevice device, final int screen)
static void resizeX11Window(final AbstractGraphicsDevice device, final Rectangle clientArea, final long x11Window)
static void setRealized(final Control swtControl, final boolean realize)
Encapsulates a graphics device on X11 platforms.
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
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
static GLException newGLException(final Throwable t)
Constructs a GLException object with the specified root cause with a decorating message including the...
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 void initSingleton()
Static initialization of JOGL.
Definition: GLProfile.java:204
static JoglVersion getInstance()
static StringBuilder getGLInfo(final GL gl, final StringBuilder sb)
static StringBuilder getDefaultOpenGLInfo(AbstractGraphicsDevice device, StringBuilder sb, final boolean withCapabilitiesInfo)
Native SWT Canvas implementing GLAutoDrawable.
Definition: GLCanvas.java:98
GLEventListener removeGLEventListener(final GLEventListener listener)
Removes the given listener from this drawable queue.
Definition: GLCanvas.java:748
final GLDrawable getDelegatedDrawable()
If the implementation uses delegation, return the delegated GLDrawable instance, otherwise return thi...
Definition: GLCanvas.java:786
void setAutoSwapBufferMode(final boolean arg0)
Enables or disables automatic buffer swapping for this drawable.
Definition: GLCanvas.java:827
GLProfile getGLProfile()
Fetches the GLProfile for this drawable.
Definition: GLCanvas.java:899
boolean isRealized()
Returns true if this drawable is realized, otherwise false.
Definition: GLCanvas.java:916
final RecursiveLock getUpstreamLock()
Returns the recursive lock object of the upstream widget to synchronize multithreaded access on top o...
Definition: GLCanvas.java:687
GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx)
Associate the new context, newtCtx, to this auto-drawable.
Definition: GLCanvas.java:832
void destroy()
Destroys all resources associated with this GLAutoDrawable, inclusive the GLContext....
Definition: GLCanvas.java:761
static void main(final String[] args)
Definition: GLCanvas.java:1006
boolean invoke(final boolean wait, final GLRunnable runnable)
Enqueues a one-shot GLRunnable, which will be executed within the next display() call after all regis...
Definition: GLCanvas.java:807
long getHandle()
Returns the GL drawable handle, guaranteed to be valid after realization and while it's surface is be...
Definition: GLCanvas.java:904
GLCanvas(final Composite parent, final int style, final GLCapabilitiesImmutable capsReqUser, final GLCapabilitiesChooser capsChooser)
Creates a new SWT GLCanvas.
Definition: GLCanvas.java:341
GLContext getContext()
Returns the context associated with this drawable.
Definition: GLCanvas.java:791
NativeSurface getNativeSurface()
Returns the associated NativeSurface of this NativeSurfaceHolder.Returns the underlying NativeSurface...
Definition: GLCanvas.java:910
void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized)
Sets the given listener's initialized state.
Definition: GLCanvas.java:736
boolean areAllGLEventListenerInitialized()
Returns true if all added GLEventListener are initialized, otherwise false.
Definition: GLCanvas.java:726
void addGLEventListener(final int idx, final GLEventListener listener)
Adds the given listener at the given index of this drawable queue.
Definition: GLCanvas.java:711
int getGLEventListenerCount()
Returns the number of GLEventListener of this drawable queue.
Definition: GLCanvas.java:716
int getSurfaceWidth()
Returns the width of this GLDrawable's surface client area in pixel units.
Definition: GLCanvas.java:690
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:741
boolean invoke(final boolean wait, final List< GLRunnable > runnables)
Extends invoke(boolean, GLRunnable) functionality allowing to inject a list of GLRunnables.
Definition: GLCanvas.java:812
boolean isGLOriented()
Returns true if the drawable is rendered in OpenGL's coordinate system, origin at bottom left.
Definition: GLCanvas.java:700
static GLCanvas create(final Composite parent, final int style, final GLCapabilitiesImmutable caps, final GLCapabilitiesChooser chooser)
Creates an instance using GLCanvas(Composite, int, GLCapabilitiesImmutable, GLCapabilitiesChooser) on...
Definition: GLCanvas.java:313
GL setGL(final GL arg0)
Sets the GL pipeline object this GLAutoDrawable uses.
Definition: GLCanvas.java:855
GLEventListener getGLEventListener(final int index)
Returns the GLEventListener at the given index of this drawable queue.
Definition: GLCanvas.java:721
void setRealized(final boolean arg0)
Indicates to GLDrawable implementations whether the underlying surface has been created and can be dr...
Definition: GLCanvas.java:922
GLCapabilitiesImmutable getRequestedGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the user requested OpenGL capabilities (pixel fo...
Definition: GLCanvas.java:887
final Object getUpstreamWidget()
Method may return the upstream UI toolkit object holding this GLAutoDrawable instance,...
Definition: GLCanvas.java:682
final Thread getExclusiveContextThread()
Definition: GLCanvas.java:776
GLCapabilitiesImmutable getChosenGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the chosen OpenGL capabilities (pixel format / v...
Definition: GLCanvas.java:881
boolean getAutoSwapBufferMode()
Indicates whether automatic buffer swapping is enabled for this drawable.
Definition: GLCanvas.java:781
int getSurfaceHeight()
Returns the height of this GLDrawable's surface client area in pixel units.
Definition: GLCanvas.java:695
boolean getGLEventListenerInitState(final GLEventListener listener)
Retrieves whether the given listener is initialized or not.
Definition: GLCanvas.java:731
void flushGLRunnables()
Flushes all enqueued GLRunnable of this GLAutoDrawable including notifying waiting executor.
Definition: GLCanvas.java:817
final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable)
Specifies an GLAutoDrawable, which OpenGL context shall be shared by this GLAutoDrawable's GLContext.
Definition: GLCanvas.java:417
final boolean isThreadGLCapable()
Indicates whether the current thread is capable of performing OpenGL-related work....
Definition: GLCanvas.java:938
final Thread setExclusiveContextThread(final Thread t)
Dedicates this instance's GLContext to the given thread.
Definition: GLCanvas.java:771
void addGLEventListener(final GLEventListener listener)
Adds the given listener to the end of this drawable queue.
Definition: GLCanvas.java:706
final void setSharedContext(final GLContext sharedContext)
Specifies an OpenGL context, which shall be shared by this GLAutoDrawable's GLContext.
Definition: GLCanvas.java:412
void dispose()
@Override public boolean forceFocus() { final boolean r = super.forceFocus(); if(r && 0 !...
Definition: GLCanvas.java:657
GLContext createContext(final GLContext shareWith)
Creates a new context for drawing to this drawable that will optionally share buffer objects,...
Definition: GLCanvas.java:865
GLAnimatorControl getAnimator()
Definition: GLCanvas.java:766
final boolean validateDrawableAndContextWithCheck()
assumes drawable == null (implying !drawable.isRealized()) ! Checks of !isDispose() and isVisible()
Definition: GLCanvas.java:508
void swapBuffers()
Swaps the front and back buffers of this drawable.
Definition: GLCanvas.java:927
void setContextCreationFlags(final int arg0)
Definition: GLCanvas.java:846
GLDrawableFactory getFactory()
Return the GLDrawableFactory being used to create this instance.
Definition: GLCanvas.java:893
void setAnimator(final GLAnimatorControl arg0)
Registers the usage of an animator, an com.jogamp.opengl.GLAnimatorControl implementation.
Definition: GLCanvas.java:822
GL getGL()
Returns the GL pipeline object this GLAutoDrawable uses.
Definition: GLCanvas.java:801
A interface describing a graphics device in a toolkit-independent manner.
boolean close()
Optionally closing the device if handle is not null.
boolean open()
Optionally [re]opening the device if handle is null.
static int DEFAULT_UNIT
Default unit id for the 1st device: 0.
String getConnection()
Returns the semantic GraphicsDevice connection.
A interface describing a graphics screen in a toolkit-independent manner.
int getIndex()
Returns the screen index this graphics screen is valid for.
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...
Provides a mutable NativeSurface, i.e.
Interface allowing upstream caller to pass lifecycle actions and size info to a ProxySurface instance...
An animator control interface, which implementation may drive a com.jogamp.opengl....
boolean resume()
Resumes animation if paused.
boolean pause()
Pauses this animator.
A higher-level abstraction than GLDrawable which supplies an event based mechanism (GLEventListener) ...
GL getGL()
Returns the GL pipeline object this GLAutoDrawable uses.
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
GLCapabilitiesImmutable getChosenGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the chosen OpenGL capabilities (pixel format / v...
int getSurfaceWidth()
Returns the width of this GLDrawable's surface client area in pixel units.
GLCapabilitiesImmutable getRequestedGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the user requested OpenGL capabilities (pixel fo...
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.
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.