41package com.jogamp.opengl.awt;
43import java.beans.Beans;
44import java.awt.Canvas;
46import java.awt.FontMetrics;
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;
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;
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;
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;
168@SuppressWarnings(
"serial")
172 private static final boolean DEBUG = Debug.debug(
"GLCanvas");
174 private static JAWTUtil.BackgroundEraseControl backgroundEraseControl =
new JAWTUtil.BackgroundEraseControl();
176 private final RecursiveLock lock = LockFactory.createRecursiveLock();
177 private final GLDrawableHelper helper =
new GLDrawableHelper();
178 private volatile GLDrawableImpl drawable;
180 private volatile GLContextImpl context;
181 private volatile boolean sendReshape =
false;
187 private int additionalCtxCreationFlags = 0;
188 private boolean shallUseOffscreenLayer =
false;
190 private volatile GraphicsDevice awtDeviceReq;
192 private volatile boolean isShowing;
193 private final HierarchyListener hierarchyListener =
new HierarchyListener() {
195 public void hierarchyChanged(
final HierarchyEvent e) {
196 isShowing =
GLCanvas.this.isShowing();
230 this(capsReqUser,
null,
null);
250 final GraphicsDevice device)
262 if(
null==capsReqUser) {
269 setShallUseOffscreenLayer(
true);
273 awtDeviceReq = device;
276 this.chooser = chooser;
278 this.addHierarchyListener(hierarchyListener);
279 this.isShowing = isShowing();
284 helper.setSharedContext(this.context, sharedContext);
289 helper.setSharedAutoDrawable(
this, sharedAutoDrawable);
305 shallUseOffscreenLayer = v;
310 return shallUseOffscreenLayer;
316 if(
null != _jawtWindow) {
346 final GraphicsConfiguration parentGC = super.getGraphicsConfiguration();
348 if( Beans.isDesignTime() ) {
353 if (
null != parentGC &&
null != oldGC && !oldGC.equals(parentGC) ) {
356 if ( !oldGC.getDevice().getIDstring().equals(parentGC.getDevice().getIDstring()) ) {
366 chooser, parentGC.getDevice());
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);
382 if (
null != newGC ) {
387 setAWTGraphicsConfiguration(newConfig);
388 createJAWTDrawableAndContext();
389 validateGLDrawable();
391 setAWTGraphicsConfiguration(newConfig);
398 System.err.println(getThreadName()+
": Info: getGraphicsConfiguration - end.01: newGC "+newGC);
403 System.err.println(getThreadName()+
": Info: getGraphicsConfiguration - end.00: oldGC "+oldGC);
414 }
else if (
null == parentGC) {
433 final RecursiveLock _lock = lock;
436 if(drawable !=
null) {
437 final GLContext _ctx = drawable.createContext(shareWith);
447 private final void setRealizedImpl(
final boolean realized) {
448 final RecursiveLock _lock = lock;
452 if(
null == _drawable || realized == _drawable.
isRealized() ||
464 private final Runnable realizeOnEDTAction =
new Runnable() {
466 public void run() { setRealizedImpl(
true); }
468 private final Runnable unrealizeOnEDTAction =
new Runnable() {
470 public void run() { setRealizedImpl(
false); }
476 AWTEDTExecutor.singleton.invoke(getTreeLock(),
false ,
true , realized ? realizeOnEDTAction : unrealizeOnEDTAction);
482 return (
null != _drawable ) ? _drawable.
isRealized() :
false;
497 if( !validateGLDrawable() ) {
499 System.err.println(getThreadName()+
": Info: GLCanvas display - skipped GL render, drawable not valid yet");
503 if( isShowing && !printActive ) {
522 destroyImpl(
false );
525 protected void destroyImpl(
final boolean destroyJAWTWindowAndAWTDevice) {
527 if( destroyJAWTWindowAndAWTDevice ) {
528 AWTEDTExecutor.singleton.invoke(getTreeLock(),
true ,
true , disposeJAWTWindowAndAWTDeviceOnEDT);
538 public void paint(
final Graphics g) {
539 if( Beans.isDesignTime() ) {
541 g.setColor(Color.BLACK);
542 g.fillRect(0, 0, getWidth(), getHeight());
543 final FontMetrics fm = g.getFontMetrics();
544 String name = getName();
546 name = getClass().getName();
547 final int idx = name.lastIndexOf(
'.');
549 name = name.substring(idx + 1);
552 final Rectangle2D bounds = fm.getStringBounds(name, g);
553 g.setColor(Color.WHITE);
555 (
int) ((getWidth() - bounds.getWidth()) / 2),
556 (
int) ((getHeight() + bounds.getHeight()) / 2));
557 }
else if( !this.helper.isAnimatorAnimatingOnOtherThread() ) {
570 @SuppressWarnings(
"deprecation")
573 final RecursiveLock _lock = lock;
576 final boolean isBeansDesignTime = Beans.isDesignTime();
579 System.err.println(getThreadName()+
": Info: addNotify - start, bounds: "+this.getBounds()+
", isBeansDesignTime "+isBeansDesignTime);
583 if( isBeansDesignTime ) {
596 if( OSType.WINDOWS != Platform.getOSType() ) {
597 backgroundEraseControl.disable(
this);
600 final GraphicsDevice awtDevice;
601 if(
null==awtDeviceReq) {
603 final GraphicsConfiguration gc = super.getGraphicsConfiguration();
605 throw new GLException(
"Error: NULL AWT GraphicsConfiguration");
607 awtDevice = gc.getDevice();
610 awtDevice = awtDeviceReq;
613 final AWTGraphicsConfiguration awtConfig = chooseGraphicsConfiguration(capsReqUser, capsReqUser, chooser, awtDevice);
614 if(
null==awtConfig) {
615 throw new GLException(
"Error: NULL AWTGraphicsConfiguration");
617 setAWTGraphicsConfiguration(awtConfig);
623 if( OSType.WINDOWS == Platform.getOSType() ) {
624 backgroundEraseControl.disable(
this);
627 createJAWTDrawableAndContext();
636 System.err.println(getThreadName()+
": Info: addNotify - end");
663 private final boolean updatePixelScale() {
664 if( jawtWindow.hasPixelScaleChanged() ) {
666 final float[] old = { hasPixelScale[0], hasPixelScale[1] };
668 System.err.printf(
"GLCanvas.updatePixelScale hasPixelScale %.2f %.2f -> %.2f %.2f\n", old[0], old[1], hasPixelScale[0], hasPixelScale[1]);
693 System.arraycopy(hasPixelScale, 0, result, 0, 2);
718 System.arraycopy(hasPixelScale, 0, result, 0, 2);
722 private void createJAWTDrawableAndContext() {
723 if ( !Beans.isDesignTime() ) {
735 createContextImpl(drawable);
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);
748 System.err.println(getThreadName()+
": Context created: has shared "+(
null != shareWith[0]));
753 System.err.println(getThreadName()+
": Context !created: pending share");
759 private boolean validateGLDrawable() {
760 if( Beans.isDesignTime() || !isDisplayable() ) {
763 final GLDrawable _drawable = drawable;
764 if (
null != _drawable ) {
768 if( 0 >= _drawable.getSurfaceWidth() || 0 >= _drawable.getSurfaceHeight() ) {
772 res = _drawable.isRealized();
774 System.err.println(getThreadName()+
": Realized Drawable: isRealized "+res+
", "+_drawable.toString());
778 if( res &&
null == context ) {
780 res = createContextImpl(_drawable);
787 private void setAWTGraphicsConfiguration(
final AWTGraphicsConfiguration config) {
790 if(
null != jawtWindow ) {
804 @SuppressWarnings(
"deprecation")
808 System.err.println(getThreadName()+
": Info: removeNotify - start");
814 if( Beans.isDesignTime() ) {
815 super.removeNotify();
820 super.removeNotify();
824 System.err.println(getThreadName()+
": Info: removeNotify - end");
835 @SuppressWarnings(
"deprecation")
837 public void reshape(
final int x,
final int y,
final int width,
final int height) {
838 synchronized (getTreeLock()) {
839 super.reshape(x, y, width, height);
840 reshapeImpl(width, height);
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]);
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));
856 if( validateGLDrawable() && !printActive ) {
857 final GLDrawableImpl _drawable = drawable;
858 if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) {
859 final RecursiveLock _lock = lock;
862 final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, scaledWidth, scaledHeight);
863 if(_drawable != _drawableNew) {
865 drawable = _drawableNew;
884 private volatile boolean printActive =
false;
887 private AWTTilePainter printAWTTiles =
null;
890 public void setupPrint(
final double scaleMatX,
final double scaleMatY,
final int numSamples,
final int tileWidth,
final int tileHeight) {
892 final int componentCount = isOpaque() ? 3 : 4;
894 printAWTTiles =
new AWTTilePainter(printRenderer, componentCount, scaleMatX, scaleMatY, numSamples, tileWidth, tileHeight, DEBUG);
895 AWTEDTExecutor.singleton.invoke(getTreeLock(),
true ,
true , setupPrintOnEDT);
897 private final Runnable setupPrintOnEDT =
new Runnable() {
900 final RecursiveLock _lock = lock;
903 if( !validateGLDrawable() ) {
905 System.err.println(getThreadName()+
": Info: GLCanvas setupPrint - skipped GL render, drawable not valid yet");
912 System.err.println(getThreadName()+
": Info: GLCanvas setupPrint - skipped GL render, canvas not visible");
918 printAnimator = helper.getAnimator();
919 if(
null != printAnimator ) {
920 printAnimator.
remove(GLCanvas.this);
922 printGLAD = GLCanvas.this;
923 final GLCapabilitiesImmutable gladCaps = getChosenGLCapabilities();
924 final int printNumSamples = printAWTTiles.getNumSamples(gladCaps);
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();
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);
938 final boolean reqNewGLADSafe = GLDrawableUtil.isSwapGLContextSafe(getRequestedGLCapabilities(), gladCaps, newGLADCaps);
940 final boolean reqNewGLAD = ( reqNewGLADOnscrn || reqNewGLADSamples || reqNewGLADSize ) && reqNewGLADSafe;
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);
950 final GLDrawableFactory factory = GLDrawableFactory.getFactory(newGLADCaps.getGLProfile());
951 GLOffscreenAutoDrawable offGLAD =
null;
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) {
958 System.err.println(
"Caught: "+gle.getMessage());
959 gle.printStackTrace();
962 if(
null != offGLAD ) {
964 GLDrawableUtil.swapGLContextAndAllGLEventListener(GLCanvas.this, printGLAD);
969 printAWTTiles.renderer.setTileSize(printDrawable.getSurfaceWidth(), printDrawable.getSurfaceHeight(), 0);
970 printAWTTiles.renderer.attachAutoDrawable(printGLAD);
972 System.err.println(
"AWT print.setup "+printAWTTiles);
973 System.err.println(
"AWT print.setup AA "+printNumSamples+
", "+newGLADCaps);
975 System.err.println(
"AWT print.setup printDraw: "+printDrawable.getSurfaceWidth()+
"x"+printDrawable.getSurfaceHeight()+
", "+printDrawable);
985 if( !printActive ||
null == printGLAD ) {
986 throw new IllegalStateException(
"setupPrint() not called");
989 AWTEDTExecutor.singleton.invoke(getTreeLock(),
true ,
true , releasePrintOnEDT);
991 private final Runnable releasePrintOnEDT =
new Runnable() {
994 final RecursiveLock _lock = lock;
998 System.err.println(
"AWT print.release "+printAWTTiles);
1000 printAWTTiles.dispose();
1001 printAWTTiles=
null;
1002 if( printGLAD != GLCanvas.this ) {
1007 if(
null != printAnimator ) {
1008 printAnimator.
add(GLCanvas.this);
1009 printAnimator =
null;
1012 printActive =
false;
1021 public void print(
final Graphics graphics) {
1022 if( !printActive ||
null == printGLAD ) {
1023 throw new IllegalStateException(
"setupPrint() not called");
1025 if(DEBUG && !EventQueue.isDispatchThread()) {
1026 System.err.println(getThreadName()+
": Warning: GLCanvas print - not called from AWT-EDT");
1029 sendReshape =
false;
1031 final Graphics2D g2d = (Graphics2D)graphics;
1033 printAWTTiles.setupGraphics2DAndClipBounds(g2d, getWidth(), getHeight());
1034 final TileRenderer tileRenderer = printAWTTiles.renderer;
1036 System.err.println(
"AWT print.0: "+tileRenderer);
1038 if( !tileRenderer.
eot() ) {
1046 }
while ( !tileRenderer.
eot() );
1048 System.err.println(
"AWT print.1: "+printAWTTiles);
1051 tileRenderer.
reset();
1052 printAWTTiles.resetGraphics2D();
1055 }
catch (
final NoninvertibleTransformException nte) {
1056 System.err.println(
"Caught: Inversion failed of: "+g2d.getTransform());
1057 nte.printStackTrace();
1060 System.err.println(
"AWT print.X: "+printAWTTiles);
1066 helper.addGLEventListener(listener);
1071 helper.addGLEventListener(index, listener);
1076 return helper.getGLEventListenerCount();
1081 return helper.getGLEventListener(index);
1086 return helper.areAllGLEventListenerInitialized();
1091 return helper.getGLEventListenerInitState(listener);
1096 helper.setGLEventListenerInitState(listener, initialized);
1101 final DisposeGLEventListenerAction r =
new DisposeGLEventListenerAction(listener,
remove);
1108 return helper.removeGLEventListener(listener);
1113 helper.setAnimator(animatorControl);
1118 return helper.getAnimator();
1123 return helper.setExclusiveContextThread(t, context);
1128 return helper.getExclusiveContextThread();
1132 public boolean invoke(
final boolean wait,
final GLRunnable glRunnable)
throws IllegalStateException {
1133 return helper.invoke(
this, wait, glRunnable);
1137 public boolean invoke(
final boolean wait,
final List<GLRunnable> glRunnables)
throws IllegalStateException {
1138 return helper.invoke(
this, wait, glRunnables);
1143 helper.flushGLRunnables();
1148 final RecursiveLock _lock = lock;
1152 GLDrawableHelper.switchContext(drawable, oldCtx, destroyPrevCtx, newCtx, additionalCtxCreationFlags);
1153 context=(GLContextImpl)newCtx;
1172 if( Beans.isDesignTime() ) {
1176 return (_context ==
null) ? null : _context.
getGL();
1182 if (_context !=
null) {
1192 helper.setAutoSwapBufferMode(onOrOff);
1197 return helper.getAutoSwapBufferMode();
1207 additionalCtxCreationFlags = flags;
1209 if(
null != _context) {
1216 return additionalCtxCreationFlags;
1226 if( Beans.isDesignTime() ) {
1228 }
else if(
null == awtConfig ) {
1229 throw new GLException(
"No AWTGraphicsConfiguration: "+
this);
1236 if(
null == awtConfig ) {
1244 return SurfaceScaleUtils.scale(getWidth(), hasPixelScale[0]);
1249 return SurfaceScaleUtils.scale(getHeight(), hasPixelScale[1]);
1255 return null != _drawable ? _drawable.
isGLOriented() :
true;
1267 return (
null != _drawable) ? _drawable.
getHandle() : 0;
1273 return (
null != _drawable) ? _drawable.
getFactory() :
null;
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+
"]]";
1296 private final String getPixelScaleStr() {
return "["+hasPixelScale[0]+
", "+hasPixelScale[1]+
"]"; }
1298 private final Runnable destroyOnEDTAction =
new Runnable() {
1301 final RecursiveLock _lock = lock;
1307 System.err.println(getThreadName()+
": Info: destroyOnEDTAction() - START, hasContext " +
1308 (
null!=context) +
", hasDrawable " + (
null!=drawable)+
", "+animator);
1312 final boolean animatorPaused;
1313 if(
null!=animator) {
1315 animatorPaused = animator.
pause();
1317 animatorPaused =
false;
1320 GLException exceptionOnDisposeGL =
null;
1323 if(
null != context ) {
1324 if( context.isCreated() ) {
1326 helper.disposeGL(GLCanvas.this, context,
true);
1328 System.err.println(getThreadName()+
": destroyOnEDTAction() - post ctx: "+context);
1330 }
catch (
final GLException gle) {
1331 exceptionOnDisposeGL = gle;
1337 Throwable exceptionOnUnrealize =
null;
1338 if(
null != drawable ) {
1340 drawable.setRealized(
false);
1342 System.err.println(getThreadName()+
": destroyOnEDTAction() - post drawable: "+drawable);
1344 }
catch(
final Throwable re ) {
1345 exceptionOnUnrealize = re;
1350 if(animatorPaused) {
1355 if(
null != exceptionOnDisposeGL ) {
1356 throw exceptionOnDisposeGL;
1358 if(
null != exceptionOnUnrealize ) {
1359 throw GLException.newGLException(exceptionOnUnrealize);
1363 System.err.println(getThreadName()+
": dispose() - END, animator "+animator);
1381 private final Runnable disposeJAWTWindowAndAWTDeviceOnEDT =
new Runnable() {
1387 if(
null != jawtWindow ) {
1390 System.err.println(getThreadName()+
": GLCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post JAWTWindow: "+jawtWindow);
1395 hasPixelScale[1] = ScalableSurface.IDENTITY_PIXELSCALE;
1397 if(
null != awtConfig) {
1400 final String adeviceMsg;
1402 adeviceMsg = adevice.toString();
1406 final boolean closed = adevice.
close();
1408 System.err.println(getThreadName()+
": GLCanvas.disposeJAWTWindowAndAWTDeviceOnEDT(): post GraphicsDevice: "+adeviceMsg+
", result: "+closed);
1415 private final Runnable initAction =
new Runnable() {
1418 helper.init(GLCanvas.this, !sendReshape);
1422 private final Runnable displayAction =
new Runnable() {
1427 System.err.println(getThreadName()+
": Reshape: "+getSurfaceWidth()+
"x"+getSurfaceHeight());
1431 helper.reshape(GLCanvas.this, 0, 0, getSurfaceWidth(), getSurfaceHeight());
1432 sendReshape =
false;
1435 helper.display(GLCanvas.this);
1439 private final Runnable displayOnEDTAction =
new Runnable() {
1442 final RecursiveLock _lock = lock;
1445 if(
null != drawable && drawable.isRealized() ) {
1446 if( GLCanvas.this.updatePixelScale() ) {
1447 GLCanvas.this.reshapeImpl(getWidth(), getHeight());
1449 helper.invokeGL(drawable, context, displayAction, initAction);
1457 private final Runnable swapBuffersOnEDTAction =
new Runnable() {
1460 final RecursiveLock _lock = lock;
1463 if(
null != drawable && drawable.isRealized() ) {
1464 drawable.swapBuffers();
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;
1482 final RecursiveLock _lock = lock;
1485 listener = helper.disposeGLEventListener(GLCanvas.this, drawable, context, listener,
remove);
1504 private AWTGraphicsConfiguration chooseGraphicsConfiguration(
final GLCapabilitiesImmutable capsChosen,
1505 final GLCapabilitiesImmutable capsRequested,
1506 final GLCapabilitiesChooser chooser,
1507 final GraphicsDevice device) {
1509 if( Beans.isDesignTime() ) {
1512 if(
null == device ) {
1513 throw new GLException(
"Error: NULL AWT GraphicsDevice");
1515 final AbstractGraphicsScreen aScreen = AWTGraphicsScreen.createScreenDevice(device, AbstractGraphicsDevice.DEFAULT_UNIT);
1516 AWTGraphicsConfiguration config =
null;
1518 if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) {
1519 config = (AWTGraphicsConfiguration)
1520 GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
1522 chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
1525 final ArrayList<AWTGraphicsConfiguration> bucket =
new ArrayList<AWTGraphicsConfiguration>(1);
1526 EventQueue.invokeAndWait(
new Runnable() {
1529 final AWTGraphicsConfiguration c = (AWTGraphicsConfiguration)
1530 GraphicsConfigurationFactory.getFactory(AWTGraphicsDevice.class, GLCapabilitiesImmutable.class).chooseGraphicsConfiguration(capsChosen,
1532 chooser, aScreen, VisualIDHolder.VID_UNDEFINED);
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);
1544 if (
null == config ) {
1545 throw new GLException(
"Error: Couldn't fetch AWTGraphicsConfiguration");
1551 protected static String
getThreadName() {
return Thread.currentThread().getName(); }
1556 public static void main(
final String args[]) {
1557 System.err.println(VersionUtil.getPlatformInfo());
1558 System.err.println(GlueGenVersion.getInstance());
1565 final Frame frame =
new Frame(
"JOGL AWT Test");
1568 frame.add(glCanvas);
1569 frame.setSize(128, 128);
1574 final GL gl = drawable.
getGL();
1578 public void reshape(
final GLAutoDrawable drawable,
final int x,
final int y,
final int width,
final int height) { }
1586 javax.swing.SwingUtilities.invokeAndWait(
new Runnable() {
1589 frame.setVisible(
true);
1591 }
catch (
final Throwable t) {
1592 t.printStackTrace();
1596 javax.swing.SwingUtilities.invokeAndWait(
new Runnable() {
1601 }
catch (
final Throwable t) {
1602 t.printStackTrace();
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 WindowClosingMode getDefaultCloseOperation()
final boolean removeClosingListener()
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.
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.
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.
static GLProfile getDefault(final AbstractGraphicsDevice device)
Returns a default GLProfile object, reflecting the best for the running platform.
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...
static final boolean isOpenGLThread()
Indicates whether the current thread is capable of performing OpenGL-related work.
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...
A heavyweight AWT component which provides OpenGL rendering support.
int getContextCreationFlags()
final float[] getRequestedSurfaceScale(final float[] result)
Returns the requested pixel scale of the associated NativeSurface.If canSetSurfaceScale() returns fal...
final void setSharedAutoDrawable(final GLAutoDrawable sharedAutoDrawable)
Specifies an GLAutoDrawable, which OpenGL context shall be shared by this GLAutoDrawable's GLContext.
void update(final Graphics g)
Overridden from Canvas to prevent the AWT's clearing of the canvas from interfering with the OpenGL r...
boolean isRealized()
Returns true if this drawable is realized, otherwise false.
void destroyImpl(final boolean destroyJAWTWindowAndAWTDevice)
GLEventListener disposeGLEventListener(final GLEventListener listener, final boolean remove)
Disposes the given listener via dispose(..) if it has been initialized and added to this queue.
void setGLEventListenerInitState(final GLEventListener listener, final boolean initialized)
Sets the given listener's initialized state.
GL setGL(final GL gl)
Sets the GL pipeline object this GLAutoDrawable uses.
final Thread setExclusiveContextThread(final Thread t)
Dedicates this instance's GLContext to the given thread.
GLCapabilitiesImmutable getRequestedGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the user requested OpenGL capabilities (pixel fo...
GLContext setContext(final GLContext newCtx, final boolean destroyPrevCtx)
Associate the new context, newtCtx, to this auto-drawable.
WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op)
void addNotify()
Overridden to track when this component is added to a container.
GLDrawableFactory getFactory()
Return the GLDrawableFactory being used to create this instance.
void print(final Graphics graphics)
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.
GLEventListener getGLEventListener(final int index)
Returns the GLEventListener at the given index of this drawable queue.
GLContext getContext()
Returns the context associated with this drawable.
GL getGL()
Returns the GL pipeline object this GLAutoDrawable uses.
GLProfile getGLProfile()
Fetches the GLProfile for this drawable.
boolean areAllGLEventListenerInitialized()
Returns true if all added GLEventListener are initialized, otherwise false.
final RecursiveLock getUpstreamLock()
Returns the recursive lock object of the upstream widget to synchronize multithreaded access on top o...
final Thread getExclusiveContextThread()
void paint(final Graphics g)
Overridden to cause OpenGL rendering to be performed during repaint cycles.
void setAutoSwapBufferMode(final boolean onOrOff)
Enables or disables automatic buffer swapping for this drawable.
GLCanvas()
Creates a new GLCanvas component with a default set of OpenGL capabilities, using the default OpenGL ...
static String getThreadName()
void flushGLRunnables()
Flushes all enqueued GLRunnable of this GLAutoDrawable including notifying waiting executor.
final GLDrawable getDelegatedDrawable()
If the implementation uses delegation, return the delegated GLDrawable instance, otherwise return thi...
final void setSharedContext(final GLContext sharedContext)
Specifies an OpenGL context, which shall be shared by this GLAutoDrawable's GLContext.
boolean getAutoSwapBufferMode()
Indicates whether automatic buffer swapping is enabled for this drawable.
final boolean setSurfaceScale(final float[] pixelScale)
Request a pixel scale in x- and y-direction for the associated NativeSurface, where size_in_pixel_uni...
static void main(final String args[])
A most simple JOGL AWT test entry.
void destroy()
Destroys all resources associated with this GLAutoDrawable, inclusive the GLContext....
GLEventListener removeGLEventListener(final GLEventListener listener)
Removes the given listener from this drawable queue.
final Object getUpstreamWidget()
Method may return the upstream UI toolkit object holding this GLAutoDrawable instance,...
void setupPrint(final double scaleMatX, final double scaleMatY, final int numSamples, final int tileWidth, final int tileHeight)
Shall be called before PrinterJob#print().
final boolean isThreadGLCapable()
Indicates whether the current thread is capable of performing OpenGL-related work.
GLCanvas(final GLCapabilitiesImmutable capsReqUser, final GLCapabilitiesChooser chooser, final GraphicsDevice device)
Creates a new GLCanvas component.
int getSurfaceHeight()
Returns the height of this GLDrawable's surface client area in pixel units.
int getSurfaceWidth()
Returns the width of this GLDrawable's surface client area in pixel units.
GraphicsConfiguration getGraphicsConfiguration()
void setShallUseOffscreenLayer(final boolean v)
Request an offscreen layer, if supported.
void swapBuffers()
Swaps the front and back buffers of this drawable.
GLAnimatorControl getAnimator()
boolean getGLEventListenerInitState(final GLEventListener listener)
Retrieves whether the given listener is initialized or not.
void releasePrint()
Shall be called after PrinterJob#print().
final boolean canSetSurfaceScale()
Returns true if setSurfaceScale(float[]) is supported, otherwise false.For pure downstream scalable s...
WindowClosingMode getDefaultCloseOperation()
int getGLEventListenerCount()
Returns the number of GLEventListener of this drawable queue.
final void setRealized(final boolean realized)
Indicates to GLDrawable implementations whether the underlying surface has been created and can be dr...
boolean invoke(final boolean wait, final List< GLRunnable > glRunnables)
Extends invoke(boolean, GLRunnable) functionality allowing to inject a list of GLRunnables.
float[] getMinimumSurfaceScale(final float[] result)
Returns the minimum pixel scale of the associated NativeSurface.the passed storage containing the min...
boolean isGLOriented()
Returns true if the drawable is rendered in OpenGL's coordinate system, origin at bottom left.
long getHandle()
Returns the GL drawable handle, guaranteed to be valid after realization and while it's surface is be...
GLContext createContext(final GLContext shareWith)
Creates a new context for drawing to this drawable that will optionally share buffer objects,...
final boolean isOffscreenLayerSurfaceEnabled()
Returns true if this instance uses an offscreen layer, otherwise false.
NativeSurface getNativeSurface()
Returns the associated NativeSurface of this NativeSurfaceHolder.Returns the underlying NativeSurface...
void addGLEventListener(final GLEventListener listener)
Adds the given listener to the end of this drawable queue.
void addGLEventListener(final int index, final GLEventListener listener)
Adds the given listener at the given index of this drawable queue.
final boolean getShallUseOffscreenLayer()
Returns the property set by setShallUseOffscreenLayer(boolean).
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...
float[] getMaximumSurfaceScale(final float[] result)
Returns the maximum pixel scale of the associated NativeSurface.The maximum pixel scale maybe used to...
GLCapabilitiesImmutable getChosenGLCapabilities()
Fetches the GLCapabilitiesImmutable corresponding to the chosen OpenGL capabilities (pixel format / v...
void setAnimator(final GLAnimatorControl animatorControl)
Registers the usage of an animator, an com.jogamp.opengl.GLAnimatorControl implementation.
void setContextCreationFlags(final int flags)
final float[] getCurrentSurfaceScale(final float[] result)
Returns the current pixel scale of the associated NativeSurface.
GLCanvas(final GLCapabilitiesImmutable capsReqUser)
Creates a new GLCanvas component with the requested set of OpenGL capabilities, using the default Ope...
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.
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.